k8s中初始化容器(init container)的作用及其使用方法

一就是一發表於2022-01-11

概述

在容器的部署過程中,有的時候需要在容器執行之前進行一些預配置的工作,比如下載配置,判斷某些服務是否啟動,修改配置等一些準備的工作,想要實現這些功能,在k8s中可以使用初始化容器,在應用容器執行之前進行一些預處理的工作。

本文件介紹在k8s中初始化容器的使用方法。

使用方法

以下的例子使用初始化容器,在nginx容器啟動之前下載一個index.html檔案

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: initnginx
spec:
  initContainers:
  - name: install
    image: busybox
    command:
    - wget
    - "-O"
    - "/var/index.html"
    - "https://www.baidu.com"
  containers:
  - name: nginx
    image: 172.20.45.174:81/base/nginx:1.15-alpine
    ports:
    - containerPort: 80
  dnsPolicy: Default
EOF

檢視pod的狀態

[root@nccztsjb-node-11 ~]# kubectl get pod
NAME                          READY   STATUS     RESTARTS   AGE
cm-test-app                   1/1     Running    0          20h
cm-test-nginx                 1/1     Running    0          175m
cm-test-pod                   1/1     Running    0          20h
initnginx                     0/1     Init:0/1   0          16s  #在初始化階段
nginx-test-5c7f8fc697-lrvpm   1/1     Running    0          32d
nginx-test-5c7f8fc697-whx4g   1/1     Running    0          32d
web-0                         1/1     Running    0          32d
web-1                         1/1     Running    0          32d
web-2                         1/1     Running    0          32d

# 初始化容器執行完成後,pod狀態變為Running

[root@nccztsjb-node-11 ~]# kubectl get pod
NAME                          READY   STATUS    RESTARTS   AGE
cm-test-app                   1/1     Running   0          20h
cm-test-nginx                 1/1     Running   0          178m
cm-test-pod                   1/1     Running   0          20h
initnginx                     1/1     Running   0          9s
nginx-test-5c7f8fc697-lrvpm   1/1     Running   0          32d
nginx-test-5c7f8fc697-whx4g   1/1     Running   0          32d
web-0                         1/1     Running   0          32d
web-1                         1/1     Running   0          32d
web-2                         1/1     Running   0          32d
[root@nccztsjb-node-11 ~]# 

檢視初始化容器的日誌

[root@nccztsjb-node-11 ~]# kubectl logs initnginx -c install
Connecting to www.baidu.com (103.235.46.39:443)
wget: note: TLS certificate validation not implemented
saving to '/var/index.html'
index.html           100% |********************************|  2443  0:00:00 ETA
'/var/index.html' saved
[root@nccztsjb-node-11 ~]#

說明執行命令是成功的。

進入容器中,檢視是否存在該檔案

[root@nccztsjb-node-11 ~]# kubectl exec -it initnginx -- bash
[initnginx root:~]# cd /var/
[initnginx root:/var]# ls
cache  empty  git  lib  local  lock  log  opt  run  spool  tmp
[initnginx root:/var]# 

發現並沒有該檔案!

問題在於install容器和nginx容器不是同一個容器所以,下載的/var/index.html只是在install容器的/var目錄下。

為了實現nginx可以訪問初始化容器中的內容,可以掛載一個資料捲進行2個容器的共享,修改pod定義如下:

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: initnginx
spec:
  initContainers:
  - name: install
    image: busybox
    command:
    - wget
    - "-O"
    - "/work-dir/index.html"
    - "https://www.baidu.com"
    volumeMounts:
    - name: workdir
      mountPath: /work-dir
  containers:
  - name: nginx
    image: 172.20.45.174:81/base/nginx:1.15-alpine
    ports:
    - containerPort: 80
    volumeMounts:
    - name: workdir
      mountPath: /usr/share/nginx/html
  dnsPolicy: Default
  volumes:
  - name: workdir
    emptyDir: {}
EOF

這樣的化,2個容器中就都掛載了workdir這個資料卷,初始化容器中下載的檔案,就可以被nginx應用容器來使用了。

建立pod後檢視nginx容器中的檔案

[root@nccztsjb-node-11 ~]# kubectl exec -it initnginx -- bash
[initnginx root:~]# cd /usr/share/nginx/
[initnginx root:/usr/share/nginx]# ls
html
[initnginx root:/usr/share/nginx]# cd html/
[initnginx root:/usr/share/nginx/html]# ls
index.html
[initnginx root:/usr/share/nginx/html]# cat index.html 
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn" autofocus></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新聞</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地圖</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>視訊</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>貼吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登入</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登入</a>');
                </script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多產品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>關於百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/>使用百度前必讀</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意見反饋</a>&nbsp;京ICP證030173號&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
[initnginx root:/usr/share/nginx/html]# 

發現index.html檔案已經生成了,就是在初始化容器中建立的檔案被掛載到nginx中來使用。

檢視初始化容器的日誌

[root@nccztsjb-node-11 ~]# kubectl logs initnginx -c install
Connecting to www.baidu.com (103.235.46.39:443)
wget: note: TLS certificate validation not implemented
saving to '/work-dir/index.html'
index.html           100% |********************************|  2443  0:00:00 ETA
'/work-dir/index.html' saved
[root@nccztsjb-node-11 ~]# 

OK,通過日誌發現是向/work-dir/目錄中寫了index.html檔案。

以上就是初始化容器的基本的用法。

檢視pod的事件也可以看到pod中容器執行的順序

[root@nccztsjb-node-11 ~]# kubectl describe pod  initnginx
Name:         initnginx
Namespace:    default
Priority:     0
Node:         172.20.59.57/172.20.59.57
Start Time:   Tue, 11 Jan 2022 13:49:57 +0800
Labels:       <none>
Annotations:  cni.projectcalico.org/podIP: 172.23.29.31/32
              cni.projectcalico.org/podIPs: 172.23.29.31/32
Status:       Running
IP:           172.23.29.31
IPs:
  IP:  172.23.29.31
Init Containers:
  install:
    Container ID:  docker://9d2aec37255a02a2b13abced64717057eb100dd329bc6b6529211e30595f1c93
    Image:         busybox
    Image ID:      docker-pullable://busybox@sha256:5acba83a746c7608ed544dc1533b87c737a0b0fb730301639a0179f9344b1678
    Port:          <none>
    Host Port:     <none>
    Command:
      wget
      -O
      /work-dir/index.html
      https://www.baidu.com
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Tue, 11 Jan 2022 13:50:05 +0800
      Finished:     Tue, 11 Jan 2022 13:50:08 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-8ss8s (ro)
      /work-dir from workdir (rw)
Containers:
  nginx:
    Container ID:   docker://9f088e80c72e6691ea48bf3a9edf3983ccf8e8d32dd17e27425916efdfec4ff4
    Image:          172.20.45.174:81/base/nginx:1.15-alpine
    Image ID:       docker-pullable://172.20.45.174:81/base/nginx@sha256:478a73bcec93acc3e814ddd6fb2f95c6f6b4b0d0f168a4feaa039513d260a5d9
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Tue, 11 Jan 2022 13:50:08 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /usr/share/nginx/html from workdir (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-8ss8s (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  workdir:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:     
    SizeLimit:  <unset>
  default-token-8ss8s:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-8ss8s
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  6m27s  default-scheduler  Successfully assigned default/initnginx to 172.20.59.57
  Normal  Pulling    6m26s  kubelet            Pulling image "busybox"
  Normal  Pulled     6m20s  kubelet            Successfully pulled image "busybox" in 6.378365555s
  Normal  Created    6m20s  kubelet            Created container install
  Normal  Started    6m19s  kubelet            Started container install
  Normal  Pulled     6m16s  kubelet            Container image "172.20.45.174:81/base/nginx:1.15-alpine" already present on machine
  Normal  Created    6m16s  kubelet            Created container nginx
  Normal  Started    6m16s  kubelet            Started container nginx
[root@nccztsjb-node-11 ~]# 

即先建立初始化容器,執行結束後,才是執行nginx這個應用容器。

初始化容器使用的說明

關於初始化容器的使用,有幾點說明

  • 在pod中可以有一個或者多個初始化容器
  • 初始化容器執行成功後,應用的容器才能被執行
  • 初始化容器是僅執行一次的任務

相關文章