> For the complete documentation index, see [llms.txt](https://yangsijie151104.gitbook.io/k8s-note/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yangsijie151104.gitbook.io/k8s-note/gao-ji-tiao-du/12.-gao-ji-tiao-du/pod-zhong-de-qin-yuan-xing/pod-yu-pod-de-qin-yuan-xing.md).

# 与 Pod 的亲缘性

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

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

{% hint style="info" %}
配置当前 Pod 与其他 Pod 亲缘，并不意味着将该 Pod 尽可能调度至目标 Pod 所在 Node 中，而是调度至与目标 Pod 所在 Node 具有某个相同标签的 Node 子集中（非亲缘性规则同理），详情可以参考下文 `topologyKey` 字段的详细解释及调度流程
{% endhint %}

## 亲缘性

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

* `preferredDuringSchedulingIgnoredDuringExecution`: 从 `preferredDuringScheduling` 可以看出是非强制的，如果满足亲缘性规则的 Pod 不满足其他需求，那么也可以部署在其他 Node 中；
* `requiredDuringSchedulingIgnoredDuringExecution`：从 `requiredDuringScheduling` 可以看出是强制的，强制将 Pod 部署在满足亲缘性规则的 Node 中，如果不满足需求，则该 Pod 调度失败；

{% hint style="info" %}
`IgnoredDuringExecution` 表示当前的亲缘性规则只会当该 Pod 被调度时生效，不会令已经在运行的 Pod 被剔除重新调度
{% endhint %}

### 强制性

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

```yaml
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"
```

{% hint style="info" %}
🔥 调度过程详解

1. 首先找出匹配的目标 Pod 所在的 Node；
2. 根据定义的 `topologyKey` 找出该 Node 对应的标签；
3. 将本 Pod 调度至包含该标签的 Node 子集中；
   {% endhint %}

### 非强制性

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

```yaml
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 调度失败；

{% hint style="info" %}
`IgnoredDuringExecution` 表示当前的亲缘性规则只会当该 Pod 被调度时生效，不会令已经在运行的 Pod 被剔除重新调度
{% endhint %}

### 强制性

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

```yaml
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 中：

```yaml
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"
```
