采用 Sidecar 容器

本节适用于为其工作负载采用新的内置sidecar 容器功能的人员。

正如博客文章中所述,Sidecar 容器并非新概念。Kubernetes 允许在 Pod 中运行多个容器来实现此概念。但是,将 sidecar 容器作为常规容器运行存在许多限制,这些限制正在通过新的内置 sidecar 容器支持得到修复。

特性状态: Kubernetes v1.33 [stable] (默认启用:true)

目标

  • 了解对 sidecar 容器的需求
  • 能够排查 sidecar 容器的问题
  • 了解通用“注入”sidecar 容器到任何工作负载的选项

准备工作

你需要拥有一个 Kubernetes 集群,并且 kubectl 命令行工具必须配置为与你的集群通信。建议在至少有两个节点(不作为控制平面主机)的集群上运行本教程。如果你还没有集群,可以使用 minikube 创建一个,或者使用这些 Kubernetes 游乐场之一

你的 Kubernetes 服务器版本必须是 1.29 或更高版本。

要检查版本,请输入 kubectl version

Sidecar 容器概述

Sidecar 容器是与主应用容器在同一个Pod 中运行的辅助容器。这些容器用于通过提供附加服务或功能(例如日志记录、监控、安全性或数据同步)来增强或扩展主*应用容器*的功能,而无需直接修改主应用程序代码。你可以在Sidecar 容器概念页面中了解更多信息。

Sidecar 容器的概念并非新鲜事物,并且存在多种实现此概念的方法。除了你(定义 Pod 的人)希望运行的 sidecar 容器之外,你还会发现一些附加组件会在 Pod 启动前修改 Pod,从而添加额外的 sidecar 容器。注入这些额外 sidecar 的机制通常是准入控制器(MutatingAdmissionWebhook)。例如,服务网格附加组件可能会注入一个 sidecar,用于配置不同 Pod 之间的相互 TLS 和传输中加密。

虽然 sidecar 容器的概念并非新概念,但 Kubernetes 中该功能的原生实现却是新的。与每个新功能一样,采用此功能可能会带来某些挑战。

本教程探讨了最终用户以及 sidecar 容器作者可能遇到的挑战和解决方案。

内置 Sidecar 容器的优势

使用 Kubernetes 对 Sidecar 容器的本地支持提供了多项优势

  1. 你可以配置原生 sidecar 容器在初始化容器之前启动。
  2. 内置 sidecar 容器可以被编写为保证它们最后终止。一旦所有常规容器完成并终止,sidecar 容器将收到 SIGTERM 信号而终止。如果 sidecar 容器未优雅关闭,将使用 SIGKILL 信号终止它。
  3. 对于 Jobs,当 Pod 的 restartPolicy: OnFailurerestartPolicy: Never 时,原生 sidecar 容器不会阻止 Pod 完成。对于传统的 sidecar 容器,需要特别注意处理这种情况。
  4. 此外,对于 Jobs,即使常规容器不会使用 Pod 的 restartPolicy: Never,内置 sidecar 容器一旦完成仍会持续重启。

请参阅与 Init 容器的区别以了解更多信息。

采用内置 sidecar 容器

从 Kubernetes 1.29 版本开始,SidecarContainers 功能门控处于 Beta 状态,并默认启用。某些集群可能已禁用此功能或安装了与此功能不兼容的软件。

发生这种情况时,Pod 可能会被拒绝,或者 sidecar 容器可能会阻止 Pod 启动,使 Pod 无法使用。这种情况很容易检测,因为 Pod 只是卡在初始化阶段。然而,通常不清楚是什么导致了问题。

以下是为工作负载采用 sidecar 容器时可以考虑和采取的故障排除步骤。

确保功能门控已启用

作为第一步,请确保 API 服务器和节点都运行 Kubernetes v1.29 或更高版本。在节点运行早期版本(未启用该功能)的集群上,该功能将无法正常工作。

你应该确保控制平面中的 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 构建。

如果工具使用各种修补策略原样传递未知字段来修改 Pod 对象,这不会是问题。然而,有些工具会删除未知字段;如果你有这些工具,它们必须使用 v1.28+ 版本的 Kubernetes API 客户端代码重新编译。

检查此问题的方法是使用 `kubectl describe pod` 命令以及已通过可变准入的 Pod。如果有任何工具删除了新字段(`restartPolicy:Always`),你将不会在命令输出中看到它。

如果遇到此类问题,请建议工具或 Webhook 的作者使用其中一种修补策略来修改对象,而不是进行完整的对象更新。

Sidecar 的自动注入

如果您正在使用自动注入 sidecar 的软件,您可以遵循以下几种策略来确保可以使用原生 sidecar 容器。所有策略通常都是您可以选择的选项,以决定 sidecar 将注入的 Pod 是否会落在支持该功能的节点上。

例如,你可以关注 Istio 社区的讨论。该讨论探讨了以下选项。

  1. 标记那些支持 sidecar 的 Pod。你可以使用节点标签和节点亲和性来标记支持 sidecar 容器的节点以及落在这些节点上的 Pod。
  2. 在注入时检查节点兼容性。在 sidecar 注入期间,你可以使用以下策略来检查节点兼容性:
    • 查询节点版本并假设该功能门控在 v1.29+ 版本上已启用
    • 查询节点 Prometheus 指标并检查功能启用状态
    • 假设节点正在以与 API 服务器支持的版本偏差运行
    • 可能还有其他自定义方法来检测节点兼容性。
  3. 开发一个通用 Sidecar 注入器。通用 Sidecar 注入器的想法是将 Sidecar 容器作为常规容器以及原生 Sidecar 容器注入。并具有运行时逻辑来决定哪个将起作用。通用 Sidecar 注入器是浪费的,因为它将请求计数两次,但可以被认为是特殊情况下的可行解决方案。
    • 一种方法是在原生 sidecar 容器启动时检测节点版本,如果该版本不支持 sidecar 功能,则立即退出。
    • 考虑运行时功能检测设计
      • 定义一个空目录,以便容器可以相互通信
      • 注入一个初始化容器,我们称之为 NativeSidecar,其 restartPolicy=Always
      • NativeSidecar 必须向一个空目录写入一个文件,表示首次运行,并立即以退出码 0 退出。
      • NativeSidecar 在重启时(当支持原生 sidecar 时)检查该文件是否已存在于空目录中,并修改它——表明内置 sidecar 容器受到支持且正在运行。
      • 注入常规容器,我们称之为 OldWaySidecar
      • OldWaySidecar 启动时检查空目录中是否存在文件。
      • 如果文件表明 NativeSidecar 未运行,则它假定 sidecar 功能不受支持,并将其作为 sidecar 运行。
      • 如果文件指示 NativeSidecar 正在运行,它要么什么都不做并永远休眠(在 Pod 的 restartPolicy=Always 的情况下),要么立即以退出代码 0 退出(在 Pod 的 restartPolicy!=Always 的情况下)。

下一步

最后修改时间:2024 年 11 月 6 日太平洋标准时间上午 10:05:清理教程:pod-sidecar-containers.md (96d69d62fe)