Kubernetes Pod 重启之谜:何时重启?何时静默?

为什么配置更新了,Pod 却毫无反应?


🤔 开篇:凌晨2点的困惑

你更新了 ConfigMap,期待应用自动加载新配置。然而,Pod 纹丝不动。

真相:90% 的工程师对"Pod 重启"存在误解。


📊 四种"重启",天壤之别

类型UID 变化IP 变化重启计数本质
容器重启+1同一 Pod 内进程重启
Pod 重建归零滚动更新、驱逐
CPU 原地扩容0cgroup 配额更新
内存原地扩容+1取决于策略

黄金法则:

kubectl get pod <pod> -o jsonpath='{.metadata.uid}'
# UID 变了 = Pod 重建
# UID 没变 = 容器重启

🧠 核心真相:kubelet 只监视 Pod Spec

# ❌ kubelet 不在乎:
- ConfigMap/Secret 内容变更
- Istio 路由规则
- NetworkPolicy

# ✅ 只有这些触发 kubelet:
- 容器镜像
- 环境变量
- 资源限制

决策矩阵:

  • 必须重建:镜像、命令、探针、资源限制
  • 应用决定:ConfigMap/Secret 卷挂载(文件自动更新,应用需热加载)
  • 无需重启:CPU 原地扩容、Istio 路由(xDS 推送)、NetworkPolicy
  • 手动触发:ConfigMap/Secret 环境变量注入

🎬 五大实战场景

场景 1:ConfigMap 的两种命运

环境变量模式(envFrom):

envFrom:
- configMapRef:
    name: my-config

结果:配置更新后,Pod 纹丝不动
原因:环境变量在进程启动时复制,无法动态修改

卷挂载模式(Volume Mount):

volumeMounts:
- name: config
  mountPath: /etc/config
volumes:
- name: config
  configMap:
    name: my-config

结果:文件自动同步(kubelet 通过原子 symlink 交换)

⚠️ 陷阱:应用需监控目录创建事件,而非文件修改


场景 2:镜像更新的三种结局

  1. 成功滚动更新:UID 变化,重启计数归零 = Pod 重建
  2. ImagePullBackOff:旧 Pod 保留,新 Pod 卡住
  3. CrashLoopBackOff:UID 不变,重启计数持续增加 = 崩溃循环

诊断法则:重启计数上升 + UID 不变 = 崩溃循环


场景 3:原地资源扩容(K8s 1.35+)

革命性特性:无需重建 Pod 即可调整资源!

resizePolicy:
- resourceName: cpu
  restartPolicy: NotRequired      # 无感知
- resourceName: memory
  restartPolicy: RestartContainer # 容器重启

⚠️ 致命陷阱:不指定 resizePolicy,JVM 堆内存不会自动调整!

应用方法

kubectl patch pod my-pod --subresource resize \
  -p '{"spec":{"containers":[{"name":"app","resources":{
    "requests":{"cpu":"250m","memory":"128Mi"}
  }}]}}'

场景 4:Istio 路由 —— 零重启魔法

原理:Istiod 通过 xDS 协议推送,毫秒级生效

100% v1 → 80/20 金丝雀 → 50/50 → 100% v2
重启计数:[0,0,0,0] → [0,0,0,0]

⚠️ 陷阱:Envoy 可能静默拒绝推送,需监控 pilot_xds_push_errors


场景 5:Stakater Reloader 救星

问题:ConfigMap 以环境变量注入时,需手动重启

方案

annotations:
  reloader.stakater.com/auto: "true"

⚠️ 生产陷阱:默认只监视自身命名空间,需设置 watchGlobally=true


🛠️ 运维必备命令

# 判断重启类型
kubectl get pod <pod> -o custom-columns=\
  "UID:.metadata.uid,RESTARTS:.status.containerStatuses[0].restartCount"

# 查看事件
kubectl describe pod <pod> | grep -A 20 "Events:"

# 检查原地扩容
kubectl get pod <pod> -o jsonpath='{.status.resize}'

📈 热重载 vs 容器重启

维度容器重启热重载
可用性短暂中断零中断
失败模式立即报错静默出错
调试难度容易困难

决策树

  • 环境变量/镜像/探针 → 容器重启 ✅
  • 配置文件 + 应用支持 → 热重载 🔄
  • Istio 路由 → xDS 推送 ⚡

🎓 三大原则

  1. 理解本质:UID 变化 = 重建;UID 不变 + 计数增加 = 容器重启
  2. kubelet 只关心 Pod Spec:ConfigMap 内容变化 ≠ Spec 变化
  3. 重启不是敌人,静默失败才是:选择应深思熟虑

💡 记住:目标不是更快重启,而是理解何时该重启,何时该静默。

0
0
0
0
评论
未登录
暂无评论