Kubernetes Pod生命周期深度解析
Pod从创建到销毁的完整过程被称为Pod生命周期。这个过程包含多个关键阶段:创建Pod对象、运行初始化容器、启动主容器、执行钩子函数、进行健康检查,以及最终的Pod终止。
Pod阶段状态
在整个生命周期中,Pod会经历以下五种状态:
- Pending(挂起):Pod资源已在API Server中创建,但尚未完成调度或镜像下载
- Running(运行中):Pod已调度到某个节点,所有容器已被kubelet创建并启动
- Succeeded(成功):Pod内所有容器正常终止且不会被重启
- Failed(失败):容器终止,但至少有一个容器以非零退出码失败
- Unknown(未知):API Server无法获取Pod状态,通常由网络通信问题导致
Pod创建与终止流程
创建过程
- 用户通过kubectl或其他客户端向API Server提交Pod创建请求
- API Server生成Pod对象并将信息存储到etcd,返回确认给客户端
- API Server通过watch机制通知其他组件Pod变化
- Scheduler检测到新Pod,分配节点并更新API Server
- 目标节点上的kubelet发现Pod调度过来,启动容器并返回状态
- API Server将Pod状态写入etcd
终止过程
- 用户发送删除Pod请求到API Server
- API Server更新Pod信息,在宽限期(默认30秒)内将Pod标记为Dead
- Pod状态变为Terminating
- kubelet监控到Terminating状态,启动关闭流程
- 节点控制器将Pod从匹配的Service端点列表中移除
- 如果定义了preStop钩子,则同步执行
- 容器进程收到停止信号(SIGTERM)
- 宽限期结束后,仍在运行的进程收到SIGKILL信号
- kubelet将宽限期设为0,完成删除操作
初始化容器
初始化容器在主容器启动前运行,用于完成前置准备工作。它们具有两个核心特性:必须运行到成功完成,且按定义顺序串行执行。
常见应用场景包括:
- 提供主容器镜像中不包含的工具或代码
- 延迟主容器启动直到依赖条件满足
以下示例演示如何使用初始化容器确保MySQL和Redis服务可达后再启动Nginx:
apiVersion: v1
kind: Pod
metadata:
name: init-container-demo
namespace: dev
spec:
containers:
- name: nginx-main
image: nginx:1.17.1
ports:
- containerPort: 80
initContainers:
- name: check-mysql
image: busybox:1.30
command: ['sh', '-c', 'until ping 192.168.100.10 -c 1 ; do echo waiting for mysql...; sleep 2; done;']
- name: check-redis
image: busybox:1.30
command: ['sh', '-c', 'until ping 192.168.100.20 -c 1 ; do echo waiting for redis...; sleep 2; done;']
# 创建Pod
kubectl apply -f init-container-demo.yaml
# 查看状态
kubectl get pod init-container-demo -n dev -w
kubectl describe pod init-container-demo -n dev
在另一个终端中模拟添加网络接口:
ifconfig ens33:1 192.168.5.14 netmask 255.255.255.0 up
ifconfig ens33:2 192.168.5.15 netmask 255.255.255.0 up
钩子函数
Kubernetes在主容器生命周期中提供两个钩子:容器启动后(postStart)和容器终止前(preStop)。
钩子支持的动作类型
- Exec命令:在容器内执行命令
- TCPSocket:尝试访问容器的指定TCP端口
- HTTPGet:向容器的指定URL发起HTTP请求
以下示例使用Exec钩子在Nginx启动时修改首页,并在容器停止前优雅关闭服务:
apiVersion: v1
kind: Pod
metadata:
name: hook-exec-demo
namespace: dev
spec:
containers:
- name: nginx-main
image: nginx:1.17.1
ports:
- containerPort: 80
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo 'Pod started' > /usr/share/nginx/html/index.html"]
preStop:
exec:
command: ["/usr/sbin/nginx", "-s", "quit"]
钩子函数的定义位置在spec.containers.lifecycle下,每个容器都可以独立配置自己的钩子。