ACK基于新版的Scheduling framework实现CPU拓扑感知调度,针对CPU敏感型的工作负载提供更好的性能。本文介绍如何使用CPU拓扑感知调度。
前提条件
- 已创建ACK Pro版集群。具体操作,请参见Create a professional managed Kubernetes cluster。
注意 目前CPU拓扑感知调度仅支持ACK Pro托管版集群。如果您需要使用专有版集群,请
提交工单申请白名单。
- 已预先安装ack-slo-manager组件。具体操作,请参见使用说明。
说明 ack-slo-manager在原resource-controller组件的基础上做了升级优化,如果您正在使用resource-controller,需要您在安装ack-slo-manager后,卸载resource-controller。
背景信息
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拓扑感知调度时,可通过在所创建Pod的annotations处设置cpu-policy为static-burst,从而控制自动绑核策略。该策略能够对计算密集性负载,有效避免进程的物理核心争用及跨片内存访问,最大化利用碎片化CPU,在不改变硬件及虚拟机资源的前提下为密集计算型负载优化可用资源,进一步提升CPU使用率。
使用限制
系统组件版本要求具体如下表所示。
组件 |
版本要求 |
Kubernetes |
≥v1.18 |
ack-slo-manager |
≥0.2.0 |
Helm版本 |
≥v3.0 |
操作系统 |
Alibaba Cloud Linux 2、CentOS 7.6、CentOS 7.7 |
注意事项
- 在使用CPU拓扑感知调度前,请保证已部署组件ack-slo-manager。
- 在使用CPU拓扑感知调度时,请保证节点的
cpu-policy=none
。
- 若需要限制应用的调度,请使用
nodeSelector
字段。
注意 请不要使用nodeName
字段,该方式将无法进入调度器逻辑使用CPU拓扑感知调度。
使用CPU拓扑感知调度
激活CPU拓扑感知调度前,需要在提交Pod时设置
annotations和
Containers的值。满足以下条件:
- 在annotations处,设置cpuset-scheduler为true,激活CPU拓扑感知调度。
- 需要设置Containers的
resources.limit.cpu
值,且该值为整数。
- 使用以下模板创建go-demo.yaml文件,在Deployment中使用CPU拓扑感知调度。
apiVersion: apps/v1
kind: Deployment
metadata:
name: go-demo
spec:
replicas: 4
selector:
matchLabels:
app: go-demo
template:
metadata:
annotations:
cpuset-scheduler: "true" #表示CPU拓扑感知调度。
#cpu-policy: 'static-burst' #控制自动绑核策略,提升CPU碎片利用率。
labels:
app: go-demo
spec:
containers:
- name: go-demo
image: registry.cn-hangzhou.aliyuncs.com/haoshuwei24/go-demo:1k
imagePullPolicy: Always
ports:
- containerPort: 8080
resources:
requests:
cpu: 1
limits:
cpu: 4 #需要设置resources.limit.cpu值。
注意
- 在配置CPU拓扑感知调度时,可通过在annotations下设置cpu-policy为static-burst,从而控制自动绑核策略。需要配置时,请删除cpu-policy前的
#
。
- 在
template.metadata
下配置Pod的annotations
。
- 执行以下命令,创建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服务配置文件。
-
service.yamlapiVersion: v1
kind: Service
metadata:
name: nginx-service-nodeport
spec:
selector:
app: nginx
ports:
- name: http
port: 8000
protocol: TCP
targetPort: 80
nodePort: 32257
type: NodePort
-
configmap.yamlapiVersion: v1
kind: ConfigMap
metadata:
name: nginx-configmap
data:
nginx_conf: |-
user nginx;
worker_processes 4;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 65535;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
-
nginx.yamlapiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
annotations:
#cpuset-scheduler: "true" 默认情况,不使用CPU拓扑感知调度。
labels:
app: nginx
spec:
nodeSelector:
policy: intel7
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
resources:
requests:
cpu: 4
memory: 8Gi
limits:
cpu: 4
memory: 8Gi
volumeMounts:
- mountPath: /etc/nginx/nginx.conf
name: nginx
subPath: nginx.conf
volumes:
- name: nginx
configMap:
name: nginx-configmap
items:
- key: nginx_conf
path: nginx.conf
- 执行以下命令,创建Nginx服务。
kubectl create -f service.yaml
kubectl create -f configmap.yaml
kubectl create -f nginx.yaml
- 登录压测机,执行以下命令下载
wrk
。
wget https://caishu-oss.oss-cn-beijing.aliyuncs.com/wrk?versionId=CAEQEBiBgMCGk565xxciIDdiNzg4NWIzMzZhZTQ1OTlhYzZhZjFhNmQ2MDNkMzA2 -O wrk
chmod +755 wrk
mv wrk /usr/local/bin
- 执行以下命令,在压测机上进行测试并记录数据。
taskset -c 32-45 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。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
annotations:
cpuset-scheduler: "true"
labels:
app: nginx
spec:
nodeSelector:
policy: intel7
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
resources:
requests:
cpu: 4
memory: 8Gi
limits:
cpu: 4
memory: 8Gi
volumeMounts:
- mountPath: /etc/nginx/nginx.conf
name: nginx
subPath: nginx.conf
volumes:
- name: nginx
configMap:
name: nginx-configmap
items:
- key: nginx_conf
path: nginx.conf
- 执行以下命令,在压测机上进行测试并记录数据进行对比。
taskset -c 32-45 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拓扑感知调度。
- 使用以下模板创建go-demo.yaml文件,在Deployment中使用CPU拓扑感知调度。
apiVersion: apps/v1
kind: Deployment
metadata:
name: go-demo
spec:
replicas: 4
selector:
matchLabels:
app: go-demo
template:
metadata:
annotations:
cpuset-scheduler: "true" #表示CPU拓扑感知调度。
cpu-policy: 'static-burst' #控制自动绑核策略,提升CPU碎片利用率。
labels:
app: go-demo
spec:
containers:
- name: go-demo
image: registry.cn-hangzhou.aliyuncs.com/haoshuwei24/go-demo:1k
imagePullPolicy: Always
ports:
- containerPort: 8080
resources:
requests:
cpu: 1
limits:
cpu: 4 #需要设置resources.limit.cpu值。
- 执行以下命令,创建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%。