Ansible Playbook 编写与模块详解

前言

[1. Playbook 基本结构](#1. Playbook 基本结构)

[2. Tasks 模块](#2. Tasks 模块)

概念

用法

[3. Variables 模块](#3. Variables 模块)

概念

用法

[4. Templates 模块(Jinja2 模板)](#4. Templates 模块(Jinja2 模板))

概念

用法

[5. Handlers 模块](#5. Handlers 模块)

概念

用法

[6. Tags 模块](#6. Tags 模块)

概念

用法

[7. 条件判断 when](#7. 条件判断 when)

概念

用法

[8. 循环 with_items / loop](#8. 循环 with_items / loop)

概念

用法

[9.Roles 模块详解](#9.Roles 模块详解)

[Roles 的概念](#Roles 的概念)

[Roles 的目录结构](#Roles 的目录结构)

[创建 Roles 的步骤](#创建 Roles 的步骤)

[创建 roles 目录](#创建 roles 目录)

创建角色目录和子目录

[在各目录创建 main.yml 文件](#在各目录创建 main.yml 文件)

[在 Roles 中定义任务和变量](#在 Roles 中定义任务和变量)

任务文件(tasks/main.yml):

变量文件(vars/main.yml):

[在 Playbook 中调用 Roles](#在 Playbook 中调用 Roles)

[Roles 与变量的灵活使用](#Roles 与变量的灵活使用)

[Roles 依赖关系(meta/main.yml)](#Roles 依赖关系(meta/main.yml))

综合案例

[10. 总结](#10. 总结)

前言

Ansible 的 Playbook 是自动化运维的核心工具,它用 YAML 文件描述在远程主机上执行的一系列任务。本文详细介绍 Playbook 的结构及其各模块的概念、用途和写法,适合初学者和有经验的运维人员查阅。


1. Playbook 基本结构

Playbook 由一个或多个 Play 组成,每个 Play 负责对一组主机执行任务。主要模块:

模块 概念 用途
Tasks 定义要执行的具体任务,每个任务调用一个模块(如 yumcopy 控制任务执行顺序
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: dbservers
  vars:
    groupname: mysql
    username: nginx
  tasks:
    - 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 时替换成真实值。

用法

  1. 创建模板文件(以 .j2 为后缀):
复制代码
# /opt/httpd.conf.j2
Listen {{ http_port }}
ServerName {{ server_name }}
DocumentRoot "{{ root_dir }}"
  1. 在主机清单定义变量:
复制代码
[webservers]
192.168.10.14 http_port=80 server_name=www.accp.com root_dir=/etc/httpd/htdocs
  1. 在 Playbook 中调用模板:
复制代码
- hosts: webservers
  tasks:
    - 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.conf
    notify: restart httpd
​
handlers:
  - name: restart httpd
    service: name=httpd state=restarted

Tips

  • Handlers 在 Play 执行完所有普通任务后统一执行

  • 多次 notify 同一 handler 只执行一次


6. Tags 模块

概念

Tags 用于给任务打标签,执行 Playbook 时可以指定只执行特定标签的任务。

用法

复制代码
tasks:
  - name: 拷贝 hosts 文件
    copy: src=/etc/hosts dest=/opt/hosts
    tags: [only]
​
  - name: 永远执行的任务
    file: path=/opt/testhost state=touch
    tags: [always]

执行:

复制代码
ansible-playbook play.yaml --tags="only"

Tipsalways 标签的任务无论执行哪个 tags 都会执行。


7. 条件判断 when

概念

when 用于按条件执行任务,只在条件为 true 时执行。

用法

复制代码
tasks:
  - name: 仅在特定 IP 上重启
    command: /sbin/shutdown -r now
    when: 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: directory
  with_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 }

Tipsloop 是 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: 安装 Apache
  yum: name={{pkg}} state=latest
- name: 启动 Apache
  service: 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: webservers
  remote_user: root
  roles:
    - 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/hostsgroup_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 角色时,会自动先执行 httpdmysql 角色。


综合案例

复制代码
# 创建角色
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 apache
  yum: name={{pkg}} state=latest
- name: start apache
  service: 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: webservers
  remote_user: root
  roles:
    - httpd
    - mysql
    - php

执行:

复制代码
cd /etc/ansible
ansible-playbook site.yml

效果:在 webservers 主机组上依次安装 httpd、mysql、php 并启动服务。

10. 总结

  • Tasks 是执行单元

  • Variables 提供灵活性

  • Templates 动态生成配置文件

  • Handlers 响应变更,统一处理

  • Tags 定向执行特定任务

  • when/loop 控制条件和循环

  • Roles 模块化管理大型 Playbook

相关推荐
和光同尘20232 小时前
CentOS7搭建ELK日志分析系统
运维·elasticsearch·云原生·kubernetes·centos·kibana·logstash
苦逼IT运维2 小时前
Windows 作为 Ansible 节点的完整部署流程(含 Docker 部署 Ansible)
windows·docker·ansible
科技那些事儿3 小时前
海外代理IP软件哪家好?高性价比海外代理IP服务商平台
服务器·网络·tcp/ip
神秘面具男033 小时前
NFS 服务器 iSCSI 服务器
运维·服务器
iconball3 小时前
个人用云计算学习笔记 --17(DNS 服务器)
linux·运维·笔记·学习·云计算
iconball3 小时前
个人用云计算学习笔记 --16(DHCP 服务器)
linux·运维·笔记·学习·云计算
cpsvps3 小时前
容器主机名解析在香港服务器内部网络的调试方案
运维·服务器·网络
Lin_Aries_04213 小时前
部署 Jenkins 服务器
运维·服务器·docker·容器·云计算·jenkins
vortex53 小时前
在 Kali Linux 上配置 MySQL 服务器并实现 Windows 远程连接
linux·数据库·mysql