kubernetes之初始容器(init container)

系列目录

理解初始容器

一个pod里可以运行多个容器,它也可以运行一个或者多个初始容器,初始容器先于应用容器运行,除了以下两点外,初始容器和普通容器没有什么两样:

它们总是run to completion

一个初始容器必须成功运行另一个才能运行

如果pod中的一个初始容器运行失败,则kubernetes会尝试重启pod直到初始容器成功运行,如果pod的重启策略设置为从不(never),则不会重启.

创建容器时,在podspec里添加initContainers字段,则指定容器即为初始容器,它们的返回状态作为数组保存在.status.initContainerStatuses里(与普通容器状态存储字段.status.containerStatuses类似)

初始容器和普通容器的不同:

初始容器支持所有普通容器的特征,包括资源配额限制和存储卷以及安全设置.但是对资源申请和限制处理初始容器略有不同,下面会介绍.此外,初始容器不支持可用性探针(readiness probe),因为它在ready之前必须run to completion

如果在一个pod里指定了多个初始容器,则它们会依次启动起来(pod内的普通容器并行启动),并且只有上一个成功下一个才能启动.当所有的初始容器都启动了,kubernetes才开始启普通应用容器.

初始容器能做什么

由于初始容器和普通应用容器是分开的镜像,因此他在做一些初始化工作很有优势:

它们可以包含并且运行一些出于安全考虑不适合和应用放在一块的小工具.

它们可以一些小工具和自定义代码来做些初始化工作,这样就不需要在普通应用容器里使用sed,awk,python或者dig来做初始化工作了

应用构建者和发布者可以独立工作,而不必再联合起来处理同一个pod

它们使用linux namespaces因此它们和普通应用pod拥有不同的文件系统视图.因此他们可以被赋予普通应用容器获取不到的secrets

它们在应用容器启动前运行,因此它们可以阻止或者延缓普通应用容器的初始化直到需要的条件满足

示例:

通过执行shell命令来等待一个服务创建完成,命令如下:

for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; done; exit 1

通过downward API把当前pod注册到远程服务器,命令如下:

curl -X POST $MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'

在容器启动之前等待一定时间:例如sleep 60

克隆一个git仓库到存储目录

通过模板工具动态把一些值写入到主应用程序的配置文件里.

更多详细示例请查看pod应用环境布置指南

初始容器使用 apiVersion: v1 kind: Pod metadata: name: myapp-pod labels: app: myapp spec: containers: - name: myapp-container image: busybox command: ['sh', '-c', 'echo The app is running! && sleep 3600'] initContainers: - name: init-myservice image: busybox command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;'] - name: init-mydb image: busybox command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']

以上pod定义包含两个初始容器,第一个等待myservice服务可用,第二个等待mydb服务可用,这两个pod执行完成,应用容器开始执行.

下面是myservice和mydb两个服务的yaml文件

kind: Service apiVersion: v1 metadata: name: myservice spec: ports: - protocol: TCP port: 80 targetPort: 9376 --- kind: Service apiVersion: v1 metadata: name: mydb spec: ports: - protocol: TCP port: 80 targetPort: 9377

上面定义的pod可以通过以下使用初始化和调试

kubectl create -f myapp.yaml pod/myapp-pod created kubectl get -f myapp.yaml NAME READY STATUS RESTARTS AGE myapp-pod 0/1 Init:0/2 0 6m Name: myapp-pod Namespace: default [...] Labels: app=myapp Status: Pending [...] Init Containers: init-myservice: [...] State: Running [...] init-mydb: [...] State: Waiting Reason: PodInitializing Ready: False [...] Containers: myapp-container: [...] State: Waiting Reason: PodInitializing Ready: False [...] Events: FirstSeen LastSeen Count From SubObjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 16s 16s 1 {default-scheduler } Normal Scheduled Successfully assigned myapp-pod to 172.17.4.201 16s 16s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulling pulling image "busybox" 13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulled Successfully pulled image "busybox" 13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Created Created container with docker id 5ced34a04634; Security:[seccomp=unconfined] 13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Started Started container with docker id 5ced34a04634 kubectl logs myapp-pod -c init-myservice # Inspect the first init container kubectl logs myapp-pod -c init-mydb # Inspect the second init container

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygpyf.html