与 Pod 的亲缘性

Pod 支持配置与其他 Pod 的亲缘性及非亲缘性规则:

  1. 通过 pod.spec.affinity.podAffinity 配置与其他 Pod 的 强制或非强制 亲缘性规则;

  2. 通过 pod.spec.affinity.podAntiAffinity 配置与其他 Pod 的 强制或非强制 非亲缘性规则;

配置当前 Pod 与其他 Pod 亲缘,并不意味着将该 Pod 尽可能调度至目标 Pod 所在 Node 中,而是调度至与目标 Pod 所在 Node 具有某个相同标签的 Node 子集中(非亲缘性规则同理),详情可以参考下文 topologyKey 字段的详细解释及调度流程

亲缘性

🐽 在 pod.spec.affinity.podAffinity 下面有两个配置项,用于指定是采用强制性还是非强制性的亲缘性规则:

  • preferredDuringSchedulingIgnoredDuringExecution: 从 preferredDuringScheduling 可以看出是非强制的,如果满足亲缘性规则的 Pod 不满足其他需求,那么也可以部署在其他 Node 中;

  • requiredDuringSchedulingIgnoredDuringExecution:从 requiredDuringScheduling 可以看出是强制的,强制将 Pod 部署在满足亲缘性规则的 Node 中,如果不满足需求,则该 Pod 调度失败;

IgnoredDuringExecution 表示当前的亲缘性规则只会当该 Pod 被调度时生效,不会令已经在运行的 Pod 被剔除重新调度

强制性

下面展示一个创建案例,强制创建的 Pod 与具有 app=backend 标签的 Pod 在同一个 Node 中,且匹配的目标 Pod 存在于 defaultn1 命名空间中:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  selector:
    matchLabels:
      app: frontend
  replicas: 5
  template:
    metadata:
      labels:
        app: frontend
    spec:
      affinity:
        podAffinity:    # 配置与 Pod 的亲缘性规则
          requiredDuringSchedulingIgnoredDuringExecution:    # 强制性
          - topologyKey: kubernetes.io/hostname    # 强制将该 Pod 调度至与目标 Pod 所在 Node 具有相同 key=kubernetes.io/hostname 以及 value 相同的 Node 子集中(由于 kubernetes.io/hostname 标签是每个 Node 都有的,但 value 各不相同,因此这里可以实现强制将 Pod 与目标 Pod 绑定至同一 Node 中)
            namespaces:    # 匹配的目标 Pod 存在于 default 和 n1 命名空间中
            - default
            - n1
            labelSelector:    # 匹配亲缘的目标 Pod(也可以使用 matchExpressions 字段进行复杂匹配)
              matchLabels:
                app: backend
      containers:
      - name: main
        image: busybox
        args:
        - sleep
        - "99999"

🔥 调度过程详解

  1. 首先找出匹配的目标 Pod 所在的 Node;

  2. 根据定义的 topologyKey 找出该 Node 对应的标签;

  3. 将本 Pod 调度至包含该标签的 Node 子集中;

非强制性

下面展示一个创建案例,优先将 Pod 创建在包含 app=backend 标签的目标 Pod 所在的 Node 中:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  selector:
    matchLabels:
      app: frontend
  replicas: 5
  template:
    metadata:
      labels:
        app: frontend
    spec:
      affinity:
        podAffinity:    # 与 Pod 的亲缘性规则
          preferredDuringSchedulingIgnoredDuringExecution:    # 非强制性
          - weight: 80    # 选择该类 Pod 的权重
            podAffinityTerm:
              topologyKey: kubernetes.io/hostname    # 尽可能将该 Pod 调度至与目标 Pod 所在 Node 具有相同 key=kubernetes.io/hostname 以及 value 相同的 Node 子集中
              labelSelector:    # 匹配的目标 Pod
                matchLabels:
                  app: backend
      containers:
      - name: main
        image: busybox
        args:
        - sleep
        - "99999"

非亲缘性

与亲缘性相对的,Pod 还支持配置与其他 Pod 的非亲缘性规则,可以尽可能令 Pod 之间彼此远离。

🐽 在 pod.spec.affinity.podAntiAffinity 下面有两个配置项,用于指定是采用强制性还是非强制性的亲缘性规则:

  • preferredDuringSchedulingIgnoredDuringExecution: 从 preferredDuringScheduling 可以看出是非强制的,如果满足亲缘性规则的 Pod 不满足其他需求,那么也可以部署在其他 Node 中;

  • requiredDuringSchedulingIgnoredDuringExecution:从 requiredDuringScheduling 可以看出是强制的,强制将 Pod 部署在满足亲缘性规则的 Node 中,如果不满足需求,则该 Pod 调度失败;

IgnoredDuringExecution 表示当前的亲缘性规则只会当该 Pod 被调度时生效,不会令已经在运行的 Pod 被剔除重新调度

强制性

下面展示一个创建案例,强制将本 Pod 调度至与包含 app=frontend 标签的 Pod 所在 Node 不同的其他 Node 中:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  selector:
    matchLabels:
      app: frontend
  replicas: 5
  template:
    metadata:
      labels:
        app: frontend
    spec:
      affinity:
        podAntiAffinity:    # 与 Pod 的非亲缘性
          requiredDuringSchedulingIgnoredDuringExecution:    # 强制性
          - topologyKey: kubernetes.io/hostname    # 强制将该 Pod 调度至与目标 Pod 所在 Node 具有相同 key=kubernetes.io/hostname 以及 value 不同的 Node 中
            labelSelector:    # 匹配的目标 Pod
              matchLabels:
                app: frontend
      containers:
      - name: main
        image: busybox
        args:
        - sleep
        - "99999"

非强制性

下面展示一个创建案例,优先将本 Pod 调度至与包含 app=frontend 标签的 Pod 所在 Node 不同的其他 Node 中:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  selector:
    matchLabels:
      app: frontend
  replicas: 5
  template:
    metadata:
      labels:
        app: frontend
    spec:
      affinity:
        podAntiAffinity:    # 与 Pod 的非亲缘性
          preferredDuringSchedulingIgnoredDuringExecution:    # 非强制性
          - topologyKey: kubernetes.io/hostname    # 优先将该 Pod 调度至与目标 Pod 所在 Node 具有相同 key=kubernetes.io/hostname 以及 value 不同的 Node 中
            labelSelector:    # 匹配的目标 Pod
              matchLabels:
                app: frontend
      containers:
      - name: main
        image: busybox
        args:
        - sleep
        - "99999"

Last updated

Was this helpful?