Pod间亲和性调度

Pod间亲和性调度策略,用于表达Pod之间的亲和性偏好,相较于节点亲和性,Pod间亲和性调度支持基于已经在虚拟节点上运行的Pod的标签来约束Pod可以调度到的范围。在ACS集群中,您可以通过Kubernetes原生调度语义实现Pod间亲和性调度,通过在podAffinity或podAntiAffinity字段中填写拓扑域和标签规则,可以将Pod调度到指定的拓扑域。本文详细介绍在ACS中使用Pod间亲和性调度的约束条件和使用方式。

前提条件

  • 已创建ACS集群。具体操作,请参见创建ACS集群

  • 已安装kube-scheduler组件,详见kube-scheduler

  • 已安装acs-virtual-node,版本为v2.12.0-acs.4或以上。

注意事项

Pod间亲和性功能包括亲和性和反亲和性两种使用方式,两种方式的协议格式相同,都由requiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecution组成,其中必填的协议字段是拓扑域标签TopologyKey,对应虚拟节点中的标签。针对不同种类的虚拟节点,ACS分别支持以下拓扑标签。

虚拟节点类型

Label

含义

样例

普通虚拟节点

topology.kubernetes.io/zone

网络可用区

topology.kubernetes.io/zone: cn-shanghai-b

ACS支持多种计算类型(compute class),对于不同的compute class,在使用Pod间亲和性的其他协议时还存在以下约束。

  • requiredDuringSchedulingIgnoredDuringExecution协议。

    计算类

    字段

    含义

    约束条件

    • 通用型

    • 性能型

    LabelSelector

    用于查找匹配的Pod,匹配此标签的Pod将被统计,以确定相应拓扑域中Pod的数量。

    其他计算类型(GPU型、高性能网络GPU型)的Pod在计算匹配数量时将不参与统计。

    Namespaces

    用于指定查找匹配命名空间,搭配LabelSelector使用。

    NamespaceSelector

    与Namespaces字段类似,区别在于是通过命名空间的标签进行查找。

    • GPU型

    LabelSelector

    同上,略。

    其他计算类型(通用型、性能型)的Pod在计算匹配数量时将不参与统计。

    Namespaces

    同上,略。

    不支持

    NamespaceSelector

    同上,略。

    不支持

  • preferredDuringSchedulingIgnoredDuringExecution协议。

    计算类

    字段

    含义

    约束条件

    • 通用型

    • 性能型

    LabelSelector

    Namespaces

    NamespaceSelector

    其他计算类型(GPU型、高性能网络GPU型)的Pod在计算匹配数量时将不参与统计。

有关各字段详细信息的说明,请参见Pod间亲和性与反亲和性

操作示例

示例中展示了通过配置podAffinity将应用调度到指定可用区的效果。

  1. 执行以下命令查看集群中的虚拟节点。

    kubectl get node

    预期输出:

    NAME                            STATUS   ROLES   AGE     VERSION
    virtual-kubelet-cn-hangzhou-i   Ready    agent   5h42m   v1.28.3-xx
    virtual-kubelet-cn-hangzhou-j   Ready    agent   5h42m   v1.28.3-xx
  2. 使用以下YAML内容,创建with-affinity-pod.yaml文件。

    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        pod-affinity-label: with-pod-affinity
      name: with-affinity-label-pod
    spec:
      containers:
        - args:
            - 'infinity'
          command:
            - sleep
          image: registry-cn-hangzhou.ack.aliyuncs.com/acs/stress:v1.0.4
          imagePullPolicy: IfNotPresent
          name: stress
          resources:
            limits:
              cpu: '1'
              memory: 1Gi
            requests:
              cpu: '1'
              memory: 1Gi
  3. 执行以下命令,将with-affinity-label-pod部署到集群。

    kubectl apply -f with-affinity-pod.yaml
  4. 执行以下命令,查看Pod调度的分布情况。

    kubectl get pod -o wide

    预期输出:

    NAME                      READY   STATUS    RESTARTS   AGE   IP              NODE                            NOMINATED NODE   READINESS GATES
    with-affinity-label-pod   1/1     Running   0          75s   192.168.xx.xxx  virtual-kubelet-cn-hangzhou-i   <none>           <none>

    可以看到Pod已经被调度到可用区cn-hangzhou-i。

  5. 使用以下YAML内容,创建origin-affinity-pod.yaml文件。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: dep-pod-affinity
      labels:
        app: pod-affinity-demo
    spec:
      replicas: 4
      selector:
        matchLabels:
          app: pod-affinity-demo
      template:
        metadata:
          labels:
            app: pod-affinity-demo
        spec:
          containers:
          - name: pod-affinity-demo
            image: registry-cn-hangzhou.ack.aliyuncs.com/acs/stress:v1.0.4
            command:
            - "sleep"
            - "infinity"
            resources:
              limits:
                cpu: '1'
                memory: 1Gi
              requests:
                cpu: '1'
                memory: 1Gi
          # 指定Pod间亲和性,表示需要和带有<pod-affinity-label:with-pod-affinity>标签的Pod部署在同一个可用区
          affinity:
            podAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
              - labelSelector:
                  matchExpressions:
                  - key: pod-affinity-label
                    operator: In
                    values:
                    - with-pod-affinity
                topologyKey: topology.kubernetes.io/zone
  6. 执行以下命令,将origin-affinity-pod.yaml部署到集群。

    kubectl apply -f origin-affinity-pod.yaml
  7. 执行以下命令,查看Pod调度的分布情况。

    kubectl get pod -o wide

    预期输出:

    NAME                                READY   STATUS    RESTARTS   AGE     IP              NODE                            NOMINATED NODE   READINESS GATES
    dep-pod-affinity-6b9d4f7c87-5jlfx   1/1     Running   0          3m26s   192.168.xx.xxx  virtual-kubelet-cn-hangzhou-i   <none>           <none>
    dep-pod-affinity-6b9d4f7c87-hwdpc   1/1     Running   0          3m26s   192.168.xx.xxx  virtual-kubelet-cn-hangzhou-i   <none>           <none>
    dep-pod-affinity-6b9d4f7c87-jfcrq   1/1     Running   0          3m26s   192.168.xx.xxx  virtual-kubelet-cn-hangzhou-i   <none>           <none>
    dep-pod-affinity-6b9d4f7c87-xwbfr   1/1     Running   0          3m26s   192.168.xx.xxx  virtual-kubelet-cn-hangzhou-i   <none>           <none>
    with-affinity-label-pod             1/1     Running   0          6m30s   192.168.xx.xxx  virtual-kubelet-cn-hangzhou-i   <none>           <none>

    可以看到所有Pod都分布同一个可用区。