0. 参考
- Kubernetes容器生命周期 —— 钩子函数详解(postStart、preStop) - 人艰不拆_zmc - 博客园
- 详解Kubernetes Pod优雅退出 - 人艰不拆_zmc - 博客园
1. Kubernetes 生命周期钩子概述
在 Kubernetes 中,生命周期钩子(Lifecycle Hooks) 是容器启动和终止时执行的自定义操作。它们允许你在容器的生命周期中插入“定制逻辑”,比如初始化、资源清理、通知外部系统等。
Kubernetes 为每个容器提供两个主要的生命周期钩子(hooks):
生命周期钩子 | 触发时机 | 作用示例 |
---|---|---|
postStart |
容器启动完成后立即 | 日志初始化、加载缓存、通知系统 |
preStop |
容器被终止前 | 优雅下线、关闭连接、清理资源等 |
2. 使用示例
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Container started at $(date) >> /var/log/start.log"]
preStop:
exec:
command: ["/bin/sh", "-c", "echo Shutting down >> /var/log/shutdown.log && sleep 10"]
3. 生命周期流程图(简化)
Pod 创建
└──> 容器启动
└──> postStart Hook
└──> 运行主进程
...
└──> SIGTERM (优雅终止)
└──> preStop Hook
└──> 容器停止
4. 应用场景举例
Hook 类型 | 应用场景 |
---|---|
postStart |
- 通知注册中心上线 - 初始化缓存 - 自定义日志记录 |
preStop |
- 通知下游服务断开连接 - 等待请求处理完毕 - 注销注册中心 |
5. 注意事项
- 两个钩子都 运行在容器内,使用
exec
。 postStart
会 阻塞容器运行(直到命令完成);若失败会导致容器崩溃。preStop
默认最多等待 30 秒(由terminationGracePeriodSeconds
控制)。- 不能保证 preStop 一定成功执行(例如容器被 kill -9)
6. 总结理解
生命周期钩子 = 容器级别的定制启动/退出脚本,用于插入优雅上线、下线、清理、注册、通知等逻辑,是构建高可用服务的重要工具之一。
7. 示例1
✅ 目标场景
当容器被终止时,执行以下步骤:
- 通知外部系统(通过 curl 发出“下线”请求)
- 等待 5 秒,让请求完成
- 再由 Kubernetes 终止容器
🧩 示例:使用 preStop
实现优雅下线
apiVersion: apps/v1
kind: Deployment
metadata:
name: graceful-shutdown-demo
spec:
replicas: 1
selector:
matchLabels:
app: graceful-demo
template:
metadata:
labels:
app: graceful-demo
spec:
terminationGracePeriodSeconds: 10 # 容器 SIGTERM 后有最多 10 秒来执行 preStop
containers:
- name: app
image: busybox
command: ["/bin/sh", "-c", "while true; do echo 'Running...'; sleep 5; done"]
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- |
echo "[preStop] Notifying external system..."
curl -X POST http://example.com/deregister -d 'pod=graceful-demo'
echo "[preStop] Waiting for in-flight requests to complete..."
sleep 5
🔍 关键点说明
字段/参数 | 含义 |
---|---|
preStop.exec.command |
容器内执行 shell 脚本,通知外部系统并等待 |
terminationGracePeriodSeconds |
容器被终止前最大等待时间(默认 30 秒) |
curl -X POST |
模拟通知外部系统(如服务注册中心) |
sleep 5 |
给上游时间处理关闭流程,确保不中断服务 |
8. 示例2
✅ 示例:包含 postStart
和 preStop
的容器
yaml
复制编辑
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
terminationGracePeriodSeconds: 15 # 为 preStop 提供充足时间
containers:
- name: demo-container
image: busybox
command: ["/bin/sh", "-c", "echo 'App running...'; sleep 3600"]
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- |
echo "[postStart] Initializing container..." >> /tmp/startup.log
date >> /tmp/startup.log
preStop:
exec:
command:
- /bin/sh
- -c
- |
echo "[preStop] Cleaning up before shutdown..." >> /tmp/shutdown.log
sleep 5 # 模拟等待资源释放或通知外部系统
🧠 解释每一部分
🔹 postStart
- 触发时机:容器启动完成后立即执行
- 作用:
- 可做初始化动作,如写日志、预热缓存、启动守护进程等
- 示例逻辑:
- 在
/tmp/startup.log
记录“启动”信息和时间戳
- 在
🔹 preStop
- 触发时机:容器收到终止信号(如删除 Pod 或更新镜像)前执行
- 作用:
- 用于优雅下线,如关闭连接、注销注册、等待请求处理完毕等
- 示例逻辑:
- 写一条“即将关闭”的日志
sleep 5
模拟清理或等待请求完成
⏱️ terminationGracePeriodSeconds
- 告诉 Kubelet:给容器最多
15s
时间完成preStop
- 若
preStop
没完成,时间一到仍会强制终止容器