基于eRDMA双机部署Qwen3-235B-A22B模型

使用vllmsglang推理框架,在阿里云GPU实例上快速部署双机Qwen3-235B-A22B模型,并启用eRDMA加速。根据PD分离(Prefill-decode disaggregation)和PD不分离两种架构来部署模型,其中PD分离架构是基于Mooncake作为后端存储引擎的。

费用说明

如果您按照ecs.ebmgn8v.48xlarge规格完成部署(大约需要50分钟)操作及体验,且时间不超过2小时,预计费用570元左右。实际情况中可能会因您操作过程中实际使用的流量差异,导致费用有所变化,请以控制台显示的实际报价以及最终账单为准。

操作步骤

步骤一:部署资源

  1. 为云服务器ECS实例构建云上的私有网络。

    1. 登录专有网络管理控制台,单击创建专有网络

    2. 创建专有网络页面,配置1个专有网络和1台交换机。

      配置项

      说明

      示例值

      VPC名称

      名称长度为2-128个字符,以字母或中文开头,可包含数字、下划线(_)和连字符(-)。

      VPC_QW

      地域

      选择计划创建云资源的地域。

      华东1(杭州)

      IPv4网段

      在创建VPC时,须按照无类域间路由块(CIDR block)的格式为专有网络划分私网网段。

      192.168.0.0/16

      交换机名称

      名称长度为2-128个字符,以字母或中文开头,可包含数字、下划线(_)和连字符(-)。

      vsw_001

      可用区

      选择可用区时,优先考虑较新的可用区。较新的可用区通常拥有更充足的资源,并能优先获得新的实例规格。

      杭州 可用区K

      IPv4网段

      虚拟交换机需要一个IPv4网段。

      192.168.0.0/24

  2. 创建安全组用于控制云资源的入站和出站网络流量。

    1. 前往ECS控制台-安全组

    2. 在页面左侧顶部,选择目标资源所在的资源组和地域。地域

    3. 单击创建安全组

      配置项

      说明

      示例值

      安全组名称

      设置安全组的名称。

      SecurityGroup_1

      网络

      选择之前规划的专有网络VPC。

      VPC_QW

      规则配置

      添加一条入站规则,放行3000端口的流量,并移除其他所有默认规则。

      3000

  3. 创建两台GPU实例并正确安装驱动,未提及配置项均使用默认配置即可。

    1. 前往ECS控制台-自定义购买

    2. 创建GPU实例,创建过程中需注意以下配置项,未说明的参数,可使用默认值。

      配置项

      说明

      示例值

      付费类型

      付费类型影响实例的计费和收费规则。ECS 计费的详细信息请参见计费方式概述

      按量付费

      地域

      实例所在地域。

      华东1(杭州)

      网络及可用区

      选择专有网络VPC和交换机。

      VPC_QW、vsw_001

      实例

      ECS的实例规格及内核、vCPU 数量。关于 ECS选型的最佳实践请参见实例规格选型指导

      ecs.ebmgn8v.48xlarge

      镜像

      ECS的装机盘,为ECS实例提供操作系统、预装软件等。

      公共镜像中选择 Alibaba Cloud Linux

      镜像的版本。

      Alibaba Cloud Linux 3.2104 LTS 64

      安装 GPU 驱动。

      勾选安装GPU驱动,在下拉列表中选择:

      CUDA 版本 12.8.1/Driver 版本 570.133.20/CUDNN 版本 9.8.0.87

      系统盘类型

      硬盘类型。

      ESSD 云盘

      系统盘容量

      硬盘容量。

      100 GiB

      数据盘

      用于存放模型。

      单击添加数据盘容量填写500GiB,勾选随实例释放

      公网 IP

      用于访问外网和提供企业门户网站服务。

      选中分配公网 IPv4 地址

      安全组

      使用之前创建的安全组。选择已有安全组

      SecurityGroup_1

      管理设置

      选择设置自定义密码,方便后续登录机器安装服务环境。

      自定义密码

步骤二:准备环境

在进行模型部署之前,需要先准备好运行环境,确保GPU资源能够被正确调用,并且通过Docker和 NVIDIA容器工具包实现环境的隔离和一致性。

  1. 执行以下脚本会在您的实例上安装DockerNVIDIA容器工具包,当输出日志安装完成表示成功安装。

    由于需要下载网络资源,安装脚本需要3-10分钟左右,请您耐心等待。
    # 脚本支持Alibaba Cloud Linux、CentOS
    curl -fsSL https://help-static-aliyun-doc.aliyuncs.com/qwen3/install-script/install-docker.sh | bash
  2. 初始化数据盘,并将数据盘挂载到/mnt目录。

    1. 执行lsblk命令,查看数据盘的信息。image

    2. 执行以下命令,创建并挂载文件系统至/mnt目录下。

      sudo mkfs.ext4 /dev/vdb
      sudo mount /dev/vdb /mnt
    3. 执行lsblk命令,查看数据盘已挂载至/mnt目录下。

      image

步骤三:下载模型

  1. 安装并配置ossutil,具体操作请参见安装ossutil配置ossutil

  2. 执行以下脚本通过ossutil下载模型文件(存储在/mnt/Qwen3-235B-A22B目录下),当输出日志Qwen3-235B-A22B downloads successfully!表示模型下载成功。

    说明
    • 由于模型较大,下载时间为15-20分钟左右,请您耐心等待。

    • 模型下载是通过ossutil并使用cp命令在内网环境执行下载,以起到下载加速的目的,如果您的ECS在非杭州地域,执行下载脚本会出现网络连接错误,您也可以通过ModelScope的模型库下载Qwen3-235B-A22B

    curl -fsSL https://help-static-aliyun-doc.aliyuncs.com/qwen3/install-script/235b-a22b-0522/download.sh | bash

步骤四:部署模型

第一次启动容器时需要下载推理服务镜像,耗时约1015分钟,请您耐心等待。
  1. 启动容器

    vllm

    # 定义模型名称。
    MODEL_NAME="Qwen3-235B-A22B"
    
    # 设置本地存储路径。
    LOCAL_SAVE_PATH="/mnt/Qwen3-235B-A22B"
    
    # 确保当前用户对该目录有读写权限,根据实际情况调整权限
    sudo chmod ugo+rw ${LOCAL_SAVE_PATH}
    
    # 启动Docker容器
    docker run -t -d \
        --name="vllm-test" \
        --ipc=host \
        --cap-add=SYS_PTRACE \
        --network=host \
        --gpus all \
        --privileged \
        --ulimit memlock=-1 \
        --ulimit stack=67108864 \
        -v /mnt:/mnt \
        -e NCCL_SOCKET_IFNAME=eth0,eth1 \
        -e NCCL_IB_DISABLE=0 \
        -e GLOO_SOCKET_IFNAME=eth0 \
        egs-registry.cn-hangzhou.cr.aliyuncs.com/egs/vllm:0.8.5-pytorch2.6-cu124-20250429

    sglang

    # 定义模型名称。
    MODEL_NAME="Qwen3-235B-A22B"
    
    # 设置本地存储路径。
    LOCAL_SAVE_PATH="/mnt/Qwen3-235B-A22B"
    
    # 确保当前用户对该目录有读写权限,根据实际情况调整权限
    sudo chmod ugo+rw ${LOCAL_SAVE_PATH}
    
    # 启动Docker容器
    docker run -t -d \
        --name="vllm-test" \
        --ipc=host \
        --cap-add=SYS_PTRACE \
        --network=host \
        --gpus all \
        --privileged \
        --ulimit memlock=-1 \
        --ulimit stack=67108864 \
        -v /mnt:/mnt \
        -e NCCL_SOCKET_IFNAME=eth0,eth1 \
        -e NCCL_IB_DISABLE=0 \
        -e GLOO_SOCKET_IFNAME=eth0 \
        egs-registry.cn-hangzhou.cr.aliyuncs.com/egs/sglang:0.4.6.post1-pytorch2.6-cu124-20250429
  2. 为容器部署eRDMA驱动程序包。

    1. 执行以下命令,进入vllm-test容器。

      docker exec -it vllm-test bash
    2. 部署eRDMA驱动程序包。

      如果部署成功可以通过命令ibv_devinfo查看到eRDMA设备信息。
      # 添加PGP签名
      wget -qO - http://mirrors.cloud.aliyuncs.com/erdma/GPGKEY | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/erdma.gpg
      # 添加apt源
      echo "deb [ ] http://mirrors.cloud.aliyuncs.com/erdma/apt/ubuntu jammy/erdma main" | sudo tee /etc/apt/sources.list.d/erdma.list
      # 更新apt源
      sudo apt update
      # 安装用户态驱动
      sudo apt install libibverbs1 ibverbs-providers ibverbs-utils librdmacm1 -y
  3. 创建集群推理环境(PD分离模式下无需执行)。

    1. 执行以下命令,进入vllm-test容器。

      docker exec -it vllm-test bash
    2. 作为集群head节点。执行命令。

      pip3 install ray
      ray start --head --dashboard-host 0.0.0.0

      会出现类似下述回显信息。image.png

    3. 在另一个节点容器中运行上图红框内的命令,以创建Ray集群。随后在集群任一节点上运行ray status命令,检查集群状态。

  4. 在任意节点的容器中运行以下命令,启动Qwen3-235B-A22B推理服务。将/path/to/model替换为实际的模型路径。

    • PD不分离架构。

      1. # 启动vllm推理服务
        vllm serve /path/to/model \
        --tensor-parallel-size 8 \
        --pipeline-parallel-size 2 \
        --trust-remote-code \
        --enable-chunked-prefill \
        --host 0.0.0.0
        
        # 启动sglang推理服务
        # 在node1容器上执行
        python3 -m sglang.launch_server --model-path /path/to/model --port 8000 --tp 8 --nnodes 2 --ep 2 --trust-remote-code --host 0.0.0.0  --node-rank 0 --dist-init-addr <node1 ip>:50000
      2. 等待推理服务初始化完成。然后打开一个新终端,运行以下命令发送推理请求。命令的输出即为模型返回的结果。

        curl http://localhost:8000/v1/chat/completions \
        -H "Content-Type:application/json" \
        -d '{
          "model":"/data/Qwen3-8B",
          "messages":[{"role": "user", "content": "写一首20字的月亮诗"}],
          "stream":false}'
      3. 进行模型性能评估。

        1. 在容器中克隆ShareGPT_V3_unfiltered_cleaned_split数据集仓库。

          git lfs clone https://www.modelscope.cn/datasets/gliang1001/ShareGPT_V3_unfiltered_cleaned_split.git
        2. 在容器终端运行命令,测试vllm/sglang serving模式的性能。将/path/to/ShareGPT_V3_unfiltered_cleaned_split.json替换为评估数据集的本地路径。

          vllm

          # 启用vllm serving模式性能评估
          # 获取vllm源码
          git lfs clone https://github.com/vllm-project/vllm.git -b v0.8.5
          
          python3 ./vllm/benchmarks/benchmark_serving.py \
            --backend vllm \
            --model /path/to/model \
            --dataset-name random \
            --random-output-len 4096 \
            --random-input-len 512 \
            --num-prompts 10 \
            --max-concurrency 1 \
            --dataset-path /path/to/ShareGPT_V3_unfiltered_cleaned_split/ShareGPT_V3_unfiltered_cleaned_split.json

          sglang

          # 启用sglang serving模式性能评估
          python3 -m sglang.bench_serving \
             --backend sglang \
             --model /data/Qwen3-8B \
             --port 8000 \
             --dataset-name random \
             --random-input-len 3000 \
             --random-output-len 1 \
             --num-prompts 100 \
             --max-concurrency 1 \
             --dataset-path /path/to/ShareGPT_V3_unfiltered_cleaned_split/ShareGPT_V3_unfiltered_cleaned_split.json
    • 基于mooncake存储的PD分离架构。

      1. 环境配置。

        # 安装mooncake-transfer-engine,可以使用阿里镜像源加速
        pip3 install "mooncake-transfer-engine==0.3.7" -i https://mirrors.aliyun.com/pypi/simple
        
        # 搭建vllm PD分离架构需要执行以下步骤
        # 更新vllm版本
        pip3 install "vllm==0.11.0" -i https://mirrors.aliyun.com/pypi/simple
        
        # 安装LMCache,其实现了对应的连接器以支持KVCache的存储、传输和加载,完成PD节点间的协同操作
        pip3 install "lmcache==0.3.9" -i https://mirrors.aliyun.com/pypi/simple
        
        # 在node1上启动mooncake master节点
        mooncake_master -port 50052 -max_threads 64 -metrics_port 9004 \
          --enable_http_metadata_server=true \
          --http_metadata_server_host=0.0.0.0 \
          --http_metadata_server_port=8080
      2. node 1上启动prefill节点。

        vllm

        # 构建prefill配置文件
        cat > /mnt/mooncake-prefiller-config.yaml << 'EOF'
        chunk_size: 256
        remote_url: "mooncakestore://<node1 ip>:50052/"
        remote_serde: "naive"
        local_cpu: False
        max_local_cpu_size: 1
        
        extra_config:
          local_hostname: "<node1 ip>"
          metadata_server: "http://<node1 ip>:8080/metadata"
          protocol: "rdma"
          device_name: "erdma_0" # 多个RDMA设备可以通过逗号隔开
          master_server_address: "<node1 ip>:50052"
          global_segment_size: 524288000
          local_buffer_size: 524288000
          transfer_timeout: 1
          save_chunk_meta: False
        EOF
        
        LMCACHE_CONFIG_FILE=/mnt/mooncake-prefiller-config.yaml vllm serve /path/to/model --tensor-parallel-size 8 --port 7100 --kv-transfer-config '{"kv_connector":"LMCacheConnectorV1","kv_role":"kv_producer"}'

        sglang

        python3 -m sglang.launch_server \
                --model-path /data/Qwen3-8B/ \
                --trust-remote-code \
                --port 30500 \
                --host 10.0.1.46 \
                --tp-size 8    \
                --disaggregation-mode prefill \
                --disaggregation-transfer-backend mooncake
      3. node 2上启动decode节点。

        vllm

        # 构建decode配置文件
        cat > /mnt/mooncake-decoder-config.yaml << 'EOF'
        chunk_size: 256
        remote_url: "mooncakestore://<node1 ip>:50052/"
        remote_serde: "naive"
        local_cpu: False
        max_local_cpu_size: 1
        
        extra_config:
          local_hostname: "<node2 ip>"
          metadata_server: "http://<node1 ip>:8080/metadata"
          protocol: "rdma"
          device_name: "erdma_0" # 多个RDMA设备可以通过逗号隔开
          master_server_address: "<node1 ip>:50052"
          global_segment_size: 524288000
          local_buffer_size: 524288000
          transfer_timeout: 1
          save_chunk_meta: False
        EOF
        
        LMCACHE_CONFIG_FILE=/mnt/mooncake-decoder-config.yaml vllm serve /path/to/model --tensor-parallel-size 8 --port 7200 --kv-transfer-config '{"kv_connector":"LMCacheConnectorV1","kv_role":"kv_consumer"}'

        sglang

        python3 -m sglang.launch_server \
                --model-path /data/Qwen3-8B \
                --trust-remote-code \
                --port 30500 \
                --host 10.0.0.249 \
                --tp-size 8    \
                --cuda-graph-bs 32 40 48 56 64 96 \
                --disaggregation-mode decode \
                --disaggregation-transfer-backend mooncake
      4. 启动proxy server,协调PD分离架构。

        vllm

        # 使用lmcache提供的proxy server启动脚本
        wget https://raw.githubusercontent.com/LMCache/LMCache/v0.3.9/examples/disagg_prefill/disagg_proxy_server.py
        
        # 使用mooncake作为后端存储时需要注释掉脚本中一处KVCache就绪等待逻辑
        # 找到以下两行:
        #    # Wait until decode node signals that kv is ready
        #    await wait_decode_kv_ready(req_id, num_tp_rank)
        # 将第二行注释掉,改为:
        #    # await wait_decode_kv_ready(req_id, num_tp_rank)
        
        # 启动proxy server
        python3 disagg_proxy_server.py --host localhost --port 9000 --prefiller-host <node1 ip> --prefiller-port 7100 --decoder-host <node2 ip> --decoder-port 7200

        sglang

        # 使用sglang提供的轻量级Load Balancer
        python3 -m sglang.srt.disaggregation.mini_lb --prefill "http://10.0.1.46:30500"  --decode  "http://10.0.0.249:30500" --host 0.0.0.0 --port 8000
      5. 推理测试验证。sglang PD分离的推理测试验证命令同上述PD不分离架构。

        vllm bench serve --port 9000 \
            --model /path/to/model \
            --dataset-name random \
            --random-input-len 512 \
            --random-output-len 4096 \
            --random-range-ratio 0.2 \
            --num-prompts 10

资源释放

在本文中,您创建了多个云资源。测试完方案后,您可以参考以下规则处理对应产品的实例,避免继续产生费用。

  1. 释放云服务器ECS实例:

    登录ECS控制台,在实例页面,找到目标实例,然后在操作列选择216更多-竖向..png>释放,根据界面提示释放实例。

  2. 删除安全组:

    登录ECS 控制台,在安全组页面,找到目标安全组,然后在操作列单击删除,按照界面提示删除安全组。

  3. 删除交换机:

    登录专有网络控制台,在交换机页面,找到目标交换机,然后在操作列单击删除,按照界面提示删除交换机。

  4. 释放专有网络VPC:

    登录专有网络控制台,在专有网络页面,找到目标VPC,然后在操作列单击删除,按照界面提示释放专有网络VPC。