在现实场景中,我们为了降低业务耦合,往往会将一个大大的功能拆解成若干独立的小功能。比如主要业务启动前,需要将其所依赖的各种资源都拉下来。一种做法是在一个Pod内完成上述两步操作,但是会导致业务逻辑不够独立;另外一种做法就是启动一个Pod专门用于拉取资源,待其完成后再启动业务Pod。
错误的示例
下面部署的Pod将启动3个容器。前两个运行的容器只在/data/whoami追加了一行文本后就退出了。
# common-container.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: common-container-deployment
spec:replicas: 1selector:matchLabels:app: common-containertemplate:metadata:labels:app: common-containerspec:containers:- name: common-container-1image: busyboxcommand: ["/bin/sh", "-c", "echo \"this is init-common-container1\"; echo \"this is init-common-container-1\" >> /data/whoami"]volumeMounts:- name: emptydir-volumemountPath: /data- name: common-container-2image: busyboxcommand: ["/bin/sh", "-c", "echo \"this is init-common-container2\"; echo \"this is init-common-container-2\" >> /data/whoami"]volumeMounts:- name: emptydir-volumemountPath: /data- name: common-containerimage: busyboxcommand: ["/bin/sh", "-c", "while true; do cat /data/whoami; sleep 5; done"]volumeMounts:- name: emptydir-volumemountPath: /datavolumes:- name: emptydir-volumeemptyDir: medium: MemorysizeLimit: 1Gi
查看Pod状态,可以发现Pod因为前两个容器中脚本执行结束后,没有了前台进程,容器就退出了。进而导致Pod创建失败。
kubectl get pod
NAME                                           READY   STATUS             RESTARTS     AGE
common-container-deployment-5569564499-qchgq   1/3     CrashLoopBackOff   4 (7s ago)   40s
kubectl describe pod common-container-deployment-5569564499-qchgq 
……
Events:Type     Reason     Age                From               Message----     ------     ----               ----               -------Normal   Scheduled  17s                default-scheduler  Successfully assigned default/common-container-deployment-5569564499-qchgq to ubuntubNormal   Pulled     15s                kubelet            Successfully pulled image "busybox" in 2.257083309s (2.257101009s including waiting)Normal   Pulled     13s                kubelet            Successfully pulled image "busybox" in 2.260848562s (2.260857362s including waiting)Normal   Pulling    13s                kubelet            Pulling image "busybox"Normal   Pulled     11s                kubelet            Successfully pulled image "busybox" in 1.989747468s (1.989754568s including waiting)Normal   Created    11s                kubelet            Created container common-containerNormal   Started    10s                kubelet            Started container common-containerNormal   Pulling    10s (x2 over 17s)  kubelet            Pulling image "busybox"Normal   Pulled     8s                 kubelet            Successfully pulled image "busybox" in 2.033723483s (2.033734083s including waiting)Normal   Created    8s (x2 over 15s)   kubelet            Created container common-container-1Normal   Started    8s (x2 over 15s)   kubelet            Started container common-container-1Normal   Pulling    8s (x2 over 15s)   kubelet            Pulling image "busybox"Normal   Pulled     6s                 kubelet            Successfully pulled image "busybox" in 2.032193623s (2.032200723s including waiting)Normal   Created    6s (x2 over 13s)   kubelet            Created container common-container-2Normal   Started    6s (x2 over 13s)   kubelet            Started container common-container-2Warning  BackOff    4s (x2 over 5s)    kubelet            Back-off restarting failed container common-container-1 in pod common-container-deployment-5569564499-qchgq_default(fd19ae72-5fd0-420d-9931-0d976175cf77)Warning  BackOff    4s (x2 over 5s)    kubelet            Back-off restarting failed container common-container-2 in pod common-container-deployment-5569564499-qchgq_default(fd19ae72-5fd0-420d-9931-0d976175cf77)
正确的示例
我们将需要一次性运行结束后可以退出的容器使用initContainers描述。
# init_container.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: init-container
spec:replicas: 1selector:matchLabels:app: init-containertemplate:metadata:labels:app: init-containerspec:initContainers:- name: init-container-1image: busyboxcommand: ["/bin/sh", "-c", "echo \"this is init-container-1\"; echo \"this is init-container-1\" >> /data/whoami"]volumeMounts:- name: emptydir-volumemountPath: /data- name: init-container-2image: busyboxcommand: ["/bin/sh", "-c", "echo \"this is init-container-2\"; echo \"this is init-container-2\" >> /data/whoami"]volumeMounts:- name: emptydir-volumemountPath: /datacontainers:- name: init-containerimage: busyboxcommand: ["/bin/sh", "-c", "while true; do cat /data/whoami; sleep 5; done"]volumeMounts:- name: emptydir-volumemountPath: /datavolumes:- name: emptydir-volumeemptyDir: medium: MemorysizeLimit: 1Gi
查看Pod状态,可以发现已处于运行状态。说明Pod创建成功了。
kubectl get pod
NAME                              READY   STATUS    RESTARTS   AGE
init-container-55c6d46676-5knwk   1/1     Running   0          33s
使用initContainers描述的容器已经无法连接,只有最后一个有前台程序的容器在运行。
kubectl logs pods/init-container-55c6d46676-5knwk init-container1
error: container init-container1 is not valid for pod init-container-55c6d46676-5knwk
 kubectl logs pods/init-container-55c6d46676-5knwk init-container2
error: container init-container2 is not valid for pod init-container-55c6d46676-5knwk
kubectl logs pods/init-container-55c6d46676-5knwk init-container
this is init-container-1
this is init-container-2
总结
初始化容器用于运行一次就可以退出的业务场景,而普通容器则要一直有前台程序在运行。