一、postStart 和 preStop 分别解决什么问题¶
Kubernetes 为容器提供了两个非常实用的生命周期钩子:
postStart:容器启动后立刻触发preStop:容器终止前触发
常见用途包括:
- 启动后写入标记文件、注册状态、预热资源
- 终止前先摘流量、通知服务下线、等待连接处理完成
示例:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: lifecycle-demo-container
image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
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"]
二、postStart 有什么容易误解的地方¶
postStart 虽然名字像“启动后再执行”,但它并不意味着一定严格晚于主进程所有启动动作完成。尤其当容器本身也有启动命令时,两者更接近并行触发,而不是绝对先后顺序。
所以,如果你的需求是“必须在主容器真正启动前先完成某一步准备工作”,更合适的做法通常不是 postStart,而是 initContainer。
三、如何验证 postStart 生效了¶
创建 Pod 后:
kubectl create -f nginx.yml
kubectl get po nginx
进入容器查看:
kubectl exec -it nginx -- cat /usr/share/message
如果输出:
Hello from the postStart handler
就说明钩子已经按预期执行。
四、preStop 在 Kubernetes 1.30 前后有什么变化¶
在较早版本里,常见写法是:
preStop:
exec:
command: ["sleep", "60"]
而在较新版本中,preStop 增加了更直接的 sleep 写法:
preStop:
sleep:
seconds: 60
这类变化的本质,是让优雅终止配置更直观,也更容易表达“给服务留出缓冲时间”这件事。
五、零宕机发布最关键的不是滚动更新本身,而是配套细节¶
很多人以为只要用了 RollingUpdate 就天然零宕机,其实不够。
一个更稳妥的基础配置通常是:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
但这只是第一步。真正决定能不能平滑切流的,还包括探针和优雅终止。
六、探针要怎么配,才更适合生产发布¶
一个比较实用的思路是:
1. 就绪探针必须有¶
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
它直接决定了新 Pod 什么时候能接流量,也是旧 Pod 下线前流量能否及时摘除的关键。
2. 存活探针按需配¶
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 15
它更偏向故障恢复,而不是流量切换。
3. 慢启动应用加 startupProbe¶
startupProbe:
httpGet:
path: /health/started
port: 8080
failureThreshold: 30
periodSeconds: 5
它能避免应用初始化还没结束,就被过早判定失败。
七、优雅终止为什么经常决定零宕机是否成立¶
如果 Pod 收到终止信号后直接退出,往往会出现这些问题:
- 长连接被硬切断
- 注册中心里还没摘除实例
- 请求已经进来但还没处理完
因此常见做法是,在 preStop 里先执行下线逻辑,例如:
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- "pkill java; sleep 30"
对像 Nacos 这类注册中心或需要优雅下线的服务,这种做法尤其重要。
八、gRPC 服务怎么做健康检查¶
从 Kubernetes 1.24 起,gRPC 探针逐渐进入更常见的使用场景。
如果你的服务本身就是 gRPC,可以直接使用:
apiVersion: v1
kind: Pod
metadata:
name: etcd
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.1-0
name: etcd
command:
- /usr/local/bin/etcd
- --data-dir
- /var/lib/etcd
- --listen-client-urls
- http://0.0.0.0:2379
- --advertise-client-urls
- http://127.0.0.1:2379
- --log-level
- debug
ports:
- containerPort: 2379
livenessProbe:
grpc:
port: 2379
initialDelaySeconds: 10
创建后查看:
kubectl create -f grpc.yml
kubectl get po etcd
这类探针的前提,是应用实现了标准的 gRPC 健康检查接口。
九、这一篇最值得记住的发布思路¶
如果把优雅终止和零宕机发布压缩成一套简单方法论,可以记成:
- 用滚动更新控制替换节奏
- 用
readinessProbe控制何时接流量 - 用
startupProbe保护慢启动阶段 - 用
preStop给下线留缓冲 - 对 gRPC 服务使用原生 gRPC 探针
真正稳定的发布,从来不是“换 Pod 很快”,而是“新实例准备好之后再接流量,旧实例摘流量后再退出”。