Kubernetes Pod亲和性调度与节点污点管理实战

Kubernetes Pod亲和性调度与节点污点管理实战

Kubernetes集群中Pod调度由kube-scheduler完成,默认调度策略只考虑资源请求量。生产环境中需要控制Pod分布——IO密集型服务避开计算节点、数据库Pod分散到不同物理机、敏感服务隔离到专用节点。Pod亲和性规则和节点污点机制提供了精细化的调度控制能力。

节点污点(Taint)与容忍度(Toleration)配置

污点机制将节点标记为”排斥”状态,只有声明了对应容忍度的Pod才会被调度到该节点。适用于GPU节点专用、生产/测试环境隔离等场景。

# 为GPU节点添加污点
kubectl taint nodes gpu-node-01 gpu=true:NoSchedule

# 为生产专用节点添加污点
kubectl taint nodes prod-node-01 environment=production:NoSchedule

# 查看节点污点
kubectl describe node gpu-node-01 | grep Taint

污点效果分三种:

  • NoSchedule:不调度新Pod,已运行Pod不受影响
  • PreferNoSchedule:尽量不调度,资源紧张时仍可能调度
  • NoExecute:不调度新Pod,且驱逐已运行的不容忍Pod

Pod声明容忍度以匹配污点:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: llm-inference
spec:
  replicas: 2
  selector:
    matchLabels:
      app: llm-inference
  template:
    metadata:
      labels:
        app: llm-inference
    spec:
      containers:
      - name: inference
        image: vllm/vllm:latest
        resources:
          limits:
            nvidia.com/gpu: 1
            memory: 32Gi
          requests:
            cpu: 4
            memory: 16Gi
      tolerations:
      - key: "gpu"
        operator: "Equal"
        value: "true"
        effect: "NoSchedule"
      - key: "environment"
        operator: "Equal"
        value: "production"
        effect: "NoSchedule"

operator支持Equal(精确匹配key=value)和Exists(只匹配key,忽略value)。Exists模式适合容忍所有同key不同value的污点。

Pod亲和性(Affinity)与反亲和性(Anti-Affinity)

亲和性规则控制Pod之间的分布关系。反亲和性确保同一服务的多个副本不集中在同一节点,避免单节点故障导致服务不可用。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-gateway
spec:
  replicas: 3
  template:
    spec:
      affinity:
        # Pod反亲和性:同服务副本分散到不同节点
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values: ["api-gateway"]
            topologyKey: kubernetes.io/hostname
        # 软反亲和性:尽量分散到不同可用区
        preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values: ["api-gateway"]
              topologyKey: topology.kubernetes.io/zone
      containers:
      - name: gateway
        image: nginx:1.25
        resources:
          requests:
            cpu: 2
            memory: 4Gi

硬性规则(required)和软性规则(preferred)的区别:

  • required:调度器必须满足,不满足则Pod保持Pending状态
  • preferred:调度器尽量满足,不满足时仍可调度到其他节点,weight值1-100决定优先级

topologyKey定义拓扑域:kubernetes.io/hostname表示以节点为域(分散到不同物理机),topology.kubernetes.io/zone表示以可用区为域(跨可用区分布)。

节点亲和性:控制Pod调度到特定节点

节点亲和性替代了nodeSelector,支持更灵活的匹配规则:

spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: node-role
            operator: In
            values: ["compute-optimized"]
          - key: cpu-arch
            operator: In
            values: ["amd64", "arm64"]
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
          - key: disk-type
            operator: In
            values: ["nvme-ssd"]
      - weight: 20
        preference:
          matchExpressions:
          - key: network
            operator: In
            values: ["10gbps"]

该配置硬性要求Pod调度到标记为node-role=compute-optimized的节点,且CPU架构为amd64或arm64。软性规则优先选择NVMe SSD磁盘和高带宽网络的节点。

拓扑分布约束(Topology Spread Constraints)

当反亲和性无法满足跨域均匀分布需求时,Topology Spread Constraints提供更精确的控制:

spec:
  topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: topology.kubernetes.io/zone
    whenUnsatisfiable: DoNotSchedule
    labelSelector:
      matchLabels:
        app: api-gateway
  - maxSkew: 2
    topologyKey: kubernetes.io/hostname
    whenUnsatisfiable: ScheduleAnyway
    labelSelector:
      matchLabels:
        app: api-gateway

maxSkew: 1表示任意两个可用区之间Pod数量差不能超过1。DoNotSchedule为硬约束,ScheduleAnyway为软约束。maxSkew: 2在节点级别允许更大偏差,避免在节点数量有限的集群中Pod无法调度。

调度失败诊断方法

Pod长时间处于Pending状态时,通过kubectl describe查看调度失败原因:

kubectl describe pod api-gateway-xxx | tail -20

# 常见调度失败原因:
# 0/12 nodes are available: 6 Insufficient cpu, 4 Insufficient memory, 
# 2 node(s) had untolerated taint

# 查看节点资源使用情况
kubectl top nodes

# 查看各节点详细资源分配
kubectl describe node node-01 | grep -A 10 "Allocated resources"

排查流程:

  1. 确认resources.requests是否合理,过大导致无节点可满足
  2. 检查nodeAffinitynodeSelector是否过严,可用kubectl get nodes --show-labels查看节点标签
  3. 检查taints是否阻止调度,对比Pod的tolerations是否匹配
  4. 检查podAntiAffinity是否要求过于严格,required规则在副本数超过节点数时必然失败

一个常见陷阱:3副本Deployment配置required级别的Pod反亲和性,但集群只有2个节点。第三个Pod永远无法调度。解决方案是将反亲和性改为preferred,或增加节点数。

生产环境调度策略建议

对于不同类型的工作负载,推荐以下调度配置组合:

  • 无状态服务:Pod反亲和性(preferred)+ Topology Spread(maxSkew=1, zone级别)
  • 有状态服务(如数据库):Pod反亲和性(required, hostname级别)+ nodeAffinity指定专用节点 + toleration匹配专用节点污点
  • 批处理任务:nodeAffinity指定计算节点 + resource requests设为节点资源的80%
  • GPU推理服务:nodeAffinity匹配GPU标签 + toleration匹配GPU污点 + Pod反亲和性(required, hostname级别)

调度策略配置完成后,通过kubectl get pods -o wide验证Pod分布是否符合预期。跨可用区部署的服务还需验证服务网格或网络策略是否正确配置跨区通信。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetespod-qin-he-xing-diao-du-yu-jie-dian-wu-dian-guan/

(0)
小编小编
上一篇 18小时前
下一篇 18小时前

相关推荐