在ACK集群中,如果您希望将已申请但未使用的资源分配给低优先级应用,可以启用动态资源超卖功能。动态资源超卖可以实时收集节点的真实负载数据,量化集群中已分配但未使用的CPU和内存资源,为BestEffort作业提供资源并保证BestEffort作业之间的资源公平性。
为了帮助您更好地理解本文档并使用本功能,推荐您参见Kubernetes官方文档了解Pod Qos类、为容器和 Pod 分配内存资源等概念。
为什么需要启用动态资源超卖
Kubernetes会参考Pod的Qos类(Guaranteed、Burstable和BestEffort)来管理单机容器的资源质量,例如OOM优先级控制等。
为了提高应用稳定性,应用管理员在部署应用时会预留相当数量的资源Buffer来应对上下游链路的负载波动。这会导致在大部分时间段内,容器的Request会远高于实际的资源利用率。为了提升集群资源利用率,集群管理员可能会考虑提交一些BestEffort的低优任务,利用那些已分配但未使用的资源,实现对集群资源的超卖。但这种传统模式存在以下缺点。
系统无法根据节点当前的实际负载情况来决定是否为BE任务提供更多资源,导致即使某些节点实际负载已经很高,但由于BE任务没有资源容量约束,仍然会被调度到节点上运行。
BE任务之间缺乏公平性保证,任务所需的资源规格不同,但无法在Pod描述中声明。
为了解决上述问题,ACK提供了将可动态超卖的资源量化的能力。ack-koordinator组件支持收集节点真实的负载数据,以标准扩展资源的形式实时更新到Kubernetes的节点元信息中。低优的BE任务可以在Request和Limit中声明所需的超卖资源量,ACK调度器会参考其资源需求分配节点,并合理设置cgroup资源隔离参数,保障应用能够合理使用资源。
为体现与原生资源类型的差异性,ack-koordinator使用Batch的概念描述该部分超卖资源,CPU和内存资源对应分别为batch-cpu和batch-memory。如下图所示,Reclaimed资源代表可动态超卖的资源量,Buffered代表预留的资源Buffer、Usage代表实际已使用的资源量。
费用说明
ack-koordinator组件本身的安装和使用是免费的,不过需要注意的是,在以下场景中可能产生额外的费用:
ack-koordinator是非托管组件,安装后将占用Worker节点资源。您可以在安装组件时配置各模块的资源申请量。
ack-koordinator默认会将资源画像、精细化调度等功能的监控指标以Prometheus的格式对外透出。若您配置组件时开启了ACK-Koordinator开启Prometheus监控指标选项并使用了阿里云Prometheus服务,这些指标将被视为自定义指标并产生相应费用。具体费用取决于您的集群规模和应用数量等因素。建议您在启用此功能前,仔细阅读阿里云Prometheus计费说明,了解自定义指标的免费额度和收费策略。您可以通过账单和用量查询,监控和管理您的资源使用情况。
前提条件
已创建ACK集群Pro版,请参见创建ACK Pro版集群。
已安装ack-koordinator组件,且组件版本为0.8.0及以上,请参见ack-koordinator。
操作步骤
您可以通过ConfigMap在集群维度开启动态资源超卖功能,然后在Pod的YAML文件中通过Labelkoordinator.sh/qosClass
声明Pod对应的QoS类,并在Request和Limit中添加对应的Batch资源配置,让Pod使用动态超卖的资源。
1、开启动态资源超卖
您可以通过ConfigMap开启动态资源超卖功能,也可以在ConfigMap中配置相关参数,例如节点资源的预留系数、计算节点资源容量的策略等,实现更灵活的超卖资源管理。
参见以下ConfigMap,创建configmap.yaml文件。
apiVersion: v1 kind: ConfigMap metadata: name: ack-slo-config namespace: kube-system data: colocation-config: | { "enable": true, "metricAggregateDurationSeconds": 60, "cpuReclaimThresholdPercent": 60, "memoryReclaimThresholdPercent": 70, "memoryCalculatePolicy": "usage" }
您可以修改ConfigMap中的配置项,实现对batch-cpu和batch-memory资源的灵活管理。
参数说明
参数
格式
说明
enable
Boolean
是否开启节点Batch资源的动态更新。关闭时,Batch资源量会被重置为
0
。默认值为false
。metricAggregateDurationSeconds
Int
系统在多长时间周期内聚合一次指标数据,以决定是否需要更新或调整Batch资源,单位为秒。通常建议使用默认值,60秒。
cpuReclaimThresholdPercent
Int
计算节点batch-cpu资源容量时的预留系数。关于如何计算可动态超卖的CPU资源量,请参见计算可用的动态超卖资源量。默认值为
65
,单位为百分比。memoryReclaimThresholdPercent
Int
计算节点batch-memory资源容量时的预留系数。关于如何计算可动态超卖的内存资源量,请参见计算可用的动态超卖资源量。默认值为
65
,单位为百分比。memoryCalculatePolicy
String
计算节点batch-memory资源容量时所采用的策略。
"usage"
:默认值,表示会按照高优先级Pod的内存真实使用量计算可用的batch-memory资源,包括节点未申请的资源以及已申请但未使用的资源量。"request"
:会按照高优先级Pod的内存Request计算可用的batch-memory资源,仅包括节点未申请的资源。
计算可用的动态超卖资源量
根据Pod Request计算Batch内存可用资源
查看命名空间kube-system下是否存在ConfigMap
ack-slo-config
。存在:使用PATCH方式进行更新,避免干扰ConfigMap中其他配置项。
kubectl patch cm -n kube-system ack-slo-config --patch "$(cat configmap.yaml)"
不存在:执行以下命令创建ConfigMap。
kubectl apply -f configmap.yaml
2、为应用Pod申请Batch资源
配置完成后,根据节点当前可用的Batch资源总量,您可以在Pod YAML文件的metadata
字段中通过Labelkoordinator.sh/qosClass
来声明Pod对应的QoS类,并在Request和Limit中声明所需的资源。
执行以下命令,查看节点当前可用的Batch资源总量。
# 将$nodeName替换为要查询的目标节点名称。 kubectl get node $nodeName -o yaml
预期输出:
# 节点信息。 status: allocatable: # 单位为千分之一核,以下表示50核。 kubernetes.io/batch-cpu: 50000 # 单位为字节,以下表示50 GB。 kubernetes.io/batch-memory: 53687091200
创建Pod并申请Batch资源。
重要若您通过Deployment或其他类型的工作负载提交了Pod,请在
template.metadata
字段下进行配置。同一个Pod不能同时申请Batch资源和普通的CPU或Memory资源。Koordinator组件会根据节点当前的实际负载来动态调整可为Pod分配的Batch资源。极少数情况下,kubelet同步节点状态信息可能存在一定的延迟,导致Pod因资源不足而调度失败。此时,请删除并重建该Pod。
受Kubernetes的约束,扩展资源必须为整数格式,因此batch-cpu资源需要以千分之一核为单位进行配置。
metadata: labels: # 必填,标记为低优先级Pod。 koordinator.sh/qosClass: "BE" spec: containers: - resources: requests: # 单位为千分之一核,如下表示1核。 kubernetes.io/batch-cpu: "1k" # 单位为字节,如下表示1 GB。 kubernetes.io/batch-memory: "1Gi" limits: kubernetes.io/batch-cpu: "1k" kubernetes.io/batch-memory: "1Gi"
使用示例
本示例展示如何在开启动态资源超卖功能后,部署一个申请Batch资源的BE Pod。部署完成后,通过在单机端的cgroup分组中查看BE Pod资源限制的生效情况,验证配置是否成功。
执行以下命令,查看节点当前可用的Batch资源总量。
kubectl get node $nodeName -o yaml
预期输出:
# 节点信息。 status: allocatable: # 单位为千分之一核,以下表示50核。 kubernetes.io/batch-cpu: 50000 # 单位为字节,以下表示50 GB。 kubernetes.io/batch-memory: 53687091200
使用以下YAML内容,创建名为be-pod-demo.yaml文件。
apiVersion: v1 kind: Pod metadata: lables: koordinator.sh/qosClass: "BE" name: be-demo spec: containers: - command: - "sleep" - "100h" image: registry-cn-beijing.ack.aliyuncs.com/acs/stress:v1.0.4 imagePullPolicy: Always name: be-demo resources: limits: kubernetes.io/batch-cpu: "50k" kubernetes.io/batch-memory: "10Gi" requests: kubernetes.io/batch-cpu: "50k" kubernetes.io/batch-memory: "10Gi" schedulerName: default-scheduler
使用以下命令,部署be-pod-demo作为目标评测应用。
kubectl apply -f be-pod-demo.yaml
在单机端的Cgroup分组中查看BE Pod资源限制的生效情况。
执行以下命令,查看CPU资源限制参数。
cat /sys/fs/cgroup/cpu,cpuacct/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod4b6e96c8_042d_471c_b6ef_b7e0686a****.slice/cri-containerd-11111c202adfefdd63d7d002ccde8907d08291e706671438c4ccedfecba5****.scope/cpu.cfs_quota_us
预期输出:
# 容器对应的CPU Cgroup为50核。 5000000
执行以下命令,查看Memory资源限制参数。
cat /sys/fs/cgroup/memory/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod4b6e96c8_042d_471c_b6ef_b7e0686a****.slice/cri-containerd-11111c202adfefdd63d7d002ccde8907d08291e706671438c4ccedfecba5****.scope/memory.limit_in_bytes
预期输出:
# 容器对应的Memory Cgroup为10 GB。 10737418240
相关操作
通过Prometheus查看Batch资源使用情况
ACK集群集成了阿里云Prometheus,提供Prometheus监控大盘。您可以在ACK控制台查看Batch资源的使用情况。
登录容器服务管理控制台,在左侧导航栏选择集群。
在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择 。
单击其他页签,然后单击k8s-reclaimed-resource页签。
您可以在此页签查看集群混部的资源收益,以及集群、节点和Pod维度的混部资源容量数据。详细信息,请参见启用在离线混部监控。
若您自建了Prometheus大盘,也可以参见下述指标查看混部资源数据情况。
# 节点batch-cpu可分配总量。 koordlet_node_resource_allocatable{resource="kubernetes.io/batch-cpu",node="$node"} # 节点batch-cpu已分配量。 koordlet_container_resource_requests{resource="kubernetes.io/batch-cpu",node="$node"} # 节点batch-memory可分配总量。 kube_node_status_allocatable{resource="kubernetes.io/batch-memory",node="$node"} # 节点batch-memory已分配量。 koordlet_container_resource_requests{resource="kubernetes.io/batch-memory",node="$node"}
常见问题
当前已通过ack-slo-manager的旧版本协议使用了动态资源超卖功能,升级为ack-koordinator组件后是否继续支持?
旧版本的动态资源超卖协议包括两部分:
在Pod的Annotation中填写的
alibabacloud.com/qosClass
。在Pod的Request和Limit中填写的
alibabacloud.com/reclaimed
。
ack-koordinator兼容以上旧版本协议,并在ACK集群Pro版的调度器中统一计算新旧版本协议的资源申请量和可用量。您可将组件无缝升级至ack-koordinator。
ack-koordinator对旧版本协议的兼容期限截止至2023年07月30日。强烈建议您将原协议资源字段及时升级到新版本。
ACK集群Pro版的调度器和ack-koordinator对各版本协议的适配如下。
调度器版本 | ack-koordinator版本(ack-slo-manager) | alibabacloud.com协议 | koordinator.sh协议 |
≥1.18且<1.22.15-ack-2.0 | ≥0.3.0 | 支持 | 不支持 |
≥1.22.15-ack-2.0 | ≥0.8.0 | 支持 | 支持 |
应用使用了Batch资源后,内存资源用量为什么突然变得更高?
对于在Pod Limit中配置了kubernetes.io/batch-memory
的应用(简称batch limit),ack-koordinator会等待容器创建后根据batch limit在节点上为其设置Cgroup限制参数。由于部分应用在启动时会根据容器Cgroup参数自动申请内存,若应用在Cgroup的memory.limit参数设置前就完成了启动,其内存的真实用量可能会超过batch limit。而操作系统不会立即缩减该进程的内存使用,从而导致容器的内存Cgroup参数无法设置成功,需等待至其真实用量降低至batch limit以下。
此时,建议您适当调整应用配置参数,控制其内存真实用量在batch limit以下,或在应用启动脚本中首先检查内存限制参数,确认完成设置后再进行启动,确保应用的内存用量存在合理限制,避免出现OOM等情况。
您可以在容器内执行以下命令,查看内存资源限制参数。
# 单位为字节。
cat /sys/fs/cgroup/memory/memory.limit_in_bytes
# 预期输出。
1048576000