Skip to content

01 - K8s 调度机制

调度器工作原理

Scheduler 决定 Pod 运行在哪个节点,过程分为两步:

新 Pod 创建


┌─────────────────┐
│   过滤 (Filter)  │ 排除不满足条件的节点
│   - 资源是否足够  │
│   - 标签是否匹配  │
│   - 污点容忍     │
└────────┬────────┘
         │ 候选节点列表

┌─────────────────┐
│   打分 (Score)   │ 给候选节点排序
│   - 资源均衡     │
│   - 亲和性权重   │
│   - 自定义优先级  │
└────────┬────────┘
         │ 最高分节点

    绑定 Pod 到节点

nodeSelector(最简单的调度约束)

bash
# 给节点打标签
kubectl label nodes node-1 disktype=ssd
kubectl label nodes node-2 disktype=hdd
yaml
spec:
  nodeSelector:
    disktype: ssd         # Pod 只会调度到有此标签的节点
  containers:
  - name: app
    image: myapp

Node Affinity(节点亲和性)

比 nodeSelector 更灵活,支持"软性"偏好:

yaml
spec:
  affinity:
    nodeAffinity:
      # 硬性要求(必须满足)
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/os
            operator: In
            values: ["linux"]
      # 软性偏好(尽量满足,不满足也能调度)
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
          - key: disktype
            operator: In
            values: ["ssd"]

操作符

操作符含义
In值在列表中
NotIn值不在列表中
Exists键存在
DoesNotExist键不存在
Gt大于(仅限数字)
Lt小于(仅限数字)

Pod Affinity / Anti-Affinity(Pod 亲和/反亲和)

控制 Pod 之间的调度关系。

yaml
spec:
  affinity:
    # Pod 亲和:和某些 Pod 调度到同一区域
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchLabels:
            app: cache
        topologyKey: kubernetes.io/hostname
    # Pod 反亲和:和某些 Pod 不在同一个节点
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchLabels:
              app: web
          topologyKey: kubernetes.io/hostname

使用场景

  • 亲和:把 Web 和 Cache 调度到同一节点(减少网络延迟)
  • 反亲和:同一 Deployment 的 Pod 分散到不同节点(高可用)

Taints 和 Tolerations(污点与容忍)

Taint(污点)标记在节点上,阻止 Pod 调度过来。 Toleration(容忍)声明在 Pod 上,表示可以容忍某些污点。

bash
# 给节点添加污点
kubectl taint nodes node-1 gpu=true:NoSchedule

# 移除污点
kubectl taint nodes node-1 gpu=true:NoSchedule-
yaml
# Pod 声明容忍
spec:
  tolerations:
  - key: "gpu"
    operator: "Equal"
    value: "true"
    effect: "NoSchedule"
  containers:
  - name: training
    image: pytorch

Taint Effect(效果)

效果说明
NoSchedule不容忍的 Pod 不会被调度到此节点
PreferNoSchedule尽量不调度(软性)
NoExecute不容忍的 Pod 会被驱逐,新的不会调度

典型场景

  • GPU 节点只跑训练任务
  • Master 节点不跑业务 Pod
  • 维护节点驱逐所有 Pod

实操练习

bash
# 查看节点标签
kubectl get nodes --show-labels

# 查看节点的污点
kubectl describe node <node-name> | grep Taints

# Docker Desktop 的单节点上实验
kubectl label node docker-desktop env=dev
kubectl get nodes -l env=dev

下一步

02 - 自动扩缩容