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-az23) Pod Affinity / Anti-Affinity(Pod 亲和与反亲和)
问题:我不只想按“节点标签”调度,还想按“Pod 和 Pod 的关系”来调度,比如:
- 让同一应用的 Pod 尽量分散到不同节点(反亲和)
- 让某类 Pod 尽量和另一类 Pod 放在一起(亲和)
Pod 亲和/反亲和(podAffinity / podAntiAffinity)的字段形态和 nodeAffinity 类似:
requiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecution
备注: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: NoSchedule5) 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-points7) 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: value2Labels 更像“筛选条件”(给 Kubernetes 选对象用)
Annotations 更像“备注信息”(给人/工具读)参考
https://kubernetes.io/docs/reference/scheduling/config/#extension-points
https://cloud.tencent.com/developer/article/1833485