参考:https://kubernetes.io/docs/concepts/workloads/pods/init-containers/

初始化容器是什么?

在kubernetes中,一个pod可以包含多个容器,其中的init container,顾名思义主要负责初始化工作,一个pod也可以包含多个init container。后文统一用"初始化容器"表示"init container"。初始化容器也是容器,在pod的定义中,如果将"containers"改成"initContainers",那么这个数组内定义的所有容器就都是初始化容器,定义初始化容器与普通应用容器的语法相同。但是,初始化容器不支持readiness类型探针,这个很容易理解,初始化容器主要负责初始化工作,在它没有运行完成之前pod一定处于未就绪状态(unready),所以readiness类型探针一定会诊断失败,没有意义。另外初始化容器在资源请求与限制方面与普通的应用容器有细微差别,后文详细描述。

初始化容器先于普通应用容器执行,如果pod有多个初始化容器,那么它们按定义的顺序逐个执行,并且前一个必需执行成功后一个才可以执行,所有的初始化容器执行成功后,普通应用容器才可以执行。当初始化容器执行失败时,如果restart policy是OnFailure或者Always,那么会重复执行失败的初始化容器一直到成功,如果restart policy是Never,则不会重启失败的初始化容器。如果初始化容器执行成功,那么无论restart policy是什么,即使是Always,也不会再次被重启。

初始化容器的状态可以通过pod的.status.initContainerStatuses字段查看,它的值是一个数组,分别表示每个初始化容器的状态。数组中每个成员的结果与表示普通应用容器状态的结构一样,字段含义相同。

初始化容器有什么用?

在开发一个程序时,通常初化代码与主体业务代码放置在同一个程序中。为什么kubernetes提供初始化容器这种功能,将初始化工作从普通容器中隔离出来?这种特性有什么用呢?初始化容器与普通容器有各自独立的image,本质上是将初始化逻辑与主体业务逻辑分离并放置在不同的image中,以下是初始化容器的主要用处:

  • 初始化容器可以包含不能随普通容器一起发布出去的敏感信息。
  • 初始化容器可以包含用户自定义的代码、工具,如sed、awk、python等方便完成初始化、设置工作。
  • 因为初始化逻辑与主体业务逻辑分布在不同的image中,因此image构建者与主体业务逻辑开发者可以各自独立的工作。
  • 初始化容器使用Linux namespace,不同于普通应用容器,具有不同的文件系统视图,并且对于低层的操作系统有更在的访问权限。
  • 当应用启动的前置条件不具备时,初始化容器可以阻止普通应用容器启动,避免在条件不具备时反复启动注定会失败的容器而浪费系统资源。(问题:同一个pod中的多个普通应用容器是否可以编排它们的启动顺序?)

示例

以下是如何使用初始化容器的一些想法、idea:

  • 使用shell命令等待某个service可用,类似于编排。如:   for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; done; exit 1
  • 使用命令,通过downward API向远程服务注册当前pod,如:curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d ‘instance=$()&ip=$()’
  • 使用命令在启动应用之前延迟一定时间,如sleep 60。
  • 将git repository克隆到volume。
  • 在一个配置文件中写入具体的配置值,然后通过临时工具动态的生成运行应用容器需要使用的配置。如将POD_IP写入一个配置文件,然后通过Jinja生成主应用容器的配置文件。

以下是具备示例:

Pod有两个初始化容器,一个等待myservice被创建,第二个等待mydb,当两个服务都创建后,应用容器才会启动。注意,文件中涉及初始化容器的语法适用于1.8及以后的版本。

apiVersion: v1
kind: Pod
metadata:name: myapp-podlabels:app: myapp
spec:containers:- name: myapp-containerimage: busyboxcommand: ['sh', '-c', 'echo The app is running! && sleep 3600']initContainers:- name: init-myserviceimage: busyboxcommand: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']- name: init-mydbimage: busyboxcommand: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']

以下是myservice与mydb:

kind: Service
apiVersion: v1
metadata:name: myservice
spec:ports:- protocol: TCPport: 80targetPort: 9376
---
kind: Service
apiVersion: v1
metadata:name: mydb
spec:ports:- protocol: TCPport: 80targetPort: 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
$ kubectl describe -f myapp.yaml
Name:          myapp-pod
Namespace:     default
[...]
Labels:        app=myapp
Status:        Pending
[...]
Init Containers:init-myservice:
[...]State:         Running
[...]init-mydb:
[...]State:         WaitingReason:      PodInitializingReady:         False
[...]
Containers:myapp-container:
[...]State:         WaitingReason:      PodInitializingReady:         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.20116s          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

由以上输出可以看出,pod中唯一的应用容器没有到达"ready"阶段,状态显示需要成功执行两个初始化容器,但目前执行成功的个数是0。进一步确认,pod处于peding状态,初始化容器1已经成功运行,但是无法成功结束,所以整个pod被阻塞在了pending状态。通过kubectl logs可分别查看两个初始化容器的日志。

创建myservice与mydb服务,再确认pod状态:

$ kubectl create -f services.yaml
service "myservice" created
service "mydb" created
$ kubectl get -f myapp.yaml
NAME        READY     STATUS    RESTARTS   AGE
myapp-pod   1/1       Running   0          9m

可以看到,pod完全处于ready阶段,状态显示为running,表明两个初始化容器已经成功结束。

初始化容器详细行为

初始化容器先于普通应用容器启动,如果有多个则按定义顺序逐个启动,并且前一个必需成功后才可以启动后一下,所有的都成功后才可以启动应用容器。关于初始化容器与restart policy,前文已描述。需要注册的是,网络与volume的初始化要先于初始化容器,或者说pod的pause根容器先于初始化容器启动。

当初始化容器正在运行时,整个pod处于pending阶段,状态为Initializing。如果整个pod被restart,则所有容器包括初始化容器也要再运行一次。

对初始化容器的变更仅限于image字段,其它字段不可以再行更改。变更初始化容器的image字段会导致整个pod重新启动。

初始化容器可以被重启、重复运行多次。因些注意解决"幂等"问题,如初始化容器第一次运行时创建文件并写入内容,那么第二次运行时文件已经存在并且已经有内容,要注意解决这类问题。

资源请求与限制

以几下几条规则:

  • 初如化有效初始化request/limit(effective init request/limit):指的是所有初始化容器request/limit的最大值,就是从初始化容器中取最大值。
  • pod有效初始化request/limit的值要比以下值都高:
    1.初如化有效初始化request/limit
    2.各应用容器request/limit的总合
  • Scheduling is done based on effective requests/limits, which means Init Containers can reserve resources for initialization that are not used during the life of the Pod.
  • QoS tier of the Pod’s effective QoS tier is the QoS tier for Init Containers and app containers alike.

初始化容器重启原因

  • 修改初始化容器的image会导致整个pod重启,但是,更新应用容器的image只会导致相应的容器重启,而不是整个pod。
  • 根容器重启导致整个pod重启,初始化容器也会重启。这种情况很少见。
  • 初始化容器执行成功记录丢失

kubernetes之初始化容器相关推荐

  1. Kubernetes的初始化容器initContainers

    initContainers是一种专用的容器,在应用程序容器启动之前运行,可以包括一些应用程序镜像中不存在的实用工具和安装脚本,可以完成应用的必要数据初始化等工作.总的来说就是在正式的容器启动之前做一 ...

  2. Kubernetes 初始化容器顺序启动

    最近工作中需要保证容器启动之前PostgreSQL先启动,然后Apollo再启动,不然会出现配置加载错误的问题.Kubernetes的初始化容器就能够满足这种场景. InitContainers能够按 ...

  3. Kubernetes(k8s)四、Pod生命周期(初始化容器的应用,探针liveness、readliness应用,)

    Pod生命周期 学习目标:初始化容器的应用及两个探针的应用 探针 是由 kubelet 对容器执行的定期诊断: Kubelet 可以选择是否执行在容器上运行的三种探针执行和做出反应: liveness ...

  4. CC00204.CloudKubernetes——|KuberNetes高级调度.V07|——|初始化容器|InitContainer操作|

    一.InitContainer概述 ### --- InitContainer概述~~~ # InitContainer: ~~~ 初始化容器:预处理.预判断.与执行命令操作:在我应用容器启动之前做的 ...

  5. k8s 重启策略、健康检查、环境变量、初始化容器

    深入理解Pod对象:基本管理 Pod基本概念 Pod存在意义 Pod资源共享实现机制 Pod管理命令 重启策略 健康检查 环境变量 init Container(初始化容器) 先简单的做出两个运行ht ...

  6. 5. Kubernetes 进阶之容器组(Pod)

    Pod详解 Pod介绍 术语中英文对照: 英文全称 英文缩写 中文翻译 Pod Pod 容器组 Container Container 容器 Controller Controller 控制器 什么是 ...

  7. k8s pod生命周期、初始化容器、钩子函数、容器探测、重启策略

    pod结构 Pause容器 Pause容器是每个Pod都会有的一个根容器,它的作用有两个 可以以它为根据,评估整个pod的健康状态 可以在根容器上设置IP地址,其他容器都以此IP(Pod IP),以实 ...

  8. C++列表初始化容器

    initializer_list是一个模板类,可能你已经用过它了但不知道而已,比如下面的代码就用了 #include <iostream> #include <vector>i ...

  9. spring读取配置文件初始化容器操作总结

    Spring初始化容器.三种经常用到的实现: 一.ClassPathXmlApplicationContext:从类路径中加载. 二.FileSystemXmlApplicationContext:从 ...

最新文章

  1. JavaSript模块规范 - AMD规范与CMD规范介绍[转]
  2. Redis缓存穿透、击穿、雪崩及主从复制
  3. boost::hana::trait用法的测试程序
  4. grep,sort,uniq 用法例子
  5. 2095 : 我只看看不写题(贪心)
  6. c++ 使用nacos_为什么选用Nacos?虎牙直播微服务改造实践
  7. 最后2天,BDTC 2019 早鸟票即将售罄,超强阵容及议题抢先曝光!
  8. linux监听端口无响应,linux – tomcat运行,但是8080端口没有响应
  9. OCS2007标准版服务器部署
  10. mysql取分组最新的一条_基于mysql实现group by取各分组最新一条数据
  11. STC8H8K64U单片机学习-2-后续所需软件介绍
  12. 036.crud准备
  13. nginx方向代理域名访问
  14. css所有缩写属性,CSS常见属性缩写与全写对比
  15. Blockchains Distributed L week3 爱宝授课记录(1)
  16. PS教程:紫色光晕效果实现
  17. 论文阅读:Deep Residual Shrinkage Networksfor Fault Diagnosis
  18. (白帽生存法则)常见的网站攻击方式
  19. 翻译:《JavaScript 权威指南(第5版)》第一章(一)
  20. 【毕业设计源码】基于微信小程序的校园活动管理系统的设计与实现

热门文章

  1. Android通过百度AI 实现拍照或相册图像识别
  2. filter基本用法
  3. 执行数据库操作命令对象SqlCommand
  4. UE4 材质 制作噪声图
  5. usb共享网络在switch上的一次尝试
  6. 宝塔面板安装mediawiki
  7. cocos shader 用到的数学 抛物线,直线方程篇
  8. python中文路径与英文路径的拼接
  9. java中上传图片的原理_js实现图片上传预览原理分析
  10. 【Python】过拟合解决