Ansible:系统配置与应用部署¶
Ansible 从控制端通过 SSH 连接目标 Linux 主机,根据 Playbook 执行用户、软件包、配置文件、服务和应用部署等任务。目标主机通常不需要安装 Agent。
控制端
├── Inventory:管理哪些主机、如何分组
├── Playbook / Role:主机应该达到什么状态
├── Variables:环境和主机差异
└── Vault / 密钥系统:敏感参数
↓ SSH
目标 Linux 主机
核心概念¶
| 概念 | 作用 | 示例 |
|---|---|---|
| Inventory | 定义主机、分组和连接参数 | web、database、prod |
| Play | 将任务应用到指定主机组 | hosts: web |
| Task | 调用一个 Module 完成一个动作 | 安装 nginx、写配置 |
| Module | Ansible 提供的操作单元 | package、template、systemd_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 密码不能放在同一仓库;流水线通过受保护变量或外部密钥系统提供密码。
安全执行顺序¶
修改防火墙、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 仓库。
- 两类工具不要管理同一个对象的同一属性。