边车容器

功能状态: Kubernetes v1.29 [beta]

边车容器是在同一Pod 内与主应用程序容器一起运行的辅助容器。这些容器用于增强或扩展主应用程序容器的功能,提供额外的服务或功能,例如日志记录、监控、安全性或数据同步,而无需直接更改主应用程序代码。

通常,在一个 Pod 中只有一个应用程序容器。例如,如果你的 Web 应用程序需要一个本地 Web 服务器,则本地 Web 服务器是边车容器,而 Web 应用程序本身是应用程序容器。

Kubernetes 中的边车容器

Kubernetes 将边车容器实现为 初始化容器 的一个特例;边车容器在 Pod 启动后仍然保持运行。本文档使用术语常规初始化容器来清楚地指代仅在 Pod 启动期间运行的容器。

前提是你的集群启用了 SidecarContainers 功能门控(该功能自 Kubernetes v1.29 起默认启用),你可以在 Pod 的 initContainers 字段中为列出的容器指定 restartPolicy。这些可重启的边车容器独立于其他初始化容器以及同一 Pod 内的主应用程序容器。它们可以启动、停止或重启,而不会影响主应用程序容器和其他初始化容器。

你还可以运行包含多个容器的 Pod,这些容器未标记为初始化容器或边车容器。如果 Pod 中的容器是 Pod 整体工作所必需的,但你不需要控制哪些容器先启动或停止,则这样做是合适的。如果你的 Kubernetes 版本较旧,不支持容器级的 restartPolicy 字段,你也可以这样做。

示例应用程序

这是一个包含两个容器的 Deployment 示例,其中一个是边车容器

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  labels:
    app: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp
          image: alpine:latest
          command: ['sh', '-c', 'while true; do echo "logging" >> /opt/logs.txt; sleep 1; done']
          volumeMounts:
            - name: data
              mountPath: /opt
      initContainers:
        - name: logshipper
          image: alpine:latest
          restartPolicy: Always
          command: ['sh', '-c', 'tail -F /opt/logs.txt']
          volumeMounts:
            - name: data
              mountPath: /opt
      volumes:
        - name: data
          emptyDir: {}

边车容器和 Pod 生命周期

如果创建的初始化容器的 restartPolicy 设置为 Always,它将在 Pod 的整个生命周期内启动并保持运行。这有助于运行与主应用程序容器分离的支持服务。

如果为此初始化容器指定了 readinessProbe,则其结果将用于确定 Pod 的 ready 状态。

由于这些容器被定义为初始化容器,它们受益于与常规初始化容器相同的排序和顺序保证,允许你将边车容器与常规初始化容器混合使用,以实现复杂的 Pod 初始化流程。

与常规初始化容器相比,在 initContainers 中定义的边车容器在启动后会继续运行。当 Pod 的 .spec.initContainers 中有多个条目时,这一点很重要。在边车风格的初始化容器运行后(kubelet 将该初始化容器的 started 状态设置为 true),kubelet 将从排序的 .spec.initContainers 列表中启动下一个初始化容器。该状态变为 true,要么是因为容器中正在运行进程且未定义启动探测,要么是因为其 startupProbe 成功。

在 Pod 终止 时,kubelet 会推迟终止边车容器,直到主应用程序容器完全停止。然后,边车容器将按照其在 Pod 规范中出现的相反顺序关闭。这种方法确保边车容器保持运行,支持 Pod 内的其他容器,直到不再需要它们的服务。

带有边车容器的 Job

如果定义使用 Kubernetes 风格的初始化容器的带有边车容器的 Job,则每个 Pod 中的边车容器不会阻止 Job 在主容器完成后完成。

这是一个包含两个容器的 Job 示例,其中一个是边车容器

apiVersion: batch/v1
kind: Job
metadata:
  name: myjob
spec:
  template:
    spec:
      containers:
        - name: myjob
          image: alpine:latest
          command: ['sh', '-c', 'echo "logging" > /opt/logs.txt']
          volumeMounts:
            - name: data
              mountPath: /opt
      initContainers:
        - name: logshipper
          image: alpine:latest
          restartPolicy: Always
          command: ['sh', '-c', 'tail -F /opt/logs.txt']
          volumeMounts:
            - name: data
              mountPath: /opt
      restartPolicy: Never
      volumes:
        - name: data
          emptyDir: {}

与应用程序容器的区别

边车容器与同一 Pod 中的应用程序容器一起运行。但是,它们不执行主应用程序逻辑;相反,它们为主要应用程序提供支持功能。

边车容器具有自己的独立生命周期。它们可以独立于应用程序容器启动、停止和重启。这意味着你可以更新、扩展或维护边车容器,而不会影响主应用程序。

边车容器与主容器共享相同的网络和存储命名空间。这种并置允许它们紧密交互并共享资源。

从 Kubernetes 的角度来看,边车容器的优雅终止不太重要。当其他容器耗尽所有分配的优雅终止时间时,边车容器将比预期更快地收到 SIGTERM,然后是 SIGKILL。因此,对于边车容器,与 0 不同的退出代码(0 表示成功退出)在 Pod 终止时是正常的,通常应被外部工具忽略。

与初始化容器的区别

边车容器与主容器一起工作,扩展其功能并提供额外的服务。

边车容器与主应用程序容器并发运行。它们在 Pod 的整个生命周期内都处于活动状态,并且可以独立于主容器启动和停止。与初始化容器不同,边车容器支持探测来控制其生命周期。

边车容器可以直接与主应用程序容器交互,因为它们像初始化容器一样始终共享相同的网络,并且可以选择共享卷(文件系统)。

初始化容器在主容器启动之前停止,因此初始化容器无法与 Pod 中的应用程序容器交换消息。任何数据传递都是单向的(例如,初始化容器可以将信息放入 emptyDir 卷中)。

容器内的资源共享

鉴于初始化容器、边车容器和应用程序容器的执行顺序,以下资源使用规则适用

  • 所有初始化容器上定义的任何特定资源请求或限制的最高值是有效初始化请求/限制。如果任何资源未指定资源限制,则将其视为最高限制。
  • Pod 的资源的有效请求/限制Pod 开销 与以下较高者之和:
    • 所有非初始化容器(应用程序容器和边车容器)的资源的请求/限制的总和
    • 资源的有效初始化请求/限制
  • 调度是基于有效的请求/限制完成的,这意味着初始化容器可以为初始化保留在 Pod 生命周期内不使用的资源。
  • Pod 的有效 QoS 层的 QoS(服务质量)层是所有初始化容器、边车容器和应用程序容器的 QoS 层。

配额和限制是基于有效的 Pod 请求和限制应用的。

边车容器和 Linux cgroup

在 Linux 上,Pod 级控制组(cgroup)的资源分配基于有效的 Pod 请求和限制,与调度器相同。

下一步

上次修改时间为 2024 年 10 月 6 日下午 10:40 PST:[SidecarContainer] 提供边车实现最佳实践提示 (7195f5feaa)