跳转至

Ansible:系统配置与应用部署

Ansible 从控制端通过 SSH 连接目标 Linux 主机,根据 Playbook 执行用户、软件包、配置文件、服务和应用部署等任务。目标主机通常不需要安装 Agent。

控制端
  ├── Inventory:管理哪些主机、如何分组
  ├── Playbook / Role:主机应该达到什么状态
  ├── Variables:环境和主机差异
  └── Vault / 密钥系统:敏感参数
          ↓ SSH
目标 Linux 主机

核心概念

概念 作用 示例
Inventory 定义主机、分组和连接参数 webdatabaseprod
Play 将任务应用到指定主机组 hosts: web
Task 调用一个 Module 完成一个动作 安装 nginx、写配置
Module Ansible 提供的操作单元 packagetemplatesystemd_service
Handler 仅在被通知时执行 配置变化后重启 nginx
Role 封装任务、变量、模板和 Handler roles/nginx
Facts 目标主机的系统信息 系统类型、IP、CPU
Vault 加密敏感变量文件 数据库密码、API 密钥

Inventory 示例

[web]
web01 ansible_host=192.168.10.21
web02 ansible_host=192.168.10.22

[database]
db01 ansible_host=192.168.10.31

[all:vars]
ansible_user=ops
ansible_ssh_private_key_file=/secure/path/ops_ed25519

生产私钥不能放进项目目录。Inventory 可以提交非敏感的主机名和分组,密码、令牌和私钥从 Vault、CI Secret 或企业密钥系统注入。

Playbook 示例

---
- name: Configure web servers
  hosts: web
  become: true

  tasks:
    - name: Install nginx
      ansible.builtin.package:
        name: nginx
        state: present

    - name: Deploy nginx configuration
      ansible.builtin.template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: "0644"
        validate: "nginx -t -c %s"
      notify: Restart nginx

    - name: Ensure nginx is enabled and running
      ansible.builtin.systemd_service:
        name: nginx
        enabled: true
        state: started

  handlers:
    - name: Restart nginx
      ansible.builtin.systemd_service:
        name: nginx
        state: restarted

优先使用 Module 描述期望状态,而不是用 shell 拼接命令。模板内容变化时才通知 Handler,校验成功后才替换配置,这样重复执行时不会无意义地反复修改系统。

检查和执行

ansible-inventory -i inventories/prod/hosts.ini --graph
ansible all -i inventories/prod/hosts.ini -m ping
ansible-playbook -i inventories/prod/hosts.ini playbooks/web.yml --syntax-check
ansible-playbook -i inventories/prod/hosts.ini playbooks/web.yml --check --diff
ansible-playbook -i inventories/prod/hosts.ini playbooks/web.yml --limit web01
ansible-playbook -i inventories/prod/hosts.ini playbooks/web.yml
参数 作用 注意事项
--syntax-check 检查基本语法 不验证所有运行时条件
--check 预演可能发生的变化 部分 Module 不完全支持
--diff 展示文件差异 可能泄露敏感配置,保护 CI 日志
--limit web01 只操作指定目标 适合单机灰度,执行前确认匹配结果
--tags config 只执行特定标签任务 标签不完整可能漏掉依赖步骤

Role 目录

roles/nginx/
├── defaults/main.yml
├── vars/main.yml
├── tasks/main.yml
├── handlers/main.yml
├── templates/nginx.conf.j2
└── files/
  • defaults 放允许环境覆盖的默认值。
  • vars 放 Role 内相对固定的变量,不放秘密。
  • tasks 定义执行步骤。
  • templates 保存 Jinja 配置模板。
  • handlers 处理重启、reload 等通知动作。

Vault 与变量

变量来源太多会让最终值难以追踪。建议公共默认值放 Role defaults,环境差异放对应 Inventory 的 group_vars,临时覆盖需要留下变更记录。

ansible-vault create inventories/prod/group_vars/all/vault.yml
ansible-vault edit inventories/prod/group_vars/all/vault.yml
ansible-playbook -i inventories/prod/hosts.ini playbooks/site.yml --ask-vault-pass

Vault 密文可以提交到 Git,但 Vault 密码不能放在同一仓库;流水线通过受保护变量或外部密钥系统提供密码。

安全执行顺序

检查 Inventory 匹配范围
  → syntax-check
  → check + diff
  → limit 一台灰度主机
  → 验证服务与业务
  → 小批量执行
  → 全量执行
  → 保存运行日志和版本

修改防火墙、SSH、网络和 sudo 时要保留第二条管理通道,防止批量配置错误导致所有主机同时失联。

常见问题

现象 优先检查
UNREACHABLE 地址、SSH 端口、用户、私钥、跳板机与防火墙
Permission denied SSH 身份、私钥权限、sudo/become 配置
每次运行都显示 changed 是否滥用 shell;模板是否含动态时间;Module 是否幂等
配置改变但服务未生效 Handler 是否被通知;服务名与 restart/reload 是否正确
本想操作一台却匹配多台 先查看 Inventory graph 或 --list-hosts,再使用 --limit
Check mode 成功但执行失败 预演不等于真实变更,仍需单机灰度和回滚验证

与 IaC 的交接

  • Terraform/OpenTofu 创建虚拟机、网络、磁盘和安全组。
  • Ansible 配置虚拟机内部的软件包、用户、文件、systemd 和应用。
  • IaC Output 可以生成动态 Inventory,但 State 和密码不能复制进 Ansible 仓库。
  • 两类工具不要管理同一个对象的同一属性。

官方资料