初始化容器
Init Container就是用来做初始化工作的容器,可以是一个或者多个,如果有多个的话,这些容器会按定义的顺序依次执行,只有所有的Init Container执行完后,主容器才会被启动。一个Pod里面的所有容器是共享数据卷和网络命名空间的,所以Init Container里面产生的数据可以被主容器使用到的。
Init Container和之前的钩子函数有点类似,只是是在容器执行前来做一些工作,从直观的角度看上去的话,初始化容器的确有点像PreStart,但是钩子函数和我们的InitContainer是处在不同的阶段的,我们可以通过下面的图来了解:
从上面这张图我们可以直观的看到PostStart和PreStop包括liveness和readiness是属于主容器的生命周期范围内的,而Init Container是独立于主容器之外的,当然他们都属于Pod的生命周期范畴之内的。
另外我们可以看到上面我们的Pod右边还有一个infra的容器,我们可以在集群环境中去查看下任意一个Pod对应的运行的Docker容器,可以发现每一个Pod下面都包含了一个pause-amd64的镜像,这个就是我们的infra镜像,我们知道Pod下面的所有容器是共享同一个网络命名空间的,这个镜像就是来做这个事情的,所以每一个Pod当中都会包含一个这个镜像。
很多 Pod 启动不起来就是因为这个 infra 镜像没有被拉下来,所以需要提前拉取到节点上面。
Init容器与普通容器区别:
- Init容器总是运行到成功为止。
- 每个Init容器都必须在下一个Init容器启动之前成功完成。
如果Pod的Init容器失败,Kubenetes会不断地重启该Pod,直到Init容器成功为止。然而,如果Pod对应的restartPolicy为Never,它不会重新启动。
Init容器的优势:
- 它可以包含并运行实用工具。出于安全考虑,不建议在应用程序容器镜像中包含这些实用工具的。
- 他们可以包含使用工具和定制代码来安装,但是不能出现在应用程序容器镜像中。例如:创建镜像没有必要FROM另一个镜像,只需要在安装过程中使用类似sed、awk、python或dig这样的工具。
- 应用程序容器镜像可以分离出创建和部署的角色,而没有必要联合它们构建一个单独的镜像。
- Init容器使用LinuxNamespace,所以相对应用程序容器来说具有不同的文件系统视图。因此,Init容器能够具有Secret的权限,而应用程序容器则不能。
- 它们必须在应用程序容器启动之前运行完成,而应用程序容器是并行运行的,所以Init容器能够提供一种简单的阻塞或延迟应用程序容器的启动方法,直到满足先决条件。
Init容器应用场景:
- 等待其他模块Ready:可以用来解决服务之间的依赖问题,比如我们有一个 Web服务,该服务又依赖于另外一个数据库服务,但是在我们启动这个 Web服务的时候我们并不能保证依赖的这个数据库服务就已经启动起来了,所以可能会出现一段时间内 Web服务连接数据库异常。要解决这个问题的话我们就可以在 Web 服务的 Pod 中使用一个nitContainer,在这个初始化容器中去检查数据库是否已经准备好了,准备好了过后初始化容器就结束退出,然后我们的主容器 Web服务被启动起来,这个时候去连接数据库就不会有问题了。