Init 容器
Init 容器是一种特殊容器,在 Pod 内的应用容器启动之前运行。Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本。、
可以在 Pod 的规约中与用来描述应用容器的 containers
数组平行的位置指定 Init 容器。
理解 Init 容器
如果 Pod 的 Init 容器失败,kubelet 会不断地重启该 Init 容器直到该容器成功为止。 然而,如果 Pod 对应的restartPolicy
值为 "Never",并且 Pod 的 Init 容器失败, 则 Kubernetes 会将整个 Pod 状态设置为失败。
为 Pod 设置 Init 容器需要在 Pod 规约中添加 initContainers
字段。
与普通容器的不同之处
Init 容器支持应用容器的全部字段和特性,包括资源限制、 数据卷和安全设置。 然而,Init 容器对资源请求和限制的处理稍有不同, 在下面容器内的资源共享节有说明。
常规的 Init 容器(即不包括边车容器)不支持 lifecycle
、livenessProbe
、readinessProbe
或 startupProbe
字段。Init 容器必须在 Pod 准备就绪之前完成运行;而边车容器在 Pod 的生命周期内继续运行, 它支持一些探针。
如果为一个 Pod 指定了多个 Init 容器,这些容器会按顺序逐个运行。 每个 Init 容器必须运行成功,下一个才能够运行。当所有的 Init 容器运行完成时, Kubernetes 才会为 Pod 初始化应用容器并像平常一样运行。
与边车容器的不同之处
Init 容器在主应用容器启动之前运行并完成其任务。 与边车容器不同, Init 容器不会持续与主容器一起运行。
Init 容器按顺序完成运行,等到所有 Init 容器成功完成之后,主容器才会启动。
Init 容器不支持 lifecycle
、livenessProbe
、readinessProbe
或 startupProbe
, 而边车容器支持所有这些探针以控制其生命周期。
Init 容器与主应用容器共享资源(CPU、内存、网络),但不直接与主应用容器进行交互。 不过这些容器可以使用共享卷进行数据交换。
使用 Init 容器
应用容器镜像通常追求精简、安全和小巧。在应用启动前,你可能需要执行一些初始化任务,这些任务可能需要 sed
, awk
, python
, dig
, curl
, sql
客户端等工具。为了在应用容器里运行这些工具,你可能需要在构建应用镜像时把这些工具也打包进去。这会导致增加了不必要的层和大小、增加了应用容器的攻击面。你可以为 Init 容器选择一个独立的、包含所需工具的镜像,Init 容器运行完任务后就退出,这些工具不会出现在最终运行的应用容器中。应用容器仍然可以保持精简和安全。
你可以将包含敏感信息的 Secret 只挂载给 Init 容器。Init 容器可以使用这些 Secret 来完成初始化(例如,用密码初始化数据库或配置连接),然后将处理后的、非敏感的结果(如生成的配置文件)写入一个共享的、空的卷。应用容器启动后,只能访问这个共享卷里的非敏感结果文件,而无法直接访问原始的 Secret。
应用容器可能依赖于外部服务(如数据库、消息队列、API)或其他 Pod 就绪。如果应用容器在这些依赖项准备好之前启动,它们可能会崩溃或行为异常。 Init 容器必须成功运行完成(以退出码 0 退出),Pod 才会启动应用容器。
边车容器
边车容器是与主应用容器在同一个 Pod 中运行的辅助容器。 这些容器通过提供额外的服务或功能(如日志记录、监控、安全性或数据同步)来增强或扩展主应用容器的功能, 而无需直接修改主应用代码。
通常,一个 Pod 中只有一个应用容器。 例如,如果你有一个需要本地 Web 服务器的 Web 应用, 则本地 Web 服务器以边车容器形式运行,而 Web 应用本身以应用容器形式运行。
Kubernetes 中的边车容器
Kubernetes 将边车容器作为 Init 容器的一个特例来实现, Pod 启动后,边车容器仍保持运行状态。使用术语"常规 Init 容器"来明确指代仅在 Pod 启动期间运行的容器。
如果你的集群启用了 SidecarContainers
特性门控 (该特性自 Kubernetes v1.29 起默认启用),你可以为 Pod 的 initContainers
字段中列出的容器指定 restartPolicy
。 这些可重新启动的边车(Sidecar) 容器独立于其他 Init 容器以及同一 Pod 内的主应用容器, 这些容器可以启动、停止和重新启动,而不会影响主应用容器和其他 Init 容器。
下面是一个包含两个容器的 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 中的应用容器并行运行。不过边车容器不执行主应用逻辑,而是为主应用提供支持功能。
边车容器具有独立的生命周期。它们可以独立于应用容器启动、停止和重启。 这意味着你可以更新、扩展或维护边车容器,而不影响主应用。
边车容器与主容器共享相同的网络和存储命名空间。这种共存使它们能够紧密交互并共享资源。
从 Kubernetes 的角度来看,边车容器的体面终止(Graceful Termination)相对不那么重要。 当其他容器耗尽了分配的体面终止时间后,边车容器将在尚未完成体面终止时间的情况下接收到 SIGTERM
信号,随后是 SIGKILL
信号。 因此,在 Pod 终止时,边车容器退出码不为 0
(0
表示成功退出)是正常的, 通常应该被外部工具忽略。
与 Init 容器的区别
边车容器与主应用容器同时运行。它们在整个 Pod 的生命周期中都处于活动状态,并且可以独立于主容器启动和停止。 与 Init 容器不同, 边车容器支持探针来控制其生命周期。
边车容器可以直接与主应用容器交互,因为与 Init 容器一样, 它们总是与应用容器共享相同的网络,并且还可以选择共享卷(文件系统)。
Init 容器在主容器启动之前停止,因此 Init 容器无法与 Pod 中的应用容器交换消息。 所有数据传递都是单向的(例如,Init 容器可以将信息放入 emptyDir
卷中)。
变更边车容器的镜像不会导致 Pod 重启,但会触发容器重启.