自定义弹性资源优先级调度是阿里云提供的弹性调度策略。您可以在应用发布或扩容过程中,自定义资源策略(ResourcePolicy),设置应用实例Pod被调度到不同类型节点资源的顺序。同时在缩容过程中按照原调度顺序逆序缩容。本文介绍如何使用自定义弹性资源优先级调度功能。

前提条件

  • Kubernetes集群为ACK Pro且版本为1.20.11及以上。关于如何升级,请参见升级ACK集群K8s版本
  • 对于不同ACK版本的集群,调度器版本需要满足以下要求。关于调度器各版本支持的功能,请参见kube-scheduler
    ACK版本调度器版本
    1.201.20.4-ack-7.0及以上
    1.221.22.15-ack-2.0及以上
    1.24v1.24.3-ack-2.0及以上
  • 需要使用ECI资源时,已部署ack-virtual-node。具体操作,请参见ACK使用ECI

使用限制

  • 本功能与pod-deletion-cost冲突,不能同时使用。关于pod-deletion-cost的更多信息,请参见pod-deletion-cost
  • 本功能暂不支持与使用ECI弹性调度混合使用。关于ECI弹性调度的更多信息,请参见使用ECI弹性调度
  • 本功能目前使用的是BestEffort策略,无法保证一定按照逆序缩容。
  • 创建ResourcePolicy时请保证当前无已调度的Pod,否则已调度的Pod将会被最优先缩容。
  • 修改ResourcePolicy的策略时,已调度的Pod将按照原ResourcePolicy的顺序进行缩容,新建的Pod将按照更新后ResourcePolicy的顺序进行缩容。
  • 使用本功能时,ECI类型的Unit必须作为最后一个Unit使用。
  • 本功能暂不支持在自定义优先级调度时触发弹性资源池生产资源。

使用方式

创建ResourcePolicy定义弹性资源优先级:

apiVersion: scheduling.alibabacloud.com/v1alpha1
kind: ResourcePolicy
metadata:
  name: xxx
  namespace: xxx
spec:
  selector:
    key1: value1
  strategy: prefer
  units:
  - resource: ecs
    nodeSelector:
      key2: value2
  - resource: ecs
    nodeSelector:
      key3: value3
  - resource: eci
  • selector:声明ResourcePolicy作用于同一命名空间下label上打了key1=value1的Pod。
  • strategy:调度策略选择,目前只支持prefer
  • units:用户自定义的调度单元。扩容时,将按照units下资源的顺序进行扩容;缩容时,将按照逆序进行缩容。
    • resource:弹性资源的类型,目前支持eciecs两种类型。
    • nodeSelector:用nodelabel标识该调度单元下的节点,只对ecs资源生效。

使用场景示例

场景一:基于节点池优先级调度

当您需要部署一个Deployment,此时集群有两个节点池,一个是节点池A,一个是节点池B。您希望优先调度节点池A,资源不足时调度节点池B。当进行缩容时,优先缩容在节点池B中的Pod,然后缩容节点池A中的Pod。如下示例中,cn-beijing.10.0.3.137cn-beijing.10.0.3.138属于节点池A, cn-beijing.10.0.6.47cn-beijing.10.0.6.46属于节点池B,节点规格均为2核4 GB。基于节点池优先级调度的具体操作步骤如下:

  1. 使用以下YAML内容,创建ResourcePolicy自定义节点池调度顺序。
    apiVersion: scheduling.alibabacloud.com/v1alpha1
    kind: ResourcePolicy
    metadata:
      name: nginx
      namespace: default
    spec:
      selector:
        app: nginx # 此处要与后续创建的Pod的label相关联。
      strategy: prefer
      units:
      - resource: ecs
        nodeSelector:
          alibabacloud.com/nodepool-id: np7ec79f2235954e879de07b780058****
      - resource: ecs
        nodeSelector:
          alibabacloud.com/nodepool-id: npab2df797738644e3a7b7cbf532bb****
    说明 节点池ID可以从所在集群的节点管理 > 节点池中获取。具体操作,请参见创建节点池
  2. 使用以下YAML内容创建Deployment,部署2个Pod。
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          name: nginx
          labels:
            app: nginx # 此处要与上一步创建的ResourcePolicy的selector相关联。
        spec:
          containers:
          - name: nginx
            image: nginx
            resources:
              limits:
                cpu: 2
              requests:
                cpu: 2
  3. 创建应用Nginx并查看部署结果。
    1. 执行以下命令,创建应用Nginx。
      kubectl apply -f nginx.yaml

      预期输出:

      deployment.apps/nginx created
    2. 执行以下命令,查看部署结果。
      kubectl get pods -o wide

      预期输出:

      NAME                    READY   STATUS    RESTARTS   AGE   IP               NODE                    NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-b****   1/1     Running   0          17s   172.29.112.216   cn-beijing.10.0.3.137   <none>           <none>
      nginx-9cdf7bbf9-k****   1/1     Running   0          17s   172.29.113.24    cn-beijing.10.0.3.138   <none>           <none>
      由预期输出得到,前两个Pod被调度在节点池A的节点上。
  4. 对Pod进行扩容。
    1. 执行以下命令,将Pod扩容到4个。
      kubectl scale deployment nginx --replicas 4                      

      预期输出:

      deployment.apps/nginx scaled
    2. 执行以下命令,查看Pod状态。
      kubectl get pods -o wide

      预期输出:

      NAME                    READY   STATUS    RESTARTS   AGE    IP               NODE                    NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-b****   1/1     Running   0          101s   172.29.112.216   cn-beijing.10.0.3.137   <none>           <none>
      nginx-9cdf7bbf9-k****   1/1     Running   0          101s   172.29.113.24    cn-beijing.10.0.3.138   <none>           <none>
      nginx-9cdf7bbf9-m****   1/1     Running   0          18s    172.29.113.156   cn-beijing.10.0.6.47    <none>           <none>
      nginx-9cdf7bbf9-x****   1/1     Running   0          18s    172.29.113.89    cn-beijing.10.0.6.46    <none>           <none>

      由预期输出得到,当节点池A的节点资源不足时,调度到节点池B的节点上。

  5. 对Pod进行缩容。
    1. 执行以下命令,将Pod从4个副本缩容到2个。
      kubectl scale deployment nginx --replicas 2

      预期输出:

      deployment.apps/nginx scaled
    2. 执行以下命令,查看Pod状态。
      kubectl get pods -o wide

      预期输出:

      NAME                    READY   STATUS        RESTARTS   AGE     IP               NODE                    NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-b****   1/1     Running       0          2m41s   172.29.112.216   cn-beijing.10.0.3.137   <none>           <none>
      nginx-9cdf7bbf9-k****   1/1     Running       0          2m41s   172.29.113.24    cn-beijing.10.0.3.138   <none>           <none>
      nginx-9cdf7bbf9-m****   0/1     Terminating   0          78s     172.29.113.156   cn-beijing.10.0.6.47    <none>           <none>
      nginx-9cdf7bbf9-x****   0/1     Terminating   0          78s     172.29.113.89    cn-beijing.10.0.6.46    <none>           <none>

      由预期输出得到,根据调度的逆序,优先缩容在节点池B中的Pod。

场景二:ECS和ECI混合调度

当您需要部署一个Deployment,此时集群中有3种类型的资源,分别是包年包月的ECS、按量付费的ECS和弹性实例ECI。为了降低资源使用成本,您希望部署的服务优先调度顺序依次为:包年包月的ECS、按量付费的ECS、弹性实例ECI。同时在服务缩容时优先删除ECI上的Pod,释放ECI的节点资源,然后删除按量付费的ECS上的Pod,最后删除包年包月的ECS上的Pod。示例节点为2核4 GB,ECS和ECI混合调度的具体操作步骤如下:

  1. 执行以下命令,对不同付费类型的节点分别打不同的label(此处也可以通过节点池的功能自动标识label)。
    kubectl label node cn-beijing.10.0.3.137 paidtype=subscription
    kubectl label node cn-beijing.10.0.3.138 paidtype=subscription
    kubectl label node cn-beijing.10.0.6.46 paidtype=pay-as-you-go
    kubectl label node cn-beijing.10.0.6.47 paidtype=pay-as-you-go
  2. 使用以下YAML内容,创建ResourcePolicy自定义节点池调度顺序。
    apiVersion: scheduling.alibabacloud.com/v1alpha1
    kind: ResourcePolicy
    metadata:
      name: nginx
      namespace: default
    spec:
      selector:
        app: nginx # 此处要与后续创建的Pod的label相关联。
      strategy: prefer
      units:
      - resource: ecs
        nodeSelector:
          paidtype: subscription
      - resource: ecs
        nodeSelector:
          paidtype: pay-as-you-go
      - resource: eci
  3. 使用以下YAML内容创建Deployment,部署2个Pod。
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          name: nginx
          labels:
            app: nginx # 此处要上一步创建的ResourcePolicy的selector相关联。
        spec:
          containers:
          - name: nginx
            image: nginx
            resources:
              limits:
                cpu: 2
              requests:
                cpu: 2
  4. 创建应用Nginx并查看部署结果。
    1. 执行以下命令,创建应用Nginx。
      kubectl apply -f nginx.yaml

      预期输出:

      deployment.apps/nginx created
    2. 执行以下命令,查看部署结果。
      kubectl get pods -o wide

      预期输出:

      NAME                    READY   STATUS    RESTARTS   AGE   IP               NODE                    NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-b****   1/1     Running   0          66s   172.29.112.215   cn-beijing.10.0.3.137   <none>           <none>
      nginx-9cdf7bbf9-r****   1/1     Running   0          66s   172.29.113.23    cn-beijing.10.0.3.138   <none>           <none>

      由预期输出得到,前两个Pod被调度到labelpaidtype=subscription的节点上。

  5. 对Pod进行扩容。
    1. 执行以下命令,将Pod扩容到4个。
      kubectl scale deployment nginx --replicas 4

      预期输出:

      deployment.apps/nginx scaled
    2. 执行以下命令,查看Pod状态。
      kubectl get pods -o wide

      预期输出:

      NAME                    READY   STATUS    RESTARTS   AGE     IP               NODE                    NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-4****   1/1     Running   0          16s     172.29.113.155   cn-beijing.10.0.6.47    <none>           <none>
      nginx-9cdf7bbf9-b****   1/1     Running   0          3m48s   172.29.112.215   cn-beijing.10.0.3.137   <none>           <none>
      nginx-9cdf7bbf9-f****   1/1     Running   0          16s     172.29.113.88    cn-beijing.10.0.6.46    <none>           <none>
      nginx-9cdf7bbf9-r****   1/1     Running   0          3m48s   172.29.113.23    cn-beijing.10.0.3.138   <none>           <none>

      由预期输出得到,当labelpaidtype=subscription的节点资源不足时,调度到labelpaidtype=pay-as-you-go的节点上。

    3. 执行以下命令,将Pod扩容到6个。
      kubectl scale deployment nginx --replicas 6

      预期输出:

      deployment.apps/nginx scaled
    4. 执行以下命令,查看Pod状态。
      kubectl get pods -o wide

      预期输出:

      NAME                    READY   STATUS    RESTARTS   AGE     IP               NODE                           NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-4****   1/1     Running   0          3m10s   172.29.113.155   cn-beijing.10.0.6.47           <none>           <none>
      nginx-9cdf7bbf9-b****   1/1     Running   0          6m42s   172.29.112.215   cn-beijing.10.0.3.137          <none>           <none>
      nginx-9cdf7bbf9-f****   1/1     Running   0          3m10s   172.29.113.88    cn-beijing.10.0.6.46           <none>           <none>
      nginx-9cdf7bbf9-r****   1/1     Running   0          6m42s   172.29.113.23    cn-beijing.10.0.3.138          <none>           <none>
      nginx-9cdf7bbf9-s****   1/1     Running   0          36s     10.0.6.68        virtual-kubelet-cn-beijing-j   <none>           <none>
      nginx-9cdf7bbf9-v****   1/1     Running   0          36s     10.0.6.67        virtual-kubelet-cn-beijing-j   <none>           <none>

      由预期输出得到,ECS上的资源不足,Pod被调度ECI的资源上。

  6. 对Pod进行缩容。
    1. 执行以下命令,将Pod从6个副本缩容到4个。
      kubectl scale deployment nginx --replicas 4

      预期输出:

      deployment.apps/nginx scaled
    2. 执行以下命令,命令查看Pod状态。
      kubectl get pods -o wide

      预期输出:

      NAME                    READY   STATUS        RESTARTS   AGE     IP               NODE                           NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-4****   1/1     Running       0          4m59s   172.29.113.155   cn-beijing.10.0.6.47           <none>           <none>
      nginx-9cdf7bbf9-b****   1/1     Running       0          8m31s   172.29.112.215   cn-beijing.10.0.3.137          <none>           <none>
      nginx-9cdf7bbf9-f****   1/1     Running       0          4m59s   172.29.113.88    cn-beijing.10.0.6.46           <none>           <none>
      nginx-9cdf7bbf9-r****   1/1     Running       0          8m31s   172.29.113.23    cn-beijing.10.0.3.138          <none>           <none>
      nginx-9cdf7bbf9-s****   1/1     Terminating   0          2m25s   10.0.6.68        virtual-kubelet-cn-beijing-j   <none>           <none>
      nginx-9cdf7bbf9-v****   1/1     Terminating   0          2m25s   10.0.6.67        virtual-kubelet-cn-beijing-j   <none>           <none>

      由预期输出得到,根据调度节点的逆序,优先缩容在ECI上的Pod。

    3. 执行以下命令,将4个副本缩容到2个。
      kubectl scale deployment nginx --replicas 2

      预期输出:

      deployment.apps/nginx scaled
    4. 执行以下命令,查看Pod状态。
      kubectl get pods -o wide

      预期输出:

      NAME                    READY   STATUS        RESTARTS   AGE     IP               NODE                    NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-4****   0/1     Terminating   0          6m43s   172.29.113.155   cn-beijing.10.0.6.47    <none>           <none>
      nginx-9cdf7bbf9-b****   1/1     Running       0          10m     172.29.112.215   cn-beijing.10.0.3.137   <none>           <none>
      nginx-9cdf7bbf9-f****   0/1     Terminating   0          6m43s   172.29.113.88    cn-beijing.10.0.6.46    <none>           <none>
      nginx-9cdf7bbf9-r****   1/1     Running       0          10m     172.29.113.23    cn-beijing.10.0.3.138   <none>           <none>

      由预期输出得到,根据调度节点的逆序,优先缩容位于labelpaidtype=pay-as-you-go节点上的Pod。

    5. 执行以下命令,查看Pod状态。
      kubectl get pods -o wide

      预期输出:

      NAME                    READY   STATUS    RESTARTS   AGE   IP               NODE                    NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-b****   1/1     Running   0          11m   172.29.112.215   cn-beijing.10.0.3.137   <none>           <none>
      nginx-9cdf7bbf9-r****   1/1     Running   0          11m   172.29.113.23    cn-beijing.10.0.3.138   <none>           <none>

      由预期输出得到,当前只存在labelpaidtype=subscription节点上的Pod。