1. 程式人生 > >kubernetes之容器生命週期管理

kubernetes之容器生命週期管理

大多數程式語言框架都會提供元件生使週期管理鉤子,與此類似,kubernetes通過容器的生命週期鉤子管理容器。首先要為鉤子註冊處理控制代碼,當容器生命週期發生變化時,如建立、銷燬時,觸發為鉤子註冊的控制代碼的執行。

當前,kubernetes支援的鉤子有兩種:

PostStart

當容器被建立後,為這個鉤子註冊的處理控制代碼立刻執行,但是不保證鉤子的處理控制代碼在容器的ENTRYPOINT之前執行。無法向此鉤子的處理控制代碼傳遞引數。

PreStop

在容器被終止這之前執行,如果此操作沒有執行完成,那麼它會阻塞kubelet傳送刪除容器的操作。無法向此鉤子的處理控制代碼傳遞引數。

鉤子處理控制代碼的實現也有兩種方式:

Exec

容器內的命令、指令碼、及其它可執行程式。命令本身處於與視窗相同的namespace與cgroup之下,執行命令所點用的資源計入容器。

HTTP

向容器中的某個HTTP endpoint傳送請求,由誰傳送?文件裡沒有說。

鉤子處理例外

當容器生命週期的變化事件發生時,Kubernetes management system在容器內部執行註冊相應鉤子的處理控制代碼。對於PostStart型別的鉤子處理控制代碼,如果執行時間太長或者被掛起,則容器無法進入"running"狀態。如果PreStop型別的鉤子處理控制代碼在執行時被掛起,則容器一直停留在"Terminating"狀態,並且在"terminationGracePeriodSeconds"後容器被殺死。如果PostStart或者PreStop執行失敗,則容器直接被殺死。

使用者應該儘量使鉤子處理控制代碼執行的任務更輕,以免執行時間太長,使容器無法進入"running"狀態或者無法正常終止而被系統強制殺死。但是有時候,長時間的處理句兩是有意義的,比如在停止容器之前儲存狀態。

鉤子分發保證

系統趨向於當容器生命週期狀態發生變化時,為鉤子註冊的處理控制代碼只被呼叫一次,但在某些情況下,這個特性無法保證,也就是說鉤子的處理控制代碼可能會被呼叫多次,應該由鉤子處理控制代碼的具體實現保證對此種情況的正確處理。

除錯鉤子處理控制代碼

如果鉤子處理控制代碼執行失敗,通過如下命令檢視:

kubectl describe pod <pod_name>

結果:

Events:
  FirstSeen    LastSeen    Count    From                            SubobjectPath        Type        Reason        Message
  ---------    --------    -----    ----                            -------------        --------    ------        -------
  1m        1m        1    {default-scheduler }                                Normal        Scheduled    Successfully assigned test-1730497541-cq1d2 to gke-test-cluster-default-pool-a07e5d30-siqd
  1m        1m        1    {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}    spec.containers{main}    Normal        Pulling        pulling image "test:1.0"
  1m        1m        1    {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}    spec.containers{main}    Normal        Created        Created container with docker id 5c6a256a2567; Security:[seccomp=unconfined]
  1m        1m        1    {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}    spec.containers{main}    Normal        Pulled        Successfully pulled image "test:1.0"
  1m        1m        1    {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}    spec.containers{main}    Normal        Started        Started container with docker id 5c6a256a2567
  38s        38s        1    {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}    spec.containers{main}    Normal        Killing        Killing container with docker id 5c6a256a2567: PostStart handler: Error executing in Docker Container: 1
  37s        37s        1    {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}    spec.containers{main}    Normal        Killing        Killing container with docker id 8df9fdfd7054: PostStart handler: Error executing in Docker Container: 1
  38s        37s        2    {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}                Warning        FailedSync    Error syncing pod, skipping: failed to "StartContainer" for "main" with RunContainerError: "PostStart handler: Error executing in Docker Container: 1"
  1m         22s         2     {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}    spec.containers{main}    Warning        FailedPostStartHook

為容器生命週期事件提供處理控制代碼

假設有如下pod定義,其中包含一個容器,容器中包含對PostStart與PreStop容器生命週期事件的處理,如下:

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: nginx
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
      preStop:
        exec:
          command: ["/usr/sbin/nginx","-s","quit"]

從以上配置檔案可以看到,當發生PostStart事件時,向/usr/share/message檔案中寫入一句話。當發生PreStop時,執行一條命令,退出nginx。

建立pod:

kubectl create -f https://k8s.io/examples/pods/lifecycle-events.yaml

 確認pod執行狀態:

kubectl get pod lifecycle-demo

在視窗內執行shell:

kubectl exec -it lifecycle-demo -- /bin/bash

在容器內確認/usr/share/message檔案內容:

Hello from the postStart handler

 可以看到PostStart事件的處理被正確執行。