1) nodeSelector(把 Pod 绑到带标签的节点)

现象:我想让某类 Pod 只跑在某些节点上。 最直接的方式是给节点打 label,然后在 PodSpec 里写 nodeSelector

 
# 例:给节点打标签
kubectl label node <node-name> disktype=ssd
 
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: docker.io/nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd

这类写法很直白,只表达“必须有这些标签”,很难表达更复杂的偏好/组合条件。

2) Node Affinity(节点亲和性)

问题:如果我想表达“必须在某些区域 / 或者更偏好某些类型节点”怎么办?

节点亲和性(nodeAffinity)把规则拆成两类:

  • requiredDuringSchedulingIgnoredDuringExecution:硬条件(调度时必须满足)
  • preferredDuringSchedulingIgnoredDuringExecution:软条件(调度时会尽量满足)

注:很多资料会提到 ...RequiredDuringExecution 这种“执行阶段强制迁移”的字段名;但在主流版本的 nodeAffinity 里常见就是上面两种(DuringExecution 的行为通常不是靠这几个字段直接表达的)

常见的写法:

apiVersion: v1
kind: Pod
metadata:
  name: demo-node-affinity
spec:
  containers:
  - name: pause
    image: registry.k8s.io/pause:3.9
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/e2e-az-name
            operator: In
            values:
            - e2e-az1
            - e2e-az2

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

问题:我不只想按“节点标签”调度,还想按“Pod 和 Pod 的关系”来调度,比如:

  • 让同一应用的 Pod 尽量分散到不同节点(反亲和)
  • 让某类 Pod 尽量和另一类 Pod 放在一起(亲和)

Pod 亲和/反亲和(podAffinity / podAntiAffinity)的字段形态和 nodeAffinity 类似:

  • requiredDuringSchedulingIgnoredDuringExecution
  • preferredDuringSchedulingIgnoredDuringExecution

备注:pod 亲和/反亲和会带来额外计算(要在全局 Pod 集合里做匹配),调度规模上去后会影响调度耗时。

4) Taint & Toleration(污点与容忍)

问题:如果我想把节点“留给特定 Pod”,让其他 Pod 默认别来碰这个节点,怎么做?

做法是:

  • 先给节点打 taint(污点)
  • 再让需要上这台节点的 Pod 声明 toleration(容忍)
# 给节点打污点:NoSchedule 表示不容忍就别调度过来
kubectl taint node <node-name> dedicated=ml:NoSchedule
# 取消污点
kubectl taint node <node-name> dedicated=ml:NoSchedule-
 
apiVersion: v1
kind: Pod
metadata:
  name: demo-toleration
spec:
  containers:
  - name: pause
    image: registry.k8s.io/pause:3.9
  tolerations:
  - key: dedicated
    operator: Equal
    value: ml
    effect: NoSchedule

5) PriorityClass 与 Preemption(抢占)

问题:当节点资源不够,Pod 一直 Pending,能不能让“更重要”的 Pod 把“不重要”的 Pod 挤下去?

Kubernetes 里常见的组合是:

  • 用 PriorityClass 给 Pod 一个优先级
  • 当调度器发现资源不足时,可能触发 preemption(抢占):删掉低优先级 Pod 来释放资源

PriorityClass 示例(新版本常见是 scheduling.k8s.io/v1;旧版可能写 v1alpha1):

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for XYZ service pods only."

Pod 引用 PriorityClass:

apiVersion: v1
kind: Pod
metadata:
  name: demo-priority
spec:
  priorityClassName: high-priority
  containers:
  - name: pause
    image: registry.k8s.io/pause:3.9

抢占一般发生在:调度器尝试调度某个 Pod,但找不到任何节点满足资源/约束,于是会尝试在某个节点上驱逐一批低优先级 Pod 来“腾位置”。

6) Scheduler 的调度/绑定流程

  • scheduling cycle:找到可行节点、打分排序
  • binding cycle:把决策落到 apiserver(绑定)

Scheduler Framework(按调用顺序):

QueueSort
PreFilter
Filter
PostFilter
PreScore
Score
NormalizeScore
Reserve
Permit
PreBind
Bind
PostBind
 

参考(官方):

https://kubernetes.io/docs/reference/scheduling/config/#extension-points

7) Scheduler 性能参数:percentageOfNodesToScore

问题:节点数很大时,为每个 Pod 在所有节点上做打分会很重;那 scheduler 是不是一定要“全局最优”?

percentageOfNodesToScore 做的事情是:限制参与打分的节点比例。

一个配置片段(字段随版本可能略有变化):

 
apiVersion: kubescheduler.config.k8s.io/v1alpha1
kind: KubeSchedulerConfiguration
percentageOfNodesToScore: 50
 

只要超过 percentageOfNodesToScore 指定百分比的节点是可行的,scheduler 会在这部分节点里做评分选最优,而不会把全部节点都遍历一遍。

8)额外: Labels vs Annotations

Labels:更偏“给系统看的”,用来选择/分组(selector) Annotations:更偏“给人/工具看的”,放一些非标识类的元信息

一个 annotations 例子:

metadata:
  annotations:
    key1: value1
    key2: value2
Labels 更像“筛选条件”(给 Kubernetes 选对象用)
Annotations 更像“备注信息”(给人/工具读)

参考

 
https://kubernetes.io/docs/reference/scheduling/config/#extension-points
https://cloud.tencent.com/developer/article/1833485