Sidecar 容器
Kubernetes v1.29 [beta]
Sidecar 容器是与主应用容器一起在同一个Pod 内运行的辅助容器。这些容器通过提供额外的服务或功能(例如日志记录、监控、安全性或数据同步),用来增强或扩展主应用容器的功能,而无需直接更改主应用程序代码。
通常,一个 Pod 中只有一个应用容器。例如,如果你有一个需要本地 Web 服务器的 Web 应用程序,那么本地 Web 服务器就是一个 sidecar,而 Web 应用程序本身就是应用容器。
Kubernetes 中的 Sidecar 容器
Kubernetes 将 Sidecar 容器实现为Init 容器 的一种特殊情况;Sidecar 容器在 Pod 启动后仍然保持运行。本文档使用常规 Init 容器这个术语来明确指代那些仅在 Pod 启动期间运行的容器。
前提是你的集群启用了 SidecarContainers
feature gate(该特性自 Kubernetes v1.29 起默认启用),你可以为 Pod 的 initContainers
字段中列出的容器指定 restartPolicy
。这些可重启的Sidecar 容器独立于同一 Pod 中的其他 Init 容器和主应用容器。它们可以启动、停止或重启,而不影响主应用容器和其他 Init 容器。
你还可以运行包含多个未标记为 Init 或 Sidecar 容器的 Pod。如果 Pod 中的容器是 Pod 整体工作所必需的,但你不需要控制哪些容器先启动或停止,这种方式是合适的。如果你需要支持不支持容器级别 restartPolicy
字段的旧版本 Kubernetes,也可以这样做。
应用示例
这是一个包含两个容器(其中一个为 Sidecar)的 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: {}
Sidecar 容器和 Pod 生命周期
如果创建 Init 容器时将其 restartPolicy
设置为 Always
,则它将在 Pod 的整个生命周期内启动并保持运行。这对于运行与主应用容器分离的辅助服务很有帮助。
如果为此 Init 容器指定了 readinessProbe
,则其结果将用于确定 Pod 的 ready
状态。
由于这些容器被定义为 Init 容器,它们受益于与常规 Init 容器相同的顺序和顺序保证,这使得你可以将 Sidecar 容器与常规 Init 容器混合使用,以实现复杂的 Pod 初始化流程。
与常规 Init 容器相比,在 initContainers
中定义的 Sidecar 在启动后会持续运行。当 Pod 的 .spec.initContainers
中有多个条目时,这一点很重要。当一个 Sidecar 风格的 Init 容器正在运行时(kubelet 已将该 Init 容器的 started
状态设置为 true),kubelet 随后将从有序的 .spec.initContainers
列表中启动下一个 Init 容器。这个状态变为 true 要么是因为容器中有进程正在运行并且没有定义启动探针,要么是因为其 startupProbe
成功。
Pod 终止时,kubelet 会推迟终止 Sidecar 容器,直到主应用容器完全停止。然后,Sidecar 容器将按照它们在 Pod 规范中出现的相反顺序关闭。这种方法确保 Sidecar 在需要其服务之前,能够一直保持运行,支持 Pod 中的其他容器。
带有 Sidecar 容器的 Job
如果你定义了一个使用 Kubernetes 风格 Init 容器作为 Sidecar 的 Job,则每个 Pod 中的 Sidecar 容器不会阻止 Job 在主容器完成之后结束。
这是一个包含两个容器(其中一个为 Sidecar)的 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: {}
与应用容器的区别
Sidecar 容器与应用容器在同一个 Pod 中并行运行。然而,它们不执行主要的应用程序逻辑;相反,它们为主应用程序提供辅助功能。
Sidecar 容器拥有自己独立的生命周期。它们可以独立于应用容器启动、停止和重启。这意味着你可以更新、扩展或维护 Sidecar 容器,而不会影响主应用程序。
Sidecar 容器与主容器共享相同的网络和存储命名空间。这种共置使它们能够紧密交互和共享资源。
从 Kubernetes 的角度来看,Sidecar 容器的优雅终止不那么重要。当其他容器占用了所有分配的优雅终止时间后,Sidecar 容器将在没有时间进行优雅终止之前,先收到 SIGTERM
信号,接着是 SIGKILL
信号。因此,Sidecar 容器在 Pod 终止时的退出码不同于 0
(0
表示成功退出)是正常的,通常应被外部工具忽略。
与 Init 容器的区别
Sidecar 容器与主容器协同工作,扩展其功能并提供额外服务。
Sidecar 容器与主应用容器并行运行。它们在 Pod 的整个生命周期中都是活跃的,并且可以独立于主容器启动和停止。与Init 容器不同,Sidecar 容器支持探针来控制其生命周期。
Sidecar 容器可以直接与主应用容器交互,因为它们像 Init 容器一样总是共享相同的网络,并且也可以选择性地共享卷(文件系统)。
Init 容器在主容器启动之前停止,因此 Init 容器不能与 Pod 中的应用容器交换消息。任何数据传递都是单向的(例如,Init 容器可以将信息放入 emptyDir
卷中)。
更改 Sidecar 容器的镜像不会导致 Pod 重启,但会触发容器重启。
容器内的资源共享
考虑到 Init、Sidecar 和应用容器的执行顺序,以下资源使用规则适用:
- 所有 Init 容器上定义的任何特定资源请求或限制的最高值是有效的 Init 请求/限制。如果任何资源没有指定资源限制,则将其视为最高限制。
- Pod 的资源的有效请求/限制是Pod 开销与以下两者中较高的值之和:
- 所有非 Init 容器(应用容器和 Sidecar 容器)对资源的请求/限制之和
- 资源的有效 Init 请求/限制
- 调度基于有效请求/限制进行,这意味着 Init 容器可以为初始化保留在 Pod 生命周期内不使用的资源。
- Pod 的 QoS(服务质量)层级(有效 QoS 层级)对所有 Init、Sidecar 和应用容器都一样。
Quota 和限制基于有效的 Pod 请求和限制应用。
Sidecar 容器和 Linux cgroups
在 Linux 上,Pod 级别控制组 (cgroups) 的资源分配是基于有效的 Pod 请求和限制,这与调度器相同。
下一步
- 了解如何采用 Sidecar 容器
- 阅读关于原生 Sidecar 容器 的博客文章。
- 阅读关于创建带有 Init 容器的 Pod。
- 了解探针类型:存活性探针、就绪性探针、启动探针。
- 了解Pod 开销。