vLLM Ascend 昇腾推理部署:从硬件检测到生产上线

华为昇腾 NPU 上部署 vLLM 的完整指南:NPU 设备检测、Docker/Docker Compose/Kubelet 四种部署方式、Qwen3/DeepSeek/GLM 等 30+ 模型支持,以及 PD 分离和监控。

一、vllm-ascend 是什么

vllm-ascend 是 华为和 vLLM 社区官方合作 的昇腾 NPU 后端插件(Apache 2.0)。它让 vLLM 支持的每一行代码对昇腾 NPU 都有效 — 不需要改推理逻辑,只换后端硬件。

二、NPU 设备发现与检测

部署前最重要的一步:确认服务器上是否有 NPU、是否可用。以下是从硬件到软件栈的完整检测流程。

2.1 硬件层:NPU 是否存在

# 1. PCIe 设备检测 — 查看是否有华为昇腾 NPU
# 华为 Vendor ID = 19e5,用 -d 按厂商 ID 过滤最准确
lspci -d 19e5:
# 或者按厂商名(部分设备名不含 "ascend" 字样,用 "huawei" 更可靠)
lspci | grep -i huawei
# Atlas 300I/800 系列 PCIe 卡会在这里显示

# 2. davinci 设备文件 — 最直接的判断
ls -la /dev/davinci*

# 期望输出(8 卡服务器):
# /dev/davinci0  /dev/davinci1  /dev/davinci2  /dev/davinci3
# /dev/davinci4  /dev/davinci5  /dev/davinci6  /dev/davinci7
# /dev/davinci_manager
# /dev/devmm_svm
# /dev/hisi_hdc

# 3. 统计 NPU 数量
ls /dev/davinci[0-9]* | wc -l

2.2 驱动层:npu-smi 工具

npu-smi 是昇腾 NPU 的标配管理工具(类似 NVIDIA 的 nvidia-smi),但参数体系更复杂:昇腾硬件有三层编号 —— NPU(物理卡槽)、Chip(卡内芯片)、Device(操作系统设备号)。

# 第一步:先看总览
npu-smi info

典型输出(Atlas 300I Pro 310P3,一张卡内含 2 个 Chip):

+-------------------------------+-----------------+--------------------------+
| NPU     Name      | Health    | Power(W)  Temp(C) Hugepages-Usage(page)    |
| Chip    Device    | Bus-Id    | AICore(%) Memory-Usage(MB)                 |
+===================+===========+=============================================+
| 1       310P3     | OK        | NA        75       0     / 0               |  ← NPU ID=1
| 0       0         | 0000:01..| 0         1439 / 44280                      |  ← Chip 0, Device 0
+-------------------------------+-----------------+--------------------------+
| 1       310P3     | OK        | NA        73       0     / 0               |  ← 同一张卡 NPU ID=1
| 1       1         | 0000:01..| 0         1501 / 43693                      |  ← Chip 1, Device 1
+-------------------------------+-----------------+--------------------------+
| 2       310P3     | OK        | NA        74       0     / 0               |  ← NPU ID=2
| 0       2         | 0000:02..| 0         1495 / 44280                      |
+-------------------------------+-----------------+--------------------------+
| 2       310P3     | OK        | NA        73       0     / 0               |
| 1       3         | 0000:02..| 0         1443 / 43693                      |
+-------------------------------+-----------------+--------------------------+
  ... NPU 4,5 同理(NPU 0,3 槽位为空)

三层编号解读

  • NPU ID-i):物理卡槽编号,310P3 等双芯卡上不连续(如 1,2,4,5)
  • Chip ID-c):卡内芯片编号,双芯卡为 0 和 1
  • Device:操作系统设备号,对应 /dev/davinci0 ~ /dev/davinci7,供 docker --device 使用

大多数查询必须同时指定 -i-c 才能定位到一个具体 chip。

npu-smi 常用命令

# 查看 NPU 1, Chip 0 的详细信息
npu-smi info -i 1 -c 0

# 板卡信息(型号/序列号/IP)
npu-smi info -t board -i 1 -c 0

# 温度
npu-smi info -t temp -i 1 -c 0

# 显存(HBM)使用情况
npu-smi info -t memory -i 1 -c 0

# AICore 使用率
npu-smi info -t usages -i 1 -c 0

# 固件版本(卡级属性,只认 -i 不认 -c)
npu-smi info -t firmware -i 1

# 持续监控(不带 -i/-c 看全部)
watch -n 1 npu-smi info

常见错误-i 0Invalid card id。因为 NPU ID 是物理槽位号,和 /dev/davinci 的设备号不是同一个东西。以 npu-smi info 输出的 NPU 列为准。

2.3 驱动版本确认

# 查看驱动版本
cat /usr/local/Ascend/driver/version.info
# 输出示例:driver_version=23.0.0

# 查看 ascend 安装信息
cat /etc/ascend_install.info

# 查看 CANN 版本
cat /usr/local/Ascend/ascend-toolkit/latest/opp/built-in/op_impl/ai_core/tbe/version.info 2>/dev/null
# 或者
ls /usr/local/Ascend/ascend-toolkit/
# 输出示例:9.0.0

# 查看 NNAL 版本
ls /usr/local/Ascend/nnal/
# 输出示例:9.0.0

2.4 Python 层:torch-npu 检测

# 检查 torch-npu 是否安装
python3 -c "import torch_npu; print(torch_npu.__version__)"

# NPU 是否可用(最关键的一行)
python3 -c "import torch; print('NPU available:', torch.npu.is_available())"

# 设备数量
python3 -c "import torch; print('NPU count:', torch.npu.device_count())"

# 设备名称
python3 -c "import torch; [print(f'Device {i}: {torch.npu.get_device_name(i)}') for i in range(torch.npu.device_count())]"

# 完整检测脚本
python3 << 'EOF'
import torch
print(f"PyTorch version: {torch.__version__}")
print(f"NPU available: {torch.npu.is_available()}")
if torch.npu.is_available():
    print(f"NPU count: {torch.npu.device_count()}")
    for i in range(torch.npu.device_count()):
        print(f"  Device {i}: {torch.npu.get_device_name(i)}")
        print(f"    Memory: {torch.npu.get_device_properties(i).total_memory / 1024**3:.1f} GB")
else:
    print("WARNING: torch.npu.is_available() = False!")
    print("Check: CANN version matches torch-npu version? Driver loaded?")
EOF

2.5 设备不存在时的排障路径

现象可能原因检查命令
/dev/davinci* 不存在驱动未安装或未加载lsmod | grep drv
npu-smi 命令未找到CANN 未安装或 PATH 未设ls /usr/local/Ascend/
npu-smi 报错驱动版本与固件不匹配dmesg | grep -i davinci
torch.npu.is_available() = Falsetorch-npu 版本与 CANN 不匹配pip show torch-npu
容器内看不到设备--device 未正确挂载检查 docker run--device 参数

完整的环境就绪确认清单

✅ lspci -d 19e5: 或 lspci | grep huawei 能看到华为设备
✅ /dev/davinci0 ... /dev/davinciN 存在
✅ /dev/davinci_manager 存在
✅ npu-smi info 输出正常、Health = OK
✅ /usr/local/Ascend/driver/version.info 存在
✅ /usr/local/Ascend/ascend-toolkit/latest → 指向 CANN 9.0.0
✅ torch.npu.is_available() = True
✅ torch.npu.device_count() = 期望值

三、硬件要求

支持的设备

系列型号用途
Atlas A2 训练800T A2 / 900 A2 PoD / 200T A2 Box16 / 300T A2训练+推理
Atlas A2 推理800I A2高吞吐推理
Atlas A3 训练800T A3 / 900 A3 SuperPoD / 9000 A3 SuperPoD训练+推理
Atlas A3 推理800I A3高吞吐推理
Atlas 300I300I Pro (310P3) / 300I Duo推理(PCIe 标卡,43GB HBM)

软件栈版本

┌──────────────────────────────────┐
│           vllm-ascend             │  v0.20.2rc1+
├──────────────────────────────────┤
│          torch-npu 2.10.0        │  昇腾版 PyTorch
├──────────────────────────────────┤
│          torch 2.10.0            │
├──────────────────────────────────┤
│          CANN 9.0.0              │  昇腾计算架构(= CUDA 等价物)
├──────────────────────────────────┤
│          NNAL 9.0.0              │  昇腾神经网络加速库(libatb.so)
├──────────────────────────────────┤
│       Ascend HDK / 驱动           │  固件+驱动
├──────────────────────────────────┤
│       昇腾 NPU 硬件               │  Atlas A2/A3
└──────────────────────────────────┘

四、模型准备(ModelScope)

国内环境 HuggingFace 访问不稳定,推荐用 ModelScope 下载模型到本地,然后让 vLLM 直接读本地路径。

# 安装 ModelScope CLI
pip install modelscope

# 下载模型到本地目录(路径按自己习惯组织)
modelscope download --model Qwen/Qwen3-0.6B --local_dir /path/to/models/Qwen3-0.6B
modelscope download --model Qwen/Qwen3-8B   --local_dir /path/to/models/Qwen3-8B

# 启动时用本地路径替代 HuggingFace model ID
# ❌ vllm serve Qwen/Qwen3-8B           # 会尝试从 HF 拉取
# ✅ vllm serve /path/to/models/Qwen3-8B  # 直接用本地文件

关键点:容器部署时,通过 -v /path/to/models:/models:ro 把宿主机模型目录挂载进容器,容器内用 /models/Qwen3-8B 即可。


五、Docker 单机部署

5.1 拉取镜像并启动

挂载说明:下面的 -v 中,driver/lib64driver/version.infoascend_install.info 是推理必须的。hccn_tool(卡间通信工具)仅在多节点部署时需要,且训练卡才有 — 如果你的 /usr/local/Ascend/driver/tools/hccn_tool 不存在,直接去掉这一行即可。

# 设置要用的 NPU 设备
export DEVICE=/dev/davinci0

# 选择镜像(A2 和 A3 不同)
# Atlas A2:
export IMAGE=quay.io/ascend/vllm-ascend:v0.20.2rc1
# Atlas A3:
# export IMAGE=quay.io/ascend/vllm-ascend:v0.20.2rc1-a3

docker run --rm \
  --name vllm-ascend \
  --shm-size=1g \
  --device $DEVICE \
  --device /dev/davinci_manager \
  --device /dev/devmm_svm \
  --device /dev/hisi_hdc \
  -v /usr/local/dcmi:/usr/local/dcmi \
  -v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
  -v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \
  -v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \
  -v /etc/ascend_install.info:/etc/ascend_install.info \
  -v /root/.cache:/root/.cache \
  -p 8000:8000 \
  -it $IMAGE bash

5.2 多卡 Docker 启动

# 使用 4 张 NPU(davinci0 ~ davinci3)
docker run --rm \
  --name vllm-ascend \
  --shm-size=1g \
  --device /dev/davinci0 \
  --device /dev/davinci1 \
  --device /dev/davinci2 \
  --device /dev/davinci3 \
  --device /dev/davinci_manager \
  --device /dev/devmm_svm \
  --device /dev/hisi_hdc \
  -v /usr/local/dcmi:/usr/local/dcmi \
  -v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
  -v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \
  -v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \
  -v /etc/ascend_install.info:/etc/ascend_install.info \
  -v /root/.cache:/root/.cache \
  -p 8000:8000 \
  -it $IMAGE bash

# 容器内验证
npu-smi info                          # 看到 4 张卡
python3 -c "import torch; print(torch.npu.device_count())"  # 4

5.3 验证 NPU 可用

# 在容器内
npu-smi info
# 输出 NPU 型号、温度、显存使用

python3 -c "import torch; print(torch.npu.is_available())"
# True

5.4 启动推理服务 — Qwen3-0.6B

# 在容器内
vllm serve /models/Qwen3-0.6B \
  --host 0.0.0.0 \
  --port 8000

# 另一个终端测试
curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3-0.6b",
    "messages": [{"role": "user", "content": "你好"}]
  }'

六、Docker Compose 部署

Docker Compose 适合持久化运行、多卡管理、以及需要精确控制资源和服务依赖的场景。

关于 shm_size/dev/shm 是容器内共享内存,默认仅 64MB。PyTorch 的 DataLoader 和多卡并行(tensor parallelism)依赖 /dev/shm 做进程间 tensor 通信,64MB 完全不够 — 典型表现为 DataLoader worker exited unexpectedly 或 OOM。单卡设 1gb,多卡或大 batch 设 2gb 以上。

6.1 基础 docker-compose.yml

version: "3.8"

services:
  vllm-ascend:
    image: quay.io/ascend/vllm-ascend:v0.20.2rc1
    container_name: vllm-ascend
    # 使用 command 直接启动服务,无需手动进容器
    command: >
      vllm serve /models/Qwen3-8B
        --host 0.0.0.0
        --port 8000
        --max-model-len 8192
    shm_size: "1gb"
    ports:
      - "8000:8000"
    devices:
      # 挂载全部 8 张 NPU
      - /dev/davinci0:/dev/davinci0
      - /dev/davinci1:/dev/davinci1
      - /dev/davinci2:/dev/davinci2
      - /dev/davinci3:/dev/davinci3
      - /dev/davinci4:/dev/davinci4
      - /dev/davinci5:/dev/davinci5
      - /dev/davinci6:/dev/davinci6
      - /dev/davinci7:/dev/davinci7
      - /dev/davinci_manager:/dev/davinci_manager
      - /dev/devmm_svm:/dev/devmm_svm
      - /dev/hisi_hdc:/dev/hisi_hdc
    volumes:
      # 驱动和工具挂载
      - /usr/local/dcmi:/usr/local/dcmi
      - /usr/local/bin/npu-smi:/usr/local/bin/npu-smi
      - /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/
      - /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info
      - /etc/ascend_install.info:/etc/ascend_install.info
      # 模型缓存持久化(避免每次重建容器重新下载)
      - /path/to/models:/models:ro
      # 可写日志目录
      - /data/logs/vllm:/var/log/vllm
    environment:
      - HF_HOME=/root/.cache/huggingface
    restart: unless-stopped
    # 健康检查
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 120s
    deploy:
      resources:
        reservations:
          devices:
            - driver: ascend
              count: all
              capabilities: [npu]

6.2 多服务编排(推理 + 网关)

version: "3.8"

services:
  # === Qwen3-8B 推理服务(NPU 0-3) ===
  vllm-qwen:
    image: quay.io/ascend/vllm-ascend:v0.20.2rc1
    container_name: vllm-qwen
    command: >
      vllm serve /models/Qwen3-8B
        --host 0.0.0.0
        --port 8000
        --tensor-parallel-size 4
    shm_size: "2gb"
    devices:
      - /dev/davinci0:/dev/davinci0
      - /dev/davinci1:/dev/davinci1
      - /dev/davinci2:/dev/davinci2
      - /dev/davinci3:/dev/davinci3
      - /dev/davinci_manager:/dev/davinci_manager
      - /dev/devmm_svm:/dev/devmm_svm
      - /dev/hisi_hdc:/dev/hisi_hdc
    volumes:
      - /usr/local/dcmi:/usr/local/dcmi
      - /usr/local/bin/npu-smi:/usr/local/bin/npu-smi
      - /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/
      - /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info
      - /etc/ascend_install.info:/etc/ascend_install.info
      - /path/to/models:/models:ro
    environment:
      - HF_HOME=/root/.cache/huggingface
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 180s

  # === DeepSeek-R1 推理服务(NPU 4-7) ===
  vllm-deepseek:
    image: quay.io/ascend/vllm-ascend:v0.20.2rc1
    container_name: vllm-deepseek
    command: >
      vllm serve /models/DeepSeek-R1
        --host 0.0.0.0
        --port 8001
        --tensor-parallel-size 4
    shm_size: "2gb"
    devices:
      - /dev/davinci4:/dev/davinci4
      - /dev/davinci5:/dev/davinci5
      - /dev/davinci6:/dev/davinci6
      - /dev/davinci7:/dev/davinci7
      - /dev/davinci_manager:/dev/davinci_manager
      - /dev/devmm_svm:/dev/devmm_svm
      - /dev/hisi_hdc:/dev/hisi_hdc
    volumes:
      - /usr/local/dcmi:/usr/local/dcmi
      - /usr/local/bin/npu-smi:/usr/local/bin/npu-smi
      - /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/
      - /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info
      - /etc/ascend_install.info:/etc/ascend_install.info
      - /path/to/models:/models:ro
    environment:
      - HF_HOME=/root/.cache/huggingface
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8001/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 300s

  # === Nginx 反向代理(统一入口) ===
  nginx:
    image: nginx:alpine
    container_name: vllm-gateway
    ports:
      - "8080:8080"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      vllm-qwen:
        condition: service_healthy
      vllm-deepseek:
        condition: service_healthy
    restart: unless-stopped

配套的 nginx.conf

worker_processes auto;
events { worker_connections 1024; }

http {
    # 按模型名路由到对应后端
    # Qwen3 → 8000,DeepSeek → 8001
    # 客户端请求时传 model 参数,Nginx 按 model 分流

    server {
        listen 8080;

        # Qwen 系列
        location /v1/chat/completions {
            # 需要更复杂的 Lua/OpenResty 逻辑来按请求体中的 model 路由
            # 简单场景下可直接代理到默认后端
            proxy_pass http://vllm-qwen:8000;
            proxy_http_version 1.1;
            proxy_set_header Host $host;
            proxy_read_timeout 600s;
        }

        # DeepSeek 系列指定路径
        location /deepseek/v1/chat/completions {
            proxy_pass http://vllm-deepseek:8001/v1/chat/completions;
            proxy_http_version 1.1;
            proxy_set_header Host $host;
            proxy_read_timeout 600s;
        }

        # 健康检查聚合
        location /health {
            # 返回所有后端健康状态
            return 200 '{"qwen":"http://vllm-qwen:8000/health","deepseek":"http://vllm-deepseek:8001/health"}';
        }
    }
}

6.3 Compose 运维命令

# 启动所有服务
docker compose up -d

# 查看日志
docker compose logs -f vllm-qwen

# 仅重启单个服务
docker compose restart vllm-deepseek

# 停止并删除(保留模型缓存卷)
docker compose down

# 停止并删除全部(含模型缓存)
docker compose down -v

七、Kubelet 静态 Pod 部署

当你有一台或几台昇腾服务器,不想搭完整 K8s 集群,但希望用 Pod 的方式管理容器生命周期时,Kubelet 静态 Pod 是最轻量的方案。

7.1 前置条件

# 1. 安装 kubelet(无需 API Server/etcd)
# Ubuntu:
apt-get install -y kubelet kubeadm kubectl
# 或者只装 kubelet(如果你有其他方式装 kubectl)

# 2. 确认 kubelet 运行
systemctl status kubelet

# 3. 确认静态 Pod 目录存在
ls /etc/kubernetes/manifests/
# 默认静态 Pod 清单目录,放入 YAML 即可自动创建

Kubelet 会持续监控 /etc/kubernetes/manifests/ 目录,放入的任何 Pod YAML 会被自动创建,删除文件则 Pod 被删除。不需要 API Server,kubelet 独立完成。

7.2 静态 Pod YAML

# /etc/kubernetes/manifests/vllm-ascend.yaml
apiVersion: v1
kind: Pod
metadata:
  name: vllm-ascend
  namespace: default
  labels:
    app: vllm-ascend
    model: qwen3-8b
spec:
  # 不指定 restartPolicy 时静态 Pod 默认为 Always
  restartPolicy: Always
  hostNetwork: true          # 使用宿主机网络,NPU 通信需要
  hostIPC: true              # NPU 跨进程通信
  containers:
  - name: vllm
    image: quay.io/ascend/vllm-ascend:v0.20.2rc1
    command:
    - vllm
    - serve
    - /models/Qwen3-8B
    - --host
    - "0.0.0.0"
    - --port
    - "8000"
    - --max-model-len
    - "8192"
    ports:
    - containerPort: 8000
      hostPort: 8000
    resources:
      limits:
        # 声明 4 张昇腾 NPU
        huawei.com/Ascend910: 4
      requests:
        huawei.com/Ascend910: 4
    volumeMounts:
    - name: driver
      mountPath: /usr/local/Ascend/driver
      readOnly: true
    - name: dcmi
      mountPath: /usr/local/dcmi
      readOnly: true
    - name: npu-smi
      mountPath: /usr/local/bin/npu-smi
      readOnly: true
    - name: ascend-install
      mountPath: /etc/ascend_install.info
      readOnly: true
    - name: model-cache
      mountPath: /root/.cache/huggingface
    - name: shm
      mountPath: /dev/shm
    env:
    - name: HF_HOME
      value: /root/.cache/huggingface
    securityContext:
      privileged: true      # NPU 设备访问需要特权
  volumes:
  - name: driver
    hostPath:
      path: /usr/local/Ascend/driver
  - name: dcmi
    hostPath:
      path: /usr/local/dcmi
  - name: npu-smi
    hostPath:
      path: /usr/local/bin/npu-smi
  - name: ascend-install
    hostPath:
      path: /etc/ascend_install.info
  - name: model-cache
    hostPath:
      path: /data/models
      type: DirectoryOrCreate
  - name: shm
    hostPath:
      path: /dev/shm

7.3 NPU Device Plugin(可选,但推荐)

如果你的 kubelet 需要调度 NPU 资源(huawei.com/Ascend910),需要部署昇腾设备插件:

# 昇腾官方设备插件(DaemonSet 形式,但静态 Pod 也可以用)
# 方式 1:直接在宿主机给 kubelet 配置 NPU 资源
# 编辑 /var/lib/kubelet/config.yaml 或 kubelet 启动参数
# 添加:
#   --feature-gates=DevicePlugins=true

# 方式 2:如果没有设备插件,可以去掉 resources 段
# 裸用 hostPath 挂载 /dev/davinci* 也是可以的

不用设备插件的简化版(裸设备挂载)

# /etc/kubernetes/manifests/vllm-ascend-noplugin.yaml
apiVersion: v1
kind: Pod
metadata:
  name: vllm-ascend-noplugin
spec:
  restartPolicy: Always
  hostNetwork: true
  hostIPC: true
  containers:
  - name: vllm
    image: quay.io/ascend/vllm-ascend:v0.20.2rc1
    command:
    - vllm
    - serve
    - /models/Qwen3-8B
    - --host
    - "0.0.0.0"
    - --port
    - "8000"
    ports:
    - containerPort: 8000
      hostPort: 8000
    volumeMounts:
    - name: davinci0
      mountPath: /dev/davinci0
    - name: davinci1
      mountPath: /dev/davinci1
    - name: davinci-manager
      mountPath: /dev/davinci_manager
    - name: devmm-svm
      mountPath: /dev/devmm_svm
    - name: hisi-hdc
      mountPath: /dev/hisi_hdc
    - name: driver
      mountPath: /usr/local/Ascend/driver
      readOnly: true
    - name: npu-smi
      mountPath: /usr/local/bin/npu-smi
      readOnly: true
    - name: model-cache
      mountPath: /root/.cache/huggingface
    - name: shm
      mountPath: /dev/shm
    env:
    - name: HF_HOME
      value: /root/.cache/huggingface
    securityContext:
      privileged: true
  volumes:
  - name: davinci0
    hostPath:
      path: /dev/davinci0
      type: CharDevice
  - name: davinci1
    hostPath:
      path: /dev/davinci1
      type: CharDevice
  - name: davinci-manager
    hostPath:
      path: /dev/davinci_manager
      type: CharDevice
  - name: devmm-svm
    hostPath:
      path: /dev/devmm_svm
      type: CharDevice
  - name: hisi-hdc
    hostPath:
      path: /dev/hisi_hdc
      type: CharDevice
  - name: driver
    hostPath:
      path: /usr/local/Ascend/driver
  - name: npu-smi
    hostPath:
      path: /usr/local/bin/npu-smi
  - name: model-cache
    hostPath:
      path: /data/models
      type: DirectoryOrCreate
  - name: shm
    hostPath:
      path: /dev/shm

7.4 静态 Pod 运维

# 放入 YAML 后自动启动
cp vllm-ascend.yaml /etc/kubernetes/manifests/

# 查看 Pod 状态(通过 kubelet 的只读端口)
curl -s http://localhost:10255/pods | jq '.items[] | select(.metadata.name | startswith("vllm")) | {name: .metadata.name, phase: .status.phase}'

# 或者直接查容器
docker ps | grep vllm
# 静态 Pod 容器名格式:k8s_<container>_<pod>_<namespace>_<uid>

# 查看日志
docker logs -f <container-id>

# 修改 Pod:直接编辑 YAML,kubelet 自动 apply
vi /etc/kubernetes/manifests/vllm-ascend.yaml

# 删除 Pod:删除 YAML 文件
rm /etc/kubernetes/manifests/vllm-ascend.yaml
# Pod 自动被终止

# 临时停止(保留 YAML,不删除):移走
mv /etc/kubernetes/manifests/vllm-ascend.yaml /tmp/
# 恢复:
mv /tmp/vllm-ascend.yaml /etc/kubernetes/manifests/

7.5 何时用 Kubelet 而非 Docker Compose

场景推荐
单台服务器,手动管理Docker Compose
单台服务器,未来可能加 K8sKubelet 静态 Pod(迁移到 K8s 零成本)
多台服务器,已有 kubeletKubelet 静态 Pod + Ansible 分发
需要健康检查自动重启两者都支持,Kubelet 更原生
需要资源声明(CPU/内存)Kubelet(resources.limits)
已有 K8s 集群直接用 Deployment + Volcano Job

八、多卡推理(Tensor Parallelism)

# 2 张 NPU 并行
vllm serve /models/DeepSeek-R1 \
  --tensor-parallel-size 2 \
  --host 0.0.0.0 \
  --port 8000

九、支持的模型(v0.20)

vllm-ascend 的模型支持非常丰富,以下是官方文档列出的全部模型:

Qwen3 系列(最全)

模型特点
Qwen3-Dense (0.6B/8B/32B)纯 Dense 架构
Qwen3-30B-A3BMoE,30B 参数 3B 激活
Qwen3-235B-A22BMoE,235B 参数 22B 激活
Qwen3-VL (2B/4B/8B/32B)多模态
Qwen3-Coder-30B-A3B代码模型
Qwen3-Embedding嵌入模型
Qwen3-Reranker重排序模型
Qwen3-8B-W4A8 / 32B-W4A4量化模型
Qwen3-Omni-30B-A3B-Thinking全模态+推理
Qwen3.5-27B / 397B-A17B最新代

DeepSeek 系列

模型特点
DeepSeek-V3 / V3.1MoE 671B
DeepSeek-V3.2稀疏注意力
DeepSeek-V4-Flash / V4-Pro最新代
DeepSeek-R1推理模型
DeepSeek-OCR-2OCR 专用

GLM 系列

模型特点
GLM-4.5 / 4.6 / 4.7智谱系列
GLM-5 / GLM-5.1最新代

Kimi 系列

模型特点
Kimi-K2-ThinkingMoonshot
Kimi-K2.5最新代

其他

模型来源
MiniMax-M2.5MiniMax
PaddleOCR-VL百度 OCR
Hunyuan-A13B-Instruct腾讯混元
Hy3-preview
Mixtral-8x7BMistral
gpt-oss-120bOpenAI
Qwen3-ASR-1.7B语音识别

十、多节点部署

10.1 前置检查

每个节点确认 NPU 可达:

# 获取 NPU IP(-i 填 NPU ID, -c 填 Chip ID)
npu-smi info -t board -i 1 -c 0
# 在输出中找 IP 行

# 跨节点 ping 测试
ping <other-node-npu-ip>

10.2 每节点启动容器

# 节点 1
docker run ... \
  -e VLLM_HOST_IP=<node1-ip> \
  -e VLLM_PORT=8000 \
  -it $IMAGE bash

# 节点 2
docker run ... \
  -e VLLM_HOST_IP=<node2-ip> \
  -it $IMAGE bash

10.3 多节点 Docker Compose(每节点独立)

每台节点上都放一个精简 compose 文件,只需要映射本地 NPU:

# node1 的 docker-compose.yml(4 卡)
services:
  vllm-worker:
    image: quay.io/ascend/vllm-ascend:v0.20.2rc1
    command: >
      vllm serve /models/DeepSeek-V3
        --host 0.0.0.0
        --port 8000
        --tensor-parallel-size 4
        --pipeline-parallel-size 2
    network_mode: host
    # ... devices/volumes 同上单机配置

10.4 多节点通过 Kubelet + Ansible 分发

当你有多台昇腾服务器且都装了 kubelet 时,用 Ansible 统一分发静态 Pod YAML:

# ansible playbook: deploy-vllm.yaml
- hosts: ascend_nodes
  tasks:
    - name: 复制静态 Pod YAML
      copy:
        src: files/vllm-ascend.yaml
        dest: /etc/kubernetes/manifests/vllm-ascend.yaml
        owner: root
        mode: "0644"

    - name: 等待 Pod Ready
      wait_for:
        port: 8000
        timeout: 300

十一、pip 手动安装(不推荐,仅供了解)

# 1. 准备 CANN 环境
# 用 CANN 预构建镜像
docker run --rm -it quay.io/ascend/cann:9.0.0-910b-ubuntu22.04-py3.11 bash

# 2. 创建虚拟环境
python3 -m venv vllm-ascend-env
source vllm-ascend-env/bin/activate

# 3. 安装 vllm-ascend(自动拉 torch-npu)
pip install vllm-ascend

# 4. 验证
python3 -c "import vllm; print(vllm.__version__)"

注意:pip install vllm-ascend 会自动安装 torch-npu==2.10.0torch==2.10.0,不需要手动装。


十二、和 NVIDIA vLLM 的差异

维度vLLM (NVIDIA)vLLM (Ascend)
后端CUDACANN + torch-npu
安装pip install vllmpip install vllm-ascend
启动命令vllm serve ...完全一样
OpenAI API完全兼容完全兼容
量化FP8/FP4/AWQ/GPTQW4A8/W4A16(昇腾原生)
模型支持所有 HuggingFace 模型官方适配列表(30+)
镜像源Docker Hubquay.io/ascend
Docker Compose通用需挂载设备+驱动卷
K8s 调度GPU Operator设备插件或裸设备挂载

十三、和你的现有 AI 基础设施集成

你的组件vLLM Ascend 的关系
HAMiHAMi 支持 Ascend NPU 虚拟化,vllm-ascend 可以跑在 HAMi 切分的 vNPU 上
Volcanovllm-ascend 推理服务可提交为 Volcano Job
GPUStackGPUStack 支持 Ascend NPU,底层可调用 vllm-ascend
NVIDIA GPU 集群如果你有 NVIDIA + Ascend 混合集群,vLLM 可以统一 API,后端自适应

十四、运维速查

常见命令

# === 宿主机检测 ===
lspci -d 19e5:                            # PCIe 设备(华为 Vendor ID)
ls /dev/davinci*                          # 设备文件
npu-smi info                             # 基础概览(NPU + Chip + Device 三层)
npu-smi info -t memory -i 1 -c 0          # 指定 chip 的显存详情

# === 容器内检测 ===
python3 -c "import torch; print(torch.npu.device_count())"
python3 -c "import torch; print(torch.npu.get_device_name(0))"

# === vLLM 服务 ===
vllm serve <model> --host 0.0.0.0 --port 8000
curl http://localhost:8000/v1/models    # 模型列表
curl http://localhost:8000/health        # 健康检查

# === Docker ===
docker logs -f vllm-ascend
docker compose logs -f vllm-worker

# === Kubelet ===
curl -s http://localhost:10255/pods | jq
ls /etc/kubernetes/manifests/

常见问题

问题原因解决
/dev/davinci* 不存在驱动未安装/未加载检查 dmesg | grep -i davinci
npu-smi 报错/无输出CANN 未安装或驱动版本不匹配cat /usr/local/Ascend/driver/version.info
libatb.so not foundNNAL 未安装用 CANN 预构建镜像,或手动安装 NNAL
torch.npu.is_available() = False驱动或 CANN 版本不匹配确认 CANN==9.0.0, torch-npu==2.10.0
OOM模型太大、batch 太大--tensor-parallel-size 或多节点
镜像拉取慢quay.io 国内访问慢提前同步到私有 registry
容器内看不到 NPU--device 参数遗漏核对 docker run --device /dev/davinci*
Kubelet 静态 Pod 不启动格式错误或 kubelet 未运行journalctl -u kubelet -f

自检清单

  • 能说清楚 vllm-ascend 的定位(vLLM + CANN 后端,不是新推理引擎)
  • 能在服务器上完整检测 NPU 设备(lspci → /dev/davinci* → npu-smi → torch.npu)
  • 能用 Docker 启动 vllm-ascend 容器并跑通 Qwen3-0.6B
  • 能编写 docker-compose.yml 启动持久化推理服务
  • 能编写 Kubelet 静态 Pod YAML 部署 vllm-ascend
  • 理解 Ascend 软件栈:CANN ↔ CUDA,torch-npu ↔ torch.cuda
  • 知道 vllm-ascend 和 NVIDIA vLLM 命令完全一致,差异在后端
  • 能说出昇腾硬件系列(Atlas A2/A3)和对应场景
  • 知道多卡推理用 --tensor-parallel-size,命令和 NVIDIA 一致

十五、KV Cache 与并发数

vLLM 启动成功后会打印两行关键日志,直接告诉你这个推理服务能撑多少并发:

(EngineCore pid=190) INFO 07-20 08:33:44 [kv_cache_utils.py:1710] GPU KV cache size: 741,888 tokens
(EngineCore pid=190) INFO 07-20 08:33:44 [kv_cache_utils.py:1711] Maximum concurrency for 8,192 tokens per request: 90.56x

15.1 日志含义

日志字段含义说明
GPU KV cache size: 741,888 tokensKV Cache 总容量GPU 显存中分配给 KV Cache 的 token 总数
Maximum concurrency for 8,192 tokens per request: 90.56x理论最大并发数每个请求最多 8,192 token 时,能同时处理 ~90 个请求

15.2 计算公式

最大并发数 = KV Cache 总容量 / max-model-len

741,888 / 8,192 = 90.56

max-model-len 对应启动参数 --max-model-len(默认 8192),表示每个请求允许的最大 token 数(prompt + generation)。

15.3 怎样影响并发数

调整方向做法效果
提高并发减小 --max-model-lenKV Cache 总容量不变 → 每个请求分到的 token 少 → 并发↑
降低并发增大 --max-model-len每个请求需要更多 token → 并发↓,但能处理更长的上下文
提高并发增加 GPU 数(TP 扩展)总 KV Cache 增大 → 并发↑

15.4 实际并发 vs 理论并发

日志中的 90.56x理论最大值,实际并发受以下因素影响:

  • 请求长度不均:短请求和长请求混在一起,实际分配的 KV Cache 不是平均的
  • 前缀缓存(Prefix Caching):相同 system prompt 的请求共享 KV Cache,实际并发可能高于理论值
  • 显存碎片:运行一段时间后 KV Cache 可能有碎片,实际可用略低于理论值

监控建议:运行中通过 Prometheus 指标 vllm:gpu_cache_usage_percvllm:num_requests_waiting 观察实际 KV Cache 使用率和排队情况,不要只看启动日志的理论值。