×

亲和性是 Pod 的一个属性,它控制 Pod 优先安排到的节点。反亲和性是 Pod 的一个属性,它阻止 Pod 安排到某个节点。

在 OpenShift Dedicated 中,Pod 亲和性Pod 反亲和性允许您根据其他 Pod 上的键值标签来限制 Pod 可安排到的节点。

了解 Pod 亲和性

Pod 亲和性Pod 反亲和性允许您根据其他 Pod 上的键/值标签来限制 Pod 可安排到的节点。

  • Pod 亲和性可以告诉调度器如果新 Pod 上的标签选择器与当前 Pod 上的标签匹配,则在新 Pod 与其他 Pod 相同的节点上定位新 Pod。

  • 如果新 Pod 上的标签选择器与当前 Pod 上的标签匹配,则 Pod 反亲和性可以阻止调度器在新 Pod 与具有相同标签的 Pod 相同的节点上定位新 Pod。

例如,使用亲和性规则,您可以分散或打包服务内的 Pod 或相对于其他服务中的 Pod。反亲和性规则允许您阻止特定服务的 Pod 安排到与已知会干扰第一服务 Pod 性能的其他服务的 Pod 相同的节点上。或者,您可以将服务的 Pod 分散到各个节点、可用区或可用性集中,以减少相关故障。

标签选择器可能会匹配多个 Pod 部署的 Pod。配置反亲和性规则时,请使用标签的唯一组合以避免匹配 Pod。

有两种类型的 Pod 亲和性规则:必需首选

在 Pod 可以安排到节点之前,**必须**满足必需规则。首选规则指定,如果满足规则,调度程序将尝试强制执行规则,但不保证强制执行。

根据您的 Pod 优先级和抢占设置,调度程序可能无法找到合适的节点来安排 Pod 而不会违反亲和性要求。如果是这样,则可能无法安排 Pod。

为避免这种情况,请仔细配置具有相同优先级的 Pod 的 Pod 亲和性。

您可以通过Pod规范文件配置 Pod 亲和性/反亲和性。您可以指定必需规则、首选规则或两者兼有。如果您同时指定两者,则节点必须首先满足必需规则,然后尝试满足首选规则。

以下示例显示了配置了 Pod 亲和性和反亲和性的Pod规范。

在此示例中,Pod 亲和性规则指示只有在节点上至少有一个已运行的 Pod 具有键为security且值为S1的标签时,Pod 才能调度到该节点上。Pod 反亲和性规则表示如果该节点上已运行具有键为security且值为S2的标签的 Pod,则 Pod 优先不调度到该节点上。

带有 Pod 亲和性的示例Pod配置文件
apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  affinity:
    podAffinity: (1)
      requiredDuringSchedulingIgnoredDuringExecution: (2)
      - labelSelector:
          matchExpressions:
          - key: security (3)
            operator: In (4)
            values:
            - S1 (3)
        topologyKey: topology.kubernetes.io/zone
  containers:
  - name: with-pod-affinity
    image: docker.io/ocpqe/hello-pod
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: [ALL]
1 配置 Pod 亲和性的段落。
2 定义必需规则。
3 必须匹配的键和值(标签)才能应用该规则。
4 运算符表示现有 Pod 上的标签与新 Pod 规范中matchExpression参数中的一组值之间的关系。可以是InNotInExistsDoesNotExist
带有 Pod 反亲和性的示例Pod配置文件
apiVersion: v1
kind: Pod
metadata:
  name: with-pod-antiaffinity
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  affinity:
    podAntiAffinity: (1)
      preferredDuringSchedulingIgnoredDuringExecution: (2)
      - weight: 100  (3)
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security (4)
              operator: In (5)
              values:
              - S2
          topologyKey: kubernetes.io/hostname
  containers:
  - name: with-pod-affinity
    image: docker.io/ocpqe/hello-pod
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: [ALL]
1 配置 Pod 反亲和性的段落。
2 定义首选规则。
3 为首选规则指定权重。权重最高的节点优先。
4 确定反亲和性规则何时应用的 Pod 标签的描述。为标签指定键和值。
5 运算符表示现有 Pod 上的标签与新 Pod 规范中matchExpression参数中的一组值之间的关系。可以是InNotInExistsDoesNotExist

如果节点上的标签在运行时发生更改,使得 Pod 上的亲和性规则不再满足,则 Pod 将继续在该节点上运行。

配置 Pod 亲和性规则

以下步骤演示了一个简单的双 Pod 配置,该配置创建具有标签的 Pod 和使用亲和性来允许与该 Pod 调度的 Pod。

您无法直接向已调度的 Pod 添加亲和性。

步骤
  1. 在 Pod 规范中创建具有特定标签的 Pod

    1. 创建一个包含以下内容的 YAML 文件

      apiVersion: v1
      kind: Pod
      metadata:
        name: security-s1
        labels:
          security: S1
      spec:
        securityContext:
          runAsNonRoot: true
          seccompProfile:
            type: RuntimeDefault
        containers:
        - name: security-s1
          image: docker.io/ocpqe/hello-pod
          securityContext:
            runAsNonRoot: true
            seccompProfile:
              type: RuntimeDefault
    2. 创建 Pod。

      $ oc create -f <pod-spec>.yaml
  2. 创建其他 Pod 时,请配置以下参数以添加亲和性

    1. 创建一个包含以下内容的 YAML 文件

      apiVersion: v1
      kind: Pod
      metadata:
        name: security-s1-east
      # ...
      spec:
        affinity: (1)
          podAffinity:
            requiredDuringSchedulingIgnoredDuringExecution: (2)
            - labelSelector:
                matchExpressions:
                - key: security (3)
                  values:
                  - S1
                  operator: In (4)
              topologyKey: topology.kubernetes.io/zone (5)
      # ...
      1 添加 Pod 亲和性。
      2 配置requiredDuringSchedulingIgnoredDuringExecution参数或preferredDuringSchedulingIgnoredDuringExecution参数。
      3 指定必须满足的keyvalues。如果希望新 Pod 与其他 Pod 一起调度,请使用与第一个 Pod 上的标签相同的keyvalues参数。
      4 指定一个operator。运算符可以是InNotInExistsDoesNotExist。例如,使用运算符In要求标签位于节点中。
      5 指定一个topologyKey,这是一个预填充的Kubernetes 标签,系统使用它来表示此类拓扑域。
    2. 创建 Pod。

      $ oc create -f <pod-spec>.yaml

配置 Pod 反亲和性规则

以下步骤演示了一个简单的双 Pod 配置,该配置创建具有标签的 Pod 和使用反亲和性首选规则来尝试阻止与该 Pod 调度的 Pod。

您无法直接向已调度的 Pod 添加亲和性。

步骤
  1. 在 Pod 规范中创建具有特定标签的 Pod

    1. 创建一个包含以下内容的 YAML 文件

      apiVersion: v1
      kind: Pod
      metadata:
        name: security-s1
        labels:
          security: S1
      spec:
        securityContext:
          runAsNonRoot: true
          seccompProfile:
            type: RuntimeDefault
        containers:
        - name: security-s1
          image: docker.io/ocpqe/hello-pod
          securityContext:
            allowPrivilegeEscalation: false
            capabilities:
              drop: [ALL]
    2. 创建 Pod。

      $ oc create -f <pod-spec>.yaml
  2. 创建其他 Pod 时,请配置以下参数

    1. 创建一个包含以下内容的 YAML 文件

      apiVersion: v1
      kind: Pod
      metadata:
        name: security-s2-east
      # ...
      spec:
      # ...
        affinity: (1)
          podAntiAffinity:
            preferredDuringSchedulingIgnoredDuringExecution: (2)
            - weight: 100 (3)
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                  - key: security (4)
                    values:
                    - S1
                    operator: In (5)
                topologyKey: kubernetes.io/hostname (6)
      # ...
      1 添加 Pod 反亲和性。
      2 配置requiredDuringSchedulingIgnoredDuringExecution参数或preferredDuringSchedulingIgnoredDuringExecution参数。
      3 对于首选规则,请指定节点的权重,1-100。权重最高的节点优先。
      4 指定必须满足的keyvalues。如果希望新 Pod 不与其他 Pod 一起调度,请使用与第一个 Pod 上的标签相同的keyvalues参数。
      5 指定一个operator。运算符可以是InNotInExistsDoesNotExist。例如,使用运算符In要求标签位于节点中。
      6 指定一个topologyKey,这是一个预填充的Kubernetes 标签,系统使用它来表示此类拓扑域。
    2. 创建 Pod。

      $ oc create -f <pod-spec>.yaml

Pod 亲和性和反亲和性规则示例

以下示例演示了 Pod 亲和性和 Pod 反亲和性。

Pod 亲和性

以下示例演示了具有匹配标签和标签选择器的 Pod 的 Pod 亲和性。

  • Pod team4 具有标签team:4

    apiVersion: v1
    kind: Pod
    metadata:
      name: team4
      labels:
         team: "4"
    # ...
    spec:
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      containers:
      - name: ocp
        image: docker.io/ocpqe/hello-pod
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: [ALL]
    # ...
  • Pod team4apodAffinity下具有标签选择器team:4

    apiVersion: v1
    kind: Pod
    metadata:
      name: team4a
    # ...
    spec:
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: team
                operator: In
                values:
                - "4"
            topologyKey: kubernetes.io/hostname
      containers:
      - name: pod-affinity
        image: docker.io/ocpqe/hello-pod
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: [ALL]
    # ...
  • team4a Pod 与 team4 Pod 调度到同一节点上。

Pod 反亲和性

以下示例演示了具有匹配标签和标签选择器的 Pod 的 Pod 反亲和性。

  • Pod pod-s1 具有标签security:s1

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-s1
      labels:
        security: s1
    # ...
    spec:
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      containers:
      - name: ocp
        image: docker.io/ocpqe/hello-pod
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: [ALL]
    # ...
  • Pod pod-s2podAntiAffinity下具有标签选择器security:s1

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-s2
    # ...
    spec:
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: security
                operator: In
                values:
                - s1
            topologyKey: kubernetes.io/hostname
      containers:
      - name: pod-antiaffinity
        image: docker.io/ocpqe/hello-pod
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: [ALL]
    # ...
  • Pod pod-s2 不能与pod-s1调度到同一节点上。

没有匹配标签的 Pod 亲和性

以下示例演示了没有匹配标签和标签选择器的 Pod 的 Pod 亲和性。

  • Pod pod-s1 具有标签security:s1

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-s1
      labels:
        security: s1
    # ...
    spec:
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      containers:
      - name: ocp
        image: docker.io/ocpqe/hello-pod
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: [ALL]
    # ...
  • Pod pod-s2 具有标签选择器security:s2

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-s2
    # ...
    spec:
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: security
                operator: In
                values:
                - s2
            topologyKey: kubernetes.io/hostname
      containers:
      - name: pod-affinity
        image: docker.io/ocpqe/hello-pod
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: [ALL]
    # ...
  • 除非存在具有security:s2标签的 Pod 的节点,否则不会调度 Pod pod-s2。如果没有其他具有该标签的 Pod,则新 Pod 将保持挂起状态。

    示例输出
    NAME      READY     STATUS    RESTARTS   AGE       IP        NODE
    pod-s2    0/1       Pending   0          32s       <none>