生产安全与故障排查基石:Kubernetes Pod 创建与删除完整生命周期深度剖析

在企业级 Kubernetes 容器平台的日常运维中,Pod 的“生老病死”是最频繁发生的事件。不管是执行一次平滑的业务滚动更新,还是应对突发的节点故障,Pod 的创建和删除都在底层频繁运行。

对于运维团队而言,仅仅知道 kubectl applydelete 是远远不够的。当遇到 Pod 卡在 Pending、Terminating、或者发布过程中业务出现短暂的 502/504 报错时,只有深刻理解 Pod 的完整创建与删除流程,才能快速定位并解决生产问题。

本文将以声明式管理(Deployment 控制器)为例,站在企业运维与稳定性保障的角度,详细拆解 Pod 在 K8s 内部的完整生命周期流转。


一、 声明式架构下:Pod 创建的完整流程

当我们提交一个 Deployment 的 YAML 声明文件时(例如:期望副本数为 3),K8s 内部多个组件会通过事件监听(List-Watch)机制协同工作。以下是完整的创建步骤:

+-------------------+      1. Apply YAML      +------------------+
|   Client (CI/CD)  | ----------------------> |    API Server    |
+-------------------+                         +------------------+
                                                       |
                                                       | 2. Write to ETCD
                                                       v
+-------------------+      4. Create Pod      +------------------+
|  Controller Mgr   | <---------------------- |     ETCD 数据库  |
+-------------------+                         +------------------+
          |
          | 5. Unassigned Pods (Watch)
          v
+-------------------+      6. Bind Node       +------------------+
|   Kube-Scheduler  | ----------------------> |    API Server    |
+-------------------+                         +------------------+
                                                       |
                                                       | 7. Watch Assigned Pod
                                                       v
                                              +------------------+
                                              |  Kubelet (Node)  |
                                              +------------------+
                                                       |
                                                       | 8. CRI / CNI / CSI
                                                       v
                                              +------------------+
                                              |  Container Run   |
                                              +------------------+

1. 客户端请求与准入控制 (API Server)

  • 步骤:运维人员或 CI/CD 系统执行 kubectl apply -f deployment.yaml
  • 内核机制:请求到达 kube-apiserver,它会进行以下三步合规性检查:
    1. Authentication & Authorization:验证用户身份与 RBAC 权限。
    2. Mutating Webhook:执行变更准入控制(例如:企业安全策略自动注入 Sidecar、初始化容器或默认标签)。
    3. Schema Validation & Validating Webhook:校验 YAML 格式合法性,以及是否违反企业安全基线(例如:限制不能以特权模式运行)。
  • 写入存储:验证通过后,API Server 将 Deployment 对象写入 ETCD

2. 控制器协同工作生成 Pod 模板 (Controller Manager)

  • 步骤kube-controller-manager 中的 Deployment Controller 监听到新 Deployment 的创建事件。
  • 执行动作
    1. Deployment Controller 对比期望状态,创建一个 ReplicaSet(RS) 对象并写入 ETCD。
    2. ReplicaSet Controller 监听到新 RS 的创建,发现当前的 Pod 数量(0)不满足期望数量(3)。
    3. RS Controller 循环创建 3 个 Pod 资源对象。此时,这些 Pod 对象的 spec.nodeName 为空(处于未调度状态),写入 ETCD。

3. 智能调度与决策 (Kube-Scheduler)

  • 步骤kube-scheduler 始终在监听(Watch)nodeName 为空的 Pod。
  • 执行动作
    1. 预选阶段(Filtering):过滤掉不满足条件的节点(例如:CPU/内存资源不足、节点有污点 Taint、端口冲突等)。
    2. 优选阶段(Scoring):对通过预选的节点进行打分(考虑亲和性 Affinity、镜像是否已存在、节点负载情况等)。
    3. 绑定(Binding):选择得分最高的节点,向 API Server 发起一个 Binding 请求,将该节点的名称写入 Pod 的 spec.nodeName 字段,写入 ETCD。

4. 节点本地构建 (Kubelet & 容器运行时)

  • 步骤:目标节点上的 kubelet 监听到有 Pod 被调度到了自己所在的节点。
  • 执行动作
    1. 挂载卷(CSI 介入):Kubelet 调用 CSI 插件,执行卷挂载(Attach/Mount),准备好容器所需的数据存储卷。
    2. 网络初始化(CNI 介入):Kubelet 通过 CRI 调用容器运行时(如 containerd),首先拉起 Pause 容器(基础设施容器),并调用 CNI 网络插件(如 Calico, Flannel)为 Pod 分配 IP 地址、配置网卡。
    3. 拉取镜像与启动容器(CRI 递交):CRI 下载业务镜像,先启动初始化容器(Init Container),成功后再启动主业务容器。
    4. 健康检查(Probes):如果配置了 StartupProbe(启动探针)和 LivenessProbe / ReadinessProbe(存活/就绪探针),Kubelet 开始执行探测。
    5. 反馈状态:Kubelet 将 Pod 的状态(Running、IP 等信息)更新回 API Server,存入 ETCD。

二、 生产平滑发布关键:Pod 删除的完整流程

对于运维而言,Pod 的删除流程比创建流程更为关键。不合理的删除配置是导致发布过程中出现用户访问 502/504 报错的主要原因。K8s 删除 Pod 采用的是双轨异步并行机制

                           +------------------------+
                           |  kubectl delete pod    |
                           +------------------------+
                                       |
                                       v
                           +------------------------+
                           | API Server Mark:       |
                           | Terminating (Graceful) |
                           +------------------------+
                                       |
                   +-------------------+-------------------+
                   | (异步轨道 A)                          | (异步轨道 B)
                   v                                       v
       +-----------------------+               +-----------------------+
       |  Endpoint Controller  |               |    Kubelet on Node    |
       +-----------------------+               +-----------------------+
                   |                                       |
                   v                                       v
       +-----------------------+               +-----------------------+
       | 移出 EndpointSlice,   |               | 执行 PreStop Hook     |
       | 阻断新流量进入         |               | (企业平滑发布关键)    |
       +-----------------------+               +-----------------------+
                   |                                       |
                   v                                       v
       +-----------------------+               +-----------------------+
       | kube-proxy / CoreDNS  |               | 发送 SIGTERM 信号     |
       | 刷新转发规则 (iptables)|               | 等待业务处理存量连接   |
       +-----------------------+               +-----------------------+
                   |                                       |
                   |                                       v
                   |                           +-----------------------+
                   |                           | 达到 GracePeriod      |
                   |                           | 发送 SIGKILL (强制)   |
                   |                           +-----------------------+
                   |                                       |
                   |                                       v
                   |                           +-----------------------+
                   |                           | CNI 释放 IP,          |
                   |                           | CSI 卸载卷             |
                   |                           +-----------------------+
                   |                                       |
                   +-------------------+-------------------+
                                       |
                                       v
                           +------------------------+
                           |  ETCD 清除 Pod 记录    |
                           +------------------------+

1. 触发删除与状态标记

  • 步骤:运维执行缩容或更新,ReplicaSet 发起删除 Pod 请求(或直接 kubectl delete pod)。
  • 执行动作:API Server 收到请求,并不立即物理删除该 Pod,而是执行以下操作:
    1. 设置 Pod 的 metadata.deletionTimestamp(删除时间戳)。
    2. 将 Pod 状态标记为 Terminating
    3. 设定一个宽限期 deletionGracePeriodSeconds(默认 30 秒)。

⚠️ 注意:以下两条轨道是【异步并行】执行的

2. 轨道 A:网络路由下线(控制流)

该轨道的目的是确保没有新的用户流量再流入该 Pod

  1. Endpoint Controller 监听到 Pod 处于 Terminating 状态。
  2. 控制器将该 Pod 的 IP 从对应的 EndpointsEndpointSlice 对象中移除。
  3. kube-proxy 监听到 Endpoint 变更,开始刷新各节点上的 iptablesIPVS 路由规则,不再向该 Pod 转发新流量。
  4. CoreDNS 停止将服务域名解析到该 Pod 的 IP。

3. 轨道 B:节点容器平滑停机(工作流)

该轨道的目的是给容器足够的时间处理完手里积压的历史存量请求

  1. 执行 PreStop 钩子:Kubelet 监听到 Pod 处于 Terminating。如果 Pod 中配置了 lifecycle.preStop 钩子,Kubelet 会优先在容器内执行该命令或向其发送特定的 HTTP 请求(例如:通知注册中心下线、执行优雅停机脚本)。
  2. 发送 SIGTERM 信号:PreStop 执行完毕后(或者没有配置),Kubelet 向容器内的 PID 1 进程发送 SIGTERM(信号 15),通知应用程序准备退出。
  3. 等待与优雅期限(Grace Period)
    • 应用程序在收到 SIGTERM 后,应当停止接收新请求,处理完手头已建立连接的存量请求,然后主动退出。
    • Kubelet 开始计时,等待时间为 deletionGracePeriodSeconds(默认 30 秒)。
  4. 强制终止(SIGKILL):如果宽限期结束,容器进程依然存活,Kubelet 会向其发送 SIGKILL(信号 9),强制终止容器进程。

4. 资源清理与物理销毁

  • 步骤:进程彻底退出后。
    1. Kubelet 调用 CNI 插件释放该 Pod 占用的 IP 地址。
    2. Kubelet 调用 CSI 插件卸载(Unmount/Detach)存储卷。
    3. Kubelet 向 API Server 发送请求,将 Pod 的 Finalizers 移除,API Server 从 ETCD 中彻底删除该 Pod 的所有元数据。

三、 企业运维实战:如何保障业务零宕机(Zero-Downtime)发布?

了解了上述生命周期,企业运维团队应该在实际部署中落实以下两个核心配置,以防发布过程中发生业务闪断:

1. 合理配置 preStop 钩子与 terminationGracePeriodSeconds

在许多企业应用中,特别是 Spring Boot 框架或 Nginx 服务,它们对 SIGTERM 的默认响应可能过于粗暴(直接断开连接),或者有些进程(如守护进程)根本不响应 SIGTERM

最佳实践配置示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: business-app
spec:
  replicas: 3
  template:
    spec:
      # 根据业务处理存量连接所需的最长时间合理设置宽限期(默认30秒可能不够)
      terminationGracePeriodSeconds: 60
      containers:
      - name: app
        image: enterprise-app:v1.0
        lifecycle:
          preStop:
            exec:
              command: 
              - /bin/sh
              - -c
              - |
                # 1. 优雅下线:主动在微服务注册中心注销自己
                curl -X POST http://localhost:8080/actuator/shutdown || true
                # 2. 睡眠等待:给 K8s 网络路由同步(轨道A)留出足够的时间(一般为10~15秒)
                # 确保在容器进程关闭前,所有外部路由已经切换完毕,不再有新流量进来
                sleep 15
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5

2. 为什么需要 preStop 中执行 sleep

网络规则刷新(轨道 A)和容器停止(轨道 B)是并行的
如果我们在收到 SIGTERM 时立即关闭容器进程,而此时 kube-proxy 还没有完全把 Pod 的 IP 从节点的 iptables 规则中剔除,就会导致这几秒内流入的外部用户请求遇到 502/Connection Refused 报错。
preStop 中注入 sleep 15,能够保证先切断新流量,等 15 秒路由规则完全同步后,再安全地关闭业务进程

posted on 2026-05-29 13:44  LeeHang  阅读(39)  评论(0)    收藏  举报