Kubernetes 1.3版本引入了 Alpha 版本的新特性 init container(初始化容器,在Kubernetes 1.5时被更新为 Bate 版本)用于在启动应用容器(app container)之前启动一个或多个初始化容器,init container 与应用容器本质上是一样的,但他们是仅运行一次就结束的任务,并且必须在成功执行完后,系统才能继续执行下一个容器。
在很多应用场景中,应用在启动之前都需要进行如下初始化操作。
- 等待其他量关联组件正确运行(例如数据库或某个后台服务)
- 基于环境变量或配置模板生成配置文件
- 从远程数据库获取本地所需配置,或者将吱声注册到某个中央数据库中
- 下载相关依赖包,或者对系统进行一些预配置操作
下面以 Nginx 应用为例,在启动 Nginx 之前,通过初始化容器 busybox 为 Nginx 创建一个 index.html 主页文件。这里为 init container 和 Nginx 设置一个共享的 Volume,init.yaml 代码如下:
apiVersion: v1
kind: Pod
metadata:
name: init-demo
labels:
app: init
spec:
initContainers:
- name: init
image: busybox
command:
- wget
- "-O"
- "/init-dir/index.html"
- http://kubernetes.io
volumeMounts:
- name: initdir
mountPath: "/init-dir"
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: initdir
mountPath: /usr/share/nginx/html
volumes:
- name: initdir
emptyDir: {}
创建这个 Pod:
[root@master yaml]# kubectl apply -f init.yaml
pod/init-demo created
在运行 init container 的听过程中查看 Pod 的状态,可见 init 过程还未完成:
[root@master yaml]# kubectl get po
NAME READY STATUS RESTARTS AGE
init-demo 0/1 Init:0/1 0 5s
在 init container 成功执行完成后,系统继续启动 Nginx 容器,再次查看 Pod 的状态:
[root@master yaml]# kubectl get po
NAME READY STATUS RESTARTS AGE
init-demo 1/1 Running 0 21s
查看 Pod 的事件,可以看到系统首先创建并运行 init container 容器,成功后继续创建和运行 Nginx 容器:
[root@master ~]# kubectl describe po init-demo
Name: init-demo
Namespace: pulsar
Priority: 0
PriorityClassName:
Node: tengine2test/10.12.1.222
Start Time: Sat, 11 Jul 2020 16:03:08 +0800
Labels: app=init
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"app":"init"},"name":"init-demo","namespace":"pulsar"},"spec":{"con...
Status: Running
IP: 10.33.0.7
Init Containers:
init:
Container ID: docker://84db647286a417cf8749bff62b811a6df2871d2976f98117b36ee6556f385d77
Image: busybox
Image ID: docker-pullable://busybox@sha256:9ddee63a712cea977267342e8750ecbc60d3aab25f04ceacfa795e6fce341793
Port:
Host Port:
Command:
wget
-O
/init-dir/index.html
http://kubernetes.io
State: Terminated
Reason: Completed
Exit Code: 0
Started: Sat, 11 Jul 2020 16:03:17 +0800
Finished: Sat, 11 Jul 2020 16:03:29 +0800
Ready: True
Restart Count: 0
Environment:
Mounts:
/init-dir from initdir (rw)
/var/run/secrets/kubernetes.io/serviceaccount from default-token-nhp9x (ro)
Containers:
nginx:
Container ID: docker://6641a1e669ee7a7bdeac56ba902e3274586b57d04b238494cae50012b9f7db8b
Image: nginx
Image ID: docker-pullable://nginx@sha256:a93c8a0b0974c967aebe868a186e5c205f4d3bcb5423a56559f2f9599074bbcd
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Sat, 11 Jul 2020 16:03:45 +0800
Ready: True
Restart Count: 0
Environment:
Mounts:
/usr/share/nginx/html from initdir (rw)
/var/run/secrets/kubernetes.io/serviceaccount from default-token-nhp9x (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
initdir:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
SizeLimit:
default-token-nhp9x:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-nhp9x
Optional: false
QoS Class: BestEffort
Node-Selectors:
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 59s default-scheduler Successfully assigned pulsar/init-demo to tengine2test
Normal Pulling 44s kubelet, tengine2test Pulling image "busybox"
Normal Pulled 37s kubelet, tengine2test Successfully pulled image "busybox"
Normal Created 37s kubelet, tengine2test Created container init
Normal Started 37s kubelet, tengine2test Started container init
Normal Pulling 23s kubelet, tengine2test Pulling image "nginx"
Normal Pulled 10s kubelet, tengine2test Successfully pulled image "nginx"
Normal Created 10s kubelet, tengine2test Created container nginx
Normal Started 9s kubelet, tengine2test Started container nginx
启动成功后,登录进 Nginx 容器,可以看到 /usr/share/nginx/html 目录下的 index.html 文件:
[root@master ~]# kubectl exec -it init-demo /bin/bash
root@init-demo:/usr/share/nginx/html# ls /usr/share/nginx/html
index.html
init container与应用容器的区别
1)运行方式不同,它们必须先于应用容器执行完成,当设置了多个init container时,将按顺序逐
个运行,当所有init container都成功运行后,kubernetes才会初始化Pod的各种信息。
2)在init container的定义中也可以设置资源限制,volume的使用和安全策略,但与应用容器略有不同
3)init container不能设置readinessProbe探针,因为必须在它们成功运行后才能继续运行Pod中定义的普通容器
4)在Pod重新启动时,init container将会重新运行
官方文档还给出了使用其他命令的方式:
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
到此初始化容器(Init Container)介绍完成。