Init Container

Init Container的應用場景

當我們在運用一個服務之前,通常會做一些初始化的工作,而這些工作一般只需要運行一次,成功後就不再運行。爲此kubernetes 引入了Init Container,用於在啓動應用容器之前啓動一個或多個“初始化”容器,完成應用容器的所需的預製條件。

Init Containers與常規的容器非常類似,但是它一些獨有的特徵:

  • 他們僅運行一次,成功後就會退出。
  • 每個容器必須在成功執行完成後,系統才能繼續執行下一個容器。
  • 如果Init Container運行失敗,kubernetes 將會重複重啓Pod,直到Init Container 成功運行,但是如果 Pod的重啓策略(restartPolicy)設置爲Never,則Pod不會重啓。
  • Init Container支持普通應用Container的所有參數,包括資源限制,掛載卷,安全設置等。但是Init Container 在資源的申請和限制上略有不同,同時,由於Init Container必須在Pod ready之前完成並退出,所以它不支持 readiness 探針。

Init Container 通常有如下應用方式:

  • 處於安全的考慮,可以將自定義的代碼和工具使用Init Container運行,而不必添加到 應用 容器的鏡像中。
  • 應用程序映像的構建和部署者角色可以彼此獨立,無需共同構建單個應用程序映像
  • 使用不同的Linux命名空間,可以使它們具有來自應用容器的不同文件系統權限。 因此,Init Container可以獲得應用程序容器無法訪問的Secrets。
  • Init Container在任何應用程序容器啓動之前運行完畢,而應用程序容器通常是並行運行的,因此初始容器提供了一種簡單的方法來阻止或延遲應用程序容器的啓動,直到滿足一些前提條件。

具體的應用場景示例:

  • 如使用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容器啓動前更改默認起始頁面內容:

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重啓場景如下:

  • init container的鏡像被更新時, init Container將會重新運行,導致Pod重啓。僅更新應用容器的鏡像,只會使得應用容器被重啓。
  • Pod的 pause鏡像更新時, Pod將會重啓。
  • 若Pod 中的所有應用容器都終止了,並且restartPolicy=always, 則Pod將會重啓。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章