Ansible Playbook编写实战教程
1. 什么是Ansible Playbook
Ansible Playbook是使用YAML编写的配置、部署和编排文件,它定义了一系列任务(tasks)在目标主机上执行的顺序。Playbook是Ansible的核心组件,允许我们以声明式的方式描述系统状态和自动化任务。
2. 基本结构
一个典型的Ansible Playbook包含以下元素:
Play:定义要在哪些主机上执行哪些任务
Tasks:要执行的具体操作
Modules:执行任务的工具(如copy, file, service等)
Handlers:在特定条件下触发的任务
Variables:用于动态配置的数据
2.1. 示例:基本Playbook结构
---
- name: 安装和启动Nginx
hosts: webservers
become: yes
vars:
http_port: 80
max_clients: 200
tasks:
- name: 安装Nginx包
ansible.builtin.apt:
name: nginx
state: present
- name: 启动Nginx服务
ansible.builtin.service:
name: nginx
state: started
enabled: yes
handlers:
- name: 重启Nginx
ansible.builtin.service:
name: nginx
state: restarted
3. Playbook编写步骤
定义Play基本信息
使用`name`描述Play的目的
指定目标主机`hosts`
使用`become`提权(默认为root)
定义变量
使用`vars`定义静态变量
使用`vars_files`从外部文件引入变量
支持通过`--extra-vars`命令行参数传递变量
---
- name: 配置Web服务器
hosts: webservers
vars_files:
- vars/main.yml
vars:
app_version: 1.2.3
tasks:
- name: 显示应用版本
debug:
msg: "当前应用版本: {{ app_version }}"
编写任务
每个任务使用`name`描述
调用模块执行具体操作
支持条件判断`when`
支持循环`with_items`/`loop`
---
- name: 用户管理
hosts: all
tasks:
- name: 创建开发组
ansible.builtin.group:
name: devops
state: present
- name: 创建多个用户
ansible.builtin.user:
name: "{{ item }}"
groups: devops
state: present
loop:
- alice
- bob
- charlie
when: ansible_os_family == "Debian"
使用模板和文件
使用`template`模块处理动态配置文件
使用`copy`模块复制静态文件
支持Jinja2模板语法
---
- name: 配置Nginx站点
hosts: webservers
tasks:
- name: 创建站点目录
ansible.builtin.file:
path: /var/www/example.com
state: directory
mode: '0755'
- name: 部署配置文件
ansible.builtin.template:
src: templates/nginx.conf.j2
dest: /etc/nginx/sites-available/example.com
notify: 重启Nginx
handlers:
- name: 重启Nginx
ansible.builtin.service:
name: nginx
state: restarted
4. 高级功能
错误处理
使用`ignore_errors`忽略错误
使用`failed_when`自定义失败条件
使用`rescue`和`always`进行错误恢复
---
- name: 安全的部署流程
hosts: webservers
tasks:
- name: 部署应用新版本
block:
- name: 下载新版本
get_url:
url: "https://example.com/releases/{{ app_version }}.tar.gz"
dest: /tmp/app.tar.gz
- name: 解压应用
unarchive:
src: /tmp/app.tar.gz
dest: /opt/myapp
remote_src: yes
rescue:
- name: 回滚到上一版本
command: /opt/scripts/rollback.sh
always:
- name: 清理临时文件
file:
path: /tmp/app.tar.gz
state: absent
角色复用
使用`include_role`或`import_role`组织任务
创建可重用的角色结构
---
- name: 部署LAMP环境
hosts: webservers
roles:
- common
- apache
- mysql
- php
动态清单
从云平台API获取主机信息
支持脚本清单和动态清单插件
#!/usr/bin/env python3
# 示例动态清单脚本
import json
import subprocess
def get_ec2_instances():
cmd = ["aws", "ec2", "describe-instances", "--query", "Reservations[*].Instances[*].{IP:PublicIpAddress,Name:Tags[?Key=='Name'].Value | [0]}", "--output", "json"]
result = subprocess.run(cmd, capture_output=True, text=True)
instances = json.loads(result.stdout)
inventory = {
"_meta": {
"hostvars": {}
},
"webservers": []
}
for instance in instances:
for i in instance:
if i["IP"] and "web" in i["Name"]:
inventory["webservers"].append(i["IP"])
inventory["_meta"]["hostvars"][i["IP"]] = {"instance_name": i["Name"]}
return inventory
if __name__ == "__main__":
print(json.dumps(get_ec2_instances(), indent=2))
5. 执行和调试
运行Playbook
ansible-playbook site.yml --limit webservers --ask-become-pass
语法检查
ansible-playbook site.yml --syntax-check
测试运行(Dry Run)
ansible-playbook site.yml --check
调试技巧
使用`debug`模块打印变量
使用`-v`/`-vvv`增加详细输出
使用`step`模式逐步执行
---
- name: 调试示例
hosts: localhost
gather_facts: no
vars:
complex_var:
- name: item1
value: 100
- name: item2
value: 200
tasks:
- name: 显示变量结构
debug:
var: complex_var
- name: 显示单个元素
debug:
msg: "Name: {{ item.name }} Value: {{ item.value }}"
loop: "{{ complex_var }}"
6. 最佳实践
保持Playbook幂等性
确保多次运行结果一致
使用`state`参数定义期望状态
使用角色组织代码
roles/
├── common/
│ ├── defaults/
│ ├── files/
│ ├── handlers/
│ ├── meta/
│ ├── tasks/
│ ├── templates/
│ ├── tests/
│ └── vars/
├── webserver/
└── database/
版本控制
所有Playbook和角色使用Git管理
使用标签和分支管理不同环境
安全实践
使用Ansible Vault加密敏感数据
ansible-vault encrypt secret.yml
限制特权操作(只在必要时使用become)
文档化
为每个Playbook添加说明注释
使用`ansible-doc`查看模块文档
---
# 这个Playbook用于初始化数据库服务器
# 要求:
# - 目标系统为CentOS 7+
# - 需要root权限执行
# 使用示例:
# ansible-playbook init_db.yml --extra-vars "db_name=prod_db"
- name: 初始化数据库服务器
hosts: dbservers
become: yes
vars:
db_user: "dbadmin"
db_pass: "{{ vault_db_password }}" # 来自加密变量
tasks:
# 创建数据库用户
- name: 创建数据库用户
mysql_user:
name: "{{ db_user }}"
password: "{{ db_pass }}"
priv: "*.*:ALL"
state: present
notify: 重启数据库服务
handlers:
- name: 重启数据库服务
systemd:
name: mariadb
state: restarted
7. 总结
Ansible Playbook是实现自动化运维的核心工具,通过YAML语法定义系统状态和任务序列。掌握Playbook编写需要理解以下关键概念:
基本结构:由Play、任务、模块和处理器组成
变量管理:支持静态变量、外部文件和命令行参数
任务控制:使用条件、循环和错误处理实现复杂逻辑
模板系统:结合Jinja2实现动态配置
角色复用:组织代码为可重用单元
调试技巧:使用语法检查、Dry Run和调试模块
最佳实践包括保持幂等性、使用角色、版本控制和安全加密。随着实践深入,可以结合动态清单、异步执行和回调插件等高级功能,构建强大的自动化运维体系。通过持续学习和实践,Ansible Playbook将成为您实现基础设施即代码(IaC)的利器。





