简介
在kubernetes中,容器hooks旨在解决服务进程启动与停止时的一些优雅操作需求。比如说进程停止时要给进程一个清理数据的时间,保证服务的请求正常结束,而不是强行中断服务的运行,这样在生产环境中可能会造成不优雅的结果。
截止kubernetes v1.20版本,实现了PostStart
和PreStop
两种容器hooks。
如果hooks执行失败,容器将会被kill。
容器hooks由kubelet组件管理并启动执行。
名词解释
hook 钩子,软件行业中指程序中在某一个地方定义的预留接口,而接口的实现可以后续指定。
容器Hooks介绍
-
PostStart
PostStart hook在容器启动的时候运行,但并不保证该hook一定会比容器指定的ENTRYPOINT命令先运行。就是说PostStart和ENTRYPOINT都会在容器启动后运行,至于谁先运行,谁先结束,并不一定,是随机的。如果容器启动的时候,PostStart没有成功,容器不会处于running状态。 -
PreStop
PreStop会在kubelet给Pod发送TERM信号之前执行。一般API Server会给kubelet发送结束Pod的信号,或者Pod的liveness/startup探针失败,或其它原因导致Pod失败,kubelet会尝试发送TERM信号给Pod里主进程。如果PreStop存在,kubelet则会优先启动PreStop,待PreStop结束之后再发送TERM信号给Pod。但从API Server将Pod标记为Terminating状态开始,整个Pod停止时间不能超过terminationGracePeriodSeconds所设置的时间,如果超过,kubelet需要发送KILL信号给Pod所有的进程。
举例:
如果一个Pod设置terminationGracePeriodSeconds=60,PreStop执行需要55s,服务进程停止需要10s。API Server首先将需要停止的Pod标记为Terminating状态,并且开始计算terminationGracePeriodSeconds时间。kubelet开始启动PreStop,等待55s后执行完毕,kubelet给Pod的主进程发送TERM信号,这时主进程开始清理退出,5s之后,terminationGracePeriodSeconds时间到达,kubelet将发送KILL信号给Pod所有进程,强制停止。这一通操作之后,发现主服务进程没有清理完毕就被强制停止了。面对这种情况,我们需要增加terminationGracePeriodSeconds=65。
Hooks类型
Exec 指定一个可执行命令或脚本,在容器内执行
HTTP 发送一个http请求给容器,由kubelet发送请求
Hooks执行的次数
hook至少会调用一次,意思说如果有多个触发事件,hooks可能会被调用多次。
一般情况下hooks只会调用一次,只在很少的异常时候才会调用多次。比如在Pod停止的过程中kubelet被重启,重启后的kubelet会再次发送hooks调用。
Debug Hooks
PostStart执行失败时会记录FailedPostStartHook
事件,PreStop执行失败时会记录FailedPreStopHook
事件。可以通过kubectl describe pod <pod_name>
查看。
容器Hooks配置示例
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","nginx -s quit; while killall -0 nginx; do sleep 1; done"]
参考资源
https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination
https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/