# Ansible Playbook编写详细教程
Ansible是一种强大的自动化工具,而Playbook是Ansible的核心组件,用于定义自动化任务的配置和执行流程。本教程将详细介绍如何编写高效、可维护的Ansible Playbook,包含基础概念、语法结构、常用模块以及最佳实践。
1. Ansible Playbook基础
Playbook是Ansible的核心配置、部署和编排语言,它使用YAML格式编写,描述了在一组主机上执行的任务序列。每个Playbook由一个或多个"play"组成,每个"play"定义了一组在特定主机上执行的任务。
Playbook的主要优势:
- 人类可读的YAML语法
- 幂等性(多次运行结果一致)
- 强大的错误处理
- 灵活的任务控制结构
2. Playbook结构与基本语法
一个基本的Playbook结构包含以下元素:
- `hosts`: 指定目标主机或主机组
- `remote_user`: 指定远程执行用户
- `tasks`: 定义要执行的任务列表
- `vars`: 定义变量
- `handlers`: 定义处理程序(特定任务触发时执行)
基本语法示例:
---
- name: Basic Playbook Example
hosts: webservers
remote_user: ubuntu
become: yes # 使用sudo权限执行任务
vars:
package_name: nginx
doc_root: /var/www/html
tasks:
- name: Install nginx
ansible.builtin.apt:
name: "{{ package_name }}"
state: present
update_cache: yes
- name: Start nginx service
ansible.builtin.service:
name: nginx
state: started
enabled: yes
handlers:
- name: restart nginx
ansible.builtin.service:
name: nginx
state: restarted
3. 任务(Tasks)详解
任务是Playbook的基本执行单元,每个任务调用一个Ansible模块来完成特定操作。任务可以包含名称、模块参数以及条件判断。
常用模块示例
#### 文件操作
---
- name: File Operations Example
hosts: all
tasks:
- name: Create a directory
ansible.builtin.file:
path: /opt/myapp
state: directory
mode: '0755'
- name: Create a file with content
ansible.builtin.copy:
dest: /opt/myapp/config.ini
content: |
[app]
debug = true
port = 8080
mode: '0644'
- name: Update file permissions
ansible.builtin.file:
path: /opt/myapp/config.ini
mode: '0600'
#### 包管理
---
- name: Package Management Example
hosts: db_servers
tasks:
- name: Install multiple packages (Debian/Ubuntu)
ansible.builtin.apt:
name:
- postgresql
- postgresql-contrib
- python3-psycopg2
state: present
when: ansible_os_family == "Debian"
- name: Install multiple packages (RHEL/CentOS)
ansible.builtin.yum:
name:
- postgresql-server
- postgresql-contrib
- python3-psycopg2
state: present
when: ansible_os_family == "RedHat"
#### 服务管理
---
- name: Service Management Example
hosts: app_servers
tasks:
- name: Ensure Apache is running
ansible.builtin.service:
name: httpd
state: started
enabled: yes
- name: Restart Apache if config changed
ansible.builtin.service:
name: httpd
state: restarted
when: config_changed is defined and config_changed
4. 变量与事实(Facts)
定义和使用变量
变量可以在Playbook中定义,也可以从外部文件或命令行传入。
---
- name: Variable Usage Example
hosts: all
vars:
app_port: 8080
app_user: webapp
tasks:
- name: Create application user
ansible.builtin.user:
name: "{{ app_user }}"
shell: /bin/bash
system: yes
- name: Create config file with variables
ansible.builtin.template:
src: templates/app.conf.j2
dest: /etc/app/app.conf
notify: restart app
使用系统事实(Facts)
Ansible会自动收集目标主机的系统信息(事实),可以在Playbook中直接使用。
---
- name: Facts Usage Example
hosts: all
tasks:
- name: Display OS information
ansible.builtin.debug:
msg: "OS Family: {{ ansible_os_family }}, Distribution: {{ ansible_distribution }}-{{ ansible_distribution_version }}"
- name: Install package based on OS
ansible.builtin.package:
name: "{{ 'apache2' if ansible_os_family == 'Debian' else 'httpd' }}"
state: present
5. 条件判断与循环
条件判断(when)
使用`when`语句可以根据条件控制任务的执行。
---
- name: Conditional Tasks Example
hosts: all
tasks:
- name: Install Debian-specific package
ansible.builtin.apt:
name: "docker-ce"
state: present
when: ansible_distribution == "Debian"
- name: Install RHEL-specific package
ansible.builtin.yum:
name: "docker-ce"
state: present
when: ansible_os_family == "RedHat"
- name: Configure for production
ansible.builtin.copy:
src: production.conf
dest: /etc/app/config.conf
when: env == "production"
循环(loops)
使用循环可以重复执行任务,支持不同类型的循环结构。
---
- name: Loops Example
hosts: all
tasks:
- name: Create multiple users
ansible.builtin.user:
name: "{{ item }}"
groups: "developers"
loop:
- alice
- bob
- charlie
- name: Install multiple packages
ansible.builtin.package:
name: "{{ item.name }}"
state: "{{ item.state }}"
loop:
- { name: 'nginx', state: 'present' }
- { name: 'python3', state: 'latest' }
- name: Create multiple directories
ansible.builtin.file:
path: "/var/www/{{ item }}"
state: directory
loop:
- site1
- site2
- site3
6. 处理程序(Handlers)
处理程序是特殊的任务,只有在其他任务通知它们时才会执行。它们通常用于服务重启等操作。
---
- name: Handlers Example
hosts: web_servers
tasks:
- name: Update nginx configuration
ansible.builtin.template:
src: templates/nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
- name: Update app configuration
ansible.builtin.copy:
src: files/app.conf
dest: /etc/app/app.conf
notify:
- restart app
- check app status
handlers:
- name: restart nginx
ansible.builtin.service:
name: nginx
state: restarted
- name: restart app
ansible.builtin.service:
name: myapp
state: restarted
- name: check app status
ansible.builtin.uri:
url: "http://localhost:8080/health"
method: GET
register: health_check
until: health_check.status == 200
retries: 3
delay: 5
7. 角色(Roles)组织
角色是组织Playbook的最佳实践方式,可以将变量、任务、处理程序等按功能分组。
角色目录结构
roles/
common/
tasks/
main.yml
handlers/
main.yml
templates/
config.j2
files/
script.sh
vars/
main.yml
defaults/
main.yml
meta/
main.yml
角色使用示例
---
- name: Role Usage Example
hosts: all
roles:
- common
- { role: nginx, env: production }
- { role: app, when: deploy_app == true }
角色任务示例 (`roles/nginx/tasks/main.yml`):
---
- name: Install nginx
ansible.builtin.package:
name: nginx
state: present
- name: Configure nginx
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
- name: Start nginx
ansible.builtin.service:
name: nginx
state: started
enabled: yes
8. 错误处理与调试
错误处理策略
---
- name: Error Handling Example
hosts: all
tasks:
- name: This task may fail
ansible.builtin.command: /usr/bin/false
ignore_errors: yes # 忽略错误继续执行
register: result
failed_when: result.rc != 0 and "specific error" not in result.stderr
- name: Handle failure
ansible.builtin.debug:
msg: "Previous task failed, but we're handling it"
when: result is failed
- name: Block with rescue
block:
- name: Run risky operation
ansible.builtin.command: /usr/bin/risky-command
rescue:
- name: Rescue task
ansible.builtin.debug:
msg: "Risky operation failed, running rescue"
always:
- name: Always run
ansible.builtin.debug:
msg: "This task always runs"
调试技巧
---
- name: Debugging Example
hosts: all
tasks:
- name: Show variable values
ansible.builtin.debug:
var: ansible_os_family
- name: Show specific variable
ansible.builtin.debug:
msg: "The hostname is {{ inventory_hostname }} and OS is {{ ansible_distribution }}"
- name: Debug with verbosity
ansible.builtin.debug:
msg: "Detailed debugging information"
verbosity: 2
9. 最佳实践
1. 使用版本控制:将所有Playbook和角色存储在Git仓库中
2. 模块化设计:将功能分解为可重用的角色
3. 幂等性:确保任务可以多次安全运行
4. 变量管理:使用`group_vars`和`host_vars`组织变量
5. 错误处理:为关键任务添加适当的错误处理
6. 文档注释:为复杂的任务和角色添加说明
7. 测试:使用Molecule或Testinfra测试Playbook
8. 安全:使用Ansible Vault保护敏感数据
总结
本教程详细介绍了Ansible Playbook的编写方法,从基础概念到高级特性,包括变量使用、条件判断、循环、处理程序、角色组织和错误处理等关键内容。通过掌握这些技能,您可以创建强大、可维护的自动化配置管理方案。
关键要点回顾:
- Playbook使用YAML语法,由一个或多个play组成
- 任务是基本执行单元,调用各种Ansible模块
- 变量和事实提供了灵活的配置能力
- 条件和循环控制任务执行流程
- 处理程序实现基于通知的操作
- 角色是组织Playbook的最佳实践
- 错误处理确保自动化流程的健壮性
持续实践和探索Ansible的丰富模块生态系统,将帮助您构建更高效、更可靠的自动化解决方案。Ansible的强大之处在于其简单易学的语法和强大的功能组合,使其成为现代IT自动化的理想选择。





