iT邦幫忙

2024 iThome 鐵人賽

0
Kubernetes

一起來看 Kubernetes 官方文件吧!系列 第 14

Day14 - 一起來看 Kubernetes 官方文件吧!- Container Lifecycle Hooks

  • 分享至 

  • xImage
  •  

前言

前兩天在討論 pod 生命週期時,不斷有出現 preHook 的用法,今天就來看看吧!

今日目標

  • 了解 Container Lifecycle Hooks
  • 測試看看 PostStartPreStop 兩種 hook 的使用方式

Container Lifecycle Hooks

https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/

在某些 APP 的開發框架中,會提供元件 lifecycle hooks (e.g. Angular),而 k8s 提供 container lifecycle hooks,這些 hooks 能夠讓 container 抓到生命週期的訊息,並且執行相對應的行為 (可以確保資源或所有連線被正常的釋放)。

Container hooks

有兩種 Hooks 可以配置:

  1. PostStart:當 container 被建立時執行,此 hook 並不保證會在 container 的 ENTRYPOINT 前執行
  2. PreStop:當 container 被刪除時立即執行 (因 API 刪除 、 probe 失敗、搶佔等等原因導致的刪除)
    此 hooks 必須在 TERM 訊號前完成, pods 的 grace period (terminationGracePeriodSeconds ) 倒數會在執行 PreStop hook 前進行,因此無論 PreStop hook 的結果如何,時間到了就會被強制刪除

要特別注意的是,僅有 “刪除” 的動作會觸發 Prestop Hook,若是 Pods 的狀態為 complete 的話則不會觸發。

Hook handler implementations

與 Probe 的機制類似,hook 也可以指定要做的動作,有三種:

  1. Exec:執行特定的指令,也可以在 container 內準備好腳本執行 (e.g. pre-stop.sh)
  2. HTTP:發送 http request 到 container 內的 endpoint
  3. Sleep:暫停 container 特定的時間。在目前此功能還處於 beta-level,需要開啟 PodLifecycleSleepAction feature gate.

Hook handler execution

根據執行的動作不同,分成:

  1. kubelet:負責 httpGet, tcpSocker, sleep 三個動作
  2. container:Exec 會在 container 內部執行

PostStartPreStop 失敗時,會立刻刪除 Container

在設計 hook 時,必續確保盡可能的清量,否則 PostStart 可能會導致 container 無法進入 running 狀態,而 PreStop 會導致 pods 被強制刪除

當 container 因為 hook 導致某種失敗時,是可以在 Events 內看到的:

Events:
  Type     Reason               Age              From               Message
  ----     ------               ----             ----               -------
  Normal   Scheduled            7s               default-scheduler  Successfully assigned default/lifecycle-demo to ip-XXX-XXX-XX-XX.us-east-2...
  Normal   Started              4s (x2 over 5s)  kubelet            Started container lifecycle-demo-container
  Warning  FailedPostStartHook  4s (x2 over 5s)  kubelet            Exec lifecycle hook ([badcommand]) for Container "lifecycle-demo-container" in Pod "lifecycle-demo_default(30229739-9651-4e5a-9a32-a8f1688862db)" failed - error: command 'badcommand' exited with 126: , message: "OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: \"badcommand\": executable file not found in $PATH: unknown\r\n"
  Normal   Killing              4s (x2 over 5s)  kubelet            FailedPostStartHook
  Normal   Pulled               4s               kubelet            Successfully pulled image "nginx" in 215.66395ms

測試

範例 yaml:把 command 改成任一找不到的檔案

# test.yaml
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: ["/bin/sh","-c","badcommand"]

可看到 preStop 的 exec.command 目前是被配置為 badcommand,而我們預期讓他執行失敗
儲存為 test.yaml 後,建立 pods 後,刪除觸發看看 preStop hook:

❯ k apply -f test.yaml
❯ k get -f test.yaml
NAME             READY   STATUS    RESTARTS   AGE
lifecycle-demo   1/1     Running   0          52s
❯ k delete -f test.yaml
pod "lifecycle-demo" deleted
❯ k get events
LAST SEEN   TYPE      REASON              OBJECT               MESSAGE
2m          Normal    Scheduled           pod/lifecycle-demo   Successfully assigned default/lifecycle-demo to k8s-master3
119s        Normal    Pulling             pod/lifecycle-demo   Pulling image "nginx"
117s        Normal    Pulled              pod/lifecycle-demo   Successfully pulled image "nginx" in 2.013s (2.013s including waiting). Image size: 71027698 bytes.
117s        Normal    Created             pod/lifecycle-demo   Created container lifecycle-demo-container
117s        Normal    Started             pod/lifecycle-demo   Started container lifecycle-demo-container
24s         Normal    Killing             pod/lifecycle-demo   Stopping container lifecycle-demo-container
**24s         Warning   FailedPreStopHook   pod/lifecycle-demo   PreStopHook failed**

可看到 events 裡面會顯示 PreStopHook failed (為 Warning),pods 也立刻就被刪除了

再把 postStart 也改掉:

...
      postStart:
        exec:
#          command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
          command: ["/bin/sh","-c","badcommand"]
...         
❯ k apply -f test.yaml
❯ k get -f test.yaml
NAME             READY   STATUS             RESTARTS      AGE
lifecycle-demo   0/1     CrashLoopBackOff   1 (11s ago)   17s
❯ k describe -f test.yaml
...
Events:
  Type     Reason               Age               From               Message
  ----     ------               ----              ----               -------
  Normal   Created              7s (x3 over 28s)  kubelet            Created container lifecycle-demo-container
  Normal   Started              7s (x3 over 28s)  kubelet            Started container lifecycle-demo-container
  Warning  FailedPostStartHook  7s (x3 over 28s)  kubelet            PostStartHook failed
❯ k get evenets

109s        Warning   FailedPostStartHook   pod/lifecycle-demo   PostStartHook failed
109s        Normal    Killing               pod/lifecycle-demo   FailedPostStartHook
109s        Warning   FailedPreStopHook     pod/lifecycle-demo   PreStopHook failed

PoststartHook 失敗可以透過 describe pods 去發現,也可以看到說當因為 PostStartHook 失敗時導致關閉 container 時,同時也會觸發 PreStopHook (然後也失敗了)

結論

透過配置兩種 Hooks 可以提高 APP 的穩固性,就可以設計出越來越好用的 APP 囉 ~

參考

https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/


上一篇
Day13 - 一起來看 Kubernetes 官方文件吧!- Pod lifecycle (下)
下一篇
Day15 - 一起來看 Kubernetes 官方文件吧!- Disruptions (干擾)
系列文
一起來看 Kubernetes 官方文件吧!19
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言