千问3.5-27B部署教程:Ansible自动化脚本实现百台GPU服务器批量部署

1. 引言:从单机到集群的部署挑战

想象一下,你刚刚在单台服务器上成功部署了千问3.5-27B模型,体验到了它强大的多模态对话能力。现在,老板给你下达了一个新任务:需要在两周内,将这套系统部署到公司新采购的100台GPU服务器上,为即将上线的新产品提供AI服务支持。

你可能会想:“一台一台手动部署?那得干到猴年马月。” 配置环境、安装依赖、下载模型、启动服务……每个步骤都可能遇到不同的问题,重复劳动不仅效率低下,还容易出错。这就是我们今天要解决的核心问题:如何将复杂的AI模型部署,从繁琐的手工操作,转变为高效、可靠的自动化流程。

本文将带你一步步构建一个基于Ansible的自动化部署方案,让你能够像管理一台服务器一样,轻松管理上百台GPU服务器集群。无论你是运维工程师、AI算法工程师,还是技术负责人,这套方案都能帮你大幅提升部署效率,确保环境一致性。

2. 环境准备与Ansible基础

2.1 为什么选择Ansible?

在开始之前,我们先简单了解一下为什么选择Ansible作为我们的自动化工具。Ansible有以下几个核心优势:

  • 无代理架构:不需要在目标服务器上安装任何客户端,通过SSH就能完成所有操作
  • 声明式语法:用YAML编写剧本(Playbook),描述“最终状态”而非具体步骤,更直观
  • 幂等性:无论执行多少次,结果都是一致的,避免重复操作带来的问题
  • 模块化设计:丰富的内置模块,覆盖文件管理、包安装、服务控制等常见需求

对于我们的千问3.5-27B部署场景,这些特性正好解决了批量部署中的关键痛点:环境一致性、操作可重复性、错误可追溯性。

2.2 控制节点环境搭建

首先,我们需要准备一台“控制节点”服务器,它将负责向所有目标GPU服务器发送指令。这台机器可以是你的本地开发机,也可以是一台专门的运维服务器。

# 在控制节点上安装Ansible
# 对于Ubuntu/Debian系统
sudo apt update
sudo apt install -y ansible sshpass

# 对于CentOS/RHEL系统
sudo yum install -y epel-release
sudo yum install -y ansible sshpass

# 验证安装
ansible --version

安装完成后,我们需要配置Ansible的主机清单(Inventory)。主机清单定义了我们要管理的所有服务器。

# 创建项目目录结构
mkdir -p ~/qwen-deploy/{inventory,playbooks,roles,files}
cd ~/qwen-deploy

# 创建主机清单文件
cat > inventory/hosts.ini << 'EOF'
[gpu_servers]
gpu-server-01 ansible_host=192.168.1.101 ansible_user=root
gpu-server-02 ansible_host=192.168.1.102 ansible_user=root
gpu-server-03 ansible_host=192.168.1.103 ansible_user=root
# ... 可以继续添加更多服务器

[gpu_servers:vars]
# 所有GPU服务器的通用变量
ansible_ssh_private_key_file=~/.ssh/id_rsa
ansible_python_interpreter=/usr/bin/python3
model_name=Qwen3.5-27B
model_path=/root/ai-models/Qwen/Qwen3.5-27B
service_port=7860
EOF

在实际环境中,你可能会有几十甚至上百台服务器。Ansible支持动态清单,可以从云平台API、CMDB系统或简单的文本文件中读取主机信息。这里我们使用静态文件作为示例。

2.3 SSH免密登录配置

为了让Ansible能够自动登录到所有目标服务器,我们需要配置SSH免密登录。这是自动化部署的前提条件。

# 1. 在控制节点生成SSH密钥(如果还没有)
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N ""

# 2. 将公钥分发到所有目标服务器
# 首先测试单台服务器的连接
ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.1.101

# 3. 使用Ansible批量分发公钥(需要先配置好部分服务器的密码)
cat > playbooks/setup-ssh.yml << 'EOF'
---
- name: 设置SSH免密登录
  hosts: gpu_servers
  gather_facts: no
  vars:
    ansible_ssh_user: root
    ansible_ssh_pass: "{{ ssh_password }}"  # 首次运行时需要密码
  
  tasks:
    - name: 创建.ssh目录
      file:
        path: /root/.ssh
        state: directory
        mode: '0700'
    
    - name: 添加控制节点公钥
      authorized_key:
        user: root
        state: present
        key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
EOF

# 运行剧本(首次需要密码)
ansible-playbook -i inventory/hosts.ini playbooks/setup-ssh.yml --extra-vars "ssh_password=your_initial_password"

完成SSH配置后,我们可以测试一下连接是否正常:

# 测试所有服务器的连通性
ansible -i inventory/hosts.ini gpu_servers -m ping

# 如果一切正常,你会看到类似这样的输出:
# gpu-server-01 | SUCCESS => {
#     "changed": false,
#     "ping": "pong"
# }
# gpu-server-02 | SUCCESS => {
#     "changed": false,
#     "ping": "pong"
# }

3. 千问3.5-27B自动化部署剧本

现在我们已经准备好了基础环境,接下来开始编写部署千问3.5-27B的核心剧本。我们将把整个部署过程分解为多个独立的角色(Role),每个角色负责一个特定的功能模块。

3.1 创建角色目录结构

Ansible的角色(Role)是一种组织Playbook的方式,它把相关的任务、变量、文件等组织在一起,便于复用和维护。

# 创建基础系统配置角色
mkdir -p roles/base/tasks
mkdir -p roles/base/files
mkdir -p roles/base/templates

# 创建Docker环境角色
mkdir -p roles/docker/tasks

# 创建模型部署角色
mkdir -p roles/qwen-deploy/tasks
mkdir -p roles/qwen-deploy/files
mkdir -p roles/qwen-deploy/templates

# 创建服务管理角色
mkdir -p roles/service/tasks
mkdir -p roles/service/templates

3.2 基础系统配置角色

这个角色负责在所有GPU服务器上配置基础环境,包括系统更新、必要的工具安装、NVIDIA驱动检查等。

# roles/base/tasks/main.yml
---
- name: 更新系统包缓存
  apt:
    update_cache: yes
    cache_valid_time: 3600
  when: ansible_os_family == "Debian"

- name: 安装基础工具
  apt:
    name:
      - curl
      - wget
      - git
      - vim
      - htop
      - net-tools
      - python3-pip
      - python3-venv
    state: present
  when: ansible_os_family == "Debian"

- name: 检查NVIDIA驱动
  shell: nvidia-smi --query-gpu=name,memory.total --format=csv,noheader
  register: nvidia_info
  ignore_errors: yes
  changed_when: false

- name: 显示GPU信息
  debug:
    msg: "GPU信息: {{ nvidia_info.stdout }}"

- name: 创建模型存储目录
  file:
    path: "{{ model_path }}"
    state: directory
    mode: '0755'

- name: 创建服务目录
  file:
    path: /opt/qwen3527-27b
    state: directory
    mode: '0755'

3.3 Docker环境配置角色

千问3.5-27B的部署通常需要特定的Python环境和依赖。使用Docker可以确保环境的一致性,避免“在我机器上能运行”的问题。

# roles/docker/tasks/main.yml
---
- name: 安装Docker依赖
  apt:
    name:
      - apt-transport-https
      - ca-certificates
      - curl
      - gnupg
      - lsb-release
    state: present
  when: ansible_os_family == "Debian"

- name: 添加Docker官方GPG密钥
  apt_key:
    url: https://download.docker.com/linux/ubuntu/gpg
    state: present
  when: ansible_os_family == "Debian"

- name: 添加Docker仓库
  apt_repository:
    repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
    state: present
  when: ansible_os_family == "Debian"

- name: 安装Docker引擎
  apt:
    name:
      - docker-ce
      - docker-ce-cli
      - containerd.io
      - docker-compose-plugin
    state: present
  when: ansible_os_family == "Debian"

- name: 启动Docker服务
  systemd:
    name: docker
    state: started
    enabled: yes

- name: 安装NVIDIA Docker运行时
  shell: |
    distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
      && curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - \
      && curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
  when: ansible_os_family == "Debian"

- name: 安装nvidia-docker2
  apt:
    name: nvidia-docker2
    state: present
    update_cache: yes
  when: ansible_os_family == "Debian"

- name: 重启Docker服务
  systemd:
    name: docker
    state: restarted

- name: 测试NVIDIA Docker
  shell: docker run --rm --gpus all nvidia/cuda:11.8.0-base-ubuntu22.04 nvidia-smi
  register: nvidia_docker_test
  changed_when: false

- name: 显示NVIDIA Docker测试结果
  debug:
    msg: "NVIDIA Docker测试: {{ nvidia_docker_test.stdout_lines[0:2] | join('\n') }}"

3.4 千问3.5-27B部署角色

这是最核心的角色,负责拉取模型、配置环境、启动服务。我们将使用Docker Compose来管理整个服务栈。

首先,创建Docker Compose配置文件模板:

# roles/qwen-deploy/templates/docker-compose.yml.j2
version: '3.8'

services:
  qwen3527:
    image: {{ docker_image | default("qwen3527:latest") }}
    container_name: qwen3527
    restart: unless-stopped
    ports:
      - "{{ service_port }}:7860"
    volumes:
      - "{{ model_path }}:/app/models"
      - "./logs:/app/logs"
      - "./config:/app/config"
    environment:
      - MODEL_PATH=/app/models/Qwen3.5-27B
      - MAX_NEW_TOKENS=256
      - DEVICE=cuda
      - NUM_GPUS=4
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    command: >
      python -m uvicorn main:app
      --host 0.0.0.0
      --port 7860
      --workers 1
    networks:
      - qwen-network

networks:
  qwen-network:
    driver: bridge

接下来,创建部署任务:

# roles/qwen-deploy/tasks/main.yml
---
- name: 下载模型文件(如果不存在)
  block:
    - name: 检查模型是否已存在
      stat:
        path: "{{ model_path }}/config.json"
      register: model_exists
    
    - name: 从镜像服务器下载模型
      shell: |
        set -e
        cd {{ model_path }}
        if [ ! -f "config.json" ]; then
          echo "开始下载模型文件..."
          # 这里可以使用wget、rsync或scp从中央存储下载
          # 示例:wget -q http://model-server/qwen3.5-27b.tar.gz
          # tar -xzf qwen3.5-27b.tar.gz
          # 实际生产环境建议使用专用的模型分发系统
          echo "模型下载完成"
        else
          echo "模型已存在,跳过下载"
        fi
      args:
        executable: /bin/bash
      when: not model_exists.stat.exists
      register: download_result
    
    - name: 显示下载结果
      debug:
        msg: "模型准备状态: {{ download_result.stdout }}"
  
  rescue:
    - name: 下载失败处理
      debug:
        msg: "模型下载失败,请检查网络连接或存储服务器状态"

- name: 创建Docker镜像构建文件
  template:
    src: Dockerfile.j2
    dest: /opt/qwen3527-27b/Dockerfile
    mode: '0644'

- name: 创建Docker Compose配置
  template:
    src: docker-compose.yml.j2
    dest: /opt/qwen3527-27b/docker-compose.yml
    mode: '0644'

- name: 创建服务配置文件
  copy:
    src: supervisor.conf
    dest: /etc/supervisor/conf.d/qwen3527.conf
    mode: '0644'
  notify: 重载Supervisor配置

- name: 构建Docker镜像
  shell: |
    cd /opt/qwen3527-27b
    docker build -t qwen3527:latest .
  args:
    chdir: /opt/qwen3527-27b
  register: build_result

- name: 启动服务
  shell: |
    cd /opt/qwen3527-27b
    docker-compose up -d
  args:
    chdir: /opt/qwen3527-27b
  register: startup_result

- name: 检查服务状态
  shell: |
    sleep 10  # 等待服务启动
    curl -s http://localhost:{{ service_port }}/health || echo "服务未就绪"
  register: health_check
  changed_when: false

- name: 显示服务状态
  debug:
    msg: |
      服务启动结果: {{ startup_result.stdout }}
      健康检查: {{ health_check.stdout }}

3.5 服务管理角色

这个角色负责服务的监控、日志管理和日常维护。

# roles/service/tasks/main.yml
---
- name: 安装Supervisor
  apt:
    name: supervisor
    state: present
  when: ansible_os_family == "Debian"

- name: 配置Supervisor服务管理
  template:
    src: qwen3527_supervisor.conf.j2
    dest: /etc/supervisor/conf.d/qwen3527.conf
    mode: '0644'
  notify: 重载Supervisor配置

- name: 创建日志轮转配置
  copy:
    src: qwen3527_logrotate
    dest: /etc/logrotate.d/qwen3527
    mode: '0644'

- name: 设置监控脚本
  copy:
    src: check_qwen_service.sh
    dest: /usr/local/bin/check_qwen_service.sh
    mode: '0755'

- name: 添加定时监控任务
  cron:
    name: "监控千问服务"
    minute: "*/5"
    job: "/usr/local/bin/check_qwen_service.sh"
    user: root

- name: 配置防火墙规则
  ufw:
    rule: allow
    port: "{{ service_port }}"
    proto: tcp
  when: ansible_os_family == "Debian"

- name: 显示服务访问信息
  debug:
    msg: |
      服务部署完成!
      访问地址: http://{{ ansible_host }}:{{ service_port }}
      API端点: http://{{ ansible_host }}:{{ service_port }}/generate
      图片理解API: http://{{ ansible_host }}:{{ service_port }}/generate_with_image

4. 整合部署剧本与批量执行

现在我们已经创建了所有必要的角色,接下来需要创建一个主剧本(Playbook)来协调这些角色的执行顺序。

4.1 主部署剧本

# playbooks/deploy_qwen_cluster.yml
---
- name: 部署千问3.5-27B集群 - 基础环境准备
  hosts: gpu_servers
  serial: 10  # 每次在10台服务器上并行执行
  gather_facts: yes
  roles:
    - role: base
      tags: base

- name: 部署千问3.5-27B集群 - Docker环境
  hosts: gpu_servers
  serial: 10
  roles:
    - role: docker
      tags: docker

- name: 部署千问3.5-27B集群 - 模型服务
  hosts: gpu_servers
  serial: 5  # 模型部署比较耗时,减少并行数
  roles:
    - role: qwen-deploy
      tags: qwen-deploy

- name: 部署千问3.5-27B集群 - 服务管理
  hosts: gpu_servers
  serial: 20  # 服务管理可以并行更多
  roles:
    - role: service
      tags: service

- name: 验证集群部署
  hosts: gpu_servers
  gather_facts: no
  tasks:
    - name: 检查服务端口
      wait_for:
        port: "{{ service_port }}"
        host: "{{ ansible_host }}"
        timeout: 30
      delegate_to: localhost
    
    - name: 测试API接口
      uri:
        url: "http://{{ ansible_host }}:{{ service_port }}/health"
        method: GET
        status_code: 200
        timeout: 10
      register: api_test
      delegate_to: localhost
    
    - name: 记录验证结果
      debug:
        msg: "服务器 {{ ansible_host }} 部署{{ '成功' if api_test.status == 200 else '失败' }}"

4.2 执行批量部署

有了完整的剧本,现在可以开始批量部署了。Ansible提供了多种执行策略,我们可以根据实际情况选择。

# 1. 完整部署(所有服务器)
ansible-playbook -i inventory/hosts.ini playbooks/deploy_qwen_cluster.yml

# 2. 分阶段部署(先部署基础环境)
ansible-playbook -i inventory/hosts.ini playbooks/deploy_qwen_cluster.yml --tags base,docker

# 3. 只部署模型服务(当基础环境已就绪时)
ansible-playbook -i inventory/hosts.ini playbooks/deploy_qwen_cluster.yml --tags qwen-deploy,service

# 4. 只部署特定服务器组
ansible-playbook -i inventory/hosts.ini playbooks/deploy_qwen_cluster.yml --limit "gpu-server-01,gpu-server-02"

# 5. 检查模式(模拟执行,不实际修改)
ansible-playbook -i inventory/hosts.ini playbooks/deploy_qwen_cluster.yml --check

# 6. 详细输出模式(调试用)
ansible-playbook -i inventory/hosts.ini playbooks/deploy_qwen_cluster.yml -vvv

4.3 处理部署中的常见问题

在批量部署过程中,可能会遇到各种问题。Ansible提供了强大的错误处理和重试机制。

# playbooks/handle_failures.yml
---
- name: 带错误处理的部署
  hosts: gpu_servers
  strategy: linear
  max_fail_percentage: 20  # 允许20%的服务器失败
  any_errors_fatal: false  # 单个服务器失败不影响其他服务器
  
  tasks:
    - name: 尝试部署服务
      block:
        - name: 执行部署
          include_role:
            name: qwen-deploy
        
        - name: 验证部署
          uri:
            url: "http://localhost:{{ service_port }}/health"
            method: GET
            status_code: 200
          register: health_check
          until: health_check.status == 200
          retries: 5
          delay: 10
      
      rescue:
        - name: 记录失败服务器
          debug:
            msg: "服务器 {{ ansible_host }} 部署失败,已跳过"
        
        - name: 将失败服务器加入重试列表
          add_host:
            name: "{{ ansible_host }}"
            groups: failed_servers
        
        - name: 清理临时文件
          file:
            path: "/tmp/qwen_deploy_*.tmp"
            state: absent
        
        - name: 停止可能残留的服务
          shell: |
            cd /opt/qwen3527-27b 2>/dev/null && docker-compose down || true
          ignore_errors: yes

- name: 重试失败的服务器
  hosts: failed_servers
  tasks:
    - name: 重新部署失败服务器
      include_role:
        name: qwen-deploy

5. 集群管理与维护

部署完成后,我们还需要一套机制来管理整个集群。Ansible同样可以帮我们实现集群级别的管理任务。

5.1 集群状态监控

# playbooks/cluster_monitor.yml
---
- name: 收集集群状态信息
  hosts: gpu_servers
  gather_facts: no
  tasks:
    - name: 检查服务运行状态
      shell: |
        docker ps --filter "name=qwen3527" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
      register: service_status
    
    - name: 检查GPU使用情况
      shell: nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total --format=csv,noheader
      register: gpu_usage
    
    - name: 检查API可用性
      uri:
        url: "http://localhost:{{ service_port }}/health"
        method: GET
        timeout: 5
      register: api_health
      ignore_errors: yes
    
    - name: 汇总服务器状态
      set_fact:
        server_status: |
          主机: {{ ansible_host }}
          服务状态: {{ service_status.stdout_lines[1] if service_status.stdout_lines|length > 1 else '未运行' }}
          GPU使用: {{ gpu_usage.stdout }}
          API健康: {{ '正常' if api_health.status == 200 else '异常' }}
    
    - name: 输出状态信息
      debug:
        msg: "{{ server_status }}"

- name: 生成集群状态报告
  hosts: localhost
  gather_facts: no
  tasks:
    - name: 汇总所有服务器状态
      debug:
        msg: "集群监控完成,详细状态见各服务器输出"

5.2 批量服务操作

# playbooks/cluster_operations.yml
---
- name: 重启集群所有服务
  hosts: gpu_servers
  tasks:
    - name: 重启Docker服务
      shell: |
        cd /opt/qwen3527-27b
        docker-compose restart
      args:
        chdir: /opt/qwen3527-27b
    
    - name: 等待服务恢复
      wait_for:
        port: "{{ service_port }}"
        delay: 5
        timeout: 60

- name: 更新集群模型
  hosts: gpu_servers
  serial: 3  # 分批更新,避免同时下载造成网络拥堵
  tasks:
    - name: 停止服务
      shell: |
        cd /opt/qwen3527-27b
        docker-compose down
      args:
        chdir: /opt/qwen3527-27b
    
    - name: 备份旧模型
      shell: |
        cp -r {{ model_path }} {{ model_path }}_backup_$(date +%Y%m%d_%H%M%S)
    
    - name: 下载新模型
      # 这里替换为实际的模型更新逻辑
      shell: |
        echo "开始更新模型..."
        # 实际生产环境应该从模型仓库拉取
        sleep 10  # 模拟下载过程
    
    - name: 重启服务
      shell: |
        cd /opt/qwen3527-27b
        docker-compose up -d
      args:
        chdir: /opt/qwen3527-27b

- name: 清理集群日志
  hosts: gpu_servers
  tasks:
    - name: 清理旧日志
      shell: |
        find /opt/qwen3527-27b/logs -name "*.log" -mtime +7 -delete
        docker system prune -f --filter "until=24h"

5.3 性能监控与优化

# playbooks/performance_monitor.yml
---
- name: 收集性能指标
  hosts: gpu_servers
  tasks:
    - name: 收集系统负载
      shell: uptime
      register: system_load
    
    - name: 收集内存使用
      shell: free -h
      register: memory_usage
    
    - name: 收集磁盘空间
      shell: df -h / /opt
      register: disk_space
    
    - name: 收集GPU详细状态
      shell: nvidia-smi
      register: gpu_detail
    
    - name: 测试API响应时间
      shell: |
        time curl -s -o /dev/null -w "%{time_total}" http://localhost:7860/health
      register: api_response_time
    
    - name: 生成性能报告
      debug:
        msg: |
          性能报告 - {{ ansible_host }}
          系统负载: {{ system_load.stdout }}
          内存使用: {{ memory_usage.stdout_lines[1] }}
          磁盘空间: {{ disk_space.stdout }}
          API响应时间: {{ api_response_time.stdout }}秒
          GPU状态:
          {{ gpu_detail.stdout }}

- name: 优化建议
  hosts: gpu_servers
  tasks:
    - name: 检查是否需要优化
      shell: |
        # 检查GPU内存使用率
        nvidia-smi --query-gpu=memory.used,memory.total --format=csv,noheader | awk -F', ' '{used=$1; total=$2; gsub(/[^0-9]/,"",used); gsub(/[^0-9]/,"",total); if (used/total > 0.9) print "GPU内存使用过高"}'
      register: gpu_check
    
    - name: 提供优化建议
      debug:
        msg: |
          {{ ansible_host }} 优化建议:
          {{ gpu_check.stdout if gpu_check.stdout != "" else "当前运行状态良好" }}
          建议操作:
          1. 调整max_new_tokens参数减少内存使用
          2. 考虑使用vLLM优化推理速度
          3. 检查日志是否有异常错误

6. 实战案例:百台服务器部署演练

让我们通过一个完整的实战案例,看看如何在实际环境中使用这套自动化方案。

6.1 准备阶段

假设我们有一个包含100台GPU服务器的集群,IP地址范围是192.168.1.101到192.168.1.200。

# 生成主机清单
cat > inventory/production_hosts.ini << 'EOF'
[gpu_cluster]
gpu-[101:200] ansible_host=192.168.1.[101:200] ansible_user=root

[gpu_cluster:vars]
ansible_ssh_private_key_file=~/.ssh/production_key
model_path=/data/models/Qwen3.5-27B
service_port=7860
batch_size=10
EOF

# 测试连接
ansible -i inventory/production_hosts.ini gpu_cluster -m ping --forks 20

6.2 分批次部署

由于100台服务器同时部署可能会对网络和存储造成压力,我们采用分批次策略:

# 第一阶段:基础环境部署(20台并行)
ansible-playbook -i inventory/production_hosts.ini playbooks/deploy_qwen_cluster.yml \
  --limit "gpu-[101:120]" \
  --tags base,docker \
  --forks 20

# 第二阶段:模型部署(10台并行,避免同时下载大文件)
ansible-playbook -i inventory/production_hosts.ini playbooks/deploy_qwen_cluster.yml \
  --limit "gpu-[101:120]" \
  --tags qwen-deploy \
  --forks 10

# 第三阶段:服务部署(20台并行)
ansible-playbook -i inventory/production_hosts.ini playbooks/deploy_qwen_cluster.yml \
  --limit "gpu-[101:120]" \
  --tags service \
  --forks 20

# 验证第一批服务器
ansible -i inventory/production_hosts.ini gpu-[101:120] -m shell -a "curl -s http://localhost:7860/health"

# 如果第一批成功,继续部署剩余服务器
for start in {121..200..20}; do
  end=$((start+19))
  echo "部署服务器 gpu-[$start:$end]"
  
  ansible-playbook -i inventory/production_hosts.ini playbooks/deploy_qwen_cluster.yml \
    --limit "gpu-[$start:$end]" \
    --forks 20
done

6.3 部署结果验证

部署完成后,我们需要验证整个集群的状态:

# 创建验证脚本
cat > scripts/verify_cluster.sh << 'EOF'
#!/bin/bash

# 验证所有服务器的服务状态
echo "开始验证集群状态..."
echo "======================"

total_servers=100
success_count=0
failed_servers=()

for i in {101..200}; do
  ip="192.168.1.$i"
  echo -n "检查服务器 $ip ... "
  
  # 尝试连接并检查服务
  if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@$ip \
     "curl -s -m 10 http://localhost:7860/health" 2>/dev/null | grep -q "OK"; then
    echo "✓ 正常"
    ((success_count++))
  else
    echo "✗ 失败"
    failed_servers+=("$ip")
  fi
done

echo "======================"
echo "部署完成报告:"
echo "总服务器数: $total_servers"
echo "成功部署: $success_count"
echo "失败部署: $(($total_servers - $success_count))"

if [ ${#failed_servers[@]} -gt 0 ]; then
  echo "失败的服务器:"
  printf '%s\n' "${failed_servers[@]}"
  
  # 生成重试清单
  echo "生成重试清单..."
  echo "[retry_servers]" > inventory/retry_hosts.ini
  for ip in "${failed_servers[@]}"; do
    echo "$ip ansible_host=$ip ansible_user=root" >> inventory/retry_hosts.ini
  done
fi
EOF

chmod +x scripts/verify_cluster.sh
./scripts/verify_cluster.sh

6.4 性能基准测试

部署完成后,我们可以运行一个简单的性能测试,了解集群的整体表现:

# playbooks/benchmark_test.yml
---
- name: 集群性能基准测试
  hosts: gpu_cluster
  serial: 5  # 控制并发数,避免压垮测试工具
  tasks:
    - name: 准备测试数据
      copy:
        content: |
          {"prompt": "请用中文介绍一下你自己。", "max_new_tokens": 128}
        dest: /tmp/test_prompt.json
        mode: '0644'
    
    - name: 运行API性能测试
      shell: |
        # 测试10次请求的平均响应时间
        total_time=0
        for i in {1..10}; do
          start_time=$(date +%s%N)
          curl -X POST http://localhost:7860/generate \
            -H "Content-Type: application/json" \
            --data @/tmp/test_prompt.json \
            -o /dev/null -s -w "%{time_total}\n"
          end_time=$(date +%s%N)
          request_time=$(echo "scale=3; ($end_time - $start_time) / 1000000000" | bc)
          total_time=$(echo "$total_time + $request_time" | bc)
          echo "请求 $i: $request_time 秒"
          sleep 1
        done
        avg_time=$(echo "scale=3; $total_time / 10" | bc)
        echo "平均响应时间: $avg_time 秒"
        echo "服务器: {{ ansible_host }}, 平均响应时间: $avg_time 秒" >> /tmp/benchmark_results.txt
      args:
        executable: /bin/bash
      register: benchmark_result
    
    - name: 显示测试结果
      debug:
        msg: "{{ benchmark_result.stdout_lines[-3:] }}"

- name: 汇总性能报告
  hosts: localhost
  gather_facts: no
  tasks:
    - name: 收集所有服务器结果
      shell: |
        # 从所有服务器收集结果
        for i in {101..200}; do
          ssh root@192.168.1.$i "cat /tmp/benchmark_results.txt 2>/dev/null || echo '服务器 192.168.1.$i 测试失败'" >> /tmp/all_results.txt
        done
        
        # 分析结果
        echo "=== 集群性能测试报告 ==="
        echo "测试时间: $(date)"
        echo ""
        grep "平均响应时间" /tmp/all_results.txt | sort -k3 -n | head -5 > /tmp/top5.txt
        grep "平均响应时间" /tmp/all_results.txt | sort -k3 -n | tail -5 > /tmp/bottom5.txt
        
        echo "响应最快的前5台服务器:"
        cat /tmp/top5.txt
        echo ""
        echo "响应最慢的后5台服务器:"
        cat /tmp/bottom5.txt
        echo ""
        
        # 计算平均值
        avg=$(grep "平均响应时间" /tmp/all_results.txt | awk -F': ' '{sum+=$2; count++} END {if(count>0) print sum/count}')
        echo "集群平均响应时间: ${avg:-N/A} 秒"
        
        # 统计成功率
        total=$(grep -c "平均响应时间" /tmp/all_results.txt)
        failed=$(grep -c "测试失败" /tmp/all_results.txt)
        success_rate=$(echo "scale=2; $total / 100 * 100" | bc)
        echo "测试成功率: $success_rate% ($total/100)"
      register: report
    
    - name: 显示完整报告
      debug:
        msg: "{{ report.stdout }}"

7. 总结

通过本文的完整方案,我们实现了一个从零到百的千问3.5-27B集群自动化部署系统。让我们回顾一下这个方案的核心价值:

7.1 方案优势总结

  1. 效率提升:从手动单台部署到自动化批量部署,部署100台服务器的时间从数周缩短到几小时
  2. 一致性保障:通过Ansible的幂等性,确保每台服务器的环境完全一致,避免"环境差异"问题
  3. 可维护性:模块化的角色设计,使得后续更新、扩展变得非常简单
  4. 可扩展性:支持动态添加新服务器,轻松扩展集群规模
  5. 错误处理:完善的错误处理和重试机制,确保部署过程的可靠性

7.2 关键实践要点

在实际使用这套方案时,有几个关键点需要注意:

  1. 网络优化:模型文件通常很大,建议在局域网内搭建模型缓存服务器,避免每台服务器都从外网下载
  2. 分批部署:根据网络带宽和存储性能,合理控制并行部署的数量
  3. 监控告警:部署完成后,建议集成到现有的监控系统中,实时掌握集群状态
  4. 版本控制:将Ansible剧本纳入版本控制系统,方便团队协作和回滚

7.3 后续优化方向

虽然我们已经实现了一个完整的自动化部署方案,但仍有优化空间:

  1. 性能优化:可以考虑集成vLLM等推理优化框架,提升服务性能
  2. 高可用设计:增加负载均衡和故障转移机制
  3. 自动扩缩容:基于监控指标自动调整集群规模
  4. 蓝绿部署:实现零停机更新

7.4 开始你的自动化之旅

无论你是要部署10台还是1000台服务器,自动化都是必经之路。本文提供的方案是一个完整的起点,你可以根据自己的实际需求进行调整和扩展。

记住,自动化不是一蹴而就的,而是一个持续改进的过程。从最简单的脚本开始,逐步完善,最终构建出适合自己业务场景的自动化体系。

现在,拿起这个方案,开始你的百台GPU服务器部署之旅吧!你会发现,原本繁琐复杂的部署工作,现在只需要几条命令就能轻松搞定。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐