Kubernetes initContainer 初始容器

官方中文文档

1、理解 Init 容器

Kubernetes 1.3 版本引入了 Alpha 版本的新特性 init container(初始化容器,在 Kubernetes 1.5 时被更新为 Bate 版本)用于在启动应用容器(app container)之前启动一个或多个初始化容器,init container 与应用容器本质上是一样的,但他们是仅运行一次就结束的任务,并且必须在成功执行完后,系统才能继续执行下一个容器。

init container 一些特征:

  1. 重启策略:Init Container 的重启策略默认为 Always,如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止。如果 Pod 对应的 restartPolicy 值为 Never,它不会重新启动。

  2. 顺序执行:Init container 的运行方式与应用容器不同,它们必须先于应用容器执行完成,当设置了多个init container时,将按顺序逐个运行,并且只有前一个init container运行成功后才能运行后一个init container。当所有init container 都成功运行后,Kubernetes 才会初始化 Pod 的各种信息,并开始创建和运行应用容器。

  3. Init container 支持应用容器的全部字段和特性,包括资源限制、数据卷和安全设置。在 init container 的定义中也可以设置资源限制、Volume 的使用和安全策略,等等。但资源限制的设置与应用容器略有不同。

    • 如果多个 init container 都定义了资源请求/资源限制,则取最大的值作为所有 init container 的资源请求值/资源限制值。
    • Pod 的有效(effective)资源请求值/资源限制值取以下二者中的较大值。
      • a)所有应用容器的资源请求值/资源限制值之和。
      • b)init container 的有效资源请求值/资源限制值。
    • 调度算法将基于 Pod 的有效资源请求值/资源限制值进行计算,也就是说 init container 可以为初始化操作预留系统资源,即使后续应用容器无须使用这些资源。
    • Pod 的有效 QoS 等级适用于 init container 和应用容器。
    • 资源配额和限制将根据 Pod 的有效资源请求值/资源限制值计算生效。
    • Pod 级别的 cgroup 将基于 Pod 的有效资源请求/限制,与调度机制一致。
  4. init container 不能设置 readinessProbe 探针,因为必须在它们成功运行后才能继续运行在 Pod 中定义的普通容器。

    在 Pod 重新启动时,init container 将会重新运行,常见的 Pod 重启场景如下。

    • init container 的镜像被更新时,init container 将会重新运行,导致 Pod 重启。仅更新应用容器的镜像只会使得应用容器被重启。
    • Pod 的 infrastructure 容器更新时,Pod 将会重启
    • 若 Pod 中的所有应用容器都终止了,并且 RestartPolicy=Always,则 Pod 会重启。
  5. 容器中的所有初始容器和普通容器名称必须惟一。

  6. 指定容器为 Init 容器,需要在 Pod 的 spec 中添加 initContainers 字段,该字段內以 Container 类型对象数组的形式组织,和应用的 containers 数组同级相邻。Init 容器的状态在 status.initContainerStatuses 字段中以容器状态数组的格式返回(类似 status.containerStatuses 字段)。

2、Init 容器能做什么【使用场景】

  • 等待某些服务可用:例如,一个应用可能需要等待数据库服务启动并响应查询。
  • 执行一些初始化脚本:比如,设置数据库架构、初始化配置文件或执行其他预置条件。
  • 检查和应用迁移:对数据库执行迁移或更新。
  • 可以包含并且运行一些出于安全考虑不适合和应用放在一块的小工具
  • 等待其他量关联组件正确运行(例如数据库或某个后台服务)
  • 基于环境变量或配置模板生成配置文件
  • 从远程数据库获取本地所需配置,或者将吱声注册到某个中央数据库中
  • 下载相关依赖包,或者对系统进行一些预配置操作
  • 服务启动过慢,原因是需要加载一些资源,例如缓存加载,数据表首次创建/升级,而启动慢在k8s中就会被健康检测杀死,导致服务重启,此时可以将一些耗时,一次性的操作放到 init container 中处理
  • 服务依赖,当服务依赖于其他组件或者服务时,发现服务启动速度比被依赖的还要快,导致服务不可用,此时可以通过 init container 进行服务探测,发现依赖服务已经启动了就退出

3、示例

以 Nginx 应用为例,在启动 Nginx 之前,通过初始化容器 busybox 为 Nginx 创建一个 index.html 主页文件。这里为 init container和 Nginx 设置一个共享的 Volume,init.yaml 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# nginx-init-containers.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
annotations:
spec:
initContainers: # 这个是重点, initcontainers
- name: install
image: busybox
command:
- wget
- "-O"
- "/work-dir/index.html"
- http://kubernetes.io
volumeMounts:
- name: workdir # volume mount
mountPath: "/work-dir"
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: workdir # nginx使用这个volume
mountPath: /usr/share/nginx/html
dnsPolicy: Default
volumes: # volume
- name: workdir
emptyDir: {}
1
2
3
4
5
6
7
8
9
10
11
kubectl apply -f nginx-init-containers.yaml

# 在运行init container的过程中查看Pod的状态,可见init过程还未完成
[root@k8s-master01 init_container]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE
nginx 0/1 PodInitializing 0 10s

# 启动成功后,登录进Nginx容器,可以看到/usr/share/nginx/html目录下的index.html文件为init container所生成,其内容为:
[root@k8s-master01 init_container]# kubectl exec nginx -it -- /bin/sh
# ls /usr/share/nginx/html
index.html

Kubernetes initContainer 初始容器
https://flepeng.github.io/042-云原生-02-kubernetes-31-核心概念-Kubernetes-initContainer-初始容器/
作者
Lepeng
发布于
2023年3月1日
许可协议