Ansible 自动化:配置管理与应用部署
Ansible 自动化运维入门到精通
从零掌握 Ansible,用声明式自动化实现配置管理与应用部署,让重复劳动成为历史。
一、为什么选择 Ansible
Ansible 是一款极简主义的 IT 自动化引擎,它通过 SSH 协议(无需安装客户端)将指令推送到远程服务器执行,彻底消除“手动一台台机器操作”的痛苦。它的核心竞争力在于:
- 零客户端架构:被管理节点只需 Python 与 SSH,无需额外代理。
- 声明式配置:用人类可读的 YAML 描述期望状态,而非编写复杂脚本。
- 幂等性:多次执行同一个 Playbook,结果总是一致的,避免副作用。
- 模块化:内置 3000+ 模块,覆盖系统管理、云服务、网络设备等几乎所有领域。
- 编排能力:支持角色(Roles)、条件判断、循环与动态清单,轻松管理成千上万台服务器。
无论你管理的是 5 台还是 500 台机器,Ansible 都能帮助你实现快速部署、一致配置和标准化运维。
二、环境安装与快速验证
2.1 控制节点安装
Ansible 只需安装在控制节点(你的工作电脑或跳板机)上。首选 Python 包管理器 pip:
# 建议在虚拟环境中安装
python3 -m venv ansible-env
source ansible-env/bin/activate
pip install ansible
验证版本:
ansible --version
提示:控制节点可以使用 Linux、macOS,Windows 需通过 WSL 使用。被管理节点需要 Python 2.7 或 3.5+。
2.2 被管理节点准备
确认目标服务器 IP 可连通,并且控制节点能通过 SSH 免密登录(推荐使用 SSH 密钥):
ssh-copy-id user@192.168.1.101
也可以使用用户名密码,但不安全且不推荐。
三、基础概念与第一个命令
3.1 清单文件(Inventory)
清单文件定义被管理节点的集合。最简单的静态清单 inventory.ini:
[webservers]
web01 ansible_host=192.168.1.101 ansible_user=admin
web02 ansible_host=192.168.1.102 ansible_user=admin
[dbservers]
db01 ansible_host=10.0.0.51 ansible_user=root
组名 [webservers] 用于批量操作,之后还可嵌套成组。
3.2 第一道 Ad-Hoc 命令
Ad-Hoc 命令用于临时执行一次任务,无需编写剧本。使用 ansible 命令测试连通性:
ansible all -i inventory.ini -m ping
输出示例:
web01 | SUCCESS => {
"changed": false,
"ping": "pong"
}
-m ping 调用 ping 模块,all 代表清单中所有主机,-i 指定清单文件。
四、剧本(Playbook)与 YAML 语法精要
Playbook 是 Ansible 的核心工作流,使用 YAML 撰写,一个剧本可包含多个 Play,每个 Play 定义在一组主机上执行的一系列任务。
4.1 YAML 快速入门
- 使用缩进表示层级(空格,不能使用 Tab)
- 键值对:
key: value - 列表项:
- item1 - 字符串可加引号,但通常不需要(除非包含特殊符号)
- 布尔值:
yes/no或true/false
示例:
---
- name: 第一个Play
hosts: webservers
become: yes
tasks:
- name: 确保Nginx已安装
apt:
name: nginx
state: present
4.2 执行 Playbook
将上述内容保存为 deploy.yml,运行:
ansible-playbook -i inventory.ini deploy.yml
become: yes 表示任务需要提权(sudo),等同于 -b 参数。
五、配置管理实战
5.1 管理软件包
在不同发行版间,Ansible 使用对应模块(apt/yum/dnf/pkgng):
- name: 在Debian系上安装软件
apt:
name: "{{ packages }}"
state: present
vars:
packages:
- curl
- git
- nginx
或使用通用 package 模块(Ansible 2.0+)自动适配:
- name: 跨平台安装
package:
name: "{{ item }}"
state: latest
loop:
- htop
- vim
5.2 管理服务
确保服务运行并开机自启:
- name: 启动并启用Nginx
service:
name: nginx
state: started
enabled: yes
state 可选:started, stopped, restarted, reloaded。
5.3 管理文件与模板
拷贝文件或渲染配置文件模板(Jinja2):
- name: 放置静态配置文件
copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: 0644
notify: restart nginx
模板示例 templates/app.conf.j2:
server {
listen 80;
server_name {{ server_name }};
root {{ document_root }};
}
使用模板模块:
- name: 渲染配置文件
template:
src: app.conf.j2
dest: /etc/nginx/conf.d/app.conf
notify: reload nginx
notify 会在任务触发变更时调用 handler。
5.4 Handlers
Handlers 只在被通知时执行,且在所有任务之后集中运行:
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
- name: reload nginx
service:
name: nginx
state: reloaded
六、应用部署实战:从代码到上线
考虑一个典型的 Python Web 应用(FastAPI)部署流程,包含依赖安装、代码拉取、配置文件渲染、systemd 服务管理。
6.1 目录结构与变量
项目布局:
deploy/
├── inventory.ini
├── deploy_app.yml
├── files/
│ └── myapp.service
└── templates/
└── config.env.j2
Playbook deploy_app.yml:
---
- name: 部署MyApp
hosts: appservers
become: yes
vars:
repo_url: "https://github.com/example/myapp.git"
dest_path: "/opt/myapp"
app_user: "myapp"
app_port: 8080
database_url: "postgresql://db.example.com/myapp"
tasks:
- name: 创建应用用户
user:
name: "{{ app_user }}"
system: yes
create_home: no
- name: 安装系统依赖
package:
name:
- python3
- python3-pip
- git
state: present
- name: 克隆代码仓库
git:
repo: "{{ repo_url }}"
dest: "{{ dest_path }}"
version: main
force: yes
become_user: "{{ app_user }}"
- name: 安装Python依赖
pip:
requirements: "{{ dest_path }}/requirements.txt"
virtualenv: "{{ dest_path }}/venv"
virtualenv_command: python3 -m venv
become_user: "{{ app_user }}"
- name: 渲染环境变量文件
template:
src: config.env.j2
dest: "{{ dest_path }}/.env"
owner: "{{ app_user }}"
mode: 0600
notify: restart myapp
- name: 安装systemd服务文件
copy:
src: files/myapp.service
dest: /etc/systemd/system/myapp.service
notify: restart myapp
- name: 启动并启用应用服务
systemd:
name: myapp
state: started
enabled: yes
daemon_reload: yes
handlers:
- name: restart myapp
systemd:
name: myapp
state: restarted
模板 templates/config.env.j2:
DATABASE_URL={{ database_url }}
PORT={{ app_port }}
Systemd 单元文件 files/myapp.service:
[Unit]
Description=MyApp Web Service
After=network.target
[Service]
User=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/opt/myapp/.env
ExecStart=/opt/myapp/venv/bin/uvicorn main:app --host 0.0.0.0 --port ${PORT}
Restart=always
[Install]
WantedBy=multi-user.target
执行:
ansible-playbook -i inventory.ini deploy_app.yml
结果:应用按照统一流程完成部署,每次运行均可保证配置一致、服务运行。
七、变量、事实与流程控制
7.1 变量来源
变量可以定义在多种位置,优先级由低到高:
- 命令行
-e "key=value"(最高) - Playbook 的
vars、vars_files - 角色默认值
- 主机/组变量(
host_vars/,group_vars/) - Ansible Facts
7.2 Ansible Facts
默认会收集被管理节点的系统信息(IP、OS、内存等),这些数据以变量形式可用:
- name: 打印操作系统
debug:
msg: "系统是 {{ ansible_distribution }} {{ ansible_distribution_version }}"
禁用事实采集可提高速度:gather_facts: no。
7.3 条件判断
根据变量或事实决定是否执行:
- name: 仅在CentOS上安装epel
yum:
name: epel-release
state: present
when: ansible_distribution == "CentOS"
7.4 循环
通过 loop 或 with_* 关键字遍历列表:
- name: 创建多个用户
user:
name: "{{ item.name }}"
groups: "{{ item.groups | default('') }}"
loop:
- { name: 'alice', groups: 'dev' }
- { name: 'bob' }
对于哈希遍历,可使用 dict2items 过滤器。
八、角色(Roles):可复用的自动化单元
当 Playbook 变得庞大,必须拆分为角色。角色将变量、任务、模板、文件等组织在一个标准目录结构中:
roles/
└── nginx/
├── tasks/
│ └── main.yml
├── handlers/
│ └── main.yml
├── templates/
│ └── nginx.conf.j2
├── files/
├── vars/
│ └── main.yml
├── defaults/
│ └── main.yml
└── meta/
└── main.yml
使用角色只需在 Playbook 中引用:
---
- hosts: webservers
roles:
- nginx
- { role: app_deploy, app_port: 9090 }
角色可以通过 ansible-galaxy 命令从 Ansible Galaxy 社区下载复用:
ansible-galaxy install geerlingguy.nginx
九、最佳实践与进阶技巧
9.1 目录结构标准化
推荐的企业级项目布局:
production/
├── inventories/
│ └── production/
│ ├── hosts # 主机列表
│ └── group_vars/ # 组变量
├── roles/
├── playbooks/
│ └── site.yml
└── ansible.cfg
将清单和变量分离,通过 ansible-playbook -i inventories/production playbooks/site.yml 执行。
9.2 敏感信息加密:Ansible Vault
ansible-vault 可加密任何含有机密变量的文件:
ansible-vault encrypt group_vars/all/passwords.yml
运行时提供密码:
ansible-playbook --ask-vault-pass site.yml
或使用密码文件,更适合 CI/CD。
9.3 动态清单
云环境下主机动态变化,可编写脚本或使用插件(如 AWS EC2 Plugin)自动生成清单:
ansible-playbook -i aws_ec2.yml site.yml
9.4 执行策略与错误处理
strategy: free可并行执行任务,不等待全部主机完成。- 使用
ignore_errors: yes让某一任务失败不中断 Playbook。 any_errors_fatal: true则相反,任何主机失败立即中止。serial控制滚动更新批次,避免服务全部下线。
9.5 调试与检查模式
--check:干运行模式,不实际修改系统(但部分模块会产生副作用)。--diff:显示文件变化对比。-vvv:获得极详细的执行过程,用debug模块打印变量。
- name: 显示计算后的变量
debug:
var: database_url
十、总结与学习路径
本文从 Ansible 的核心理念出发,逐步覆盖了安装配置、Ad-Hoc 命令、Playbook 编写、配置管理、应用部署、变量与控制流、角色封装以及企业级最佳实践。掌握这些内容足以应对 90% 的日常自动化场景。
进一步深入学习建议:
- 深入研究 Ansible Galaxy 上常用角色源码。
- 阅读官方文档中的模块索引和高级执行策略。
- 使用 Molecule 测试自己的角色。
- 将 Ansible 融入 CI/CD 流程,实现 Git + Ansible 的 GitOps。
自动化不是一蹴而就,而是从第一个能够“一键部署”的 Playbook 开始。现在就写一个 Playbook,将你手头最烦人的重复操作交出去吧。