Kubernetes实战(九)-初始化容器(Init Container)

Kubernetes 1.3版本引入了 Alpha 版本的新特性 init container(初始化容器,在Kubernetes 1.5时被更新为 Bate 版本)用于在启动应用容器(app container)之前启动一个或多个初始化容器,init container 与应用容器本质上是一样的,但他们是仅运行一次就结束的任务,并且必须在成功执行完后,系统才能继续执行下一个容器。

在很多应用场景中,应用在启动之前都需要进行如下初始化操作。

  • 等待其他量关联组件正确运行(例如数据库或某个后台服务)
  • 基于环境变量或配置模板生成配置文件
  • 从远程数据库获取本地所需配置,或者将吱声注册到某个中央数据库中
  • 下载相关依赖包,或者对系统进行一些预配置操作

下面以 Nginx 应用为例,在启动 Nginx 之前,通过初始化容器 busybox 为 Nginx 创建一个 index.html 主页文件。这里为 init container 和 Nginx 设置一个共享的 Volume,init.yaml 代码如下:

apiVersion: v1
kind: Pod
metadata:
  name: init-demo
  labels:
    app: init
spec:
  initContainers:
    - name: init
      image: busybox
      command:
      - wget
      - "-O"
      - "/init-dir/index.html"
      - http://kubernetes.io
      volumeMounts:
        - name: initdir
          mountPath: "/init-dir"
  containers:
    - name: nginx
      image: nginx
      ports:
      - containerPort: 80
      volumeMounts:
        - name: initdir
          mountPath: /usr/share/nginx/html
  volumes:
    - name: initdir
      emptyDir: {}

创建这个 Pod:

[root@master yaml]# kubectl apply -f init.yaml
pod/init-demo created

在运行 init container 的听过程中查看 Pod 的状态,可见 init 过程还未完成: 

[root@master yaml]# kubectl get po
NAME        READY   STATUS     RESTARTS   AGE
init-demo   0/1     Init:0/1   0          5s

在 init container 成功执行完成后,系统继续启动 Nginx 容器,再次查看 Pod 的状态:

[root@master yaml]# kubectl get po
NAME        READY   STATUS    RESTARTS   AGE
init-demo   1/1     Running   0          21s

查看 Pod 的事件,可以看到系统首先创建并运行 init container 容器,成功后继续创建和运行 Nginx 容器:

[root@master ~]# kubectl describe po init-demo
Name:               init-demo
Namespace:          pulsar
Priority:           0
PriorityClassName:  
Node:               tengine2test/10.12.1.222
Start Time:         Sat, 11 Jul 2020 16:03:08 +0800
Labels:             app=init
Annotations:        kubectl.kubernetes.io/last-applied-configuration:
                      {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"app":"init"},"name":"init-demo","namespace":"pulsar"},"spec":{"con...
Status:             Running
IP:                 10.33.0.7
Init Containers:
  init:
    Container ID:  docker://84db647286a417cf8749bff62b811a6df2871d2976f98117b36ee6556f385d77
    Image:         busybox
    Image ID:      docker-pullable://busybox@sha256:9ddee63a712cea977267342e8750ecbc60d3aab25f04ceacfa795e6fce341793
    Port:          
    Host Port:     
    Command:
      wget
      -O
      /init-dir/index.html
      http://kubernetes.io
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Sat, 11 Jul 2020 16:03:17 +0800
      Finished:     Sat, 11 Jul 2020 16:03:29 +0800
    Ready:          True
    Restart Count:  0
    Environment:    
    Mounts:
      /init-dir from initdir (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-nhp9x (ro)
Containers:
  nginx:
    Container ID:   docker://6641a1e669ee7a7bdeac56ba902e3274586b57d04b238494cae50012b9f7db8b
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:a93c8a0b0974c967aebe868a186e5c205f4d3bcb5423a56559f2f9599074bbcd
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Sat, 11 Jul 2020 16:03:45 +0800
    Ready:          True
    Restart Count:  0
    Environment:    
    Mounts:
      /usr/share/nginx/html from initdir (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-nhp9x (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  initdir:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:     
    SizeLimit:  
  default-token-nhp9x:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-nhp9x
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age   From                   Message
  ----    ------     ----  ----                   -------
  Normal  Scheduled  59s   default-scheduler      Successfully assigned pulsar/init-demo to tengine2test
  Normal  Pulling    44s   kubelet, tengine2test  Pulling image "busybox"
  Normal  Pulled     37s   kubelet, tengine2test  Successfully pulled image "busybox"
  Normal  Created    37s   kubelet, tengine2test  Created container init
  Normal  Started    37s   kubelet, tengine2test  Started container init
  Normal  Pulling    23s   kubelet, tengine2test  Pulling image "nginx"
  Normal  Pulled     10s   kubelet, tengine2test  Successfully pulled image "nginx"
  Normal  Created    10s   kubelet, tengine2test  Created container nginx
  Normal  Started    9s    kubelet, tengine2test  Started container nginx

启动成功后,登录进 Nginx 容器,可以看到 /usr/share/nginx/html 目录下的 index.html 文件:

[root@master ~]# kubectl exec -it init-demo /bin/bash
root@init-demo:/usr/share/nginx/html# ls /usr/share/nginx/html 
index.html

init container与应用容器的区别

1)运行方式不同,它们必须先于应用容器执行完成,当设置了多个init container时,将按顺序逐
个运行,当所有init container都成功运行后,kubernetes才会初始化Pod的各种信息。

2)在init container的定义中也可以设置资源限制,volume的使用和安全策略,但与应用容器略有不同

3)init container不能设置readinessProbe探针,因为必须在它们成功运行后才能继续运行Pod中定义的普通容器

4)在Pod重新启动时,init container将会重新运行

官方文档还给出了使用其他命令的方式:

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']

到此初始化容器(Init Container)介绍完成。

你可能感兴趣的:(Kubernetes实战,Kubernetes,kubernetes)