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

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。
实操建议:
- 检查
nodeSelector、taints和tolerations是否匹配:用kubectl get nodes -o wide看节点标签,用kubectl describe node <node></node>看污点 - 确认资源请求(
resources.requests)没写成远超集群余量的值,比如写cpu: 16却只有一台 4 核机器 - 如果用了
topologySpreadConstraints,注意它可能因拓扑域不均导致“死锁式 Pending”,临时删掉它能快速验证是否是它的问题
kubectl scale 不生效的三个常见原因
kubectl scale 命令本身几乎不会报错,但副本数就是不变——本质是命令没落到真正的控制器上。最典型的是误对 Pod 直接操作,或者控制器被其他工具覆盖。
实操建议:
- 确认目标对象是
deployment、statefulset这类控制器,而不是pod:kubectl 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-cost 或 priorityClassName 干扰调度逻辑。
实操建议:
- 查 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 背后绑着的调度约束、控制器状态、以及人对“自动”二字的过度信任。