如何让 Pod 独占一个节点或者保证某些 Pod 不调度到同一节点?
在 Kubernetes 中,要实现 Pod 独占节点(即该节点只运行特定 Pod)和 Pod 互斥(即某些 Pod 不能运行在同一节点),需要使用不同的调度机制。
以下是具体的实现方案和配置示例:
场景一:让 Pod 独占一个节点 (Dedicated Node)
要实现“独占”,需要两个步骤配合:
- 驱逐闲杂人等:给节点打上“污点”(Taint),阻止普通 Pod 调度上来。
- 指定特定人员:给目标 Pod 添加“容忍”(Toleration)以允许其调度,并添加“节点亲和性”(Node Affinity)以强制其调度到该节点。
步骤 1:给节点打污点 (Taint) 和 标签 (Label)
假设我们要让节点 node-01 被独占。
# 1. 给节点打标签(用于亲和性定位)
kubectl label nodes node-01 dedicated=high-priority
# 2. 给节点打污点(用于排斥其他 Pod)
# 格式:key=value:effect
# NoSchedule 表示没有对应容忍度的 Pod 不能调度上来
kubectl taint nodes node-01 dedicated=high-priority:NoSchedule
步骤 2:配置 Pod YAML
在 Pod 的配置中,必须同时包含 NodeAffinity (我要去那里) 和 Tolerations (我有权限去那里)。
apiVersion: v1
kind: Pod
metadata:
name: exclusive-pod
labels:
app: my-app
spec:
containers:
- name: nginx
image: nginx
# 1. 节点亲和性:强制 Pod 只能去带有 dedicated=high-priority 标签的节点
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: dedicated
operator: In
values:
- high-priority
# 2. 容忍度:允许 Pod 调度到带有 dedicated=high-priority:NoSchedule 污点的节点
tolerations:
- key: "dedicated"
operator: "Equal"
value: "high-priority"
effect: "NoSchedule"
结果: 只有配置了上述 YAML 的 Pod 才能运行在 node-01 上,且该 Pod 只会往 node-01 跑。
场景二:保证某些 Pod 不调度到同一节点 (Pod Anti-Affinity)
这通常用于高可用(HA)场景,防止物理机宕机导致所有副本同时挂掉。需要使用 Pod 反亲和性 (Pod Anti-Affinity)。
方案 A:强制互斥 (Hard Anti-Affinity)
使用 requiredDuringScheduling...。如果节点不满足条件(即节点上已经有了该 Pod),则坚决不调度,Pod 会处于 Pending 状态。
apiVersion: apps/v1
kind: Deployment
metadata:
name: ha-app
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
# 关键点:topologyKey
# kubernetes.io/hostname 表示以节点主机名为拓扑域(即同一节点)
# 如果设为 topology.kubernetes.io/zone,则表示不能在同一可用区
topologyKey: "kubernetes.io/hostname"
containers:
- name: nginx
image: nginx
结果: 假设你有 3 个副本,Kubernetes 会强制将这 3 个 Pod 分散到 3 个不同的节点上。如果你只有 2 个节点,第 3 个 Pod 将无法调度(Pending)。
方案 B:软性互斥 (Soft Anti-Affinity)
使用 preferredDuringScheduling...。Kubernetes 会尽量把 Pod 分散开,但如果资源不足,允许它们挤在同一个节点上。
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100 # 权重,越高越优先遵守
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: "kubernetes.io/hostname"
结果: 尽量分散,但在节点资源紧张时,为了保证服务运行,允许同一节点运行多个副本。
场景三:更高级的分布控制 (Topology Spread Constraints)
Kubernetes v1.19+ 推荐使用 Pod 拓扑分布约束,它比反亲和性更灵活(例如:允许同一节点最多跑 2 个,而不是严格的 1 个)。
spec:
topologySpreadConstraints:
- maxSkew: 1 # 允许的最大偏差值
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule # 或者 ScheduleAnyway
labelSelector:
matchLabels:
app: web
解释: 这段配置表示尽量均匀地将 Pod 分布在不同节点上,节点之间 Pod 数量的差值不能超过 1。
总结
| 需求 | 核心技术 | 关键配置项 |
|---|---|---|
| Pod 独占节点 | Taint (污点) + Toleration (容忍) + Node Affinity (亲和性) | Node: NoSchedule TaintPod: tolerations, nodeAffinity |
| Pod 互斥 (分散) | Pod Anti-Affinity (Pod 反亲和性) | Pod: podAntiAffinitytopologyKey: kubernetes.io/hostname |
| 均匀分布 | Topology Spread Constraints | Pod: topologySpreadConstraints |