Init Container

Init Container的应用场景

当咱们在运用一个服务以前,一般会作一些初始化的工做,而这些工做通常只须要运行一次,成功后就再也不运行。为此kubernetes 引入了Init Container,用于在启动应用容器以前启动一个或多个“初始化”容器,完成应用容器的所需的预制条件。html

Init Containers与常规的容器很是相似,可是它一些独有的特征:nginx

  • 他们仅运行一次,成功后就会退出。
  • 每一个容器必须在成功执行完成后,系统才能继续执行下一个容器。
  • 若是Init Container运行失败,kubernetes 将会重复重启Pod,直到Init Container 成功运行,可是若是 Pod的重启策略(restartPolicy)设置为Never,则Pod不会重启。
  • Init Container支持普通应用Container的全部参数,包括资源限制,挂载卷,安全设置等。可是Init Container 在资源的申请和限制上略有不一样,同时,因为Init Container必须在Pod ready以前完成并退出,因此它不支持 readiness 探针。

Init Container 一般有以下应用方式:git

  • 处于安全的考虑,能够将自定义的代码和工具使用Init Container运行,而没必要添加到 应用 容器的镜像中。
  • 应用程序映像的构建和部署者角色能够彼此独立,无需共同构建单个应用程序映像
  • 使用不一样的Linux命名空间,可使它们具备来自应用容器的不一样文件系统权限。 所以,Init Container能够得到应用程序容器没法访问的Secrets。
  • Init Container在任何应用程序容器启动以前运行完毕,而应用程序容器一般是并行运行的,所以初始容器提供了一种简单的方法来阻止或延迟应用程序容器的启动,直到知足一些前提条件。

具体的应用场景示例:shell

  • 如使用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 http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d ‘instance=$()&ip=$()’
  • 在启动应用以前,等待一段时间:sleep 60
  • 从git仓库拉取配置或代码到指定的挂载卷中
  • 使用模板工具动态的生成配置,并给配置文件添加合适的参数。如使用Jinja模板将POD IP添加到应用容器的配置中。

定义Init Container

这里定义一个nginx,在nginx容器启动前更改默认起始页面内容:api

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  initContainers:
  - name: init-myservice
    image: busybox
    command: ['sh', '-c', 'echo "this init-container test page" > /html/index.html']
    volumeMounts:
    - name: index-dir
      mountPath: "/html"
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
    volumeMounts: 
    - name: index-dir
      mountPath: /usr/share/nginx/html
  volumes:
  - name: index-dir
    emptyDir: {}

建立容器后,能够看到,先执行初始化操做:安全

# kubectl  get pod
NAME        READY     STATUS     RESTARTS   AGE
myapp-pod   0/1       Init:0/1   0          12s

# 显示正在初始化:
# kubectl  get pod
NAME        READY     STATUS            RESTARTS   AGE

myapp-pod   0/1       PodInitializing   0          22s

# kubectl  get pod -o wide
NAME        READY     STATUS    RESTARTS   AGE       IP          NODE
myapp-pod   1/1       Running   0          38s       10.2.74.5   10.0.0.3

#日志信息:
# kubectl  describe pod
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              29s   default-scheduler  Successfully assigned myapp-pod to 10.0.0.3
  Normal  SuccessfulMountVolume  29s   kubelet, 10.0.0.3  MountVolume.SetUp succeeded for volume "index-dir"
  Normal  SuccessfulMountVolume  29s   kubelet, 10.0.0.3  MountVolume.SetUp succeeded for volume "default-token-hmvnc"
  Normal  Pulling                28s   kubelet, 10.0.0.3  pulling image "busybox"
  Normal  Pulled                 16s   kubelet, 10.0.0.3  Successfully pulled image "busybox"
  Normal  Created                16s   kubelet, 10.0.0.3  Created container
  Normal  Started                16s   kubelet, 10.0.0.3  Started container
  Normal  Pulling                15s   kubelet, 10.0.0.3  pulling image "nginx"
  Normal  Pulled                 1s    kubelet, 10.0.0.3  Successfully pulled image "nginx"
  Normal  Created                1s    kubelet, 10.0.0.3  Created container
  Normal  Started                1s    kubelet, 10.0.0.3  Started container

注意事项

Pod中的每一个应用程序和Init Container的名称必须是惟一的; 任何Container与另外一个Container共享一个名称都会引起验证错误。服务器

在Pod从新启动时, init Container 将会从新运行,那么所执行的初始化操做也会再次执行,这就要求Init Container的操做是能够重复执行的。例如上面的示例中,在对挂载目录中文件的添加前,能够先判断文件是否已经存在的处理,来防止出错。
常见的Pod重启场景以下:markdown

  • init container的镜像被更新时, init Container将会从新运行,致使Pod重启。仅更新应用容器的镜像,只会使得应用容器被重启。
  • Pod的 pause镜像更新时, Pod将会重启。
  • 若Pod 中的全部应用容器都终止了,而且restartPolicy=always, 则Pod将会重启。