4.3. 使用关联性和反关联性规则相对于其他 pod 放置 pod

关联性是 pod 的一个属性,用于控制它们希望调度到的节点。反关联性是 pod 的一个属性,用于阻止 pod 调度到某个节点上。

在 OpenShift Container Platform 中,可以借助 pod 关联性pod 反关联性来根据其他 pod 上的键/值标签限制 pod 有资格调度到哪些节点。

4.3.1. 了解 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 才可以调度到这个节点上。pod 反关联性则表示,如果节点已在运行带有键 security 和值 S2.的标签的 pod,则 pod 将偏向于不调度到该节点上。

具有 pod 关联性的 Pod 配置文件示例

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity: 1
      requiredDuringSchedulingIgnoredDuringExecution: 2
      - labelSelector:
          matchExpressions:
          - key: security 3
            operator: In 4
            values:
            - S1 5
        topologyKey: failure-domain.beta.kubernetes.io/zone
  containers:
  - name: with-pod-affinity
    image: docker.io/ocpqe/hello-pod

1
用于配置 pod 关联性的小节。
2
定义必要规则。
3 5
必须匹配键和值(标签)才会应用该规则。
4
运算符表示现有 pod 上的标签和新 pod 规格中 matchExpression 参数的值集合之间的关系。可以是 InNotInExistsDoesNotExist

具有 pod 反关联性的 Pod 配置文件示例

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-antiaffinity
spec:
  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

1
用于配置 pod 反关联性的小节。
2
定义偏好规则。
3
为偏好规则指定权重。优先选择权重最高的节点。
4
描述用来决定何时应用反关联性规则的 pod 标签。指定标签的键和值。
5
运算符表示现有 pod 上的标签和新 pod 规格中 matchExpression 参数的值集合之间的关系。可以是 InNotInExistsDoesNotExist
注意

如果节点标签在运行时改变,使得不再满足 pod 上的关联性规则,pod 会继续在该节点上运行。

4.3.2. 配置 pod 关联性规则

以下步骤演示了一个简单的双 pod 配置,它创建一个带有某标签的 pod,以及一个使用关联性来允许随着该 pod 一起调度的 pod。

注意

您不能直接将关联性添加到调度的 pod 中。

流程

  1. 创建 pod 规格中具有特定标签的 pod:

    1. 使用以下内容创建 YAML 文件:

      apiVersion: v1
      kind: Pod
      metadata:
        name: security-s1
        labels:
          security: S1
      spec:
        containers:
        - name: security-s1
          image: docker.io/ocpqe/hello-pod
    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

4.3.3. 配置 pod 反关联性规则

以下步骤演示了一个简单的双 pod 配置,它创建一个带有某标签的 pod,以及一个使用反关联性偏好规则来尝试阻止随着该 pod 一起调度的 pod。

注意

您不能直接将关联性添加到调度的 pod 中。

流程

  1. 创建 pod 规格中具有特定标签的 pod:

    1. 使用以下内容创建 YAML 文件:

      apiVersion: v1
      kind: Pod
      metadata:
        name: security-s1
        labels:
          security: S1
      spec:
        containers:
        - name: security-s1
          image: docker.io/ocpqe/hello-pod
    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

4.3.4. pod 关联性和反关联性规则示例

以下示例演示了 pod 关联性和 pod 反关联性。

4.3.4.1. Pod 关联性

以下示例演示了具有匹配标签和标签选择器的 pod 的 pod 关联性。

  • pod team4 具有标签 team:4

    apiVersion: v1
    kind: Pod
    metadata:
      name: team4
      labels:
         team: "4"
    #...
    spec:
      containers:
      - name: ocp
        image: docker.io/ocpqe/hello-pod
    #...
  • pod team4apodAffinity 下具有标签选择器 team:4

    apiVersion: v1
    kind: Pod
    metadata:
      name: team4a
    #...
    spec:
      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
    #...
  • team4a pod 调度到与 team4 pod 相同的节点上。

4.3.4.2. Pod 反关联性

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

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

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-s1
      labels:
        security: s1
    #...
    spec:
      containers:
      - name: ocp
        image: docker.io/ocpqe/hello-pod
    #...
  • pod pod-s2podAntiAffinity 下具有标签选择器 security:s1

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-s2
    #...
    spec:
      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
    #...
  • pod pod-s2 无法调度到与 pod-s1 相同的节点上。

4.3.4.3. 无匹配标签的 Pod 反关联性

以下示例演示了在没有匹配标签和标签选择器时的 pod 的 pod 关联性。

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

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-s1
      labels:
        security: s1
    #...
    spec:
      containers:
      - name: ocp
        image: docker.io/ocpqe/hello-pod
    #...
  • pod pod-s2 具有标签选择器 security:s2

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-s2
    #...
    spec:
      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
    #...
  • 除非节点上具有带 security:s2 标签的 pod,否则不会调度 pod-s2。如果没有具有该标签的其他 pod,新 pod 会保持在待处理状态:

    输出示例

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

4.3.5. 使用 pod 关联性和反关联性来控制安装 Operator 的位置

默认情况下,当安装 Operator 时,OpenShift Container Platform 会随机将 Operator pod 安装到其中一个 worker 节点。然而,在某些情况下,您可能希望该 pod 调度到特定节点或一组节点上。

以下示例描述了您可能希望将 Operator pod 调度到特定节点或一组节点的情况:

  • 如果 Operator 需要特定的平台,如 amd64arm64
  • 如果 Operator 需要特定的操作系统,如 Linux 或 Windows
  • 如果您希望 Operator 在同一个主机上或位于同一机架的主机上工作
  • 如果您希望 Operator 在整个基础架构中分散,以避免因为网络或硬件问题而停机

您可以通过向 Operator 的 Subscription 对象添加 pod 关联性或反关联性来控制 Operator pod 的安装位置。

以下示例演示了如何使用 pod 反关联性来防止从具有特定标签的 pod 中安装自定义 Metrics Autoscaler Operator:

将 Operator pod 放置到一个或多个特定节点的 Pod 关联性示例

apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  name: openshift-custom-metrics-autoscaler-operator
  namespace: openshift-keda
spec:
  name: my-package
  source: my-operators
  sourceNamespace: operator-registries
  config:
    affinity:
      podAffinity: 1
        requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - test
          topologyKey: kubernetes.io/hostname
#...

1
将 Operator 的 pod 放置到具有 app=test 标签的 pod 的节点上的 pod 关联性。

防止 Operator pod 来自一个或多个特定节点的 Pod 反关联性示例

apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  name: openshift-custom-metrics-autoscaler-operator
  namespace: openshift-keda
spec:
  name: my-package
  source: my-operators
  sourceNamespace: operator-registries
  config:
    affinity:
      podAntiAffinity: 1
        requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
            - key: cpu
              operator: In
              values:
              - high
          topologyKey: kubernetes.io/hostname
#...

1
一个 pod 反关联性,它可防止 Operator 的 pod 调度到具有 cpu=high 标签的 pod 的节点上。

流程

要控制 Operator pod 的放置,请完成以下步骤:

  1. 照常安装 Operator。
  2. 如果需要,请确保您的节点已标记为正确响应关联性。
  3. 编辑 Operator Subscription 对象以添加关联性:

    apiVersion: operators.coreos.com/v1alpha1
    kind: Subscription
    metadata:
      name: openshift-custom-metrics-autoscaler-operator
      namespace: openshift-keda
    spec:
      name: my-package
      source: my-operators
      sourceNamespace: operator-registries
      config:
        affinity:
          podAntiAffinity: 1
            requiredDuringSchedulingIgnoredDuringExecution:
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                  - key: kubernetes.io/hostname
                    operator: In
                    values:
                    - ip-10-0-185-229.ec2.internal
                topologyKey: topology.kubernetes.io/zone
    #...
    1
    添加 podAffinitypodAntiAffinity

验证

  • 要确保 pod 部署到特定的节点上,请运行以下命令:

    $ oc get pods -o wide

    输出示例

    NAME                                                  READY   STATUS    RESTARTS   AGE   IP            NODE                           NOMINATED NODE   READINESS GATES
    custom-metrics-autoscaler-operator-5dcc45d656-bhshg   1/1     Running   0          50s   10.131.0.20   ip-10-0-185-229.ec2.internal   <none>           <none>