Ansible 批量管理 VPS 服务器自动化运维实战

管理 1 台 VPS 靠手动,管理 10 台 VPS 靠脚本,管理 50 台 VPS 必须上自动化工具。我用 Ansible 实现了批量部署、配置管理、应用发布,50 台服务器同时操作只需 1 分钟。今天把完整实战方案分享出来。

一、为什么选择 Ansible

对比其他工具:

  • Ansible – 无需客户端,SSH 即可,学习曲线平缓
  • Puppet – 需要客户端,配置复杂
  • Chef – Ruby 语法,学习成本高
  • SaltStack – 功能强大但较重

Ansible 优势:

  • 无需在目标服务器安装任何软件
  • Playbook 语法简单,YAML 格式
  • 模块丰富,覆盖常见运维场景
  • 幂等性设计,重复执行安全

二、环境准备

控制节点(你的本地电脑或跳板机):

# 安装 Ansible
apt install ansible -y  # Ubuntu/Debian
yum install ansible -y  # CentOS

# 验证安装
ansible --version

# 创建工作组目录
mkdir -p ~/ansible/{inventory,playbooks,roles}

目标节点(所有要管理的 VPS):

  • Linux 系统(Ubuntu/CentOS)
  • 开启 SSH 服务
  • 确保 Python 已安装(大部分系统默认有)

三、配置 SSH 免密登录

步骤 1:生成 SSH 密钥对

ssh-keygen -t ed25519 -C "ansible-deploy"

步骤 2:分发公钥到所有服务器

# 创建主机列表
cat > ~/ansible/inventory/hosts.ini << 'EOF'
[webservers]
web1.example.com ansible_user=root
web2.example.com ansible_user=root

[dbservers]
db1.example.com ansible_user=root

[all:vars]
ansible_ssh_private_key_file=~/.ssh/id_ed25519
EOF

# 批量分发公钥
ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]
ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]
ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]

步骤 3:测试连通性

cd ~/ansible
ansible all -i inventory/hosts.ini -m ping
# 应看到所有服务器返回 SUCCESS

四、第一个 Playbook:批量安装 Nginx

创建 playbook:

cat > ~/ansible/playbooks/install_nginx.yml << 'EOF'
---
- name: 安装 Nginx Web 服务器
  hosts: webservers
  become: yes
  
  tasks:
    - name: 更新 apt 缓存(Ubuntu)
      apt:
        update_cache: yes
        cache_valid_time: 3600
      when: ansible_os_family == "Debian"

    - name: 安装 Nginx(Ubuntu/Debian)
      apt:
        name: nginx
        state: present
      when: ansible_os_family == "Debian"

    - name: 安装 Nginx(CentOS/RHEL)
      yum:
        name: nginx
        state: present
      when: ansible_os_family == "RedHat"

    - name: 启动 Nginx 服务
      systemd:
        name: nginx
        state: started
        enabled: yes

    - name: 创建测试页面
      copy:
        content: |
          

欢迎访问 {{ inventory_hostname }}

服务器由 Ansible 自动部署

dest: /var/www/html/index.html - name: 配置防火墙 ufw: rule: allow port: "{{ item }}" loop: - "80/tcp" - "443/tcp" when: ansible_os_family == "Debian" EOF

执行 playbook:

cd ~/ansible
ansible-playbook -i inventory/hosts.ini playbooks/install_nginx.yml

# 查看执行结果
# 应显示:ok=6, changed=5(首次执行)
# 再次执行:ok=6, changed=0(幂等性验证)

五、实战:批量部署 WordPress

创建 WordPress 部署 playbook:

cat > ~/ansible/playbooks/deploy_wordpress.yml << 'EOF'
---
- name: 批量部署 WordPress
  hosts: webservers
  become: yes
  vars:
    wp_domain: "{{ domain | default('example.com') }}"
    wp_db_name: wordpress
    wp_db_user: wpuser
    wp_db_password: "{{ lookup('password', '/dev/null length=16 chars=ascii_letters,digits') }}"
    wp_root: /var/www/wordpress

  tasks:
    - name: 安装 LNMP 环境
      apt:
        name:
          - nginx
          - mysql-server
          - php-fpm
          - php-mysql
          - php-curl
          - php-gd
          - php-mbstring
          - php-xml
        state: present
        update_cache: yes

    - name: 创建 WordPress 数据库
      mysql_db:
        name: "{{ wp_db_name }}"
        state: present
        login_unix_socket: /var/run/mysqld/mysqld.sock

    - name: 创建 WordPress 数据库用户
      mysql_user:
        name: "{{ wp_db_user }}"
        password: "{{ wp_db_password }}"
        priv: "{{ wp_db_name }}.*:ALL"
        host: localhost
        state: present
        login_unix_socket: /var/run/mysqld/mysqld.sock

    - name: 下载 WordPress
      get_url:
        url: https://wordpress.org/latest.tar.gz
        dest: /tmp/wordpress.tar.gz
        mode: '0644'

    - name: 解压 WordPress
      unarchive:
        src: /tmp/wordpress.tar.gz
        dest: /tmp/
        remote_src: yes

    - name: 移动 WordPress 到网站目录
      copy:
        src: "/tmp/wordpress/"
        dest: "{{ wp_root }}"
        remote_src: yes
        owner: www-data
        group: www-data
        mode: '0755'

    - name: 配置 Nginx
      template:
        src: templates/nginx_wordpress.conf.j2
        dest: /etc/nginx/sites-available/{{ wp_domain }}
      notify: restart nginx

    - name: 启用站点
      file:
        src: /etc/nginx/sites-available/{{ wp_domain }}
        dest: /etc/nginx/sites-enabled/{{ wp_domain }}
        state: link
      notify: restart nginx

    - name: 创建 wp-config.php
      template:
        src: templates/wp-config.php.j2
        dest: "{{ wp_root }}/wp-config.php"
        owner: www-data
        group: www-data
        mode: '0644'

  handlers:
    - name: restart nginx
      systemd:
        name: nginx
        state: restarted
EOF

六、Variables 和 Templates

创建变量文件:

cat > ~/ansible/inventory/group_vars/webservers.yml << 'EOF'
---
# 通用配置
ntp_timezone: Asia/Shanghai
admin_email: [email protected]

# WordPress 配置
wp_domain: "{{ inventory_hostname }}"
wp_title: "{{ inventory_hostname }} 博客"
wp_admin_user: admin
wp_admin_email: "{{ admin_email }}"
EOF

创建模板文件 templates/wp-config.php.j2:


七、Roles:组织复杂项目

创建 Role 结构:

mkdir -p ~/ansible/roles/nginx/{tasks,handlers,templates,files,vars,meta}

# 创建目录结构后的效果:
roles/
└── nginx/
    ├── tasks/
    │   └── main.yml
    ├── handlers/
    │   └── main.yml
    ├── templates/
    │   └── nginx.conf.j2
    ├── files/
    ├── vars/
    │   └── main.yml
    └── meta/
        └── main.yml

编写 tasks/main.yml:

---
- name: 安装 Nginx 包
  apt:
    name: nginx
    state: present

- name: 复制配置文件
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: restart nginx

- name: 启动 Nginx
  systemd:
    name: nginx
    state: started
    enabled: yes

使用 Role:

cat > ~/ansible/playbooks/deploy_all.yml << 'EOF'
---
- name: 部署所有服务
  hosts: all
  become: yes
  
  roles:
    - nginx
    - mysql
    - wordpress
    - php
EOF

八、我踩过的坑

坑 1:权限问题导致 playbook 失败

Ansible 默认用当前用户 SSH,如果目标服务器需要 root 权限,需要配置become: yes。

坑 2:模板变量未定义报错

使用 default 过滤器或 group_vars 定义默认值,避免变量缺失。

坑 3:大文件传输慢

使用synchronize 模块代替copy 模块,基于 rsync,速度更快。

坑 4:并发过高导致目标服务器压力大

在 ansible.cfg 中调整 forks 参数:forks = 10(默认是 5)。

九、高级技巧

1. 动态Inventory(云环境)

# 阿里云动态 Inventory
cat > ~/ansible/inventory/alicloud.py << 'EOF'
#!/usr/bin/env python
import json
# 调用阿里云 API 获取实例列表
print(json.dumps({"alicloud_ecs": {"hosts": ["192.168.1.10", "192.168.1.11"]}}))
EOF
chmod +x ~/ansible/inventory/alicloud.py

# 使用
ansible-playbook -i inventory/alicloud.py playbooks/deploy.yml

2. 加密敏感数据(Ansible Vault)

# 创建加密文件
ansible-vault create secrets.yml

# 编辑加密文件
ansible-vault edit secrets.yml

# 执行时使用Vault 密码
ansible-playbook -i inventory/hosts.ini playbooks/deploy.yml --ask-vault-pass

3. 并行执行优化

# 修改 ansible.cfg
[defaults]
forks = 20  # 并发数
timeout = 30  # 超时时间
retry_files_enabled = False  # 禁用重试文件

[ssh_connection]
pipelining = True  # 管道模式,减少 SSH 连接数
control_path = /tmp/ansible-%%r@%%h:%%p

十、CI/CD集成

将 Ansible 集成到 GitHub Actions:

name: Deploy with Ansible

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Ansible
      run: pip install ansible
    
    - name: Configure SSH
      run: |
        mkdir -p ~/.ssh
        echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
        chmod 600 ~/.ssh/id_rsa
        ssh-keyscan -H your-server.com >> ~/.ssh/known_hosts
    
    - name: Run Ansible Playbook
      run: |
        cd ansible
        ansible-playbook -i inventory/hosts.ini playbooks/deploy.yml

总结

用 Ansible 管理 VPS 后,我的运维效率提升显著:

  • ✅ 50 台服务器批量部署从 1 天缩短到 5 分钟
  • ✅ 配置统一,避免人为错误
  • ✅ 所有操作可追溯(Git 管理 Playbook)
  • ✅ 新服务器 5 分钟上线
  • ✅ 支持回滚和版本控制

如果你管理 3 台以上 VPS,强烈建议学习 Ansible,一劳永逸。

来源:https://mjj.728.hk/


已发布

分类

来自

标签: