Please enable Javascript to view the contents

如何添加 Huawei NPU 节点到 Kubernetes 集群

 ·  ☕ 5 分钟

1. 磁盘处理

1.1 查看磁盘

  • 查看新磁盘
1
fdisk -l
Disk /dev/nvme1n1: 3.91 TiB, 4294967296000 bytes, 8388608000 sectors

1.2 组建 RAID0

如果有多块小盘,更好的方式是组建一个 RAID0,这样不仅能获得更大的存储目录,还能获得更快的速度。

  • 创建 RAID
1
mdadm --create --verbose /dev/md0 --level=0 --raid-devices=3 /dev/nvme1n1 /dev/nvme2n1 /dev/nvme3n1
  • 查看 RAID
1
mdadm --detail /dev/md0

1.3 挂载磁盘

  • 创建文件系统
1
mkfs.xfs -f /dev/nvme1n1

或者

mkfs.ext4 /dev/nvme1n1

xfs 适合大文件处理, ext4 适合中小文件处理。

如果是 RAID0 可以执行 mkfs.xfs -f /dev/md0

  • 创建挂载目录
1
mkdir -p /data
  • 获取 UUID
1
2
UUID=$(blkid -s UUID -o value /dev/nvme1n1)
echo $UUID
  • 配置 fstab
1
grep -q "$UUID" /etc/fstab || echo "UUID=$UUID /data xfs defaults,nofail 0 2" >> /etc/fstab

或者

1
grep -q "$UUID" /etc/fstab || echo "UUID=$UUID /data ext4 defaults,nofail 0 2" >> /etc/fstab
  • 挂载存储
1
mount -a
  • 查看挂载点
1
2
3
df -h  |grep data

/dev/nvme1n1    4.0T   28G  3.9T   1% /data

2. 驱动及配置

2.1 查看系统是否识别 NPU

1
lspci |grep Huawei
1
18:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)

识别出设备为华为昇腾 NPU。

2.2 安装驱动

  • 创建 HwHiAiUser 用户
1
2
groupadd -g 1000 HwHiAiUser
useradd -g HwHiAiUser -u 1000 -d /home/HwHiAiUser -m HwHiAiUser -s /bin/bash
  • 添加目录权限
1
2
chown -R HwHiAiUser /usr/local/Ascend
chmod -R 755 /usr/local/Ascend
  • 下载驱动、固件

前往 https://www.hiascend.com/hardware/firmware-drivers/community?product=4&model=26&cann=9.0.0-beta.1&driver=Ascend+HDK+25.5.1 找到对应的驱动和固件。

  • 安装驱动
1
bash ./Ascend-hdk-910b-npu-driver_25.5.1_linux-x86-64.run --full --install-for-all
  • 安装固件
1
bash ./Ascend-hdk-910b-npu-firmware_7.8.0.6.201.run --full
  • 验证是否安装成功
1
npu-smi info

2.3 关闭 TLS

  • 关闭
1
for i in {0..15};do hccn_tool -i $i -tls -s enable 0;done
  • 查看
1
for i in {0..15};do hccn_tool -i $i -tls -g| grep 'switch';done

2.4 查看 IP

  • 查看 IP
1
for i in {0..15};do hccn_tool  -i $i  -ip -g;done
  • 查看网关
1
for i in {0..15};do hccn_tool -i $i -gateway -g;done

2.5 网卡健康状态

  • 卡健康状态:
1
for i in {0..15};do npu-smi info -t health -i $i -c 0| grep 'Health Status';done

查看具体原因:npu-smi info -t health -i -c 0

  • link 状态
1
for i in {0..15};do hccn_tool -i $i -link -g;done
  • 网络健康状态
1
for i in {0..15};do hccn_tool -i $i -net_health -g;done
  • ECC
1
for i in {0..15};do npu-smi info -t ecc -i $i;done

ECC 计数会导致程序错误 0x80E18005。

3. 安装 ascend-docker-runtime

3.1 安装 ascend-docker-runtime

  • 下载 ascend-docker-runtime

前往 https://gitcode.com/Ascend/mind-cluster/releases 找到对应架构的下载链接。

1
wget https://gitcode.com/Ascend/mind-cluster/releases/download/v26.1.0.beta.2/Ascend-docker-runtime_26.1.0.beta.2_linux-x86_64.run
  • 安装 ascend-docker-runtime
1
bash ./Ascend-docker-runtime_26.1.0.beta.2_linux-x86_64.run --install

3.2 安装 Containerd

  • 添加源
1
2
apt-get update
apt-get install -y ca-certificates curl gnupg lsb-release

如果是国内:

1
2
mkdir -p /etc/apt/keyrings
curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
1
2
3
4
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/ \
 $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  • 安装 containerd
1
2
apt update
apt install containerd.io=1.6.31-1
  • 生成 containerd 配置文件 toml
1
2
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
  • 修改 containerd 配置文件
1
2
3
4
sed -i 's#root = "/var/lib/containerd"#root = "/data/containerd"#g' /etc/containerd/config.toml
sed -i 's#state = "/run/containerd"#state = "/data/run/containerd"#g' /etc/containerd/config.toml
sed -i 's#sandbox_image = "registry.k8s.io/pause:[^"]*"#sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"#g' /etc/containerd/config.toml
sed -i 's#SystemdCgroup = false#SystemdCgroup = true#g' /etc/containerd/config.toml
  • 修改 runtime 为 ascend
1
sed -i 's#runtime = "runc"#runtime = "/usr/local/Ascend/Ascend-Docker-Runtime/ascend-docker-runtime"#g' /etc/containerd/config.toml
  • 重启 containerd
1
2
systemctl daemon-reload
systemctl restart containerd

3.3 Docker 配置 [可选]

Docker 和 Containerd 二选一。

  • 更新 Docker 配置
1
vim /etc/docker/daemon.json

添加以下内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "default-runtime": "ascend",
  "data-root": "/data/docker",
  "runtimes": {
    "ascend": {
      "path": "/usr/local/Ascend/Ascend-Docker-Runtime/ascend-docker-runtime",
      "runtimeArgs": []
    }
  }
}
  • 重启 Docker
1
2
systemctl daemon-reload
systemctl restart docker

3.4 hccl_test 验证

1
export IMAGE=registry.cn-beijing.aliyuncs.com/opshub/shaowenchen-hccl-test:8.0.RC2-ubuntu22.04
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
nerdctl run --security-opt apparmor=unconfined --security-opt seccomp=unconfined --rm -it --ipc=host \
      --device=/dev/davinci0 \
      --device=/dev/davinci1 \
      --device=/dev/davinci2 \
      --device=/dev/davinci3 \
      --device=/dev/davinci4 \
      --device=/dev/davinci5 \
      --device=/dev/davinci6 \
      --device=/dev/davinci7 \
      --device=/dev/davinci8 \
      --device=/dev/davinci9 \
      --device=/dev/davinci10 \
      --device=/dev/davinci11 \
      --device=/dev/davinci12 \
      --device=/dev/davinci13 \
      --device=/dev/davinci14 \
      --device=/dev/davinci15 \
      --device=/dev/davinci_manager \
      --device=/dev/devmm_svm \
      --device=/dev/hisi_hdc \
      -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
      -v /usr/local/Ascend/add-ons/:/usr/local/Ascend/add-ons/ \
      -v /usr/local/sbin/npu-smi:/usr/local/sbin/npu-smi \
      -v /var/log/npu/conf/slog/slog.conf:/var/log/npu/conf/slog/slog.conf \
      -v /var/log/npu/slog/:/var/log/npu/slog \
      -v /var/log/npu/profiling/:/var/log/npu/profiling \
      -v /var/log/npu/dump/:/var/log/npu/dump \
      -v /var/log/npu/:/usr/slog \
      ${IMAGE} \
      /bin/bash
1
2
3
4
5
export HCCL_RDMA_TC=100
export HCCL_RDMA_SL=3
export HCCL_BUFFSIZE=2048
export HCCL_PROC=16
mpirun -n ${HCCL_PROC} /usr/local/Ascend/ascend-toolkit/latest/tools/hccl_test/bin/all_reduce_test -b 8K -e 64M -f 2 -d fp32 -o sum -p ${HCCL_PROC}

4. 加入 K8s 集群

4.1 修改 Hostname

1
export HOSTNAME=k8s-worker-npu-01
1
hostnamectl set-hostname ${HOSTNAME}

创建设备管理插件的工作目录

1
mkdir -p /var/log/mindx-dl/devicePlugin

4.2 初始化内核参数

1
opscli task -f ~/.ops/tasks/set-host.yaml

4.3 安装 K8s 基础组件

  • 添加 K8s 源

https://developer.aliyun.com/mirror/kubernetes/ 1.28 以下版本添加

1
curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/kubernetes-aliyun.gpg
1
2
3
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
1
apt-get update
  • 软链 kubelet 的目录
1
2
mkdir -p /data/kubelet
ln -s /data/kubelet /var/lib/kubelet
  • 安装 K8s 基础组件
1
export K8S_VERSION=1.27.6
1
apt-get install kubeadm=${K8S_VERSION}-00 kubelet=${K8S_VERSION}-00 kubectl=${K8S_VERSION}-00 -y
  • 配置 kubelet
1
vim /var/lib/kubelet/kubeadm-flags.env

添加以下内容:

1
--pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9 --resolv-conf=/etc/resolv.conf  --authentication-token-webhook=true --authorization-mode=Webhook --system-reserved=cpu=1,memory=2Gi --kube-reserved=cpu=1,memory=2Gi --cpu-manager-policy=static
  • NUMA 支持
1
--topology-manager-policy=best-effort --topology-manager-scope=container --feature-gates=TopologyManager=true,CPUManager=true,MemoryManager=true

topology-manager-policy 可选 best-effort 尽量满足、restricted 一种资源不跨节点、single-numa-node 全部资源不跨节点。
topology-manager-scope 可选 container 容器级满足、pod 内全部容器满足。
feature-gates 可选 TopologyManager=true,CPUManager=true,MemoryManager=true 开启拓扑管理、CPU 管理、内存管理。

  • 多网卡

在上面的 kubelet 配置中添加 --node-ip= 参数指定节点 IP 地址,--hostname-override= 参数指定节点 Hostname。

1
--node-ip=x.x.x.x --hostname-override=my-hostname

如果是 Flannel 需要在 DeamonSet 中添加 --iface= 参数指定网卡。

1
2
3
4
5
6
7
containers:
  - args:
      - --ip-masq
      - --kube-subnet-mgr
      - --iface-regex=^10\.0\.
    command:
      - /opt/bin/flanneld
  • 重启 kubelet
1
2
3
4
systemctl enable kubelet
systemctl daemon-reload
systemctl restart kubelet
systemctl status kubelet

4.4 加入集群

  • 生成 Token

在 master 节点生成 token

1
kubeadm token create --print-join-command
  • 加入集群
1
2
kubeadm join x.x.x.x:6443 --token xxx \
    --discovery-token-ca-cert-hash sha256:xxx

如果是 Docker 环境,需要带上 --cri-socket 参数。

1
--cri-socket unix:///var/run/cri-dockerd.sock

如果是 Containerd 环境:

1
--cri-socket unix:///run/containerd/containerd.sock -v5

如果报错 [ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables]: /proc/sys/net/bridge/bridge-nf-call-iptables does not exist 就执行一下。

1
2
3
modprobe br_netfilter
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
echo 1 > /proc/sys/net/ipv4/ip_forward

6. 部署 k8s 插件

6.1 安装 device-plugin 注册 huawei.com/Ascend910

  • 安装 device-plugin
1
kubectl apply -f https://raw.githubusercontent.com/shaowenchen/ops-hub/master/ascend/v7.1.RC1-device-plugin-910.yaml
  • 编辑
1
kubectl -n kube-system edit ds ascend-device-plugin-daemonset-910 
1
- device-plugin -useAscendDocker=false -volcanoType=false -presetVirtualDevice=true

插件中有关于 runtime、volcano 相关的配置需要根据环境进行调整

6.2 安装 rdma-shared-dev-plugin 注册 rdma/ib

为了让 Kubernetes 能够发现 RDMA 设备,比如 InfiniBand,并且被多个 Pod 使用,需要安装 k8s-rdma-shared-dev-plugin。

  • 安装 k8s-rdma-shared-dev-plugin
1
kubectl apply -f https://raw.githubusercontent.com/shaowenchen/ops-hub/master/network/k8s-rdma-shared-dev-plugin.yaml
  • 修改配置文件
1
kubectl -n kube-system edit cm rdma-devices

6.3 创建测试 Pod

  • 创建 Pod
1
export IMAGE=registry.cn-beijing.aliyuncs.com/opshub/shaowenchen-hccl-test:8.0.RC2-ubuntu22.04
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
kubectl create -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  generateName: npu-demo-
  labels:
    app: npu-demo
spec:
  nodeName: ${HOSTNAME}
  hostIPC: true
  containers:
    - name: npu-demo
      image: ${IMAGE}
      command: ["/bin/bash", "-c", "sleep infinity"]
      securityContext:
        privileged: true
      resources:
        requests:
          huawei.com/Ascend910: 4
        limits:
          huawei.com/Ascend910: 4
      volumeMounts:
      - mountPath: /usr/local/bin/npu-smi
        name: npu-smi
        readOnly: true
      - mountPath: /usr/local/Ascend/driver
        name: ascend-driver
        readOnly: true
  volumes:
    - name: npu-smi
      hostPath:
        path: /usr/local/bin/npu-smi
    - name: ascend-driver
      hostPath:
        path: /usr/local/Ascend/driver
EOF
  • 查看 Pod 状态
1
kubectl get pod -l app=npu-demo
  • 查看卡
1
kubectl exec -it npu-demo-pm28m npu-smi info
  • 删除 Pod
1
kubectl delete pod -l app=npu-demo

6. 性能优化

  • CPU 锁频高性能模式,缺点是功耗高

临时设置 CPU 锁频高性能模式

1
2
3
for cpu in /sys/devices/system/cpu/cpu[0-9]*; do
  echo performance | sudo tee $cpu/cpufreq/scaling_governor
done

永久设置 CPU 锁频高性能模式

1
apt-get install tuned -y
1
tuned-adm profile throughput-performance

查看 CPU 运行模式

1
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
  • 系统 THP 调优,缺点是内存使用率降低

关闭或调整 THP(透明大页)自动整理,防止内核后台 defrag 导致延迟卡顿,造成周期性延迟抖动。

临时关闭 THP

1
2
echo defer > /sys/kernel/mm/transparent_hugepage/defrag
echo 'defer+madvise' > /sys/kernel/mm/transparent_hugepage/defrag

永久关闭 THP

1
echo never > /sys/kernel/mm/transparent_hugepage/defrag

查看 THP 状态

1
cat /sys/kernel/mm/transparent_hugepage/defrag
  • 网卡队列(丢包问题),缺点是缓冲区增加,网络延时增加

默认值通常是 256 或 512,对于高速万兆/百兆网卡来说太小。

临时设置网卡队列

1
2
ethtool -G eth0 rx 8192 tx 8192
ethtool -G eth1 rx 8192 tx 8192

永久设置网卡队列

1
2
3
4
5
6
cat >/etc/ethtool-ring.sh <<'EOF'
#!/bin/bash
ethtool -G eth0 rx 8192 tx 8192 || true
ethtool -G eth1 rx 8192 tx 8192 || true
EOF
chmod +x /etc/ethtool-ring.sh

或者设置bond0

1
2
3
4
5
6
7
8
9
cat >/etc/ethtool-ring.sh <<'EOF'
#!/bin/bash
SLAVES=$(cat /sys/class/net/bond0/bonding/slaves 2>/dev/null)

for eth in $SLAVES; do
    ethtool -G $eth rx 8192 tx 8192 || true
done
EOF
chmod +x /etc/ethtool-ring.sh
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
cat >/etc/systemd/system/ethtool-ring.service <<'EOF'
[Unit]
Description=Set NIC ring buffer size
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/etc/ethtool-ring.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable ethtool-ring.service
systemctl start ethtool-ring.service

查看网卡队列

1
2
ethtool -g eth0
ethtool -g eth1

查看 bond0 的网卡队列

1
2
3
4
5
SLAVES=$(cat /sys/class/net/bond0/bonding/slaves 2>/dev/null)

for eth in $SLAVES; do
    ethtool -g $eth || true
done
  • 机器 clocksource hpet 改成 tsc,缺点是老旧 CPU 或多 CPU 系统上可能存在不同步问题

TSC(Time Stamp Counter) 是 CPU 内建计时器,访问极快、延迟低(纳秒级)

临时设置 clocksource

1
echo tsc | tee /sys/devices/system/clocksource/clocksource0/current_clocksource

永久设置 clocksource

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
cat >/etc/systemd/system/clocksource-tsc.service <<'EOF'
[Unit]
Description=Set clocksource to tsc
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo tsc > /sys/devices/system/clocksource/clocksource0/current_clocksource'

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable clocksource-tsc.service
systemctl start clocksource-tsc.service

查看当前的 clocksource

1
cat /sys/devices/system/clocksource/clocksource0/current_clocksource
  • 风扇速度调整到最大

一般需要在 BMC(带外管理)或 BIOS 里调节。

7. 参考

  1. https://ascend.github.io/docs/sources/ascend/quick_install.html
  2. https://gitee.com/ascend/ascend-docker-runtime

微信公众号
作者
微信公众号