采用 Sidecar 容器
本节内容适用于那些为其工作负载采用新的内置sidecar 容器特性的人员。
如博文所述,sidecar 容器并非一个新概念。Kubernetes 允许在一个 Pod 中运行多个容器来实现这一概念。然而,将 sidecar 容器作为常规容器运行存在许多限制,而新的内置 sidecar 容器支持正在解决这些限制。
Kubernetes v1.33 [稳定]
(默认启用: true)目标
- 了解 sidecar 容器的需求
- 能够排除 sidecar 容器的问题
- 理解将 sidecar 容器普遍“注入”到任何工作负载中的选项
开始之前
你需要拥有一个 Kubernetes 集群,并且 kubectl 命令行工具需要配置为与你的集群通信。建议在本教程中使用至少有两个不作为控制平面主机的节点的集群上运行。如果你还没有集群,可以使用 minikube 创建一个,或者你可以使用以下 Kubernetes 练习环境之一:
你的 Kubernetes 服务器版本必须是 1.29 或更高。要检查版本,输入 kubectl version
。
Sidecar 容器概述
Sidecar 容器是与主应用容器在同一个Pod 中一起运行的辅助容器。这些容器用于通过提供额外的服务或功能(例如日志记录、监控、安全或数据同步)来增强或扩展主应用容器的功能,而无需直接修改主应用程序代码。你可以在Sidecar 容器概念页面中阅读更多信息。
sidecar 容器的概念并不新,而且存在多种实现方式。除了你(即定义 Pod 的人员)想要运行的 sidecar 容器之外,你还会发现一些插件会在 Pod 启动前修改 Pod,以便包含额外的 sidecar 容器。注入这些额外 sidecar 的机制通常是准入 Webhook。例如,服务网格插件可能会注入一个 sidecar,用于配置不同 Pod 之间的相互 TLS 和传输中加密。
尽管 sidecar 容器的概念并不新,但 Kubernetes 中此特性的原生实现是新的。和任何新特性一样,采用此特性可能会带来一些挑战。
本教程探讨了终端用户以及 sidecar 容器的作者可能遇到的挑战和解决方案。
内置 sidecar 容器的优势
使用 Kubernetes 对 sidecar 容器的原生支持提供了多项优势:
- 你可以将原生 sidecar 容器配置为在初始化容器之前启动。
- 内置 sidecar 容器可以配置为保证它们最后被终止。一旦所有常规容器完成并终止,sidecar 容器就会收到
SIGTERM
信号并被终止。如果 sidecar 容器未优雅地关闭,将使用SIGKILL
信号强制终止它。 - 对于 Jobs,当 Pod 的
restartPolicy: OnFailure
或restartPolicy: Never
时,原生 sidecar 容器不会阻止 Pod 完成。对于传统 sidecar 容器,需要特别注意处理这种情况。 - 此外,对于 Jobs,内置 sidecar 容器一旦完成就会继续重启,即使常规容器在 Pod 的
restartPolicy: Never
下不会重启。
参见与应用容器的区别以了解更多信息。
采用内置 sidecar 容器
SidecarContainers
特性门控 从 Kubernetes 1.29 版本开始处于 Beta 状态,并且默认启用。一些集群可能禁用此特性,或安装了与此特性不兼容的软件。
发生这种情况时,Pod 可能会被拒绝,或者 sidecar 容器可能会阻塞 Pod 启动,导致 Pod 无法使用。这种情况很容易检测,因为 Pod 只是卡在初始化阶段。然而,通常不清楚是什么原因导致了问题。
以下是为工作负载采用 sidecar 容器时可以考虑的因素和故障排除步骤。
确保特性门控已启用
作为第一步,请确保 API 服务器和节点都已升级到 Kubernetes v1.29 或更高版本。如果节点运行的是早期版本且未启用此特性,则该特性将无法正常工作。
注意
该特性可以在 1.28 版本的节点上启用。内置 sidecar 容器的终止行为在 1.28 版本中有所不同,不建议调整 sidecar 的行为以适应该行为。然而,如果唯一关心的是启动顺序,则上述描述可以修改为运行 1.28 版本且启用了特性门控的节点。你应确保控制平面中的 API 服务器以及所有节点都启用了该特性门控。
检查特性门控是否启用的方法之一是运行如下命令:
对于 API 服务器
kubectl get --raw /metrics | grep kubernetes_feature_enabled | grep SidecarContainers
对于单个节点
kubectl get --raw /api/v1/nodes/<node-name>/proxy/metrics | grep kubernetes_feature_enabled | grep SidecarContainers
如果你看到类似如下的输出:
kubernetes_feature_enabled{name="SidecarContainers",stage="BETA"} 1
这意味着该特性已启用。
检查第三方工具和准入 Webhook
如果你在验证此特性时遇到问题,这可能表明某个第三方工具或准入 Webhook 已损坏。
启用 SidecarContainers
特性门控后,Pod 在其 API 中新增了一个字段。某些工具或准入 Webhook 可能基于早期版本的 Kubernetes API 构建。
如果工具使用各种补丁策略(patching strategies)按原样传递未知字段来修改 Pod 对象,则不会有问题。但是,有些工具会移除未知字段;如果你使用此类工具,则必须使用 v1.28+ 版本的 Kubernetes API 客户端代码重新编译它们。
检查方法是,对已通过准入 Webhook 修改的 Pod 使用 kubectl describe pod
命令。如果任何工具移除了新字段 (restartPolicy:Always
),你将不会在命令输出中看到它。
如果遇到此类问题,请建议工具或 Webhook 的作者使用修改对象的补丁策略之一,而不是完全对象更新。
注意
准入 Webhook 可能会根据某些条件更新 Pod。因此,sidecar 容器可能适用于某些 Pod,但对其他 Pod 失败。sidecar 的自动注入
如果你正在使用自动注入 sidecar 的软件,可以遵循一些策略来确保可以使用原生 sidecar 容器。所有策略通常都是选项,你可以选择决定注入 sidecar 的 Pod 是会落在支持该特性的节点上还是不支持的节点上。
作为示例,你可以关注Istio 社区中的此讨论。该讨论探讨了下面列出的选项。
- 标记落在支持 sidecar 的节点上的 Pod。你可以使用节点标签和节点亲和性来标记支持 sidecar 容器的节点以及落在这些节点上的 Pod。
- 在注入时检查节点兼容性。在 sidecar 注入期间,你可以使用以下策略来检查节点兼容性:
- 查询节点版本,并假设特性门控在 1.29+ 版本上已启用。
- 查询节点 prometheus 指标并检查特性启用状态
- 假设节点与 API 服务器之间存在支持的版本差异。
- 可能还有其他自定义方式来检测节点兼容性。
- 开发一个通用 sidecar 注入器。通用 sidecar 注入器的想法是将 sidecar 容器作为常规容器和原生 sidecar 容器一起注入。然后通过运行时逻辑来决定使用哪一个。通用 sidecar 注入器是浪费的,因为它会计算两次请求,但可以视为特殊情况下的可行解决方案。
- 一种方法是在原生 sidecar 容器启动时检测节点版本,如果该版本不支持 sidecar 特性,则立即退出。
- 考虑一种运行时特性检测设计
- 定义一个 emptyDir 以便容器之间可以互相通信
- 注入一个初始化容器,我们称之为
NativeSidecar
,并设置restartPolicy=Always
。 NativeSidecar
必须向一个 emptyDir 写入一个文件,表示首次运行,然后立即以退出码0
退出。NativeSidecar
在重启时(当原生 sidecar 受支持时)检查 emptyDir 中文件是否存在并修改该文件——表明内置 sidecar 容器已受支持并正在运行。- 注入常规容器,我们称之为
OldWaySidecar
。 OldWaySidecar
在启动时检查 emptyDir 中文件的存在。- 如果文件表明
NativeSidecar
未在运行,则它假定 sidecar 特性不受支持,并假设它自己就是 sidecar 来工作。 - 如果文件表明
NativeSidecar
正在运行,它要么不做任何事情并永远休眠(在 Pod 的restartPolicy=Always
的情况下),要么立即以退出码0
退出(在 Pod 的restartPolicy!=Always
的情况下)。
下一步
- 进一步了解sidecar 容器。