4. 节点亲和性配置实战:通过YAML配置节点亲和性规则、多条件组合

节点亲和性(Node Affinity)是Kubernetes调度器将Pod调度到特定节点集合的核心机制。与简单的nodeSelector相比,节点亲和性支持逻辑表达式(In、NotIn、Exists、DoesNotExist、Gt、Lt)和优先级权重(preferred vs required),能够实现精细化的调度策略。

4.1 节点亲和性两种模式对比

模式 语义 调度行为 典型场景
requiredDuringSchedulingIgnoredDuringExecution 硬约束(必须满足) 找不到匹配节点则Pod Pending 合规要求、GPU节点绑定、数据本地化
preferredDuringSchedulingIgnoredDuringExecution 软约束(尽量满足) 优先调度到匹配节点,不匹配则调度到其他节点 性能优化、成本控制、负载均衡
关键理解:两种模式名称中的"IgnoredDuringExecution"表示运行时忽略——即使节点标签在Pod运行后被修改,已运行的Pod也不会被驱逐。这是K8s调度器设计上对稳定性的保障。

4.2 节点亲和性规则语法结构

节点亲和性规则通过Pod的spec.affinity.nodeAffinity字段定义,支持多条件组合(同一规则内AND,不同规则间OR)。

apiVersion: v1
kind: Pod
metadata:
  name: gpu-inference-pod
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: accelerator
            operator: In
            values:
            - nvidia-tesla-v100
            - nvidia-a100
          - key: gpu-count
            operator: Gt
            values:
            - "2"
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
          - key: topology.kubernetes.io/zone
            operator: In
            values:
            - us-east-1a
      - weight: 20
        preference:
          matchExpressions:
          - key: node-type
            operator: In
            values:
            - spot
  containers:
  - name: inference
    image: nvidia/cuda:12.0-base
规则解析:
  • 硬约束:节点必须同时满足accelerator In (v100, a100) AND gpu-count Gt 2,两个条件在同一matchExpressions内,逻辑为AND。
  • 软约束:优先选择us-east-1a可用区(权重80),其次选择spot节点(权重20)。调度器会计算所有软约束的加权总分,选择分数最高的节点。

4.3 多条件组合逻辑详解

节点亲和性支持两层组合逻辑,理解层级关系是正确配置的关键:

节点亲和性多条件组合逻辑 Pod.spec.affinity.nodeAffinity requiredDuringScheduling preferredDuringScheduling nodeSelectorTerms[ ] matchExpressions[ ] 同一Term内:AND preference[ ] + weight matchExpressions[ ] 不同Term间:OR 关键规则:同一 matchExpressions 内的多个条件为 AND(必须全部满足) 不同 nodeSelectorTerms 之间为 OR(满足任意一个即可)

4.4 常用操作符及使用场景

操作符 语义 示例 适用场景
In 标签值在给定集合中 region In (us-east, us-west) 指定可用区、节点池
NotIn 标签值不在给定集合中 disk-type NotIn (hdd) 排除特定类型节点
Exists 节点存在该标签键(值不限) gpu Exists 检测节点是否具备某特性
DoesNotExist 节点不存在该标签键 spot DoesNotExist 排除带某标签的节点
Gt 标签值大于指定数值(字符串比较) memory-gb Gt 64 按资源容量筛选
Lt 标签值小于指定数值 cpu-cores Lt 8 选择低配节点
⚠️ 操作符使用注意:
  • Gt和Lt仅支持整数或浮点数字符串比较,不支持语义版本号(如"v1.2.3")。
  • Exists和DoesNotExist不需要values字段,只需指定key。
  • 一个matchExpressions内最多支持128个条件,但建议控制在10个以内以保持可读性。

4.5 实战:多条件组合配置示例

以下示例展示一个生产级推理服务的节点亲和性配置,同时使用硬约束和软约束:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: llm-inference
spec:
  replicas: 5
  selector:
    matchLabels:
      app: llm-inference
  template:
    metadata:
      labels:
        app: llm-inference
    spec:
      affinity:
        nodeAffinity:
          # 硬约束:必须满足
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            # Term 1:GPU节点 + 内存≥128GB
            - matchExpressions:
              - key: accelerator
                operator: In
                values:
                - nvidia-a100
                - nvidia-h100
              - key: memory-gb
                operator: Gt
                values:
                - "128"
            # Term 2:或使用CPU推理 + 高内存节点
            - matchExpressions:
              - key: node-type
                operator: In
                values:
                - cpu-highmem
              - key: memory-gb
                operator: Gt
                values:
                - "256"
          # 软约束:尽量满足
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 90
            preference:
              matchExpressions:
              - key: topology.kubernetes.io/zone
                operator: In
                values:
                - us-east-1a
          - weight: 10
            preference:
              matchExpressions:
              - key: cost-tier
                operator: In
                values:
                - reserved
      containers:
      - name: inference
        image: registry.example.com/llm:v2.1
        resources:
          requests:
            memory: "64Gi"
            cpu: "8"
配置解读:
  • 硬约束(OR逻辑):调度器会尝试匹配Term 1(A100/H100 GPU + 内存>128GB)或Term 2(CPU高内存节点 + 内存>256GB)。只要满足任意一个Term,Pod即可调度。
  • 软约束(加权评分):在满足硬约束的节点中,优先选择us-east-1a可用区(权重90),其次选择reserved预留实例(权重10)。调度器会计算所有软约束的加权总分。
  • 调度决策:如果us-east-1a中有可用节点,得分最高;否则回退到其他可用区的预留实例节点。

4.6 节点亲和性 vs 节点选择器

特性 nodeSelector nodeAffinity
表达式支持 仅等值匹配(key=value) In、NotIn、Exists、Gt、Lt等6种操作符
多条件逻辑 多个条件之间AND 支持AND(同一Term)和OR(不同Term)
软约束 不支持 支持权重优先级
可读性 简单直观 复杂但灵活
推荐场景 简单标签匹配 复杂调度策略、多条件组合
迁移建议:如果现有nodeSelector配置已经满足需求,无需强行迁移到nodeAffinity。但当需要排除节点(NotIn)、检测标签存在性(Exists)或优先级调度时,必须使用节点亲和性。

4.7 调试与验证

配置完成后,使用以下命令验证节点亲和性是否生效:

# 查看Pod调度到的节点
kubectl get pod llm-inference-xxxxx -o wide

# 查看Pod调度事件
kubectl describe pod llm-inference-xxxxx | grep -A 10 Events

# 检查节点标签是否匹配
kubectl get node <node-name> --show-labels

# 模拟调度(dry-run)
kubectl create -f pod.yaml --dry-run=server -o json | jq '.spec.nodeName'
常见问题排查:
  • Pod一直Pending:检查kubectl describe pod中的Events,查看是否提示"0/5 nodes are available"及具体不匹配条件。
  • 软约束未生效:确认weight值范围在1-100之间,且preferredDuringScheduling拼写正确。
  • 标签值类型错误:所有标签值在K8s中都是字符串,Gt和Lt比较时按字典序比较数字字符串,确保格式一致。