一、K8s资源调度那些事儿

咱们玩Kubernetes的都知道,集群资源就像小区停车位——有限且抢手。怎么让Pod停到最合适的"车位"上?今天咱们就聊聊调度优化的三大法宝:亲和性配置、污点容忍和PriorityClass。

举个栗子,假设你有个电商应用,订单服务(order-service)和Redis缓存最好部署在同一个节点上减少网络延迟。这时候就需要亲和性配置:

# 技术栈:Kubernetes 1.24+
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
spec:
  template:
    spec:
      affinity:
        podAffinity:  # Pod亲和性
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values: ["redis-cache"]  # 必须和redis-cache同节点
            topologyKey: kubernetes.io/hostname

二、亲和性配置的七十二变

亲和性分两种:硬亲和(required)和软亲和(preferred)。硬亲和就像强制婚配,不满足条件就罢工;软亲和则是优先考虑,实在不行也能凑合。

再看个复杂点的例子——让日志收集器(filebeat)避开数据库节点:

# 技术栈:Kubernetes 1.20+
affinity:
  podAntiAffinity:  # Pod反亲和
    preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 100  # 优先级权重
      podAffinityTerm:
        labelSelector:
          matchLabels:
            app: mysql
        topologyKey: kubernetes.io/hostname

注意事项

  1. topologyKey不要乱用,比如用zone做拓扑域可能导致跨机房调度
  2. 节点亲和性(nodeAffinity)更适合硬件绑定的场景,比如需要SSD的Pod

三、污点与容忍的生存法则

节点污点(Taint)就像挂了个"内有恶犬"的牌子,没有对应容忍度(Toleration)的Pod别想进来。典型场景:

# 给GPU节点打污点
kubectl taint nodes gpu-node-1 hardware=gpu:NoSchedule

# 技术栈:Kubernetes 1.18+
# 只有带这个容忍的Pod能调度到GPU节点
tolerations:
- key: "hardware"
  operator: "Equal"
  value: "gpu"
  effect: "NoSchedule"

更灵活的用法是结合effect:

  • NoSchedule:坚决不容忍
  • PreferNoSchedule:尽量不调度
  • NoExecute:已经运行的Pod也可能被驱逐

四、优先级管理的权力游戏

PriorityClass就像VIP卡,高优先级的Pod可以插队甚至挤走低优先级Pod。生产环境必备配置:

# 技术栈:Kubernetes 1.19+
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: mission-critical
value: 1000000  # 数值越大优先级越高
globalDefault: false
description: "关键业务Pod专用"

# 在Deployment中引用
priorityClassName: mission-critical

实战技巧

  1. 系统预留优先级(system-cluster-critical)的值是2000000000
  2. 普通业务建议使用1000000-10000000区间
  3. 记得设置PodDisruptionBudget防止重要服务被意外驱逐

五、组合拳实战案例

来看个综合应用场景:某AI训练平台需要调度到带GPU的专属节点,且训练任务要优先于数据分析任务:

# 技术栈:Kubernetes 1.22+
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ai-training
spec:
  template:
    spec:
      priorityClassName: gpu-task
      tolerations:
      - key: "nvidia.com/gpu"
        operator: "Exists"
        effect: "NoSchedule"
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: gpu-type
                operator: In
                values: ["a100"]

六、技术选型与避坑指南

应用场景对比

  • 亲和性:微服务拓扑管理、数据本地化
  • 污点容忍:专用硬件调度、节点隔离
  • 优先级:关键业务保障、资源抢占

常见坑点

  1. 亲和性配置过多会导致调度性能下降(建议不超过5条规则)
  2. 没设置Pod反亲和可能导致单点故障(比如所有Redis实例挤在同一节点)
  3. 优先级滥用可能引发"优先级反转"问题

七、总结与最佳实践

经过这些年的实战,我总结出三条黄金法则:

  1. 像城市规划一样设计调度策略:重要服务放核心区,普通服务放郊区
  2. 给关键业务配置PriorityClass+PDB双保险
  3. 定期用kube-scheduler-simulator做调度策略测试

最后送大家一个诊断命令锦囊:

# 查看调度失败原因
kubectl describe pod <pod-name> | grep -A10 Events

# 模拟调度过程
kubectl get pods <pod-name> -o json | jq .spec | kubectl-scheduler-simulator

记住,好的调度策略就像优秀的交通管制,既要有规则也要留弹性空间。