Linux Pod 调度策略与性能优化

1次阅读

pod 被调度到错误节点且 nodeselector 不生效,根本原因是标签键值不匹配、未打全或 pod 未触发强制匹配,kubernetes 静默跳过不匹配节点,导致 pod 持续 pending。

Linux Pod 调度策略与性能优化

Pod 被调度到错误节点,nodeSelector 不生效怎么办

根本原因通常是标签没打对、没打全,或 Pod 没有触发强制匹配逻辑。Kubernetes 不会报错,只是静默跳过不匹配的节点。

  • nodeSelector 是硬约束,只要键值对不完全匹配,Pod 就永远 Pending —— 但 kubectl describe pod 里只显示 0/3 nodes are available,不会告诉你哪条 label 缺失
  • 检查节点真实标签用 kubectl get node --show-labels,别信自己记忆里的 key 名(比如写成 disk=ssd,实际是 disk-type=ssd
  • 如果节点刚加完 label,要等几秒再创建 Pod;label 更新不是实时广播的,kube-scheduler 可能还在缓存旧状态
  • 避免混用 nodeSelectornodeAffinity:前者不支持运算符,后者支持 In/Exists,但配置稍复杂,新手容易漏写 requiredDuringSchedulingIgnoredDuringExecution

高负载下 Pod 频繁被驱逐,resources.limits 设太高反而更卡

内存 limit 不是“保证能用这么多”,而是 cgroup 的硬上限;一旦 Pod 内存使用超限,linux OOM killer 会直接杀进程,比调度失败更难排查。

  • CPU limit 实际限制的是 CPU 时间片配额,设太高会导致调度器误判节点资源余量,把多个高 CPU Pod 塞进同一台机器
  • 推荐先用 requests 做调度依据,limits 仅用于防止单个 Pod 吃光整机内存;生产环境常见组合:requests: {memory: "512Mi", cpu: "250m"}limits: {memory: "1Gi"}(CPU 不设 limit)
  • 查历史 OOM 事件kubectl get events --field-selector reason=OOMKilled,不是看 kubectl logs —— 进程被杀后日志就断了

想让两个服务尽量不在同一节点,podAntiAffinity 怎么写才可靠

反亲和性默认是“尽力而为”,不加 topologyKey 或写错 topology domain,很容易失效——比如跨 AZ 部署时用了 topologyKey: kubernetes.io/hostname,结果所有 Pod 还是挤在一台节点上。

  • 必须指定 topologyKey,常见值:kubernetes.io/hostname(同节点)、topology.kubernetes.io/zone(同可用区),注意 v1.21+ 才推荐后者
  • preferredDuringSchedulingIgnoredDuringExecution 是软策略,Pod 可能仍被调度到同节点;真要强制隔离,必须用 requiredDuringSchedulingIgnoredDuringExecution
  • 反亲和性匹配的是 Pod 自身的 label,不是 service 或 deployment 名;确保目标 Pod 的 metadata.labels 包含你用来匹配的 key(如 app: redis
  • 大规模集群中慎用 podAntiAffinity,它会让 scheduler 遍历所有节点做匹配,可能拖慢整个调度队列

Node 资源充足但 Pod 卡在 Pending,TopologySpreadConstraints 暴露的隐性瓶颈

这个字段看着是“分散部署”,实际会按 topology domain 统计已调度 Pod 数,一旦某个 domain 达到 maxSkew,后续 Pod 就无法调度进去——哪怕该节点空闲内存还有 80%。

  • 典型误配:maxSkew: 1 + 3 个 zone,但只有 2 个 zone 有节点(第 3 个 zone 节点数为 0),此时新 Pod 必然 Pending,因为无法满足“任意两个 zone 的 Pod 数差 ≤ 1”
  • whenUnsatisfiable: DoNotSchedule 是硬限制,ScheduleAnyway 才是软策略;很多人复制示例时漏改这个字段
  • 调试时用 kubectl get nodes -o wide 看各节点所属的 topology.kubernetes.io/zone 值是否一致,云厂商有时会返回空字符串或格式异常的 zone 名

调度策略真正难的不是写对 YAML,而是理解每个字段背后触发的是哪一层决策:kube-scheduler 的 predicate 阶段?priority 阶段?还是 kubelet 的 cgroup 实际执行?这些层之间有延迟、有缓存、有默认行为,不查事件、不看节点 label、不验证 topology domain,光靠重试只会掩盖问题。

text=ZqhQzanResources