自定义弹性资源优先级调度是阿里云提供的弹性调度策略。您可以在应用发布或扩容过程中,自定义资源策略(ResourcePolicy),设置应用实例Pod被调度到不同类型节点资源的顺序。同时,在缩容过程中按照原调度顺序逆序缩容。
自调度器版本v1.x.x-aliyun-6.4开始,自定义弹性资源优先级功能的ignorePreviousPod字段的默认值将修改为False,ignoreTerminatingPod字段的默认值将修改为True。涉及这些字段的存量ResourcePolicy不受影响,后续更新也不受影响。
前提条件
Kubernetes集群为ACK Pro且版本为1.20.11及以上。关于如何升级,请参见升级ACK集群K8s版本。
对于不同ACK版本的集群,调度器版本需要满足以下要求。关于调度器各版本支持的功能,请参见kube-scheduler。
ACK版本
调度器版本
1.20
v1.20.4-ack-7.0及以上
1.22
v1.22.15-ack-2.0及以上
1.24及以上
所有版本均支持
需要使用ECI资源时,已部署ack-virtual-node。具体操作,请参见ACK使用ECI。
使用限制
本功能与pod-deletion-cost冲突,不能同时使用。关于pod-deletion-cost的更多信息,请参见pod-deletion-cost。
本功能暂不支持与使用ECI弹性调度混合使用。关于ECI弹性调度的更多信息,请参见使用ECI弹性调度。
本功能目前使用的是BestEffort策略,无法保证一定按照逆序缩容。
max字段仅在集群版本为1.22及以上,且调度器版本为5.0及以上的版本中开启。
与弹性节点池同时使用时,可能导致弹性节点池无效弹出节点。使用时请将弹性节点池包含在某个Unit中,且弹性节点池的Unit不要设置max字段。
若您的调度器为5.0版本以下或集群版本为1.20及以下,请注意在ResourcePolicy创建前存在的Pod会在缩容时最先缩容。
若您的调度器为6.1版本以下或集群版本为1.20及以下,在与ResourcePolicy关联的Pod未完全删除时,请不要对ResourcePolicy进行修改。
使用方式
创建ResourcePolicy定义弹性资源优先级:
apiVersion: scheduling.alibabacloud.com/v1alpha1
kind: ResourcePolicy
metadata:
name: test
namespace: default
spec:
ignorePreviousPod: false
ignoreTerminatingPod: true
matchLabelKeys:
- pod-template-hash
preemptPolicy: AfterAllUnits
selector:
key1: value1
strategy: prefer
units:
- nodeSelector:
unit: first
resource: ecs
- nodeSelector:
unit: second
max: 10
resource: ecs
- resource: eci
whenTryNextUnits:
policy: TimeoutOrExceedMax
timeout: 1m
selector
:声明ResourcePolicy作用于同一命名空间下label
上打了key1=value1
的Pod。selector
为空时将对该命名空间下所有Pod生效。strategy
:调度策略选择,目前只支持prefer
。units
:用户自定义的调度单元。扩容时,将按照units
下资源的顺序进行扩容;缩容时,将按照逆序进行缩容。resource
:弹性资源的类型,目前支持eci
、ecs
以及elastic
三种类型。elastic
在集群版本为1.24以上,且调度器版本为6.4.3及以上版本可用。nodeSelector
:用node
的label
标识该调度单元下的节点,只对ecs
资源生效。max
(调度器为5.0版本及以上可用):在本调度单元中最多能调度的Pod的副本数。
preemptPolicy
(调度器为6.1版本及以上可用):当ResourcePolicy中存在多个unit
时,是否允许ResourcePolicy在每个Unit调度失败时尝试抢占。BeforeNextUnit表示调度器将在每个Unit调度失败时尝试抢占,AfterAllUnits表示ResourcePolicy只在最后一个Unit调度失败时尝试抢占。默认为AfterAllUnits。ignorePreviousPod
(调度器为6.1版本及以上可用):需要与units
中的max
一起使用。该值为true
时,在进行Pod数量统计时将忽略ResourcePolicy创建之前已经调度的Pod。ignoreTerminatingPod
(调度器为6.1版本及以上可用):需要与units
中的max
一起使用。该值为true
时,在进行Pod数量统计时将忽略处于Terminating状态的Pod。matchLabelKeys
(调度器为6.2版本及以上可用):需要与units
中的max
一起使用,Pod会根据自身Label的值进行分组,不同分组的Pod将适用于不同的max
计数。当使用该功能时,若Pod上缺少任务matchLabelKeys
中申明的Label,Pod将会被拒绝调度。whenTryNextUnits
(集群版本1.24及以上,调度器为6.4版本及以上可用):描述Pod在何种情况下被允许使用后续Unit中的资源。policy
:代表Pod采用的策略。可选值包括ExceedMax
、LackResourceAndNoTerminating
、TimeoutOrExceedMax
、LackResourceOrExceedMax
(默认值)。ExceedMax
:若当前Unit的Max未设置,或当前Unit中的Pod数量大于等于设置的Max值,允许Pod使用下一级资源。该策略可以与自动伸缩以及ECI配合,达到优先尝试节点池自动伸缩的效果。重要请注意,如果自动伸缩节点池长时间无法弹出节点,此策略可能导致Pod Pending。
当前由于Cluster Autoscaler未感知ResourcePolicy的Max限制,实际弹出的实例数可能会多于设置的Max值。该问题将在后续版本中进行优化。
TimeoutOrExceedMax
:当满足以下条件之一:当前Unit的Max已设置且Unit中的Pod数量小于设置的Max值时;
当前Unit的Max未设置,且当前Unit的Type为
elastic
;
若当前Unit资源不足以调度Pod,则在当前Unit中等待,等待时间的最大长度为
timeout
。该策略可以与自动伸缩以及ECI配合,达到优先尝试节点池自动伸缩,并且在超时后自动使用eci的效果。- 重要
请注意,若Timeout期间内弹出节点,在Timeout期间内节点未达到Ready状态,且Pod未容忍NotReady的污点,则Pod仍然会被调度到ECI上。
LackResourceOrExceedMax
:若当前Unit中的Pod数量大于等于设置的Max值,或当前Unit中已没有多余资源,允许Pod使用下一级资源。该策略为默认策略,适合大部分场景的基本需求。LackResourceAndNoTerminating
:若当前Unit中的Pod数量大于等于设置的Max值,或当前Unit中已没有多余资源,并且当前Unit中无处于Terminating状态的Pod时,允许Pod使用下一级资源。该策略适合与滚动更新策略配置使用,达到滚动更新时不会由于Terminating导致新Pod滚动到后续Unit上的效果。
timeout
:当policy为timeoutOrExceedMaxPolicy
时,该字段可以被用来描述超时时长,当该字段为空值时,我们将此值视为15分钟。
使用场景示例
场景一:基于节点池优先级调度
当您需要部署一个Deployment,此时集群有两个节点池,一个是节点池A,一个是节点池B。您希望优先调度节点池A,资源不足时调度节点池B。当进行缩容时,优先缩容在节点池B中的Pod,然后缩容节点池A中的Pod。如下示例中,cn-beijing.10.0.3.137
和cn-beijing.10.0.3.138
属于节点池A, cn-beijing.10.0.6.47
和cn-beijing.10.0.6.46
属于节点池B,节点规格均为2核4 GB。基于节点池优先级调度的具体操作步骤如下:
使用以下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可以从所在集群的节点管理 > 节点池中获取。具体操作,请参见创建节点池。
使用以下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
创建应用Nginx并查看部署结果。
执行以下命令,创建应用Nginx。
kubectl apply -f nginx.yaml
预期输出:
deployment.apps/nginx created
执行以下命令,查看部署结果。
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的节点上。
对Pod进行扩容。
执行以下命令,将Pod扩容到4个。
kubectl scale deployment nginx --replicas 4
预期输出:
deployment.apps/nginx scaled
执行以下命令,查看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的节点上。
对Pod进行缩容。
执行以下命令,将Pod从4个副本缩容到2个。
kubectl scale deployment nginx --replicas 2
预期输出:
deployment.apps/nginx scaled
执行以下命令,查看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混合调度的具体操作步骤如下:
执行以下命令,对不同付费类型的节点分别打不同的
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
使用以下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
使用以下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
创建应用Nginx并查看部署结果。
执行以下命令,创建应用Nginx。
kubectl apply -f nginx.yaml
预期输出:
deployment.apps/nginx created
执行以下命令,查看部署结果。
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被调度到
label
为paidtype=subscription
的节点上。
对Pod进行扩容。
执行以下命令,将Pod扩容到4个。
kubectl scale deployment nginx --replicas 4
预期输出:
deployment.apps/nginx scaled
执行以下命令,查看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>
由预期输出得到,当
label
为paidtype=subscription
的节点资源不足时,调度到label
为paidtype=pay-as-you-go
的节点上。执行以下命令,将Pod扩容到6个。
kubectl scale deployment nginx --replicas 6
预期输出:
deployment.apps/nginx scaled
执行以下命令,查看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的资源上。
对Pod进行缩容。
执行以下命令,将Pod从6个副本缩容到4个。
kubectl scale deployment nginx --replicas 4
预期输出:
deployment.apps/nginx scaled
执行以下命令,命令查看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。
执行以下命令,将4个副本缩容到2个。
kubectl scale deployment nginx --replicas 2
预期输出:
deployment.apps/nginx scaled
执行以下命令,查看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>
由预期输出得到,根据调度节点的逆序,优先缩容位于
label
为paidtype=pay-as-you-go
节点上的Pod。执行以下命令,查看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>
由预期输出得到,当前只存在
label
为paidtype=subscription
节点上的Pod。
相关文档
在ACK集群中部署服务时,您可以使用容忍度和节点亲和性来声明只使用ECS或ECI弹性资源,或者是在ECS资源不足时自动申请ECI资源。通过配置调度策略,您可以在不同工作负载场景下实现对弹性资源的不同需求。详细信息,请参见指定ECS和ECI的资源分配。
高可用以及高性能是分布式任务执行过程中的重要要求。在ACK集群Pro版中,您可以通过Kubernetes原生调度语义实现分布式任务的跨可用区打散,以达到高可用区部署的要求,或者通过Kubernetes原生调度语义实现分布式任务在指定可用区中的亲和性部署,以达到高性能部署的要求。详细信息,请参见实现ECI Pod可用区打散以及亲和调度。