梳理概念:
初始化容器,顾名思义容器启动的时候,会先启动可一个或多个容器,如果有多个,那么这几个Init Container按照定义的顺序依次执行,只有所有的Init Container执行完后,主容器才会启动。由于一个Pod里的存储卷是共享的,所以Init Container里产生的数据可以被主容器使用到。
Init Container可以在多种K8S资源里被使用到如Deployment、Daemon Set, Pet Set, Job等,但归根结底都是在Pod启动时,在主容器启动前执行,做初始化工作。
应用场景:
第一种场景:等待其它模块Ready,比如我们有一个应用里面有两个容器化的服务,一个是Web Server,另一个是数据库。其中Web Server需要访问数据库。但是当我们启动这个应用的时候,并不能保证数据库服务先启动起来,所以可能出现在一段时间内Web Server有数据库连接错误。为了解决这个问题,我们可以在运行Web Server服务的Pod里使用一个InitContainer,去检查数据库是否准备好,直到数据库可以连接,Init Container才结束退出,然后Web Server容器被启动,发起正式的数据库连接请求。
第二种场景:初始化配置,比如集群里检测所有已经存在的成员节点,为主容器准备好集群的配置信息,这样主容器起来后就能用这个配置信息加入集群。
其它使用场景:如将pod注册到一个中央数据库、下载应用依赖等。
参照样例:
初始化容器有两种写法,一种是注解的形式,样例如下图所示:
另一种是转换为PodSpec字段的形式,样例如下图所示:
Kubernetes 1.6有一个新的语法,尽管旧的注释语法仍然适用于1.6和1.7。新的语法必须用于1.8或更高版本。我们已经将init容器的声明移至spec,可以在PodSpec中指定Init Containers以及应用程序containers数组。测试版批注值仍将受到尊重并覆盖PodSpec字段值,但是,它们在1.6和1.7中已弃用。在1.8中,注释不再受支持,并且必须转换为PodSpec字段。
k8s中,spec.volumes指的是Pod中的卷,spec.container.volumeMounts,是将指定的卷mount到容器指定的位置,相当于docker里面的‘-v 宿主机目录:容器目录’,上图emptyDir{}相当于一个共享卷,是一个临时的目录,生命周期等同于pod的生命周期。
初始化容器执行完,会下载一个html文件映射到emptyDir{},而主容器也是和spec.volumes里的emptyDir{}进行映射,故nginx容器的/usr/share/nginx/html目录下会映射index.html文件。
执行结果:
由于我的k8s版本是1.9,所以我采用PodSpec的形式来启动容器,执行命令如下:
kubectl apply -f init-container.yaml
它会先启动一个初始化的容器,当初始化容器执行完成之后,然后启动主容器。
接下来看容器的详情,会先启动init-containers,再接着启动containers主容器,如下图:
整个初始化容器过程就完了,下一节容器讲述的健康检查。