73·调度与资源进阶

节点亲和性

kubernetesschedulernode-affinity

节点亲和性

学习目标

  1. 理解 nodeAffinity 的两种类型:required 和 preferred
  2. 掌握亲和性表达式的语法
  3. 了解 nodeAffinity 与 nodeSelector 的区别

核心概念

一句话解释

nodeAffinity 是 nodeSelector 的增强版,支持硬性要求和软性偏好两种调度策略。

两种类型

┌─────────────────────────────────────────────────────────┐
│                    nodeAffinity 类型                     │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  requiredDuringSchedulingIgnoredDuringExecution         │
│  ┌─────────────────────────────────────────┐           │
│  │  硬性要求:必须满足才能调度              │           │
│  │  类似 nodeSelector,但支持更丰富的表达式 │           │
│  └─────────────────────────────────────────┘           │
│                                                         │
│  preferredDuringSchedulingIgnoredDuringExecution        │
│  ┌─────────────────────────────────────────┐           │
│  │  软性偏好:尽量满足,但不强制           │           │
│  │  可以指定权重,优先调度到偏好节点        │           │
│  └─────────────────────────────────────────┘           │
│                                                         │
└─────────────────────────────────────────────────────────┘

YAML 语法

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  affinity:
    nodeAffinity:
      # 硬性要求
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/e2e-az-name
            operator: In
            values:
            - e2e-az1
            - e2e-az2
      # 软性偏好
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1                          # 权重 1-100
        preference:
          matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd
  containers:
  - name: app
    image: nginx

操作符详解

操作符说明示例
In值在列表中values: [ssd, nvme]
NotIn值不在列表中values: [hdd]
Exists标签存在key: gpu(无需 values)
DoesNotExist标签不存在key: gpu(无需 values)
Gt值大于(字符串比较)values: ["64"]
Lt值小于(字符串比较)values: ["128"]

调度流程

Pod with nodeAffinity:
  required: zone In [east, west]
  preferred: disktype=ssd (weight: 80)
             gpu=true (weight: 20)

节点列表:
┌─────────┬────────┬─────────┬─────┐
│  Node   │  zone  │ disktype │ gpu │
├─────────┼────────┼─────────┼─────┤
│  node1  │  east  │   ssd    │ no  │
│  node2  │  west  │   hdd    │ yes │
│  node3  │  north │   ssd    │ yes │
│  node4  │  east  │   ssd    │ yes │
└─────────┴────────┴─────────┴─────┘

1. 过滤阶段:
   - node1: zone=east ✓ 满足 required
   - node2: zone=west ✓ 满足 required
   - node3: zone=north ✗ 不满足 required
   - node4: zone=east ✓ 满足 required

2. 打分阶段(node1, node2, node4):
   - node1: disktype=ssd (80分) + gpu=no (0分) = 80分
   - node2: disktype=hdd (0分) + gpu=yes (20分) = 20分
   - node4: disktype=ssd (80分) + gpu=yes (20分) = 100分

3. 结果:Pod 调度到 node4

与 nodeSelector 对比

特性nodeSelectornodeAffinity
匹配方式简单标签相等复杂表达式
硬性约束
软性偏好
操作符仅 =In, NotIn, Exists 等
权重
复杂逻辑AND onlyAND, OR (多 term)

多 term 关系

# 多个 term 是 OR 关系
requiredDuringSchedulingIgnoredDuringExecution:
  nodeSelectorTerms:
  - matchExpressions:        # term 1
    - key: zone
      operator: In
      values: [east]
  - matchExpressions:        # term 2
    - key: zone
      operator: In
      values: [west]
# 满足 term 1 或 term 2 都可以

# 单个 term 内多个 expression 是 AND 关系
nodeSelectorTerms:
- matchExpressions:
  - key: zone
    operator: In
    values: [east]
  - key: disktype
    operator: In
    values: [ssd]
# 必须同时满足 zone=east 和 disktype=ssd

实践练习

练习 1:使用 required nodeAffinity

# pod-node-affinity-required.yaml
apiVersion: v1
kind: Pod
metadata:
  name: affinity-required
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/os
            operator: In
            values:
            - linux
          - key: kubernetes.io/arch
            operator: In
            values:
            - amd64
  containers:
  - name: nginx
    image: nginx
kubectl apply -f pod-node-affinity-required.yaml
kubectl get pod affinity-required -o wide

练习 2:使用 preferred nodeAffinity

# pod-node-affinity-preferred.yaml
apiVersion: v1
kind: Pod
metadata:
  name: affinity-preferred
spec:
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd
      - weight: 20
        preference:
          matchExpressions:
          - key: gpu
            operator: Exists
  containers:
  - name: nginx
    image: nginx

练习 3:组合 required 和 preferred

# pod-node-affinity-both.yaml
apiVersion: v1
kind: Pod
metadata:
  name: affinity-both
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: environment
            operator: In
            values:
            - production
            - staging
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        preference:
          matchExpressions:
          - key: environment
            operator: In
            values:
            - production
  containers:
  - name: nginx
    image: nginx

练习 4:使用 NotIn 和 DoesNotExist

# pod-node-affinity-exclude.yaml
apiVersion: v1
kind: Pod
metadata:
  name: affinity-exclude
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: node-role.kubernetes.io/master
            operator: DoesNotExist
          - key: environment
            operator: NotIn
            values:
            - test
  containers:
  - name: nginx
    image: nginx

常见使用场景

# 场景 1:GPU 工作负载
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: accelerator
            operator: In
            values:
            - nvidia-tesla-v100
            - nvidia-tesla-a100

# 场景 2:跨可用区高可用
spec:
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        preference:
          matchExpressions:
          - key: topology.kubernetes.io/zone
            operator: In
            values:
            - zone-a
            - zone-b
            - zone-c

小结

要点说明
required硬性要求,必须满足才能调度
preferred软性偏好,尽量满足但不强制
操作符In, NotIn, Exists, DoesNotExist, Gt, Lt
权重1-100,用于软性偏好排序
优势比 nodeSelector 更灵活强大

练习编辑器

bash
Loading...

继续学习

完成本课后,建议继续学习下一课「Pod 亲和性」 以巩固所学知识。