ACK基于新版的Scheduling framework实现CPU拓扑感知调度,针对CPU敏感型的工作负载提供更好的性能。本文介绍如何使用CPU拓扑感知调度。
原理介绍
Kubernetes的节点会运行多个Pod,其中部分Pod属于CPU密集型工作负载。在这种情况下,Pod之间会争抢节点的CPU资源。当争抢剧烈时,Pod会在不同的CPU Core之间进行频繁的切换,更糟糕的是在NUMA Node之间切换。这种大量的上下文切换,会影响程序运行的性能。Kubernetes虽然有CPU Manager解决方案处理以上问题,但是因为CPU Manager特性是节点级别的CPU调度选择,所以无法在集群维度中选择最优的CPU Core组合。同时CPU Manager特性要求Pod是Guaranteed时(Pod中的每个容器必须指定CPU请求和CPU限制,并且两者要相等)才能生效,且无法适用于所有类型的Pod。
在以下场景中,建议使用CPU拓扑感知调度:
工作负载为计算密集型。
应用程序对CPU敏感。
运行在神龙裸金属(Intel、AMD)等多核机器上。
通过在物理机上部署两个4核8 GB的Nginx并进行压测,发现在Intel(104核)、AMD(256核)的物理机上,使用CPU拓扑感知调度能够将应用性能提升22%~43%。具体如以下两个图所示:
性能指标
Intel
AMD
QPS
提升22.9%
提升43.6%
AVG RT
下降26.3%
下降42.5%
重要不同应用对CPU绑核的敏感程度存在差异,上述实验中的数据仅供参考,建议您将应用部署在稳定的环境中,根据机型等环境情况适当调节实验压力水位,确保应用运行正常,并在充分对比性能情况后评估是否开启CPU拓扑感知调度功能。
在激活CPU拓扑感知调度时,可通过在所创建Deployment对象的template.metadata.annotations
(或者Pod对象的metadata.annotations
)下,设置cpu-policy
为static-burst
,从而控制自动绑核策略。该策略能够对计算密集性负载,有效避免进程的物理核心争用及跨片内存访问,最大化利用碎片化CPU,在不改变硬件及虚拟机资源的前提下为密集计算型负载优化可用资源,进一步提升CPU使用率。
关于CPU拓扑感知调度的实现原理,请参见Practice of Fine-grained Cgroups Resources Scheduling in Kubernetes。
前提条件
已创建ACK Pro版集群。具体操作,请参见创建ACK Pro版集群。
已安装ack-koordinator(原ack-slo-manager)。具体操作,请参见ack-koordinator。
说明ack-koordinator在原resource-controller组件的基础上做了升级优化,如果您正在使用resource-controller,需在安装ack-koordinator后,卸载resource-controller。关于卸载的具体操作,请参见resource-controller。
使用限制
系统组件版本要求具体如下表所示。
组件 | 版本要求 |
Kubernetes | ≥v1.18 |
ack-koordinator | ≥0.2.0 |
费用说明
ack-koordinator组件本身的安装和使用是免费的,不过需要注意的是,在以下场景中可能产生额外的费用:
ack-koordinator是非托管组件,安装后将占用Worker节点资源。您可以在安装组件时配置各模块的资源申请量。
ack-koordinator默认会将资源画像、精细化调度等功能的监控指标以Prometheus的格式对外透出。若您配置组件时开启了ACK-Koordinator开启Prometheus监控指标选项并使用了阿里云Prometheus服务,这些指标将被视为自定义指标并产生相应费用。具体费用取决于您的集群规模和应用数量等因素。建议您在启用此功能前,仔细阅读阿里云Prometheus计费说明,了解自定义指标的免费额度和收费策略。您可以通过账单和用量查询,监控和管理您的资源使用情况。
注意事项
在使用CPU拓扑感知调度前,请保证已部署组件ack-koordinator。
在使用CPU拓扑感知调度时,请保证节点的
cpu-policy=none
。若需要限制应用的调度,请使用
nodeSelector
字段。重要请不要使用
nodeName
字段,该方式将无法进入调度器逻辑使用CPU拓扑感知调度。
使用CPU拓扑感知调度
激活CPU拓扑感知调度前,您需要在提交Pod时设置annotations
和Containers
的值。具体操作步骤如下:
在Deployment对象的
template.metadata.annotations
(或者在Pod对象的metadata.annotations
)下,设置cpuset-scheduler
为true
,激活CPU拓扑感知调度。在
Containers
下,设置resources.limit.cpu
的值,且该值为整数。
使用以下模板创建go-demo.yaml文件,在Deployment中使用CPU拓扑感知调度。
重要针对Deployment对象,您需要在
template.metadata
下配置Pod的annotations
。在配置CPU拓扑感知调度时,可通过在
annotations
下设置cpu-policy
为static-burst
,从而控制自动绑核策略。需要配置时,请删除cpu-policy
前的#
。
执行以下命令,创建Deployment。
kubectl create -f go-demo.yaml
验证CPU拓扑感知对应用性能的提升
本示例使用场景为:
ACK Pro版集群版本为1.20。
需要包含两个节点:一台压测机、一台测试机。
以下部署和压测命令仅供参考,您可结合自身实验环境调节资源规格和请求压力,确保应用处于正常工作状态后再进行实验。
执行以下命令,为测试机打上标签。
kubectl label node 192.168.XX.XX policy=intel/amd
在测试机上部署Nginx服务。
使用以下YAML示例,创建Nginx服务配置文件。
执行以下命令,创建Nginx服务。
kubectl create -f service.yaml
kubectl create -f configmap.yaml
kubectl create -f nginx.yaml
登录压测机,下载wrk2开源测试工具并解压安装。具体操作,请参见wrk2官方网站。
说明关于如何登录到节点,请参见使用VNC登录实例或通过密码认证登录Windows实例。
执行以下命令,在压测机上进行测试并记录数据。
wrk --timeout 2s -t 20 -c 100 -d 60s --latency http://<测试机IP>:32257
预期输出:
20 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 600.58us 3.07ms 117.51ms 99.74% Req/Sec 10.67k 2.38k 22.33k 67.79% Latency Distribution 50% 462.00us 75% 680.00us 90% 738.00us 99% 0.90ms 12762127 requests in 1.00m, 10.10GB read Requests/sec: 212350.15Transfer/sec: 172.13MB
执行以下命令,删除已部署的Nginx。
kubectl delete deployment nginx
预期输出:
deployment "nginx" deleted
使用以下YAML示例,部署开启CPU拓扑感知调度的Nginx。
执行以下命令,在压测机上进行测试并记录数据进行对比。
wrk --timeout 2s -t 20 -c 100 -d 60s --latency http://<测试机IP>:32257
预期输出:
20 threads and 100 connections ls Thread Stats Avg Stdev Max +/- Stdev Latency 345.79us 1.02ms 82.21ms 99.93% Req/Sec 15.33k 2.53k 25.84k 71.53% Latency Distribution 50% 327.00us 75% 444.00us 90% 479.00us 99% 571.00us 18337573 requests in 1.00m, 14.52GB read Requests/sec: 305119.06Transfer/sec: 247.34MB
通过两次数据的对比可以看出,开启CPU拓扑感知调度后,Nginx的性能提升43%。
验证自动绑核策略对应用性能的提升
本示例介绍在一个64核的节点上设置CPU Policy。在设置控制自动绑核策略后,相比于CPU拓扑感知调度一般可以提升7%~8%的CPU使用效率。
以下部署和压测命令仅供参考,您可结合自身实验环境调节资源规格,确保应用处于正常工作状态后再进行实验。
执行以下命令,查看Pod。
kubectl get pods | grep cal-pi
预期输出:
NAME READY STATUS RESTARTS AGE cal-pi-d**** 1/1 Running 1 9h
执行以下命令,查看应用
cal-pi-d****
的日志。kubectl logs cal-pi-d****
预期输出:
computing Pi with 3000 Threads...computed the first 20000 digets of pi in 620892 ms! the first digets are: 3.14159264 writing to pi.txt... finished!
使用CPU拓扑感知调度。
在Deployment中使用CPU拓扑感知调度并控制自动绑核策略。更多信息,请参见使用CPU拓扑感知调度。
使用以下模板创建go-demo.yaml文件,在Deployment中使用CPU拓扑感知调度。
重要针对Deployment对象,您需要在
template.metadata
下配置Pod的annotations
。执行以下命令,创建Deployment。
kubectl create -f go-demo.yaml
执行以下命令,查看Pod。
kubectl get pods | grep go-demo
预期输出:
NAME READY STATUS RESTARTS AGE go-demo-e**** 1/1 Running 1 9h
执行以下命令,查看应用
go-demo-e****
的日志。kubectl logs go-demo-e****
预期输出:
computing Pi with 3000 Threads...computed the first 20000 digets of pi in 571221 ms! the first digets are: 3.14159264 writing to pi.txt... finished!
通过与步骤2的日志数据对比,设置CPU Policy后Pod的性能提升8%。
相关文档
Kubernetes对节点的GPU拓扑信息不感知,调度过程中对GPU的选择比较随机,选择不同的GPU组合训练速度会存在较大的差异。基于以上问题,ACK基于Scheduling Framework机制,实现GPU拓扑感知调度,在节点的GPU组合中选择具有最优训练速度的组合。详细信息,请参见GPU拓扑感知调度。