Kubernetes 资源调度优化:亲和性/反亲和性 + Pod 拓扑分布约束配置案例

核心概念说明
  1. 亲和性(Affinity)

    • 节点亲和性:将 Pod 调度到特定标签的节点(如高配节点)
    • Pod 亲和性:将 Pod 与特定 Pod 部署在同一拓扑域(如共享缓存)
  2. 反亲和性(Anti-affinity)

    • 避免 Pod 与特定 Pod/节点共存(如避免单节点部署多个实例)
  3. Pod 拓扑分布约束
    通过 topologySpreadConstraints 控制 Pod 在拓扑域(如主机/可用区)的分布密度,例如:

    • 每个主机最多运行 2 个 Pod
    • 跨可用区均匀分布

综合配置案例

场景需求

  • Web 服务(frontend)必须与缓存服务(redis-cache)同可用区
  • 避免两个 frontend Pod 部署在同一主机
  • 每个可用区至少部署 2 个 frontend Pod
  • 每个主机最多运行 1 个 redis-cache Pod

Deployment 配置示例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 6
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      affinity:
        # 要求与 redis-cache Pod 同可用区
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values: ["redis-cache"]
            topologyKey: topology.kubernetes.io/zone
        
        # 禁止同主机部署多个 frontend
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values: ["frontend"]
            topologyKey: kubernetes.io/hostname
      
      # 拓扑分布约束:跨可用区均匀分布
      topologySpreadConstraints:
      - maxSkew: 1  # 最大不平衡度
        topologyKey: topology.kubernetes.io/zone
        whenUnsatisfiable: DoNotSchedule  # 不满足条件时禁止调度
        labelSelector:
          matchLabels:
            app: frontend
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-cache
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: redis-cache
    spec:
      # 禁止同主机部署多个 redis
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values: ["redis-cache"]
            topologyKey: kubernetes.io/hostname


关键配置解析
配置项作用说明
podAffinity.topologyKey: zone强制 frontendredis-cache 在相同可用区(通过区域拓扑键实现)
podAntiAffinity (hostname)确保同主机不运行多个相同服务的 Pod(防单点故障)
maxSkew: 1可用区间 Pod 数量差≤1(如 3 个区时分布为 2-2-2)
whenUnsatisfiable约束不满足时直接拒绝调度(避免分布不均)
调度效果验证
# 查看 Pod 分布情况
kubectl get pods -o wide --sort-by='.spec.nodeName'

# 预期结果示例:
frontend-xxx    node1 (zoneA)  # 每个主机仅1个 frontend
frontend-yyy    node2 (zoneA)  # 同可用区允许多个
frontend-zzz    node3 (zoneB)
redis-cache-aa  node1 (zoneA)  # 与 frontend 同区
redis-cache-bb  node4 (zoneC)  # 不同区独立部署

最佳实践

  1. 生产环境中优先使用 preferredDuringScheduling(软约束)避免调度僵局
  2. 结合 nodeAffinity 实现硬件定向调度(如 GPU 节点)
  3. 通过 kubectl describe node 检查节点标签确保拓扑键有效性

更多推荐