大家好!今天,我们将深入探讨一个可能让使用 Kubernetes 和 Istio 环境的工程师们都遇到过的情况——“消失的 Sidecar 容器之谜”。
如果你注入了 Istio,但在 YAML 文件中看不到代理容器,而 `kubectl` 命令却显示正常?这并非 Bug。这正是 Kubernetes 原生 Sidecar 功能在起作用。让我们来详细了解一下这个变化为何发生,以及它带来了哪些改进。🚀

1. 事件的开端:“容器数量不对劲” 🤔
在 Istio 环境中部署 Pod 时,通常会达到 2/2 的状态。
- 你自己创建的应用程序容器
- Istio 注入的代理容器 (istio-proxy)
然而,如果你查看最近版本(Istio 1.27+、K8s 1.29+)部署的 Pod 的 YAML,你会发现一个奇怪的现象。
$ kubectl get pod details-v1
NAME READY STATUS RESTARTS AGE
details-v1-766844796b-zmr86 2/2 Running 0 5m
👉 `kubectl` 命令明确显示为 READY 2/2,这意味着有两个容器正在正常运行。
但是,如果你使用 `kubectl get pod details-v1 -o yaml` 查看其配置呢?
spec:
containers:
- name: details # <--- 咦?只有一个容器?
image: docker.io/istio/examples-bookinfo-details-v1:1.20.3
...
`spec.containers` 部分缺少了 `istio-proxy`! 它明明在运行,却不在 YAML 定义中,这神秘的情况究竟是怎么回事?
2. 罪魁祸首藏在 ‘initContainers’ 中!🕵️♂️
答案不在 `spec.containers` 中,而在于 `spec.initContainers` 部分。仔细查看你提供的 YAML 文件,秘密就会揭晓。
initContainers:
- name: istio-init
image: docker.io/istio/proxyv2:1.28.1
# ... (设置 iptables 的常规 init 容器) ...
- name: istio-proxy # <--- 它藏在这里!
image: docker.io/istio/proxyv2:1.28.1
restartPolicy: Always # <--- ⭐ 关键点 ⭐
传统上,`initContainers` 应该在主应用程序启动前只执行“初始化”任务,然后退出(Completed)。但在这里,我们看到了 `istio-proxy`,而且它并没有退出,而是持续运行。
其秘诀就在于 `restartPolicy: Always` 这个设置。
3. 什么是 Kubernetes 原生 Sidecar?💡
这是自 Kubernetes v1.28 (Alpha) / v1.29 (Beta, 默认) 起引入的 SidecarContainers 功能。
旧方式 (Old Sidecar)
以前,`istio-proxy` 会被包含在常规的 `containers` 列表中。但这种方式存在致命缺点:
- 无法保证启动顺序:应用程序可能比代理先启动,导致尝试网络通信时失败。
- 终止顺序问题 (Job):批处理任务(Job)完成后,Sidecar `istio-proxy` 却不退出,导致 Pod 永远停留在 Running 状态。
当前方式 (Native Sidecar)
现在,Kubernetes 会将 `initContainers` 中设置了 `restartPolicy: Always` 的容器识别为“Sidecar 容器”。
- 最先启动:保证比主应用容器更早启动。
- 持续运行:初始化后不会退出,而是与主应用的生命周期保持一致。
- 最后终止:当主应用终止时,Kubernetes 会自动关闭 Sidecar。(解决了 Job 的问题!)
4. 为什么突然改变了?(版本历史)📅
这个变化是随着 Istio 和 Kubernetes 版本升级而自然发生的。
- Istio 1.27 之前:原生 Sidecar 功能存在,但需要手动开启。(需要设置 ENABLE_NATIVE_SIDECARS=true)
- Istio 1.27 之后:此功能成为默认值 (Default)。
- Kubernetes 要求:集群版本必须是v1.29 或更高。(GKE、EKS 等最新版本大多满足此要求)
你当前的环境是“Istio 1.27 及以上 + K8s 1.29 及以上”的组合,因此无需额外配置,这种最新的架构就会自动应用。🎉
5. 重新理解 2/2 的含义 🔢
现在,`kubectl get pod` 的 2/2 是如何计算的就变得清晰了。
- 主容器 (details):定义在 `spec.containers` 中 ➡️ +1
- 原生 Sidecar (istio-proxy):位于 `spec.initContainers` 中,但设置了 `restartPolicy: Always` ➡️ +1
- 常规 Init (istio-init):完成任务后退出(Completed) ➡️ 0
因此,总数为 2。这是一个完全正常且健康的状态,请放心!
6. 总结与结语 📝
这个变化不仅仅是结构上的调整,它是一个非常受欢迎的更新,从根本上解决了长期困扰 Kubernetes 工程师的“Sidecar 生命周期问题 (Lifecycle Issue)”。
- YAML 的 containers 中没有代理? 👉 请检查 `initContainers`。
- 看到了 `restartPolicy: Always`? 👉 恭喜你!你正在使用最新的原生 Sidecar 功能。
- 运行 Job(批处理)工作负载时:现在不再需要 `quitquitquit` 之类的技巧来确保代理干净地终止。
各位使用最新技术栈的朋友们,请不要被变化的 YAML 结构所困扰,尽情享受这个强大的功能吧!祝大家今天也有愉快云端航行!⛵️☁️
发表回复