目录
引言
在Kubernetes中,Pod是最小的可部署计算单元,理解Pod的生命周期对于构建可靠、可维护的Kubernetes应用至关重要。本文将深入探讨Pod从创建到终止的完整生命周期,包括各个阶段的细节、核心机制以及相关的源码分析。
一、Pod生命周期的总体视图
首先,让我们通过一个图示来了解Pod生命周期的整体流程:

(注:此处应为Pod生命周期状态)
二、Pod生命周期的详细阶段
1. Pod创建阶段
当用户通过kubectl create或API Server提交Pod定义时,Pod的生命周期就开始了。这个阶段主要包括以下步骤:
// k8s.io/kubernetes/pkg/kubelet/kubelet.go
func (kl *Kubelet) syncPod(o syncPodOptions) error {
pod := o.pod
// 1. 检查Pod是否可以被运行
if !kl.canRunPod(pod) {
return fmt.Errorf("pod cannot be run")
}
// 2. 创建Pod的数据目录
if err := kl.makePodDataDirs(pod); err != nil {
return err
}
// 3. 拉取镜像
pullSecrets := kl.getPullSecretsForPod(pod)
if err := kl.pullImages(pod, pullSecrets); err != nil {
return err
}
// ... 后续容器创建流程
}
2. Pending状态
Pod被创建后首先进入Pending状态,此时Kubernetes正在:
- 调度Pod到合适的节点
- 下载容器镜像
- 分配资源
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
containers:
- name: nginx
image: nginx:1.14.2
status:
phase: Pending
conditions:
- type: PodScheduled
status: "True"
3. Running状态
当Pod被调度到节点且所有容器被创建后,进入Running状态:
// k8s.io/kubernetes/pkg/kubelet/status/status_manager.go
func (m *manager) SetPodStatus(pod *v1.Pod, status v1.PodStatus) {
// 更新Pod状态
oldStatus := pod.Status.DeepCopy()
pod.Status = status
// 如果所有容器都运行了,设置Phase为Running
if allContainersRunning(pod) {
pod.Status.Phase = v1.PodRunning
}
// 触发状态更新
m.updateStatusInternal(pod, oldStatus)
}
4. 就绪和存活探针
Pod运行期间,Kubelet会定期执行:
- Liveness Probe:确定容器是否需要重启
- Readiness Probe:确定容器是否准备好接收流量
apiVersion: v1
kind: Pod
metadata:
name: probe-demo
spec:
containers:
- name: liveness
image: k8s.gcr.io/liveness
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 3
periodSeconds: 3
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
5. 终止阶段
当Pod需要被删除时,它会进入终止流程:
(1)、收到删除请求,Pod进入"Terminating"状态
(2)、执行preStop钩子(如果配置)
(3)、发送SIGTERM信号给容器
(4)、等待优雅终止期(默认30秒)
(5)、发送SIGKILL强制终止
// k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container.go
func (m *kubeGenericRuntimeManager) killContainer(pod *v1.Pod, containerID kubecontainer.ContainerID, containerName string, message string, gracePeriodOverride *int64) error {
// 1. 执行preStop钩子
if podContainer, ok := podContainerMap[containerID]; ok {
if err := m.runPreStopHook(pod, podContainer, containerID); err != nil {
return err
}
}
// 2. 发送TERM信号
if err := m.runtimeService.StopContainer(containerID.ID, gracePeriod); err != nil {
return err
}
// 3. 等待后发送KILL信号
if err := m.runtimeService.StopContainer(containerID.ID, 0); err != nil {
return err
}
return nil
}
三、Pod生命周期的关键事件
在Pod生命周期中,Kubernetes会生成一系列事件来跟踪状态变化:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 15s default-scheduler Successfully assigned default/nginx to node-1
Normal Pulling 14s kubelet Pulling image "nginx:1.14.2"
Normal Pulled 13s kubelet Successfully pulled image "nginx:1.14.2"
Normal Created 12s kubelet Created container nginx
Normal Started 11s kubelet Started container nginx
Normal Killing 10s kubelet Stopping container nginx
四、容器重启策略
Pod的restartPolicy决定了容器退出时的行为:
- Always:总是重启(默认)
- OnFailure:仅在失败时重启
- Never:从不重启
apiVersion: v1
kind: Pod
metadata:
name: restart-policy-demo
spec:
containers:
- name: nginx
image: nginx
restartPolicy: OnFailure
五、深入理解Init容器
Init容器在主容器启动前运行,用于设置环境:
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
containers:
- name: nginx
image: nginx
initContainers:
- name: init-myservice
image: busybox
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
Init容器的执行流程:
(1)、按顺序执行所有Init容器
(2)、只有前一个Init容器成功完成后,才会执行下一个
(3)、所有Init容器完成后,启动主容器
六、Pod生命周期的Hook机制
Kubernetes提供了两种Hook来管理Pod生命周期:
- PostStart:容器创建后立即执行
- PreStop:容器终止前执行
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: nginx
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"]
七、源码分析:Pod状态
Kubernetes通过状态机管理Pod生命周期,核心逻辑在pkg/kubelet/kubelet_pods.go中:
func (kl *Kubelet) syncPod(o syncPodOptions) error {
pod := o.pod
podStatus := o.podStatus
// 检查Pod是否可以被运行
if !kl.canRunPod(pod) {
return fmt.Errorf("pod cannot be run")
}
// 处理Pod的初始化容器
if err := kl.initializePodInitContainers(pod, podStatus); err != nil {
return err
}
// 创建普通容器
if err := kl.initializePodContainers(pod, podStatus); err != nil {
return err
}
// 更新Pod状态
kl.statusManager.SetPodStatus(pod, podStatus)
return nil
}
八、最佳实践
(1)、合理设置资源请求和限制:避免因资源不足导致Pod无法调度
(2)、配置适当的探针:确保应用健康状态被正确监控
(3)、实现优雅终止:使用preStop钩子处理未完成请求
(4)、考虑使用Init容器:进行环境准备和数据预加载
(5)、监控Pod生命周期事件:及时发现和解决问题
结论
深入理解Pod生命周期对于构建可靠的Kubernetes应用至关重要。从Pod创建、运行到终止,每个阶段都有其特定的行为和可配置的选项。通过合理利用生命周期Hook、探针和重启策略,可以显著提高应用的可靠性和可维护性。 掌握这些底层机制不仅能帮助开发者更好地设计云原生应用,也能在出现问题时快速定位和解决Pod相关的故障。
1758

被折叠的 条评论
为什么被折叠?



