LabHub
学习 学习路径 课程

Istio 服务网格

从 PERMISSIVE 一路推到 STRICT

在 LabHub 中继续学习

目标

亲手操作 mTLS 策略的三种作用范围及其优先级,并留下一个在不中断运行中服务网格的前提下升级到 STRICT 的实施计划。

为什么重要

从技术上说,切换到 STRICT 只是修改一个字段,但在生产运维中,它却是最容易引发事故的操作之一。原因很简单——原本通过明文进入的路径会毫无预警地全部中断。没有 Sidecar 的定时任务、服务网格外的批处理任务以及自定义探针,平时很难在仪表板上暴露出来,却会在启用 STRICT 的瞬间表现为故障。因此,标准做法是先保持 PERMISSIVE,全面调查明文流量的来源,再从较小的范围开始逐步升级。

另一个必须掌握的概念是方向的区分。PeerAuthentication 管理接收端(入站),DestinationRule 的 trafficPolicy.tls 管理发送端(出站)。两者不一致时,连接会失败,但应用日志中通常只会显示为 503。此外,istioctl analyze 无法发现这种组合问题——旧版本曾有专用分析器,但当前版本的分析器列表中已不存在。因此,将这两个资源成对摆放并由人工直接核对的习惯,本身就是安全保障。

此环境不会发生真实握手,因此评分会检查策略名称、作用范围、字段和静态分析结果。

步骤

**开始前的准备。**每次实验都会启动新的实验 Pod,因此不会保留前一实验的服务网格设置。如果 kubectl get crd peerauthentications.security.istio.io 没有输出,请执行 istioctl manifest generate --set profile=minimal > /root/istio/manifest.yaml,然后将 kubectl apply -f /root/istio/manifest.yaml 执行两次。该清单也会创建 istio-system 命名空间;第 2 步需要在其中放置服务网格全局策略,因此它必须存在。接着执行 kubectl create ns mesh-lab && kubectl label ns mesh-lab istio-injection=enabled,准备工作命名空间。

  1. 创建 /root/istio/mtls/pa-permissive.yaml——它是仅含一个文档的 PeerAuthentication,metadata.namedefaultmetadata.namespacemesh-labspec.mtls.modePERMISSIVE,并且不要设置 selector(这是整个命名空间的策略)。创建后应用它。
  2. istio-system 命名空间中应用名为 default 的 PeerAuthentication,将 spec.mtls.mode: STRICT,并且不设置 selector。然后在 /root/istio/mtls/out/scope-note.txt 中写明:在服务网格全局、命名空间、工作负载三个层级中,范围越窄、越具体的策略优先
  3. mesh-lab 中创建 payments 工作负载——ServiceAccount payments、Service payments(端口名称 http 8080、http-metrics 9090)以及 Deployment payments(Pod 标签 app: paymentsserviceAccountName: payments)。然后创建 PeerAuthentication legacy-metrics 并将它放在 mesh-lab 中:selector.matchLabels.apppaymentsspec.mtls.modeSTRICT,而 portLevelMtls 中**只能为端口 9090**设置 mode: DISABLE
  4. mesh-lab 中创建 DestinationRule payments-mtlsspec.hostpaymentsspec.trafficPolicy.tls.modeISTIO_MUTUAL。然后在 /root/istio/mtls/out/direction-note.txt 中写明两者的区别:PeerAuthentication 管理接收端(入站),DestinationRule 管理发送端(客户端/出站)。
  5. /root/istio/mtls/identity.txt 中用准确的一行写出 payments 工作负载的 SPIFFE 身份:spiffe://cluster.local/ns/mesh-lab/sa/payments。然后在 /root/istio/mtls/out/identity-note.txt 中写明,服务网格中的身份不是 IP 地址,而是服务账号。
  6. mesh-lab 中创建 RequestAuthentication jwt-paymentsselector.matchLabels.apppaymentsjwtRules[0].issuerhttps://idp.labhub.example/jwtRules[0].jwksUrihttps://idp.labhub.example/.well-known/jwks.json。然后在 /root/istio/mtls/out/jwt-note.txt 中写明,仅靠该资源无法阻止没有令牌的请求,还需要配合 AuthorizationPolicy。
  7. mesh-lab 中的 default PeerAuthentication 改为 STRICT 并应用。在此状态下,应用一个 spec.trafficPolicy.tls.mode: DISABLE 的 DestinationRule(例如 payments-plaintext),并将 istioctl analyze -n mesh-lab 的结果保存到 /root/istio/mtls/out/analyze-conflict.txt。当前版本的分析器列表中没有检查 mTLS 组合冲突的分析器,所以输出中不会显示该冲突——请追加一行,记录哪两项设置彼此不一致。随后删除该 DestinationRule,或将其改为 ISTIO_MUTUAL 以消除冲突;再次分析并将结果保存到 /root/istio/mtls/out/analyze-fixed.txtmesh-lab 中不得遗留任何 tls.mode: DISABLE 的 DestinationRule。
  8. 编写不少于 400 字节的 /root/istio/mtls/migration.md。文档中,PERMISSIVE 和观测(指标/监控)的内容必须先于(位于更上方的行)STRICT 一词出现,并且必须包含按命名空间分阶段应用以及回滚(恢复)方法。最后确保 mesh-lab 中的 default PeerAuthentication 处于 STRICT 状态。

参考

将命名空间默认策略设为 PERMISSIVE

创建 /root/istio/mtls/pa-permissive.yaml——它是仅含一个文档的 PeerAuthentication,metadata.namedefaultmetadata.namespacemesh-labspec.mtls.modePERMISSIVE,并且不要设置 selector(这是整个命名空间的策略)。创建后应用它。

作用于整个命名空间的策略使用固定名称,并且不设置 selector。切换应从同时接受明文和密文的状态开始。

将服务网格全局默认值升级为 STRICT

istio-system 命名空间中应用名为 default 的 PeerAuthentication,将 spec.mtls.mode: STRICT,并且不设置 selector。然后在 /root/istio/mtls/out/scope-note.txt 中写明:在服务网格全局、命名空间、工作负载三个层级中,范围越窄、越具体的策略优先

服务网格全局策略放在根命名空间中。并请在说明中整理三个作用层级中哪一个优先。

只为单个工作负载的单个端口开放例外

mesh-lab 中创建 payments 工作负载——ServiceAccount payments、Service payments(端口名称 http 8080、http-metrics 9090)以及 Deployment payments(Pod 标签 app: paymentsserviceAccountName: payments)。然后创建 PeerAuthentication legacy-metrics 并将它放在 mesh-lab 中:selector.matchLabels.apppaymentsspec.mtls.modeSTRICT,而 portLevelMtls 中**只能为端口 9090**设置 mode: DISABLE

例外应尽可能缩小。用 selector 选择工作负载,默认仍保持 STRICT,只单独指定有问题的端口。

声明发送端的 mTLS

mesh-lab 中创建 DestinationRule payments-mtlsspec.hostpaymentsspec.trafficPolicy.tls.modeISTIO_MUTUAL。然后在 /root/istio/mtls/out/direction-note.txt 中写明两者的区别:PeerAuthentication 管理接收端(入站),DestinationRule 管理发送端(客户端/出站)。

接收端和发送端由不同资源管理。应使用专门的模式来表示采用服务网格签发的证书,而不是自行指定证书。

写出工作负载的身份

/root/istio/mtls/identity.txt 中用准确的一行写出 payments 工作负载的 SPIFFE 身份:spiffe://cluster.local/ns/mesh-lab/sa/payments。然后在 /root/istio/mtls/out/identity-note.txt 中写明,服务网格中的身份不是 IP 地址,而是服务账号。

三个组成部分按顺序出现,而且作为该身份依据的对象必须真实存在于集群中。

创建最终用户 JWT 验证策略

mesh-lab 中创建 RequestAuthentication jwt-paymentsselector.matchLabels.apppaymentsjwtRules[0].issuerhttps://idp.labhub.example/jwtRules[0].jwksUrihttps://idp.labhub.example/.well-known/jwks.json。然后在 /root/istio/mtls/out/jwt-note.txt 中写明,仅靠该资源无法阻止没有令牌的请求,还需要配合 AuthorizationPolicy。

验证签名需要同时提供签发者和公钥位置。还请在说明中写明,该资源单独使用时无法阻止什么。

制造并解决 STRICT 与 DISABLE 的冲突

mesh-lab 中的 default PeerAuthentication 改为 STRICT 并应用。在此状态下,应用一个 spec.trafficPolicy.tls.mode: DISABLE 的 DestinationRule(例如 payments-plaintext),并将 istioctl analyze -n mesh-lab 的结果保存到 /root/istio/mtls/out/analyze-conflict.txt。当前版本的分析器列表中没有检查 mTLS 组合冲突的分析器,所以输出中不会显示该冲突——请追加一行,记录哪两项设置彼此不一致。随后删除该 DestinationRule,或将其改为 ISTIO_MUTUAL 以消除冲突;再次分析并将结果保存到 /root/istio/mtls/out/analyze-fixed.txtmesh-lab 中不得遗留任何 tls.mode: DISABLE 的 DestinationRule。

接收端要求加密,而发送端坚持明文时,连接会失败。请分别保留修复前后的分析结果,并且不要遗留任何不一致设置。

编写分阶段切换计划并完成切换

编写不少于 400 字节的 /root/istio/mtls/migration.md。文档中,PERMISSIVE 和观测(指标/监控)的内容必须先于(位于更上方的行)STRICT 一词出现,并且必须包含按命名空间分阶段应用以及回滚(恢复)方法。最后确保 mesh-lab 中的 default PeerAuthentication 处于 STRICT 状态。

文档中词语出现的顺序就是阶段顺序。先写观测和 PERMISSIVE,再写 STRICT,同时加入恢复方法。