前兩天在討論 pod 生命週期時,不斷有出現 preHook 的用法,今天就來看看吧!
PostStart
與 PreStop
兩種 hook 的使用方式https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/
在某些 APP 的開發框架中,會提供元件 lifecycle hooks (e.g. Angular),而 k8s 提供 container lifecycle hooks,這些 hooks 能夠讓 container 抓到生命週期的訊息,並且執行相對應的行為 (可以確保資源或所有連線被正常的釋放)。
有兩種 Hooks 可以配置:
PostStart
:當 container 被建立時執行,此 hook 並不保證會在 container 的 ENTRYPOINT 前執行PreStop
:當 container 被刪除時立即執行 (因 API 刪除 、 probe 失敗、搶佔等等原因導致的刪除)terminationGracePeriodSeconds
) 倒數會在執行 PreStop
hook 前進行,因此無論 PreStop
hook 的結果如何,時間到了就會被強制刪除要特別注意的是,僅有 “刪除” 的動作會觸發 Prestop Hook,若是 Pods 的狀態為 complete 的話則不會觸發。
與 Probe 的機制類似,hook 也可以指定要做的動作,有三種:
pre-stop.sh
)PodLifecycleSleepAction
feature gate.根據執行的動作不同,分成:
httpGet, tcpSocker, sleep
三個動作當 PostStart
或 PreStop
失敗時,會立刻刪除 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/