pod从开始创建到终止退出的时间范围称为Pod生命周期
pod生命周期
生命周期包含以下几个重要流程:
1 | 初始化容器(initContainers) |
pod在整个生命周期的过程中总会处于以下几个状态:
1 | Pending:创建了pod资源并存入etcd中,但尚未完成调度。 |
pod生命周期的重要行为
1 | 1、在启动任何容器之前,先创建pause基础容器,它初始化Pod的环境并为后续加⼊的容器提供共享的名称空间。 |
容器的重启策略
1 | 定义是否重启Pod对象 |
pod的终止过程终止过程主要分为如下几个步骤:
1 | (1)用户发出删除 pod 命令:kubectl delete pods ,kubectl delete -f yaml |
初始化容器(init)
1 | spec字段下有个initContainers字段(初始化容器),Init容器就是做初始化工作的容器。可以有一个或多个,如果多个按照定义的顺序依次执行,先执行初始化容器1,再执行初始化容器2等,等初始化容器执行完具体操作之后初始化容器就退出了,只有所有的初始化容器执行完后,主容器才启动。 |
初始化容器与主容器区别是
1 | 1、初始化容器不支持 Readinessprobe,因为它们必须在Pod就绪之前运行完成 |
初始化容器应用:
[root@pengfei-master1 pod]# cat init-1.yaml
1 | apiVersion: v1 |
创建pod并查看pod:
1 | [root@pengfei-master1 pod]# kubectl apply -f init-1.yaml |
测试pod
1 | [root@pengfei-master1 pod]# curl 10.244.225.88 |

1 | [root@pengfei-master1 pod]# kubectl exec -it init-busybox /bin/bash |
主容器
1 | 1、容器钩子 |
- postStart:该钩子在容器被创建后立刻执行,如果该钩子对应的探测执行失败,则该容器会被杀死,并根据该容器的重启策略决定是否要重启该容器,这个钩子不需要传递任何参数。
- preStop:该钩子在容器被删除前执行,主要用于释放资源和优雅关闭程序
容器钩子:postStart和preStop
postStart:容器创建之后立刻执行,用于资源部署、环境准备等。
preStop:在容器被终止前执行,用于优雅关闭应用程序、通知其他系统等
postStart和preStop用法
1 | ...... |
测试启动和停止钩子
1 | [root@pengfei-master1 pod]# cat >pre-start.yaml>>EOF |
查看pod
1 | [root@pengfei-master1 pod]# kubectl get pods -o wide |

优雅的删除资源对象
当用户请求删除含有pod的资源对象时(如RC、deployment等),K8S为了让应用程序优雅关闭(即让应用程序完成正在处理的请求后,再关闭软件),K8S提供两种信息通知:
1 | 1)默认:K8S通知node执行docker stop命令,docker会先向容器中PID为1的进程发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认超时时间(30s),会继续发送SIGKILL的系统信号强行kill掉进程。 |
总结:
pod在整个生命周期中有非常多的用户行为:
1 | 1、初始化容器完成初始化 |
实战:通过钩子优雅停机
背景
1 | 在 Kubernetes 中,每次微服务的代码发布都意味着创建新版本的 pod 并删除旧 pod,如果部署不够优雅的话,可能出现如下两个问题: |
- 正在处理请求的pod被删除,在请求没有做幂等处理的情况下,就会出现数据重复、数据错误,亦或导致分布式系统数据不一致;
- Kubernetes 将流量路由到已被删除的 pod,导致处理请求失败造成用户体验不佳。
所以,为了让代码发布的部署过程不影响业务的正常运行和用户无感知,我们需要实现容器的优雅停机。
容器的生命周期钩子
1 | 在介绍优雅停机之前,我们先来了解下k8s的容器都有哪些生命周期钩子?作用是什么?要怎么使用? |
Kubernetes的容器有两种生命周期钩子(Lifecycle Hooks):
PostStart
这个钩子会在容器被创建后立即执行,但无法保证会在容器的起始点 ENTRYPOINT之前执行,如果执行时间太长,将会阻止Pod状态进入running,可用于数据初始化、容器启动回调等场景。如果需要保证在应用程序启动前就要执行完的任务,可以考虑放在初始化容器( Init Containers)中去实现。
PreStop
这个钩子会在容器被结束前执行,执行期间Pod状态为 Terminating,运行时间受终止宽限期( terminationGracePeriodSeconds)约束,超出宽限期Pod将被强制杀死,可用于容器回收前的数据清理、优雅停机等场景。
1 | 上述的两个钩子(PostStart 和 PreStop)都有四种类型,分别为:exec、httpGet、tcpSocket 和 sleep。由于这四种钩子类型在 PostStart 和 PreStop 中的使用方法一致,下面以 PreStop 为例介绍这四种钩子类型的使用方法 |
- exec(执行shell指令,可以是指令或shell脚本, 退出状态码为 0则为成功)
1 | # shell指令模式 |
- httpGet(执行http get请求,响应状态码在[200,400)区间则为成功
1 | lifecycle: |
- tcpSocket(执行tcp socket请求, TCP连接成功建立则为成功)
1 | lifecycle: |
- sleep(将容器暂停5秒,Kubernetes 1.30的新特性 PodLifecycleSleepAction,待验证)
1 | lifecycle: |
请注意,如果 PostStart 或 PreStop 回调失败,容器将被杀死,所以回调处理的程序应尽量轻量级及把控好执行的时间。
微服务优雅停机实现
1 | 本次将以k8s + SpringBoot + Nacos作为案例,介绍在实际业务场景中如何实现微服务的优雅停机,从而实现代码发布时的零宕机。 |
- 首先,先看看pod的默认删除过程:
1 | 1. Kube-apiserver接收到pod的删除请求,在Etcd上更新pod的状态为Terminating; |

操作步骤
1 | 在SpringBoot > 2.3.0的版本后支持应用程序优雅停机,需要在java微服务的配置中设置如下两个属性,这一步很重要!!! |
- 在微服务的yaml文件加上优雅停机的配置:通过env定义POD_IP获取当前Pod的ip,传递给preStop进行nacos反注册。
1 | apiVersion: v1 |
至此,完成微服务的优雅停机配置。