第二十四章:Service Mesh 安全

“Service Mesh 让零信任从理念变为现实 — 每个服务间的通信都被加密、认证和授权。”

        mindmap
  root((Service Mesh 安全))
    Istio
      Citadel
      Envoy
      Pilot
      SPIFFE ID
    安全特性
      自动 mTLS
      AuthorizationPolicy
      RequestAuthentication
    集成
      SPIRE
      OPA
      ext_authz
    对比
      Linkerd
      Cilium
    

24.1 Service Mesh 与零信任

Service Mesh 在基础设施层实现了零信任的核心要求:

没有 Service Mesh:
Service A ──── 明文 HTTP ────▶ Service B
               无认证、无授权、无加密

有了 Service Mesh:
Service A ──▶ [Envoy] ══ mTLS ══ [Envoy] ──▶ Service B
              Sidecar   加密+认证+授权  Sidecar
              自动注入                   自动注入

24.2 Istio 安全架构

┌─────────────────────────────────────────────────┐
│                 Istio 控制平面                    │
│  ┌──────────┐  ┌──────────┐  ┌──────────────┐  │
│  │  Istiod  │  │ Citadel  │  │   Pilot      │  │
│  │ (核心)   │  │ (证书管理)│  │ (配置分发)   │  │
│  │          │  │ SPIFFE CA│  │ xDS API      │  │
│  └──────────┘  └──────────┘  └──────────────┘  │
└──────────────────────┬──────────────────────────┘
                       │ xDS (证书 + 策略)
┌──────────────────────▼──────────────────────────┐
│                 数据平面                          │
│  ┌─────────────────────────────────────────┐    │
│  │  Pod A                                   │    │
│  │  ┌──────────┐    ┌────────────────────┐ │    │
│  │  │ Service A│◀──▶│  Envoy Sidecar     │ │    │
│  │  │          │    │  • mTLS 终止/发起  │ │    │
│  │  │          │    │  • 授权策略执行    │ │    │
│  │  │          │    │  • JWT 验证       │ │    │
│  │  │          │    │  • 遥测数据收集   │ │    │
│  │  └──────────┘    └────────────────────┘ │    │
│  └─────────────────────────────────────────┘    │
└─────────────────────────────────────────────────┘

身份模型:
每个工作负载获得 SPIFFE ID:
spiffe://cluster.local/ns/{namespace}/sa/{service-account}

24.3 自动 mTLS

PeerAuthentication

# 全局启用严格 mTLS
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: default
  namespace: istio-system
spec:
  mtls:
    mode: STRICT  # 所有服务间通信必须 mTLS

---
# 特定命名空间允许明文(迁移期间)
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: legacy-permissive
  namespace: legacy-apps
spec:
  mtls:
    mode: PERMISSIVE  # 同时接受 mTLS 和明文

---
# 特定端口排除 mTLS
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: db-service
  namespace: production
spec:
  selector:
    matchLabels:
      app: database
  mtls:
    mode: STRICT
  portLevelMtls:
    9090:
      mode: PERMISSIVE  # metrics 端口允许明文

mTLS 模式对比

模式

行为

适用场景

DISABLE

不使用 mTLS

不推荐

PERMISSIVE

同时接受 mTLS 和明文

迁移期间

STRICT

仅接受 mTLS

生产环境

UNSET

继承父级设置

默认

24.4 AuthorizationPolicy

# 只允许 frontend 访问 backend
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: backend-policy
  namespace: production
spec:
  selector:
    matchLabels:
      app: backend
  action: ALLOW
  rules:
    - from:
        - source:
            principals:
              - "cluster.local/ns/production/sa/frontend"
      to:
        - operation:
            methods: ["GET", "POST"]
            paths: ["/api/*"]

---
# 拒绝来自特定命名空间的请求
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: deny-untrusted
  namespace: production
spec:
  action: DENY
  rules:
    - from:
        - source:
            namespaces: ["untrusted"]

---
# 基于 JWT Claims 的授权
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: admin-only
  namespace: production
spec:
  selector:
    matchLabels:
      app: admin-panel
  action: ALLOW
  rules:
    - from:
        - source:
            requestPrincipals: ["https://auth.example.com/*"]
      when:
        - key: request.auth.claims[roles]
          values: ["admin"]

24.5 RequestAuthentication

# JWT 验证配置
apiVersion: security.istio.io/v1
kind: RequestAuthentication
metadata:
  name: jwt-auth
  namespace: production
spec:
  selector:
    matchLabels:
      app: api-server
  jwtRules:
    - issuer: "https://auth.example.com"
      jwksUri: "https://auth.example.com/.well-known/jwks.json"
      audiences:
        - "my-api"
      forwardOriginalToken: true
      outputPayloadToHeader: "x-jwt-payload"

24.6 Istio + SPIRE 集成

用 SPIRE 替换 Istio 内置的 Citadel CA:

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  values:
    global:
      caAddress: "spire-server.spire-system:8081"
    pilot:
      env:
        PILOT_CERT_PROVIDER: spiffe
  meshConfig:
    trustDomain: "example.org"

优势:

  • 跨集群统一身份(SPIFFE 联邦)

  • 更灵活的 CA 管理(对接 Vault、AWS PCA)

  • 非 K8s 工作负载也能参与 Mesh

24.7 Envoy 外部授权(ext_authz)

# 将授权决策委托给外部服务(如 OPA)
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: ext-authz
  namespace: istio-system
spec:
  configPatches:
    - applyTo: HTTP_FILTER
      match:
        context: SIDECAR_INBOUND
      patch:
        operation: INSERT_BEFORE
        value:
          name: envoy.filters.http.ext_authz
          typed_config:
            "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
            grpc_service:
              envoy_grpc:
                cluster_name: opa-authz
              timeout: 0.5s
            failure_mode_allow: false

24.8 Service Mesh 对比

特性

Istio

Linkerd

Cilium

代理

Envoy

linkerd2-proxy

eBPF

mTLS

✅ 自动

✅ 自动

✅ 自动

授权策略

丰富

基本

丰富(CiliumNetworkPolicy)

性能开销

中等

极低(内核级)

复杂度

SPIFFE

多集群

24.9 渐进式 mTLS 迁移

阶段 1:观察(1-2周)
├── 部署 Istio,注入 Sidecar
├── PeerAuthentication: PERMISSIVE
├── 观察流量,确认所有服务正常
└── 收集 mTLS 覆盖率指标

阶段 2:逐步启用(2-4周)
├── 按命名空间逐步切换到 STRICT
├── 先从非关键服务开始
├── 监控错误率和延迟
└── 处理不兼容的服务

阶段 3:全面启用(1-2周)
├── 全局 PeerAuthentication: STRICT
├── 部署 AuthorizationPolicy
├── 启用审计日志
└── 建立告警规则

阶段 4:持续优化
├── 细化授权策略
├── 集成 SPIRE(跨集群)
├── 添加 ext_authz(OPA)
└── 定期审查策略

24.10 小结

  • Service Mesh 在基础设施层实现零信任:自动 mTLS + 细粒度授权

  • Istio 提供最丰富的安全特性:PeerAuthentication、AuthorizationPolicy、RequestAuthentication

  • SPIRE 集成 实现跨集群、跨平台的统一工作负载身份

  • ext_authz 可以将授权决策委托给 OPA 等外部策略引擎

  • mTLS 迁移应该渐进式进行:PERMISSIVE → 逐步 STRICT → 全局 STRICT

  • Cilium 的 eBPF 方案性能最优,但生态不如 Istio 成熟