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: v1
kind: Pod
metadata:
name: nginx
annotations:
name: nginx
spec:
# These containers are run during pod initialization
initContainers:
- name: install
image: busybox
command:
- wget
- "-O"
- "/work-dir/index.html"
- http://www.baidu.com
volumeMounts:
- name: workdir
mountPath: "/work-dir"
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
dnsPolicy: Default
volumes:
- name: workdir
emptyDir: {}
创建这个 Pod:
[root@master ~]# kubectl create -f 033-nginx-init-containers.yaml
pod/nginx created
在运行 init container 的过程中查看 Pod 的状态,可见 init 过程还未完成:
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 0/1 PodInitializing 0 19s
在 init container 成功执行完成后,系统继续启动 Nginx 容器,再次查看 Pod 的状态:
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 47s
查看 Pod 的事件,可以看到系统首先创建并运行 init container 容器(名为install),成功后继续创建和运行 Nginx
容器:
[root@master ~]# kubectl describe pod nginx
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 76s default-scheduler Successfully assigned default/nginx to slave2
Normal Pulling 76s kubelet Pulling image "busybox"
Normal Pulled 59s kubelet Successfully pulled image "busybox" in 16.176115699s
Normal Created 59s kubelet Created container install
Normal Started 59s kubelet Started container install
Normal Pulling 59s kubelet Pulling image "nginx"
Normal Pulled 43s kubelet Successfully pulled image "nginx" in 16.220091242s
Normal Created 43s kubelet Created container nginx
Normal Started 43s kubelet Started container nginx
启动成功后,登录进 Nginx 容器,可以看到 /usr/share/nginx/html
目录下的 index.html
文件为 init
container所生成,其内容为:
[root@master ~]# kubectl exec -ti nginx -- bash
Defaulted container "nginx" out of: nginx, install (init)
root@nginx:/# cd /usr/share/nginx/html/
root@nginx:/usr/share/nginx/html# ls
index.html
root@nginx:/usr/share/nginx/html# cat index.html
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> ...... </body> </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 会重启。