Ansible Playbook 编写与模块详解
前言
1. Playbook 基本结构
2. Tasks 模块
概念
用法
3. Variables 模块
概念
用法
4. Templates 模块(Jinja2 模板)
概念
用法
5. Handlers 模块
概念
用法
6. Tags 模块
概念
用法
7. 条件判断 when
概念
用法
8. 循环 with_items / loop
概念
用法
9.Roles 模块详解
Roles 的概念
Roles 的目录结构
创建 Roles 的步骤
创建 roles 目录
创建角色目录和子目录
在各目录创建 main.yml 文件
在 Roles 中定义任务和变量
任务文件(tasks/main.yml):
变量文件(vars/main.yml):
在 Playbook 中调用 Roles
Roles 与变量的灵活使用
Roles 依赖关系(meta/main.yml)
综合案例
10. 总结
前言
Ansible 的 Playbook 是自动化运维的核心工具,它用 YAML 文件描述在远程主机上执行的一系列任务。本文详细介绍 Playbook 的结构及其各模块的概念、用途和写法,适合初学者和有经验的运维人员查阅。
1. Playbook 基本结构
Playbook 由一个或多个 Play 组成,每个 Play 负责对一组主机执行任务。主要模块:
模块 | 概念 | 用途 |
---|---|---|
Tasks | 定义要执行的具体任务,每个任务调用一个模块(如 yum 、copy ) | 控制任务执行顺序 |
Variables | 变量,使 Playbook 灵活可复用 | 在不同主机间传递不同值 |
Templates | Jinja2 模板,动态生成文件 | 自动化配置文件生成 |
Handlers | 响应任务变更(由 notify 触发) | 常用于服务重启、刷新配置 |
Tags | 给任务打标签 | 执行 Playbook 时只执行特定任务 |
Roles | 模块化组织 Playbook | 管理复杂剧本、提高复用性 |
2. Tasks 模块
概念
Tasks 是 Playbook 中的“执行单元”。每个任务调用一个 Ansible 模块在远程主机上执行操作。
用法
tasks:- name: 测试连通性ping: - name: 安装软件包yum: name=httpd state=latest - name: 停止防火墙service: name=firewalld state=stopped
Tips:
任务按顺序执行
每个任务尽量有
name
方便查看日志可用
ignore_errors: true
忽略失败继续执行
3. Variables 模块
概念
变量用于提高 Playbook 的通用性和可维护性。变量可以在 Playbook 中用 vars
定义,也可以通过命令行 -e
传递,还可以在 Inventory 中定义主机变量。
用法
- hosts: dbserversvars:groupname: mysqlusername: nginxtasks:- name: 创建组group: name={{ groupname }} system=yes gid=306- name: 创建用户user: name={{ username }} uid=306 group={{ groupname }}
命令行传递变量:
ansible-playbook test.yaml -e "username=nginx"
4. Templates 模块(Jinja2 模板)
概念
模板用于动态生成配置文件。通过 Jinja2 语法,把变量写进模板文件,执行 Playbook 时替换成真实值。
用法
-
创建模板文件(以
.j2
为后缀):
# /opt/httpd.conf.j2 Listen {{ http_port }} ServerName {{ server_name }} DocumentRoot "{{ root_dir }}"
-
在主机清单定义变量:
[webservers] 192.168.10.14 http_port=80 server_name=www.accp.com root_dir=/etc/httpd/htdocs
-
在 Playbook 中调用模板:
- hosts: webserverstasks:- name: 安装配置文件template: src=/opt/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
5. Handlers 模块
概念
Handlers 是特殊任务,用于响应普通任务的变更,通常结合 notify
使用,例如配置文件更新后自动重启服务。
用法
tasks:- name: 拷贝配置文件copy: src=/opt/httpd.conf dest=/etc/httpd/conf/httpd.confnotify: restart httpd handlers:- name: restart httpdservice: name=httpd state=restarted
Tips:
Handlers 在 Play 执行完所有普通任务后统一执行
多次
notify
同一 handler 只执行一次
6. Tags 模块
概念
Tags 用于给任务打标签,执行 Playbook 时可以指定只执行特定标签的任务。
用法
tasks:- name: 拷贝 hosts 文件copy: src=/etc/hosts dest=/opt/hoststags: [only] - name: 永远执行的任务file: path=/opt/testhost state=touchtags: [always]
执行:
ansible-playbook play.yaml --tags="only"
Tips:
always
标签的任务无论执行哪个 tags 都会执行。
7. 条件判断 when
概念
when
用于按条件执行任务,只在条件为 true
时执行。
用法
tasks:- name: 仅在特定 IP 上重启command: /sbin/shutdown -r nowwhen: ansible_default_ipv4.address == "192.168.10.14" - name: 按主机名判断debug: msg="This is myhost"when: inventory_hostname == "myhost"
8. 循环 with_items
/ loop
概念
循环可批量执行相似任务,比如批量创建目录或用户。
用法
- name: 创建多个目录file:path: "{{ item }}"state: directorywith_items:- /tmp/test1- /tmp/test2 - name: 创建多个用户user: name={{ item.name }} state=present groups={{ item.groups }}with_items:- { name: test1, groups: wheel }- { name: test2, groups: root }
Tips:
loop
是 Ansible 2.5+ 推荐用法,功能与with_items
相同。
9.Roles 模块详解
Roles 的概念
在 Ansible 中,随着 Playbook 的功能越来越多、越来越复杂,单个 YAML 文件可能包含几十上百个任务,难以管理和复用。 Roles(角色)就是为了解决这个问题而设计的:
-
把变量、任务、模板、文件、处理程序等按照固定目录结构分类存放
-
自动按约定位置加载文件
-
支持在不同 Playbook 中重复使用相同的角色
-
适合按“功能”组织(例如 httpd、mysql、php),提高可维护性
简而言之,Roles 就是把 Playbook 模块化。
Roles 的目录结构
每个 Role 都在 roles/
目录下有一个独立的子目录:
roles/ └── httpd/├── files/ # copy、script 模块调用的文件├── templates/ # 模板文件,template 模块自动在此目录查找├── tasks/ # 必须有 main.yml,定义任务列表├── handlers/ # 必须有 main.yml,定义处理程序(notify 响应)├── vars/ # 必须有 main.yml,定义角色使用的变量├── defaults/ # 必须有 main.yml,定义角色的默认变量(优先级最低)└── meta/ # 必须有 main.yml,定义角色依赖关系、特殊设定
注意:
tasks/main.yml
是角色的入口文件(必须存在)
handlers/vars/defaults/meta
下的 main.yml 文件名也必须固定用不到的目录可以不建
创建 Roles 的步骤
创建 roles
目录
mkdir -p /etc/ansible/roles
创建角色目录和子目录
以 httpd
角色为例:
mkdir -p /etc/ansible/roles/httpd/{files,templates,tasks,handlers,vars,defaults,meta}
在各目录创建 main.yml 文件
touch /etc/ansible/roles/httpd/{defaults,vars,tasks,meta,handlers}/main.yml
在 Roles 中定义任务和变量
任务文件(tasks/main.yml):
# /etc/ansible/roles/httpd/tasks/main.yml - name: 安装 Apacheyum: name={{pkg}} state=latest - name: 启动 Apacheservice: enabled=true name={{svc}} state=started
变量文件(vars/main.yml):
# /etc/ansible/roles/httpd/vars/main.yml pkg: httpd svc: httpd
小技巧:
一般把角色专用变量写在
vars/main.yml
把默认变量写在
defaults/main.yml
(用户可以覆盖)全局变量可以写在
/etc/ansible/group_vars/all
在 Playbook 中调用 Roles
创建 site.yml
(或任意 Playbook):
# /etc/ansible/site.yml --- - hosts: webserversremote_user: rootroles:- httpd # 调用 httpd 角色
如果有多个角色,按顺序写:
roles:- httpd- mysql- php
执行:
cd /etc/ansible ansible-playbook site.yml
Roles 与变量的灵活使用
-
角色变量:写在
roles/<role>/vars/main.yml
,作用范围仅限当前角色 -
默认变量:写在
roles/<role>/defaults/main.yml
,优先级最低,便于用户在外部覆盖 -
主机/组变量:写在
/etc/ansible/hosts
或group_vars/
中 -
命令行变量:用
-e
覆盖一切
例子:
ansible-playbook site.yml -e "pkg=nginx svc=nginx"
Roles 依赖关系(meta/main.yml)
如果某个角色依赖于其他角色,可以在 meta/main.yml
中定义:
# /etc/ansible/roles/php/meta/main.yml dependencies:- role: httpd- role: mysql
这样在调用 php
角色时,会自动先执行 httpd
和 mysql
角色。
综合案例
# 创建角色 mkdir -p /etc/ansible/roles/{httpd,mysql,php}/{files,templates,tasks,handlers,vars,defaults,meta} touch /etc/ansible/roles/{httpd,mysql,php}/{defaults,vars,tasks,meta,handlers}/main.yml
httpd/tasks/main.yml
- name: install apacheyum: name={{pkg}} state=latest - name: start apacheservice: enabled=true name={{svc}} state=started
httpd/vars/main.yml
pkg: httpd svc: httpd
mysql/vars/main.yml
pkg:- mariadb- mariadb-server svc: mariadb
php/vars/main.yml
pkg:- php- php-fpm svc: php-fpm
site.yml
--- - hosts: webserversremote_user: rootroles:- httpd- mysql- php
执行:
cd /etc/ansible ansible-playbook site.yml
效果:在 webservers 主机组上依次安装 httpd、mysql、php 并启动服务。
10. 总结
-
Tasks 是执行单元
-
Variables 提供灵活性
-
Templates 动态生成配置文件
-
Handlers 响应变更,统一处理
-
Tags 定向执行特定任务
-
when/loop 控制条件和循环
-
Roles 模块化管理大型 Playbook