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事件的處理被正確執行。