TT Lab
开始
学习 学习路径 课程

Istio 进阶 — 为什么会那样流

在部署之前先把错找出来

在 TT Lab 中继续学习

目标

Istio 配置即使语法正确,大多数时候也可能无法工作。由于其结构由名称相互引用, 只要一侧的名称发生变化,连接就会悄无声息地中断。

本实验将在没有集群的情况下,部署之前找出这类问题。

两种工具的区别

检查内容 能发现的问题
istioctl validate 单个文件的语法 拼写错误、未知字段
istioctl analyze 资源之间的引用 不存在的 subset、网关以及主机冲突

Kubernetes 无法发现这两类问题。 CRD schema 会悄悄丢弃未知字段, 所以 kubectl apply 会成功,只有流量无法通过。

使用方法

istioctl validate -f vs.yaml
istioctl analyze --use-kube=false vs.yaml dr.yaml
echo $?          # 0 이면 깨끗, 79 면 문제 있음

--use-kube=false 表示不查看集群,只检查文件。

步骤

  1. 拼写错误 → 01-validate.txt
  2. 引用断裂 → 02-analyze.txt
  3. 修复并通过 → vs.yaml、dr.yaml
  4. 主机冲突 → 04-conflict.txt
  5. 不存在的网关 → 05-gateway.txt
  6. Sidecar 注入 → 06-inject.txt
  7. analyze 无法发现的问题 → 07-blind.txt
  8. 总结 → 08-notes.md

参考

第 7 步中,不出现任何问题才是正确结果。本步骤的目的就是亲自观察静态分析的局限。

发现拼写错误

创建字段名错误的 VirtualService,用 istioctl validate 发现问题,并记录到 01-validate.txt。

尝试把 http: 下的 route: 写成 rout:。istioctl validate -f x.yaml 会报告 unknown field "rout"。Kubernetes 无法发现这个问题:CRD schema 会悄悄丢弃未知字段,因此 apply 会成功,只有流量无法通过。

Schema 正确但行为错误

只创建一个将流量发送到 subset: v1 的 VirtualService(不创建 DestinationRule),让 istioctl analyze 发现问题,并记录到 02-analyze.txt。

运行 istioctl analyze --use-kube=false vs.yaml。它会输出 IST0101 Referenced host+subset in destinationrule not found。validate 可以通过,但 analyze 能发现问题:前者检查语法,后者检查引用关系。这是 Istio 中“配置已经应用却出现 503”的首要原因。

修复并使其通过

添加定义 subset 的 DestinationRule,使 istioctl analyze 以退出码 0结束。文件名使用 vs.yaml 和 dr.yaml。

DestinationRule 的 host 必须与 VirtualService 的 destination.host 相同,subsets[].name 必须与 destination.subset 相同。确认命令:istioctl analyze --use-kube=false vs.yaml dr.yaml; echo $?,结果必须为 0(有问题时为 79)。

两个资源占用同一个主机时

再创建一个指向相同主机的 VirtualService 来引发冲突,并记录到 04-conflict.txt。

会出现 IST0109,内容为“define the same host ... which can lead to undefined behavior”。未定义哪一个会生效。 当团队分成两组、各自创建 VirtualService 时,就会发生这种情况。解决方法是合并为一个。

引用不存在的网关时

创建引用不存在网关的 VirtualService,并记录到 05-gateway.txt。必须出现两种诊断。

设置 gateways: [nope-gw]。会同时出现 IST0101 Referenced gateway not found 和 IST0132(主机不在网关中)。请将两者都保留下来。

Sidecar 实际会变成什么样

向一个 Deployment 注入 Sidecar,并将注入后的容器列表记录到 06-inject.txt。

本 Pod 中没有真正的 istiod,因此要通过文件传入配置。三个参数必须全部提供,只给两个时,istioctl 会尝试从集群中查找剩下的一个。

istioctl kube-inject -f dep.yaml \
  --injectConfigFile /opt/istio/inject-config.yaml \
  --meshConfigFile   /opt/istio/mesh-config.yaml \
  --valuesFile       /opt/istio/values-config.yaml

系统会附加 istio-proxy 容器和 istio-init 初始化容器。istio-init 会修改 iptables,使所有流量都经过代理。

analyze 无法发现的问题

将 PeerAuthentication 设为 STRICT,将同一服务的 DestinationRule 设为 tls.mode: DISABLE,运行 istioctl analyze,并把没有出现任何问题的结果记录到 07-blind.txt。再写一行说明为何危险。

analyze 会认为配置没有问题,但实际情况是:服务器要求 mTLS,而客户端使用明文连接,导致全部请求失败。 这说明静态分析并非万能。有些问题仅查看文件无法得知,必须结合集群状态分析。因此在实际工作中,会让 istioctl analyze 连接集群运行(--use-kube 默认值)。

总结三个要点

在 08-notes.md 中至少写三行:validate 与 analyze 的区别、相同主机冲突为何危险,以及静态分析无法发现的一种问题。

正文中必须包含 참조、충돌、mTLS。