Istio mTLS 跨版本兼容性测试方案

目标

验证在 Istio 金丝雀升级期间,不同 sidecar 版本 + 不同 mTLS 策略(STRICT / PERMISSIVE)下,服务间的双向互通性。

mTLS 背景

概念 说明
PeerAuthentication Istio namespace 级别的 CRD,控制入站 mTLS 策略
STRICT 模式 仅接受 mTLS 连接,拒绝明文流量
PERMISSIVE 模式 同时接受 mTLS 和明文(未设置 PA 时的默认行为)
Auto mTLS(出站) 调用方 sidecar 检测到目标有 sidecar 时,自动升级为 mTLS,与调用方自身 PA 设置无关
XFCC 头 X-Forwarded-Client-Cert,Envoy 在 mTLS 激活时注入,可在应用层验证 mTLS 是否生效

跨版本升级的风险点

  1. 新旧 Envoy 版本间的证书格式 / TLS 协商不兼容
  2. TLS 协议版本差异
  3. 不同版本 istiod 对 STRICT 策略的执行行为差异

测试架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
          ┌──────────────────────────────────────────────────┐
│ release namespace (helm test pods) │
│ │
│ test-1 test-2 test-3 ... test-8 │
│ (pod-level istio.io/rev 控制 sidecar 版本) │
└────┬────────┬────────┬──────────────┬───────────┘
│ │ │ │
┌──────────────┼────────┼────────┼──────────────┼──────────────┐
│ ▼ │ ▼ │ │
│ ┌─────────────────┐ │ ┌─────────────────┐ │ │
│ │ ns: old-strict │ │ │ ns: new-strict │ │ │
│ │ rev: old │ │ │ rev: new │ │ │
│ │ PA: STRICT │ │ │ PA: STRICT │ │ │
│ │ httpbin ────────│ │ │ httpbin ────────│ │ │
│ └─────────────────┘ │ └─────────────────┘ │ │
│ ▲ ▼ ▲ ▼ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ ns: old-permissive│ │ ns: new-permissive│ │
│ │ rev: old │ │ rev: new │ │
│ │ PA: (默认) │ │ PA: (默认) │ │
│ │ httpbin ─────── │ │ httpbin ─────── │ │
│ └──────────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────┘

测试场景矩阵

8 个场景,每场景 5 项断言 = 40 项检查

# 调用方 Sidecar 被调方 Namespace 被调方 mTLS 模式 说明 对应用户需求
1 旧版 新版 + STRICT STRICT 旧 sidecar → 新版 STRICT 服务 需求 #1
2 新版 旧版 + STRICT STRICT 新 sidecar → 旧版 STRICT 服务 需求 #2
3 旧版 新版 + PERMISSIVE PERMISSIVE 旧 sidecar → 新版宽松模式服务 需求 #3
4 旧版 旧版 + STRICT STRICT 同版本 STRICT 基线 补充
5 新版 新版 + STRICT STRICT 同版本 STRICT 基线 补充
6 新版 旧版 + PERMISSIVE PERMISSIVE 场景 #3 的反向 补充
7 旧版 旧版 + PERMISSIVE PERMISSIVE 同版本宽松基线 补充
8 新版 新版 + PERMISSIVE PERMISSIVE 同版本宽松基线 补充

关于用户需求 #4(未启用 mTLS 的旧版服务 → 启用 mTLS 的新版服务):
在 Istio 中调用方自身的 PeerAuthentication 不影响出站调用,auto-mTLS 会在目标有 sidecar 时自动升级为 mTLS。因此需求 #4 在网络层等价于场景 #1。场景 #1 + #3 已完整覆盖。

每场景 5 项断言

# 断言 目的
1 HTTP 200 可达 mTLS 下基本连通性
2 X-Forwarded-Client-Cert 头存在 证明 mTLS 真正生效(核心检查)
3 x-envoy-upstream-service-time 头存在 被调方 sidecar 存在性
4 自定义请求头 X-Cross-Version 转发 端到端数据完整性
5 POST body 往返 非 GET 方法在跨版本 mTLS 下正常工作

实施步骤

阶段一 — Chart 脚手架

步骤 文件 说明
1 Chart.yaml 命名 istio-mtls-cross-version-test,复用现有结构
2 values.yaml 4 个 namespace 名、revision 配置、镜像/资源/测试参数

阶段二 — Kubernetes 资源模板(可并行)

步骤 文件 说明
3 templates/namespaces.yaml 4 个 namespace,分别标记 istio.io/rev
4 templates/peer-authentication.yaml 2 个 PeerAuthentication(API security.istio.io/v1STRICT 模式),仅用于 *-strict namespace
5 templates/httpbin.yaml 4 组 httpbin Deployment + Service
6 templates/test-mtls-cross-version.yaml 8 个测试 Pod(Helm test hooks),Pod 级 istio.io/rev 标签、holdApplicationUntilProxyStarts、就绪等待、check() 函数、quitquitquit

阶段三 — 自动化脚本

步骤 文件 说明
7 run.sh 4 命令结构:install | test | uninstall | all,复制 secret 到 4 个 ns,等待 4 个 httpbin 就绪

阶段四 — 文档

步骤 文件 说明
8 README.md 测试目标、场景矩阵、前置条件、使用说明

参考文件

文件 用途
istio-cross-version-test/Chart.yaml Chart 脚手架参考
istio-cross-version-test/values.yaml 配置结构参考
istio-cross-version-test/run.sh 自动化脚本参考
istio-cross-version-test/templates/namespaces.yaml namespace 创建模式(istio.io/rev 标签)
istio-cross-version-test/templates/httpbin-old.yaml httpbin Deployment+Service 模式
istio-cross-version-test/templates/test-cross-version.yaml 测试 Pod 模式(Helm hooks、check()、就绪等待)

验证方式

# 验证 命令 / 方法
1 Lint 检查 helm lint istio-mtls-cross-version-test/
2 模板渲染 helm template test istio-mtls-cross-version-test/ — 确认 4 ns、2 PA、4 httpbin、8 test pod
3 Dry run helm install --dry-run test istio-mtls-cross-version-test/
4 集群实测 ./run.sh all(需两个 istiod 版本同时运行)— 40/40 通过
5 mTLS 验证 场景 1 & 2 日志中包含 XFCC 头
6 负面测试(手动) 无 sidecar Pod → STRICT httpbin → 连接被拒

设计决策

决策 理由
独立 Chart(不扩展现有测试) 避免回归风险,可独立运行
8 场景全矩阵 2(版本) × 2(版本) × 2(mTLS模式) = 8,无盲区
不单独测试调用方 PA PA 仅影响入站,不影响出站连通性
API security.istio.io/v1 稳定版,Istio 1.25+ / 1.27+ 均支持

待讨论

  1. DestinationRule 交互 — 是否需要测试显式 DestinationRule tls.mode: ISTIO_MUTUAL?建议初期不需要,auto-mTLS 已覆盖。
  2. 全网格 STRICT PAistio-system 中的全局 STRICT PA 属运维范畴,不在跨版本测试范围内。

环境变量(运行时可覆盖)

变量 默认值 说明
OLD_REV 1-25-0 旧版 Istio revision
NEW_REV 1-27-7 新版 Istio revision
REGISTRY artifactory.cloud.ingka-system.cn/cn-digital-hub-docker-virtual 镜像仓库
SECRET_NS kong imagePullSecret 来源 namespace
SECRET_NAME artifactory-read imagePullSecret 名称

使用示例

1
2
3
4
5
6
7
8
9
10
# 默认版本组合
./run.sh all

# 自定义版本
OLD_REV=1-25-0 NEW_REV=1-28-5 ./run.sh all

# 分步执行
./run.sh install
./run.sh test
./run.sh uninstall

故障排查

常见失败场景

失败现象 可能原因 排查命令
连接被拒绝 被调方 PA 为 STRICT 但调用方无 sidecar kubectl get peerauthentication -A
TLS 握手失败 新旧 Envoy 版本间证书/协议不兼容 istioctl proxy-config secret <pod> -n <ns>
超时 网络策略阻断或服务发现问题 istioctl proxy-status
XFCC 头缺失 mTLS 未生效,可能 PA 未正确应用 istioctl authn tls-check <pod> <svc>

调试命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 查看 mTLS 策略
kubectl get peerauthentication -n istio-mtls-old-strict -o yaml
kubectl get peerauthentication -n istio-mtls-new-strict -o yaml

# 查看 sidecar 配置
istioctl proxy-config listeners <pod> -n <namespace>

# 查看路由配置
istioctl proxy-config routes <pod> -n <namespace>

# 查看证书信息
istioctl proxy-config secret <pod> -n <namespace>

# 手动测试连接
kubectl exec -it <caller-pod> -n <namespace> -- \
curl -sv http://httpbin.<callee-ns>.svc.cluster.local/status/200

# 查看 Envoy 访问日志
kubectl logs <pod> -n <namespace> -c istio-proxy --tail=50