# 与 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"
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET 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?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
