16.6.2 节点筛选与亲和性/反亲和性
节点筛选与亲和性/反亲和性#
节点筛选用于控制 Pod 被调度到哪些节点,常见机制包括节点标签/选择器、节点亲和性与反亲和性、以及 Pod 亲和性/反亲和性。合理使用这些能力可实现隔离、高可用、性能优化与成本控制。
原理草图(调度匹配关系)#
节点标签与节点选择器#
安装/准备(环境验证)
# 查看节点列表与标签
kubectl get nodes --show-labels
# 给节点打标签(示例:磁盘类型与可用区)
kubectl label node node1 disktype=ssd zone=cn-bj1
kubectl label node node2 disktype=hdd zone=cn-bj1
# 查看单节点标签
kubectl get node node1 --show-labels
配置示例:NodeSelector(精确匹配)
# 文件:/tmp/pod-nodeselector.yaml
apiVersion: v1
kind: Pod
metadata:
name: app-ns
labels:
app: demo
spec:
containers:
- name: nginx
image: nginx:1.25
nodeSelector:
disktype: ssd
应用与验证
kubectl apply -f /tmp/pod-nodeselector.yaml
kubectl get pod app-ns -o wide
# 预期效果:Pod 调度到带 disktype=ssd 的节点
命令解释
- kubectl label node:给节点打标签,供调度筛选使用
- nodeSelector:只匹配标签完全一致的节点
节点亲和性/反亲和性(Node Affinity)#
配置示例:硬约束 + 软约束
# 文件:/tmp/pod-nodeaffinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: app-na
labels:
app: demo
spec:
containers:
- name: nginx
image: nginx:1.25
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: zone
operator: In
values: ["cn-bj1"]
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 50
preference:
matchExpressions:
- key: disktype
operator: In
values: ["ssd"]
应用与验证
kubectl apply -f /tmp/pod-nodeaffinity.yaml
kubectl get pod app-na -o wide
# 预期效果:优先调度到 zone=cn-bj1 且 disktype=ssd 的节点
命令解释
- requiredDuringSchedulingIgnoredDuringExecution:硬约束,不满足则 Pending
- preferredDuringSchedulingIgnoredDuringExecution:软约束,资源紧张可被忽略
- matchExpressions:支持 In/NotIn/Exists/Gt/Lt 等操作符
Pod 亲和性/反亲和性(Pod Affinity/Anti-Affinity)#
准备测试标签与应用
# 文件:/tmp/app-mysql.yaml
apiVersion: v1
kind: Pod
metadata:
name: mysql-1
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
value: "pass"
---
apiVersion: v1
kind: Pod
metadata:
name: api-1
labels:
app: api
spec:
containers:
- name: nginx
image: nginx:1.25
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: mysql
topologyKey: kubernetes.io/hostname
应用与验证
kubectl apply -f /tmp/app-mysql.yaml
kubectl get pod -o wide
# 预期效果:api-1 不与 mysql-1 同节点
命令解释
- podAntiAffinity:避免与指定标签的 Pod 同拓扑域
- topologyKey:定义“同域”的范围,如节点级或可用区级
关键参数与调度行为#
- 亲和/反亲和只影响调度阶段,已运行 Pod 不会被强制迁移
- 硬约束过多会导致 Pod Pending
- 软约束提高调度成功率
- 与污点/容忍度结合可实现更强的隔离与保障
排错与诊断(含命令与解释)#
1)Pod Pending
kubectl describe pod app-na
# 关注 Events 中的 FailedScheduling 原因
2)检查节点标签是否满足
kubectl get nodes --show-labels | grep -E "node1|node2"
3)检查调度器日志(控制平面节点)
# 若使用 systemd
journalctl -u kube-scheduler -n 200 --no-pager
常见原因
- 标签缺失或拼写错误
- 硬约束过多,候选节点为空
- topologyKey 不存在或节点未标注
练习#
练习 1:
为两个节点打标签 zone=cn-bj1、zone=cn-bj2,创建 Pod 仅允许调度到 cn-bj2,并验证结果。
练习 2:
创建两个 Pod,要求 app=web 与 app=db 不在同一节点(节点级反亲和),观察调度效果。
练习 3:
将硬约束改成软约束,模拟资源不足时的调度行为,记录 kubectl describe pod 的事件变化。