Ansible 自动化运维实战:从配置管理到应用部署

给十台服务器批量改配置,逐台 SSH 上去敲命令,半小时起步,还容易敲错其中一两台;如果服务器涨到五十台、一百台,这套人肉流程基本不可行。Ansible 就是为这种场景设计的自动化运维工具。它最突出的特点是「无代理」——目标机器上不需要预装任何客户端,只要开了 SSH 就能管,这让它成为上手成本最低的配置管理工具之一。

一、安装和基本概念

控制机上装一个 Ansible 就够了:

# 安装
pip install ansible

# 验证
ansible --version

几个基本概念先建立起来:

概念 说明
Control Node 运行 Ansible 的机器,也就是装了 Ansible 的那台
Managed Node 被管理的目标机器,只需能 SSH 登录
Inventory 主机清单,记录哪些机器归哪些组
Playbook YAML 格式的任务剧本,描述「要做什么」
Module 执行具体操作的模块(apt、copy、service 等)

「声明式 + 幂等」是 Ansible 的心法:每个模块都检查目标状态,已经满足就跳过,重复执行结果一致。同一个 Playbook 跑十遍和跑一遍,最终状态是一样的。这也是为什么 Ansible 适合用来做「修正漂移」:服务器被手动改乱了,重新跑一遍 Playbook 就能拉回期望状态,不需要重装系统。

二、Inventory 配置

机器清单放在 inventory 文件里,支持分组和组变量:

# hosts.ini
[web]
web1.example.com
web2.example.com

[db]
db1.example.com

[all:vars]
ansible_user=deploy
ansible_python_interpreter=/usr/bin/python3

写完之后用 ansible web -m ping -i hosts.ini 可以快速验证连通性。日常排查的时候,ansible all --list-hosts 能列出当前清单包含的所有机器,避免「改错了组」这种低级错误。分组名最好起得语义化一点(web、db、cache),配合注释说明每台机器的用途,半年后回来维护时能少费很多脑力。

三、Playbook 示例

一个完整的 Nginx 配置 Playbook,把安装、模板、启动串起来:

---
- name: Configure Web Servers
  hosts: web
  become: yes
  vars:
    nginx_port: 80

  tasks:
    - name: Install Nginx
      apt:
        name: nginx
        state: present
        update_cache: yes

    - name: Copy Nginx config
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/sites-available/default
      notify: restart nginx

    - name: Start Nginx
      service:
        name: nginx
        state: started
        enabled: yes

  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted

注意 notify: restart nginx 和底部的 handlers 的配合:只有当「Copy Nginx config」这个任务真的改变了文件,才会触发重启;没变化就跳过。这是 Ansible 避免「每次跑一遍都重启服务」的关键机制。模板文件 nginx.conf.j2 里可以用 {{ nginx_port }} 引用变量。Playbook 里另一个常用的开关是 become: yes,表示用 sudo 权限执行任务——安装软件、改系统配置基本都离不开它。给 Playbook 和每个 task 命名(name 是必填的),跑的时候终端会逐条显示执行状态:ok 表示没变化、changed 表示做了修改、failed 表示出错,一眼就能定位问题在哪一步。

四、Role 组织

Playbook 变多之后,把重复逻辑抽成 Role。一个 Role 是带固定目录结构的可复用单元:

roles/
  nginx/
    tasks/main.yml
    templates/nginx.conf.j2
    vars/main.yml
    handlers/main.yml
    defaults/main.yml

tasks 放任务,templates 放模板,varsdefaults 放变量(defaults 优先级更低、可被覆盖)。写好了可以在 Playbook 里用 roles: - nginx 直接引用,也可以在 Ansible Galaxy 上找别人写好的 Role,几十行就能集成一个成熟的部署方案。自己写 Role 时注意把「会变的值」放进 vars,把「机器相关、会随环境变化的值」放进 defaults,这样上层调用时还能覆盖。

五、常用应用场景

场景 方案
服务器初始化 安装常用软件、配置 SSH、设置时区
应用部署 从 Git 拉取代码、构建、重启服务
配置管理 管理 Nginx、MySQL、Redis 配置
安全加固 防火墙规则、Fail2ban、SSH 加固

六、Ad-hoc 命令:不用写 Playbook 的小操作

不是所有事都值得写一个 Playbook。临时查一下磁盘、批量重启某个服务,用 ad-hoc 命令一行搞定:

# 批量查看 web 组的磁盘占用
ansible web -i hosts.ini -m shell -a "df -h"

# 重启 db 组的 MySQL
ansible db -i hosts.ini -m service -a "name=mysql state=restarted"

ad-hoc 的语法是 ansible <主机组> -m <模块> -a "<参数>"。超过一两条的命令,或者要被人反复执行的操作,再升级成 Playbook——判断标准是「这事会不会再来一次」。

一个实战场景

一个团队有 30 台服务器要统一加固:关闭 root 密码登录、配置 fail2ban、统一 NTP 时区。手工做一遍至少一个下午,还会漏掉几台。用 Ansible 写一个 security Role,ansible-playbook -i hosts.ini security.yml 一条命令,十分钟内 30 台全部完成,而且下次来新人、加机器,同一套剧本还能复用。跑的时候加 --check 先看计划,加 -v 看每台机器实际执行了什么,日志全在终端里,比人肉 SSH 一遍靠谱得多。

常见问题

  • ansible 连不上目标机器? 先手动 SSH 一次确认能连,再检查 inventory 里的 ansible_user 和密钥配置,用 ansible -m ping 单独验证。
  • 跑了两次服务重启了两次? 检查是否用了 handlers 配合 notify,以及模块是否幂等;配置没变化就不该触发重启。
  • 敏感信息怎么办?ansible-vault encrypt 加密含密码的变量文件,Playbook 运行时输入口令解密,别把密钥明文提交到仓库。
  • 怎么在跑之前先预览?--check 走一遍试运行,配合 --diff 看文件会怎么变,确认无误再真正执行。
  • 多个环境怎么隔离? 用多份 inventory(如 production.ini、staging.ini),通过 group_vars 区分环境,别在代码里写死环境相关的值。

参考:Ansible 官方文档 https://docs.ansible.com/ ;Ansible Galaxy https://galaxy.ansible.com/