Linux Pod 调度与管理实战

3次阅读

pod卡在pending主因是调度器无法找到匹配node,需检查nodeselector、污点、资源请求及topologyspreadconstraints;kubectl scale无效常因操作对象错误、hpa覆盖或gitops锁住replicas;node notready时pod不迁移需核查pod-eviction-timeout和terminationgraceperiodseconds;drain节点须预演并关注statefulset策略与pdb。

Linux Pod 调度与管理实战

Pod 为什么卡在 Pending 状态不启动

绝大多数时候,Pending 是调度器找不到符合条件的 Node,不是镜像拉取或容器启动失败。先看 kubectl describe pod <name></name>,重点盯 Events 区域里最后一行——常见的是 0/3 nodes are available: 3 node(s) didn't match Pod's node selector.Insufficient cpu/memory

实操建议:

  • 检查 nodeSelectortaintstolerations 是否匹配:用 kubectl get nodes -o wide 看节点标签,用 kubectl describe node <node></node> 看污点
  • 确认资源请求(resources.requests)没写成远超集群余量的值,比如写 cpu: 16 却只有一台 4 核机器
  • 如果用了 topologySpreadConstraints,注意它可能因拓扑域不均导致“死锁式 Pending”,临时删掉它能快速验证是否是它的问题

kubectl scale 不生效的三个常见原因

kubectl scale 命令本身几乎不会报错,但副本数就是不变——本质是命令没落到真正的控制器上。最典型的是误对 Pod 直接操作,或者控制器被其他工具覆盖。

实操建议:

  • 确认目标对象是 deploymentstatefulset 这类控制器,而不是 podkubectl scale deployment/myapp --replicas=3 ✅,kubectl scale pod/myapp-xxx --replicas=3 ❌(无效)
  • 检查是否有 HorizontalPodAutoscaler(HPA)在运行:kubectl get hpa;有 HPA 时,手动 scale 会被它立刻覆盖
  • 确认 Deployment 的 replicas 字段没被 GitOps 工具(如 Argo CD、Flux)锁住:查 kubectl get deploy/myapp -o yaml 里有没有 annotations: "argocd.argoproj.io/sync-options": "SkipDryRunOnMissingResource=true" 类似字段,这类配置可能导致 apply 后状态不更新

Node NotReady 时 Pod 没自动迁移?检查这两个配置

kubernetes 默认不会立即驱逐 NotReady 节点上的 Pod,而是等 5 分钟(pod-eviction-timeout),且前提是 Pod 没设 controller.kubernetes.io/pod-deletion-costpriorityClassName 干扰调度逻辑。

实操建议:

  • 查 kube-controller-manager 启动参数是否含 --pod-eviction-timeout=30s(生产环境慎调太短,可能引发抖动)
  • 确认 Pod 的 spec.terminationGracePeriodSeconds 没设成极大值(如 86400),否则即使触发驱逐,也会卡在 “Terminating” 状态不释放 IP 和端口
  • 若用 StatefulSet,注意它默认带 podManagementPolicy: OrderedReady,新 Pod 启动前旧 Pod 必须完全终止——NotReady 节点上的旧 Pod 如果卡住,新 Pod 就一直 Pending

如何安全地 Drain 一个 Node(尤其有 StatefulSet)

kubectl drain 不是“一键清空”,它会按策略逐个处理 Pod,但对 StatefulSet、本地存储、PDB(PodDisruptionBudget)敏感,稍不注意就中断服务。

实操建议:

  • 先跑 kubectl drain <node> --dry-run=client -o wide</node>,看哪些 Pod 会被跳过(比如没配 PDB、有 local volume、或 controller.kubernetes.io/pod-deletion-cost 值极高)
  • StatefulSet,确保副本数 ≥ 2 且启用了 podManagementPolicy: Parallel,否则 drain 会等第一个 Pod 完全终止才动第二个
  • --ignore-daemonsets 是默认行为,但如果你真有关键 DaemonSet(比如网络插件),得手动确认它是否允许临时缺失——别依赖这个 flag 做业务可用性兜底
  • drain 失败后,别直接 kubectl delete pod 强删:可能破坏 StatefulSet 的序号一致性,优先用 kubectl delete pod --grace-period=0 --force 并确认 controller 已重建

事情说清了就结束。真正麻烦的从来不是命令怎么敲,而是每个 Pod 背后绑着的调度约束、控制器状态、以及人对“自动”二字的过度信任。

text=ZqhQzanResources