基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

如何让 Pod 独占一个节点或者保证某些 Pod 不调度到同一节点?

知识点图片

在 Kubernetes 中,要实现 Pod 独占节点(即该节点只运行特定 Pod)和 Pod 互斥(即某些 Pod 不能运行在同一节点),需要使用不同的调度机制。

以下是具体的实现方案和配置示例:


场景一:让 Pod 独占一个节点 (Dedicated Node)

要实现“独占”,需要两个步骤配合:

  1. 驱逐闲杂人等:给节点打上“污点”(Taint),阻止普通 Pod 调度上来。
  2. 指定特定人员:给目标 Pod 添加“容忍”(Toleration)以允许其调度,并添加“节点亲和性”(Node Affinity)以强制其调度到该节点。

步骤 1:给节点打污点 (Taint) 和 标签 (Label)

假设我们要让节点 node-01 被独占。

bash
# 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 (我有权限去那里)。

yaml
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 状态。

yaml
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 分散开,但如果资源不足,允许它们挤在同一个节点上。

yaml
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 个)。

yaml
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 Taint
Pod: tolerations, nodeAffinity
Pod 互斥 (分散) Pod Anti-Affinity (Pod 反亲和性) Pod: podAntiAffinity
topologyKey: kubernetes.io/hostname
均匀分布 Topology Spread Constraints Pod: topologySpreadConstraints
00:00
00:00