# cloud-native **Repository Path**: kunpeng_compute/cloud-native ## Basic Information - **Project Name**: cloud-native - **Description**: 鲲鹏云计算-云原生领域代码仓,基于k8s、docker等开源组件开发鲲鹏Boostkit云原生特性 - **Primary Language**: C - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 3 - **Created**: 2025-04-01 - **Last Updated**: 2025-09-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 项目介绍 鲲鹏云原生项目集合,包含多个针对鲲鹏处理器优化的云原生组件。 # 版本说明 **表 1** 版本说明

项目名

版本

说明

K8s MPAM Controller

0.1.0

  • 支持K8s中MPAM纳管Pod。
  • 在离线混部场景下,支持动态限制离线业务,保障在线业务。

Kunpeng Topology Aware Plugin

v0.3(待发布)

-

# 环境部署 ## Kunpeng TAP(Topology Aware Plugin) **硬件要求** 硬件要求如[表1](#table1911819583242)所示。 **表 1** 硬件要求

项目

说明

处理器

鲲鹏920系列处理器

**软件要求** 软件要求如[表2](#table18216177162517)所示。 **表 2** 软件要求

项目

版本

获取方法

OS

openEuler 20.03 LTS SP3

获取链接

openEuler 22.03 LTS SP4

获取链接

Kunpeng TAP源代码

release-0.2

获取链接

Golang

1.23+

二进制包安装

Make

-

通过配置Yum源安装

**编译插件** 编译Kunpeng TAP源代码并生成插件可执行文件。 1. 获取Kunpeng TAP源代码,在标签中获取最新发布的release-0.2版本。 ``` git clone --branch release-0.2 https://gitee.com/kunpeng_compute/topo-affinity-plugin.git ``` 2. 进入“topo-affinity-plugin“目录,并执行构建插件的脚本。 ``` cd /path/to/topo-affinity-plugin go mod tidy make build ``` 其中“/path/to/topo-affinity-plugin“为插件源码的实际路径,请根据实际情况修改。 构建完成后,请确认在“bin“目录下生成kunpeng-tap二进制文件。 ## K8s MPAM Controller **环境依赖** - Go 1.23.6或更高版本 - Linux环境(推荐openEuler 22.03) - 支持MPAM的硬件平台(推荐鲲鹏处理器) **编译Docker镜像** ``` make mpam-docker ``` 如果K8s集群使用的是containerd作为容器运行时,需要把镜像手动导入到containerd的镜像仓库。 ``` docker save k8s-mpam-controller:0.1.0 -o k8s-mpam-controller.tar ctr -n k8s.io images import k8s-mpam-controller.tar ``` # 快速上手 ## Kunpeng TAP(Topology Aware Plugin) **部署插件** 在目标计算节点部署Kunpeng TAP,并且验证插件的运行状态。 Kunpeng TAP的运行依赖于K8s集群,当前支持使用Dockershim通信方式的Docker和Containerd。在部署该插件之前,需确保K8s集群已完成正确的网络配置,并且能够顺利部署和运行容器实例。 1. 在目标计算节点导入Kunpeng TAP的可执行文件。 2. 启动Kunpeng TAP。 **启动方式一:**systemd启动。可直接进入源代码目录下,通过**make**命令安装和启动。 1. 进入源代码目录。 ``` cd /path/to/topology-affinity-plugin ``` 其中“/path/to/topology-affinity-plugin“为Kunpeng TAP源码的实际路径,请根据实际情况修改。 2. 安装插件,默认以Docker模式启动。 ``` make install-service ``` 3. 指定运行时为Docker,运行如下安装命令。 ``` make install-service-docker ``` 如果需要修改启动参数,则在源代码目录下的“hack/kunpeng-tap.service.docker“文件的“ExecStart=“下进行修改: ``` [Unit] Description=Kunpeng Topology-Affinity Plugin Service After=network.target [Service] ExecStart=/usr/local/bin/kunpeng-tap --runtime-proxy-endpoint="/var/run/kunpeng/tap-runtime-proxy.sock" \ --container-runtime-service-endpoint="/var/run/docker.sock" --container-runtime-mode="Docker" \ --resource-policy="numa-aware" Restart=always RestartSec=5 [Install] WantedBy=multi-user.target ``` >![](figures/icon-note.gif) **说明:** >指定运行时为Containerd,运行如下安装命令,参数配置可在源代码目录下的“hack/kunpeng-tap.service.containerd“文件中修改。 >``` >make install-service-containerd >``` 4. 安装完毕后,借助如下命令启动插件,并且自动查看启动后的服务状态。 ``` make start-service ``` 5. 查看日志信息。 ``` journalctl -u kunpeng-tap ``` **启动方式二:**直接启动。 - Docker运行时下的启动命令,示例如下: ``` kunpeng-tap --runtime-proxy-endpoint="/var/run/kunpeng/tap-runtime-proxy.sock" \ --container-runtime-service-endpoint="/var/run/docker.sock" --container-runtime-mode="Docker" \ --resource-policy="numa-aware" ``` - Containerd运行时下的启动命令,示例如下: ``` kunpeng-tap --runtime-proxy-endpoint="/var/run/kunpeng/tap-runtime-proxy.sock" \ --container-runtime-service-endpoint="/var/run/containerd/containerd.sock" --container-runtime-mode="Containerd" \ --resource-policy="numa-aware" ``` >![](figures/icon-note.gif) **说明:** >用户可根据需求修改相关参数后启动。参数说明见[表1](#table105725712163)。 **表 1** 参数说明

参数名称

参数描述

默认值

配置原则

container-runtime-mode

插件对接的容器运行时,对应集群运行时设置Docker或Containerd。

Docker

依照K8s集群使用的容器运行时决定

resource-policy

容器资源的优化策略,目前支持numa-aware和topology-aware。

  • numa-aware策略支持Burstable类型容器进行CPU的NUMA亲和。
  • topology-aware策略提供Socket、Die、NUMA等拓扑层次的CPU亲和,额外支持内存、GPU资源的优化。

numa-aware

依照需求进行选择

enable-memory-topology

启用topology-aware策略后(设置“--resource-policy=topology-aware”),内存资源的NUMA优化功能默认关闭,如需开启容器内存的NUMA亲和功能,则设置“--enable-memory-topology=true”

false

暂处于Alpha阶段

v

日志信息等级,调整范围2至5。

2

等级越高,日志输出越详细

3. 在计算节点配置Kubelet参数。 为了让Kunpeng TAP成功代理Kubelet的请求,需要在Kubelet的命令行配置中增加如下参数。 - 在Docker场景下,在Kubelet启动参数中添加或修改对应参数项如下所示。 ``` --docker-endpoint=unix:///var/run/kunpeng/tap-runtime-proxy.sock ``` 以使用kubeadm安装集群为例,可以在“/var/lib/kubelet/kubeadm-flags.env“添加参数。 ``` KUBELET_KUBEADM_ARGS="--network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.6 --docker-endpoint=unix:///var/run/kunpeng/tap-runtime-proxy.sock" ``` 注意,修改Kubelet参数后,须运行如下命令重新启动Kubelet。 ``` systemctl daemon-reload systemctl restart kubelet ``` - 在Containerd场景下,修改Kubelet的启动参数。 ``` --container-runtime=remote --container-runtime-endpoint=unix:///var/run/kunpeng/tap-runtime-proxy.sock ``` 此时,“/var/lib/kubelet/kubeadm-flags.env“的参数示例可能是: ``` KUBELET_KUBEADM_ARGS="--network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.6 --container-runtime=remote --container-runtime-endpoint=unix:///var/run/kunpeng/tap-runtime-proxy.sock" ``` 注意,修改Kubelet参数后,须运行如下命令重新启动Kubelet。 ``` systemctl daemon-reload systemctl restart kubelet ``` **使用TAP插件** Kunpeng TAP允许在部署Pod时指定CPU资源需求,系统将自动按NUMA亲和性分配资源。通过编写YAML文件并指定节点选择器,可以将Pod部署到特定节点上。成功部署插件后,只需在部署其他Pod时指定CPU资源的request和limit值,系统将自动按照NUMA亲和性原则进行资源分配。 以下为部署一个单容器Pod的YAML文件示例,供用户参考。该Pod请求的CPU资源最小值为4核,最大值为8核,内存固定为4Gi,容器使用busybox作为镜像。 1. 创建YAML文件,例如example.yaml,并在YAML文件中写入以下配置。 ``` apiVersion: v1 kind: Pod metadata: name: tap-test annotations: spec: containers: - name: tap-example image: busybox:latest imagePullPolicy: IfNotPresent command: ["/bin/sh"] args: ["-c", "while true; do echo `date`; sleep 5; done"] resources: requests: cpu: "4" memory: "4Gi" limits: cpu: "8" memory: "4Gi" ``` 2. 以指定Pod在**compute01**节点上运行为例,需要在YAML文件中的**spec**部分加入以下内容。 >![](figures/icon-note.gif) **说明:** >在多个工作节点的K8s集群中,Pod可能会被调度到不同节点的NUMA内。如果希望Pod在指定的节点上运行,只需在YAML文件的**spec**部分加入**nodeSelector**字段,并指定**kubernetes.io/hostname**为目标节点的名称。 ``` nodeSelector: kubernetes.io/hostname: compute01 ``` 3. 在管理节点应用YAML文件,完成Pod部署。 ``` kubectl apply -f example.yaml ``` 4. 判断Kunpeng TAP是否生效。 1. 以Docker运行时为例,进入步骤[2](#li1795401917439)中**nodeSelector**所指定的集群节点_compute01_后,通过**docker**命令查询容器的CpusetCpus参数,判断容器是否与NUMA成功亲和。 2. 通过**docker ps**查询集群节点运行的容器任务,在**NAMES**列中找到步骤一中“spec.containers.name“指定的_nri-1_容器。 ``` # docker ps | grep nri-1 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ``` 3. 依据_CONTAINER ID_查询目标容器的部署参数_CpusetCpus_,该参数表示容器的可调度CPU范围。 ``` # docker inspect bf32de0d09fe | grep "CpusetCpus" "CpusetCpus": "0-23", ``` 如果启用了内存绑定功能,可以通过如下命令查看,注意其取值表示节点的编号。 ``` # docker inspect bf32de0d09fe | grep "CpusetMems" "CpusetMems": "0", ``` >![](figures/icon-note.gif) **说明:** >在不同的机器上查看时,绑定的NUMA节点不固定,_CpusetCpus_数字可能不一致。 Containerd运行时可以运行如下命令查看容器的可调度CPU范围。 ``` # crictl inspect bf32de0d09fe | grep "cpuset_cpus" "cpuset_cpus": "0-23", ``` 如果NUMA节点亲和失败,则可能无法查找到cpuset\_cpus输出。 4. 查询系统的NUMA信息,与上述的容器可调度CPU范围进行对比,一致则表示亲和于对应NUMA节点。 ``` # lscpu ... NUMA node0 CPU(s): 0-23 NUMA node1 CPU(s): 24-47 NUMA node2 CPU(s): 48-71 NUMA node3 CPU(s): 72-95 ... ``` “node0“表示编号为“0“的NUMA节点,“0-23“表示NUMA节点内的CPU编号。 5. 此外,对于系统中GPU的NUMA分布,可以运行如下命令查看,其中“0200“为网卡设备号。 ``` lspci -vvv -d :0200 | grep NUMA ``` 回显如下所示: ``` NUMA node: 0 NUMA node: 0 NUMA node: 0 NUMA node: 0 NUMA node: 0 NUMA node: 2 NUMA node: 2 NUMA node: 2 NUMA node: 2 NUMA node: 2 ``` ## K8s MPAM Controller **部署插件** 1. 在部署插件之前要先确保MPAM的resctrl文件系统已经挂载,在**worker节点**使用如下命令可以挂载。 ``` mount -t resctrl resctrl /sys/fs/resctrl ``` 2. 在**master节点**上执行如下命令部署插件。 ``` cd cloud-native/Boostkit_CloudNative/K8S/k8s-mpam-controller-config/samples kubectl apply -f k8s-mpam-controller.yaml ``` 3. 查看MPAM插件对应的Pod是否正常运行。 ``` kubectl get pods ``` 正常运行可能的回显如下。 ``` NAME READY STATUS RESTARTS AGE mpam-controller-daemonset-agent-bj2gv 1/1 Running 0 143m ``` **创建MPAM资源组** 当需要对Pod进行资源限制时,需要创建MPAM资源组。 1. 进入“samples“目录,修改MPAM资源组的配置文件(.yaml格式),以example-config.yaml为例。 在example-config.yaml文件中,Node资源组包括如[表1](#table8171211407)所示3种不同级别的配置,用户可以通过ConfigMap为Node节点或一组节点创建配置。创建配置后,MPAM插件将管理Kubernetes集群中的ConfigMap,并在添加或更新ConfigMap后将配置自动应用到相应的节点。 **表 1** 配置类型及其说明

配置类型

配置名称

配置说明

node配置

rc-config.node.{NODE_NAME}

该配置提供了名为Node_NAME的节点的配置。

node group配置

rc-config.group.{GROUP_NAME}

可以通过“ngroup”标签将Node节点加到对应的组中。例如,如果某个Node节点含有“ngroup=grp1”的标签,那么该节点就属于Node组grp1。如果Node节点特定的ConfigMap rc-config.node.{NODE_NAME}不存在,但节点属于名为{GROUP_NAME}的节点组,则将应用名称为“rc-config.group.{GROUP_NAME}”的ConfigMap。

默认配置

rc-config.default

如果节点不属于任何节点组,并且节点特定的ConfigMap不存在,则将应用名称为“rc-config.default”的ConfigMap。

1. 打开文件。 ``` cd samples vi example-config.yaml ``` 2. 按“i“进入编辑模式,在文件中修改name字段指定为[表1](#table8171211407)中的实际配置名称,将mpam字段下添加对应的资源组信息。 ``` apiVersion: v1 kind: ConfigMap metadata: name: ${CONFIG_NAME} namespace: rc-config data: rc.conf: | mpam: group1: llc: mb: group2: llc: mb: group3: llc: mb: ``` >![](figures/icon-note.gif) **说明:** >- 最多可以设置32个资源组(根分组默认占一个资源组,根分组下最多实际只能创建出31个资源组),每条必须要满足语法规则。 >- 如果某个资源组中没有对某一项进行配置或者已配置的配置项不满足语法规则,该资源组将使用该配置项的默认配置。L3 cache的默认配置为**"L3:0=fffffff;1=fffffff;2=fffffff;3=fffffff"**;带宽的默认配置为**"MB:0=100;1=100;2=100;3=100"** 3. 按“Esc“键退出编辑模式,输入**:wq!**,按“Enter“键保存并退出文件。 2. 在“samples“目录下,应用example-config.yaml文件以创建ConfigMap。 ``` kubectl apply -f example-config.yaml ``` 3. 在Node节点上,进入“/sys/fs/resctrl“目录,查看资源组是否已创建,以及对应的资源组配置是否和example-config.yaml中的一致。 ``` cd /sys/fs/resctrl ls ``` >![](figures/icon-note.gif) **说明:** >例如,可以通过以下命令查看资源组group1的配置。 >``` >cat group1/schemata >``` **创建Pod并指定资源组** 当需要将某个Pod加入到某个资源组中时,需要在创建Pod时指定资源组。 1. 修改Pod的配置文件(.yaml格式),以example-pod.yaml为例。 1. 进入“samples“目录,打开example-pod.yaml文件。 ``` cd samples vi example-pod.yaml ``` 2. 按“i“进入编辑模式,在配置文件中分别添加如下信息。 ``` labels: rcgroup: group2 ``` ``` nodeSelector: MPAM: enabled ``` >![](figures/icon-note.gif) **说明:** >- 在**labels**字段中通过rcgroup字段指定对应的资源组,例如将Pod加到**group2**中。 >- 在**nodeSelector**字段中增加**MPAM:enabled**,用于调度器将该Pod调度到支持MPAM特性的节点上去。 修改后的example-pod.yaml文件如下所示。 ``` apiVersion: v1 kind: Pod metadata: name: nginx labels: rcgroup: group2 spec: containers: - name: nginx image: nginx:1.16.1 ports: - containerPort: 80 hostPort: 8088 nodeSelector: MPAM: enabled ``` 3. 按“Esc“键退出编辑模式,输入**:wq!**,按“Enter“键保存并退出文件。 2. 创建Pod。 ``` kubectl apply -f example-pod.yaml ``` 3. 在Node节点上,进入“/sys/fs/resctrl“目录,再进入Pod所属的资源组中(例如Pod属于资源组group1),可以在资源组中查看对应的配置以及监控数据,还可以查看当前资源组下被限制应用的pid。 ``` cd /sys/fs/resctrl/group1 ``` - 通过以下命令查看资源组的配置。 ``` cat schemata ``` - 通过以下命令查看该资源组下的pid。 ``` cat tasks ``` - 通过以下命令查看资源组下的监控数据。 ``` grep . mon_data/* ``` **使用动态MPAM隔离功能** 当需要动态调整某些离线业务的资源使用量时可以使用动态MPAM隔离功能。 **(可选)配置动态MPAM隔离参数** 插件提供了默认配置,如果不配置configMap同样可以使用动态MPAM隔离功能。MPAM动态隔离参数通过json文件配置,参数含义请参见[表2](#table116484132237)。如果需要手动更改配置参考下面内容进行配置。 ``` { "mpamConfig":{ "adjustInterval": 5000, "perfDuration": 3000, "l3Percent": { "low": 20, "high": 50 }, "memBandPercent": { "low": 10, "high": 50 }, "cacheMiss": { "minMiss": 10, "maxMiss": 50 } } } ``` **表 2** MPAM动态隔离参数说明

参数名

参数含义

adjustInterval

每次动态调整之间的间隔,比如设置值为1000就是每隔1s执行一次动态调整。

perfDuration

perf采集指标的时间,比如设置1000就是每次perf采集就采集1s的数据。

l3Percent

动态调整过程中离线业务可以使用的L3Cache的最大值和最小值。比如设置low=20,high=50,那么在动态调整过程中离线业务最少可以使用20%的L3 CacheWay,最多可以使用50%的L3 CacheWay。

memBandPercent

动态调整过程中离线业务可以使用的内存带宽的最大值和最小值。比如设置low=10,high=50,那么在动态调整过程中离线业务最少可以使用10%的内存带宽,最多可以使用50%的内存带宽。

cacheMiss

是否进行动态调整的判别依据。比如设置minMiss=10,maxMiss=50,那么当在线业务的Cache Miss率大于50%时就降低离线业务的可用资源量,当在线业务的Cache Miss率小于10%时就增加离线业务的可用资源量。

json文件通过configMap的形式进行配置,在k8s-mpam-controller.yaml文件中配置,完整的yaml文件如下。 ``` apiVersion: v1 kind: ServiceAccount metadata: name: mpam-controller-agent --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: mpam-controller-agent rules: - apiGroups: - "" resources: - configmaps - pods verbs: - get - list - watch - apiGroups: - "" resources: - nodes verbs: - get - list - patch - update - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: mpam-controller-agent roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: mpam-controller-agent subjects: - kind: ServiceAccount name: mpam-controller-agent namespace: default --- apiVersion: v1 kind: ConfigMap metadata: name: mpam-config data: config.json: | { "mpamConfig":{ "adjustInterval": 10000, "perfDuration": 3000, "l3Percent": { "low": 20, "high": 50 }, "memBandPercent": { "low": 10, "high": 50 }, "cacheMiss": { "minMiss": 10, "maxMiss": 30 } } } --- apiVersion: apps/v1 kind: DaemonSet metadata: name: mpam-controller-daemonset-agent spec: selector: matchLabels: app: k8s-mpam-controller-agent template: metadata: labels: app: k8s-mpam-controller-agent spec: serviceAccountName: mpam-controller-agent hostPID: true hostIPC: true containers: - name: k8s-mpam-controller-agent image: k8s-mpam-controller:0.1 securityContext: privileged: true command: ["/usr/bin/agent"] args: ["-direct"] resources: limits: memory: 200Mi requests: cpu: 100m memory: 200Mi env: - name: NODE_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName volumeMounts: - name: resctrl mountPath: /sys/fs/resctrl/ - name: hostname mountPath: /etc/hostname - name: sysfs mountPath: /sys/fs/cgroup/ - name: config-volume mountPath: /var/lib/mpam-config volumes: - name: resctrl hostPath: path: /sys/fs/resctrl/ - name: hostname hostPath: path: /etc/hostname - name: sysfs hostPath: path: /sys/fs/cgroup/ - name: config-volume configMap: name: mpam-config items: - key: config.json path: config.json ``` 使用动态MPAM隔离功能后插件会在“/sys/fs/resctrl“目录下创建mpam-controller\_dynamic目录,如下图所示。 ![](figures/zh-cn_image_0000002475117233.png) **部署离线业务** 1. 在Pod的yaml文件中添加注解kunpeng.com/offline: "true",标记该Pod为离线业务,方便插件对其进行限制,示例bw-mem.yaml文件如下。 ``` apiVersion: v1 kind: Pod metadata: name: bw-mem annotations: kunpeng.com/offline: "true" spec: containers: - name: bw-mem image: bw-mem:latest imagePullPolicy: IfNotPresent command: [ "/bin/sh", "-c", "--" ] args: [ "while true; do sleep 300000; done;" ] securityContext: capabilities: add: ["ALL"] resources: requests: cpu: "9.6" limits: cpu: "9.6" ``` 2. 部署要进行限制的离线业务。 ``` kubectl apply -f bw-mem.yaml ``` 部署成功后离线业务的pid会被加入到mpam-controller\_dynamic控制组中的tasks。 3. 通过以下命令查看被限制的离线业务的pid。 ``` cd /sys/fs/resctrl/mpam-controller_dynamic cat tasks ``` # 贡献指南 欢迎提交Issue和Pull Request来改进项目。请确保: - 代码符合项目规范。 - 包含适当的测试。 - 更新相关文档。 # 免责声明 本项目不含任何明示或暗示的担保,包括但不限于适销性、特定用途适用性及不侵权保证;在任何情况下,版权所有者或贡献者均不对因使用本软件而产生的任何直接、间接、特殊、附带或后果性损害负责。使用即视为同意上述条款。 # 许可证书 本项目采用Apache License 2.0许可证。详见[LICENSE](https://gitcode.com/boostkit/cloud-native/blob/master/LICENSE)文件。