Kubernetes的Pod中进行容器初始化

在很多应用场景中,应用在启动之前都需要进行如下初始化操作:

  • 等待其他关联组件正确运行(例如数据库或某个后台服务)。

  • 基于环境变量或配置模板生成配置文件。

  • 从远程数据库获取本地所需配置,或者将自身注册到某个中央数据库中。

  • 下载相关依赖包,或者对系统进行一些预配置操作。

Kubernetes 1.3 引入了一个 Alpha 版本的新特性 init container (初始化容器,在 Kubernetes 1.5 时被更新为

Beta版本),用于在启动应用容器(app container)之前启动一个或多个初始化容器,完成应用容器所需的预置

条件,如图所示。

init container 与应用容器在本质上是一样的,但它们是仅运行一次就结束的任务,并且必须在成功执行完成后,

系统才能继续执行下一个容器。根据 Pod 的重启策略(RestartPolicy),当 init container 执行失败,而且设置了

RestartPolicy=Never 时,Pod 将会启动失败;而设置 RestartPolicy=Always 时,Pod 将会被系统自动重启。

下面以 Nginx 应用为例,在启动 Nginx 之前,通过初始化容器 busybox 为 Nginx 创建一个 index.html 主页文

件。这里为 init container 和 Nginx 设置了一个共享的 Volume,以供 Nginx 访问 init container 设置的

index.html文件。

配置文件 033-nginx-init-containers.yaml 的内容为:

apiVersion: v1kind: Podmetadata:name: nginxannotations:name: nginxspec:# These containers are run during pod initializationinitContainers:- name: installimage: busyboxcommand:- wget- "-O"- "/work-dir/index.html"- http://www.baidu.comvolumeMounts:- name: workdirmountPath: "/work-dir"containers:- name: nginximage: nginxports:- containerPort: 80volumeMounts:- name: workdirmountPath: /usr/share/nginx/htmldnsPolicy: Defaultvolumes:- name: workdiremptyDir: {} 

创建这个 Pod:

[root@master ~]# kubectl create -f 033-nginx-init-containers.yamlpod/nginx created

在运行 init container 的过程中查看 Pod 的状态,可见 init 过程还未完成:

[root@master ~]# kubectl get podsNAMEREADY STATUSRESTARTS AGEnginx 0/1 PodInitializing 019s

在 init container 成功执行完成后,系统继续启动 Nginx 容器,再次查看 Pod 的状态:

[root@master ~]# kubectl get podsNAMEREADY STATUSRESTARTS AGEnginx 1/1 Running 047s

查看 Pod 的事件,可以看到系统首先创建并运行 init container 容器(名为install),成功后继续创建和运行 Nginx

容器:

[root@master ~]# kubectl describe pod nginxEvents:TypeReason Age From Message---------- -------- -------NormalScheduled76s default-schedulerSuccessfully assigned default/nginx to slave2NormalPulling76s kubeletPulling image "busybox"NormalPulled 59s kubeletSuccessfully pulled image "busybox" in 16.176115699sNormalCreated59s kubeletCreated container installNormalStarted59s kubeletStarted container installNormalPulling59s kubeletPulling image "nginx"NormalPulled 43s kubeletSuccessfully pulled image "nginx" in 16.220091242sNormalCreated43s kubeletCreated container nginxNormalStarted43s kubeletStarted container nginx

启动成功后,登录进 Nginx 容器,可以看到 /usr/share/nginx/html 目录下的 index.html 文件为 init

container所生成,其内容为:

[root@master ~]# kubectl exec -ti nginx -- bashDefaulted container "nginx" out of: nginx, install (init)root@nginx:/# cd /usr/share/nginx/html/root@nginx:/usr/share/nginx/html# lsindex.htmlroot@nginx:/usr/share/nginx/html# cat index.html 百度一下,你就知道  ......  

init container 与应用容器的区别如下:

(1)init container 的运行方式与应用容器不同,它们必须先于应用容器执行完成,当设置了多个 init container

时,将按顺序逐个运行,并且只有前一个 init container 运行成功后才能运行后一个 init container。当所有 init

container 都成功运行后,Kubernetes 才会初始化 Pod 的各种信息,并开始创建和运行应用容器。

(2)在 init container 的定义中也可以设置资源限制、Volume 的使用和安全策略,等等。但资源限制的设置与

应用容器略有不同。

  • 如果多个 init container 都定义了资源请求/资源限制,则取最大的值作为所有 init container 的资源请求值/资

    源限制值。

  • Pod 的有效资源请求值/资源限制值取以下二者中的较大值。

    1、所有应用容器的资源请求值/资源限制值之和。

    2、init container的有效资源请求值/资源限制值。

  • 调度算法将基于 Pod 的有效资源请求值/资源限制值进行计算,也就是说 init container 可以为初始化操作预

    留系统资源,即使后续应用容器无须使用这些资源。

  • Pod 的有效 QoS 等级适用于 init container 和应用容器。

  • 资源配额和限制将根据 Pod 的有效资源请求值/资源限制值计算生效。

  • Pod 级别的 cgroup 将基于 Pod 的有效资源请求/限制,与调度机制一致。

(3)init container 不能设置 readinessProbe 探针,因为必须在它们成功运行后才能继续运行在 Pod 中定义的

普通容器。

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

  • init container 的镜像被更新时,init container 将会重新运行,导致 Pod 重启。仅更新应用容器的镜像只会

    使得应用容器被重启。

  • Pod 的 infrastructure 容器更新时,Pod 将会重启。

  • 若 Pod 中的所有应用容器都终止了,并且 RestartPolicy=Always,则 Pod 会重启。