×

亲和性是Pod的一个属性,它控制Pod首选在其上调度的节点。反亲和性是Pod的一个属性,它阻止Pod在一个节点上调度。

在Red Hat OpenShift Service on AWS中,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的节点上调度,该Pod的标签具有键security和值S1。Pod反亲和性规则表示Pod更倾向于不在节点上调度,如果该节点正在运行具有标签的Pod,则该标签的键为security,值为S2

具有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 **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 **team4a** 在podAffinity下具有标签选择器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-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** 在podAntiAffinity下具有标签选择器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-s2** Pod不能调度到与pod-s1相同的节点上。

没有匹配标签的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-s2** Pod。如果没有其他具有该标签的Pod,则新Pod将保持挂起状态。

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