目录

一、概述

二、使用InitContainer


一、概述

InitContainer即初始化容器,是 K8S官方为我们提供的一个可以用来判断环境是否已经满足运行 Pod 应用前所需要的条件

比如我们有一个应用,需要部署到Tomcat环境,那么在部署这个应用Pod之前,我们需要检查Tomcat环境是否已经准备好,InitContainer就可以用来做这个事情,我们可以让InitContainer运行 until 命令进行判断,判断是否满足我们应用运行的要求,如果满足运行要求,执行成功后便会退出,否则将会一直进行循环操作,直到条件成功。

使用InitContainer的一些优势:

  • 1、InitContainer能以不同于 Pod 内应用容器的文件系统视图运行。因此,InitContainer可以访问 应用容器不能访问的 [Secret]的权限
  • 2、由于InitContainer必须在应用容器启动之前运行完成,因此InitContainer提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。 一旦前置条件满足,Pod 内的所有的应用容器会并行启动。

二、使用InitContainer

创建 Pod 的资源清单文件: vim init-container-demo.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      initContainers: # 支持配置多个初始化容器,当前面的初始化容器运行成功后,便会进行退出操作,紧接着启动下一个容器。
        - name: my-init-container
          image: busybox:1.28
          # 通过until命令判断是否已经存在了名称为tomcat的Service,只有存在了tomcat,nginx这个Pod才能够启动成功
          command: [ 'sh', '-c', 'until nslookup tomcat;do echo Waiting for Tomcat Service started...;sleep 60;done;' ]
      containers:
        - name: nginx
          image: nginx

如上,我们通过在spec.initContainers指定了初始化容器,并且通过" until nslookup tomcat" 去检查当前是否已经存在名称为tomcat的service,只有存在tomcat service,初始化容器才会退出。如果 Pod 的InitContainer执行失败,kubelet 会不断地重启该InitContainer直到该容器成功为止。但是,如果 Pod 对应的 restartPolicy 值为 "Never",并且 Pod 的InitContainer失败, 则 Kubernetes 会将整个 Pod 状态设置为失败。

创建并查看Pod: 

$ kubectl apply -f init-container-demo.yaml 
deployment.apps/nginx created

# nginx pod一直处于Init:0/1,因为此时在执行initContainer的判断
$ kubectl get pod
NAME                     READY   STATUS     RESTARTS   AGE
nginx-7597c5f657-xfsvt   0/1     Init:0/1   0          4s

# 当前不存在tomcat service
$ kubectl get svc tomcat
Error from server (NotFound): services "tomcat" not found

# 查看my-init-container容器日志, 输出"Waiting for Tomcat Service started..."
$ kubectl logs nginx-7597c5f657-xfsvt -c my-init-container 
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Waiting for Tomcat Service started...
nslookup: can't resolve 'tomcat'

下面我们创建一个tomcat的service:

$ kubectl create service clusterip tomcat --tcp=8080
service/tomcat created

$ kubectl get svc tomcat
NAME     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
tomcat   ClusterIP   10.104.182.210   <none>        8080/TCP   3s

$ kubectl get pod 
NAME                     READY   STATUS    RESTARTS   AGE
nginx-7597c5f657-xfsvt   1/1     Running   0          2m6s

可以看到,当创建完tomcat service后,InitContainer将会等待至发现名称为tomcat的Service,判断成功后,退出初始化容器,然后nginx这个Pod就运行成功了。

当然,我们可以为一个 Pod 指定了多个InitContainer,这些容器会按顺序逐个运行。 每个InitContainer必须运行成功,下一个才能够运行。当所有的InitContainer运行完成时, Kubernetes才会为Pod 初始化应用容器,然后运行起来。配置大体如下: 

spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:   # Init容器将会等待至发现名称为 mydb 和 myservice 的 Service
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]