适用场景
本文适用于运行在 Kubernetes 集群内的微服务架构,当服务间存在敏感数据传输(订单、用户、支付信息)、安全审计要求服务间身份可验证、或需要替代自研加密中间层时,可借助 Istio 服务网格 的 mTLS 双向认证与授权策略实现统一安全治理。以下配置基于 Istio 1.18+ 与 Kubernetes 1.24+。
前置条件
- 已通过 istioctl 或 Helm 完成 Istio 安装,istiod 运行正常
- 目标命名空间可开启 sidecar 自动注入(
istio-injection=enabled标签) - 具备 kubectl 集群权限,可创建 PeerAuthentication / AuthorizationPolicy CRD 资源
原理说明
Istio 为每个 Pod 注入 Envoy sidecar 代理,服务间流量全部经过 sidecar 转发。istiod 控制面为每个工作负载签发基于 SPIFFE 的身份证书,sidecar 之间通过 mTLS 加密通信并互相验证身份。PeerAuthentication 资源控制 mTLS 模式:PERMISSIVE(兼容明文)或 STRICT(强制双向 TLS);AuthorizationPolicy 提供比网络层更细粒度的 L7 授权(按来源身份、HTTP 方法、路径)。默认集群为 PERMISSIVE 模式,生产环境应切换到 STRICT 并配合授权策略。
操作步骤
第一步:开启命名空间自动注入
# 为目标命名空间开启 sidecar 自动注入
kubectl label namespace default istio-injection=enabled
# 部署测试应用(示例为 Bookinfo 可跳过,直接使用你的服务)
kubectl rollout restart deployment -n default
第二步:配置 STRICT mTLS
创建 PeerAuthentication 资源,将命名空间内全部服务切换为强制双向 TLS:
cat <<'EOF' | kubectl apply -f -
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default-strict
namespace: default
spec:
mtls:
mode: STRICT
EOF
第三步:配置细粒度授权策略
仅允许指定服务账号访问目标服务,并限制 HTTP 方法:
cat <<'EOF' | kubectl apply -f -
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: order-api-allow
namespace: default
spec:
selector:
matchLabels:
app: order-api
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/payment"]
to:
- operation:
methods: ["GET", "POST"]
paths: ["/api/orders/*"]
EOF
第四步:按端口精细控制 mTLS 策略
若服务同时承载内部业务端口与对外健康检查端口,可对端口单独设置 mTLS 模式,避免误伤健康检查流量:
cat <<'EOF' | kubectl apply -f -
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: order-api-port-mtls
namespace: default
spec:
selector:
matchLabels:
app: order-api
mtls:
mode: STRICT
portLevelMtls:
9090:
mode: PERMISSIVE # 健康检查端口保持兼容
EOF
第五步:监控 mTLS 覆盖与异常流量
通过 Prometheus 指标监控集群内 mTLS 启用比例与请求失败率,及时发现未加密流量:
# 查询 sidecar 间非 mTLS 请求占比(应趋近于 0)
istio_requests_total{reporter="destination",connection_security_policy!="mutual_tls"}
# 查看 403 授权拒绝次数,辅助调整 AuthorizationPolicy
istio_requests_total{response_code="403"}
# 打开 Grafana Istio 面板查看服务间安全状态
istioctl dashboard grafana
第六步:验证证书与 mTLS 状态
# 查看服务间 TLS 协商结果
istioctl authn tls-check deployment/order-api-v1 default
# 查看 sidecar 中签发的证书与轮换时间
istioctl proxy-config secret order-api-v1 -o json | jq .
配置验证
# 1. 抓包确认 sidecar 间为 8443 加密流量(默认 mTLS 端口)
kubectl exec -it deploy/order-api-v1 -c istio-proxy -- \
tcpdump -i eth0 -nn -c 20 port 8080
# 2. 验证授权:非授权来源访问应返回 403
kubectl exec -it deploy/unauthorized-app -- \
curl -s -o /dev/null -w "%{http_code}\n" http://order-api:8080/api/orders/
# 3. 验证 mTLS 后明文端口不可直接访问(被 sidecar 拒绝)
kubectl exec -it deploy/payment-v1 -- curl http://order-api:8080 2>&1 | head
常见问题
Q1:切换 STRICT 后服务调用大面积失败?
通常是目标服务未注入 sidecar 或仍以明文对外通信。先确认所有涉及命名空间都开启注入并完成滚动重启,排查期可先将 PeerAuthentication 改为 PERMISSIVE 过渡,待全部 sidecar 就绪后再切 STRICT。
Q2:mTLS 与 NetworkPolicy 功能重复吗?
不重复。mTLS 负责传输加密与身份认证,NetworkPolicy 负责网络层来源白名单,两者可叠加使用:先由 NetworkPolicy 控制网段可达性,再由 mTLS + AuthorizationPolicy 控制服务身份与方法级访问。
Q3:sidecar 证书过期是否需要人工处理?
不需要。istiod 默认每 24 小时自动轮换工作负载证书,重启进程即可加载新证书。若证书异常,检查 istiod 日志、系统时间同步(NTP)与 CA 配置。
Q4:集群外服务或第三方 API 无法配置 mTLS,如何处理?
对集群外流量使用 Sidecar 资源将目标声明为 mesh-external,流量将以明文(或 TLS origination)出站;对外调用建议启用 egress TLS 并对目标域名做 allowlist,同时确保内部服务间保持 STRICT mTLS,缩小明文流量范围。
总结
Istio 服务网格通过 自动 mTLS + AuthorizationPolicy 将零信任思想落地到集群内服务间通信:STRICT 模式保证流量加密与身份可信,细粒度授权收敛东西向攻击面。建议按命名空间分批灰度切换,先 PERMISSIVE 后 STRICT,并配合监控面板持续观察 mTLS 覆盖率,逐步完成全集群安全加固。