在以往面试k8s问题的时候,经常被问的的三个问题,1.创建一个pod的完整生命周期;2.亲和性与反亲和性相关问题;3.如何优雅的关闭一个pod?
前面2个问题在之前的章节中已经有讲解,今天来针对第三个问题讲一下Pod Hook。
一、什么是Pod Hook?
Pod Hook 是 Kubernetes 为容器提供的生命周期钩子,由 kubelet 发起,用于在容器启动前或终止前执行特定操作。
核心作用:
-
环境初始化:如配置文件生成、资源预加载。
-
优雅终止:确保应用处理完现有请求后再关闭,避免数据丢失或服务中断。
二、两种钩子类型与执行机制
1. PostStart(容器启动后钩子)
- 触发时机:容器创建后立即执行,但并不一定是在容器入口命令(ENTRYPOINT)之前运行。
- 典型用途:
- 生成配置文件(例如可以写入初始化信息到
/usr/share/message,或者加载一些环境变量
)。 - 资源预加载或服务注册。
- 生成配置文件(例如可以写入初始化信息到
- 风险:若执行时间过长,可能导致容器无法进入
Running
状态。
2. PreStop(容器终止前钩子)
- 触发时机:容器终止前同步执行,阻塞删除操作直到钩子完成。
- 典型用途:
- 优雅关闭服务(如向 Nginx 发送
quit
信号)。 - 通知注册中心下线服务,避免流量损失。
- 优雅关闭服务(如向 Nginx 发送
- 风险:若钩子卡死,Pod 将停留在
Running
状态。
三、钩子的实现方式
1. Exec 命令
在容器内执行自定义命令,资源消耗计入容器配额。
示例:
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo 'Initialized' > /tmp/status"]
preStop:
exec:
command: ["/usr/sbin/nginx", "-s", "quit"] # 优雅关闭 Nginx
2. HTTP 请求
向容器内特定端点发送 HTTP 请求。
示例:
lifecycle:
postStart:
httpGet:
path: /health
port: 8080
scheme: HTTP
3. TCPSocket 探测
检查指定端口的可访问性。
示例:
lifecycle:
postStart:
tcpSocket:
port: 8080
四、配置示例与最佳实践
场景1:初始化配置文件
以下示例中,定义了一个Nginx Pod,并且设置了PostStart
钩子函数,在容器创建成功后,写入"PostStart Hook" 到/usr/share/message
文件中
apiVersion: v1
kind: Pod
metadata:
name: hook-demo
spec:
containers:
- name: app
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo 'PostStart Hook' > /usr/share/message"]
说明:容器启动后立刻向 /usr/share/message
写入初始化信息,甚至在nginx启动之前。在配置一些环境变量的时候常常用到。
验证:
① 应用这个yaml文件
② 进入容器内部
③ 查看是否输出了设置的内容
场景2:优雅终止 NGINX 应用
apiVersion: apps/v1
kind: Deployment
metadata:
name: prestop-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
terminationGracePeriodSeconds: 60 # 优雅终止超时时间(默认30秒)
containers:
- name: nginx
image: m.daocloud.io/docker.io/nginx
ports:
- containerPort: 80
lifecycle:
preStop: # 终止前钩子
exec:
command:
- "/bin/sh"
- "-c"
- "nginx -s quit && sleep 20" # 发送停止信号并等待处理完成
说明:在退出pod之前,会向pod内部发送shell命令,关闭nginx并等待20S,等待进程完全退出。这种在更新对外提供服务的的pod时候,十分必要,可以避免用户感知到连接突然中断。从而优雅的关闭这个pod。
五、典型应用场景
场景 | 钩子类型 | 操作 | 目的 |
---|---|---|---|
服务注册 | PostStart | 调用注册中心 API | 确保服务上线后及时接收流量 |
数据库连接池预热 | PostStart | 执行初始化 SQL 脚本 | 减少冷启动延迟 |
流量摘除 | PreStop | 通知负载均衡器下线节点 | 避免请求分发到终止中的 Pod |
状态保存 | PreStop | 将内存数据持久化到磁盘 | 防止数据丢失 |