42 Ansible-Playbooks 自动化剧本

文章目录

  • 前言
  • 理论部分
    • [1_Playbook 的结构](#1_Playbook 的结构)
    • [2_Ansible Playbook 示例](#2_Ansible Playbook 示例)
      • [2.1_基础 Playbook 结构](#2.1_基础 Playbook 结构)
    • [3_命令行运行 Playbook](#3_命令行运行 Playbook)
    • 4_变量和引用
    • [5_条件判断 when](#5_条件判断 when)
    • [6_迭代:with_items 与 loop](#6_迭代:with_items 与 loop)
    • [7_Templates 模块](#7_Templates 模块)
    • [8_Tags 模块](#8_Tags 模块)
    • [9_Roles 模块](#9_Roles 模块)
      • [9.1_Roles 概念](#9.1_Roles 概念)
      • [9.2_roles 目录结构及含义](#9.2_roles 目录结构及含义)
      • [9.3_使用 Roles 的步骤](#9.3_使用 Roles 的步骤)
  • 实验部分
    • [1_搭建基于 Roles 的 LAMP 环境](#1_搭建基于 Roles 的 LAMP 环境)
      • 1.1_环境规划
      • [1.2_创建 Roles 目录结构](#1.2_创建 Roles 目录结构)
      • 1.3_编写各角色内容
      • [1.4_编写主 Playbook(site.yml)](#1.4_编写主 Playbook(site.yml))
      • [1.5_执行 Playbook](#1.5_执行 Playbook)
  • 结语

前言

本文系统讲解了 Ansible Playbook 的核心编写方法,涵盖结构组成、变量使用、条件判断、循环迭代、模板(Templates)、标签(Tags)以及角色(Roles)等关键知识点,并辅以完整实验案例。通过本文学习,可掌握自动化运维中 Playbook 的规范写法与模块化设计。

  1. Playbook 的基本结构
  2. Playbook 示例与运行方式
  3. 变量定义与引用
  4. 条件判断(when)
  5. 迭代(with_items / loop)
  6. Templates 模板机制
  7. Tags 标签控制任务执行
  8. Roles 角色体系与目录结构
  9. Roles 实战部署 Web + DB + PHP 环境

理论部分

1_Playbook 的结构

Ansible Playbook 是一个 YAML 格式的配置文件,用于批量执行任务,其核心由多个 Play 组成,每个 Play 面向一组主机执行一系列操作。

1.1_核心组成部分

① Tasks(任务)

任务列表,按顺序在目标主机上执行,每个任务调用一个 Ansible 模块(如 yumcopyservice 等)。

② Variables(变量)

用于提升 Playbook 的灵活性和复用性,可在 vars 区域定义,或通过命令行 -e 传入。

③ Templates(模板)

基于 Jinja2 引擎的 .j2 文件,动态生成配置文件(如 httpd.conf.j2),支持变量替换。

④ Handlers(处理器)

仅在被 notify 触发且任务状态为 changed 时执行,常用于服务重启。所有普通任务执行完毕后才统一执行 handlers,避免重复触发。

⑤ Roles(角色)

将 tasks、handlers、vars、templates 等按功能模块化组织,形成可复用的标准化单元,便于大型项目管理。


2_Ansible Playbook 示例

2.1_基础 Playbook 结构

yaml 复制代码
---
- name: first play1
  gather_facts: false
  hosts: webservers
  remote_user: root
  tasks:
    - name: test connection
      ping:
    - name: disable selinux
      command: '/sbin/setenforce 0'
    - name: disable firewalld
      service: name=firewalld state=stopped
    - name: install httpd
      yum: name=httpd state=latest
    - name: install configuration file for httpd
      copy: src=/opt/httpd.conf dest=/etc/httpd/conf/httpd.conf
      notify: "restart httpd"
    - name: start httpd service
      service: enabled=true name=httpd state=started
  handlers:
    - name: restart httpd
      service: name=httpd state=restarted

---:YAML 文件起始标记(可省略)
gather_facts: false:跳过 facts 收集,加速执行
ping::测试连通性模块,无需参数
command:执行命令,不经过 shell,不支持管道/重定向
notify:仅当任务状态为 changed 时触发 handler
handlers:必须与 notify 名称严格一致


3_命令行运行 Playbook

常用命令参数:

shell 复制代码
ansible-playbook test1.yaml                          # 执行 playbook
ansible-playbook test1.yaml --syntax-check          # 语法检查
ansible-playbook test1.yaml --list-tasks            # 列出所有任务
ansible-playbook test1.yaml --list-hosts            # 列出影响的主机
ansible-playbook test1.yaml --start-at-task='install httpd'  # 从指定任务开始
ansible-playbook test1.yaml -k                      # 提示输入 SSH 密码
ansible-playbook test1.yaml -K                      # 提示输入 sudo 密码

-k(小写):SSH 密码
-K(大写):sudo 密码(需配合 become: yes 使用,默认未启用)


4_变量和引用

变量可在 Play 内部定义,也可通过命令行传入:

yaml 复制代码
- name: second play
  hosts: dbservers
  remote_user: root
  vars:
    groupname: mysql
    username: nginx
  tasks:
    - name: create group
      group: name={{ groupname }} system=yes gid=306
    - name: create user
      user: name={{ username }} uid=306 group={{ groupname }}
    - name: copy file
      copy: content="{{ ansible_default_ipv4.address }}" dest=/opt/vars.txt

命令行传参:

shell 复制代码
ansible-playbook test1.yaml -e "username=nginx"

{``{ }}:Jinja2 变量引用语法
ansible_default_ipv4.address:facts 中的 IP 地址变量(需 gather_facts: true


5_条件判断 when

when 指令用于控制任务是否执行,条件为真则执行。

yaml 复制代码
- name: shutdown host 
  command: /sbin/shutdown -r now  
  when: ansible_default_ipv4.address == "192.168.10.14"

- name: check hostname
  debug: msg="This is db server"
  when: inventory_hostname == "db01"

when 中的变量 无需加 {``{}} ,直接使用变量名

常用于跳过特定主机或根据硬件条件(内存、CPU)执行任务


6_迭代:with_items 与 loop

Ansible 支持对列表进行循环操作,推荐使用 loop(新语法),with_items 为旧语法但兼容。

yaml 复制代码
- name: create directories
  file:
    path: "{{ item }}"
    state: directory
  loop:
    - /tmp/test1
    - /tmp/test2

- name: add users
  user: name={{ item.name }} state=present groups={{ item.groups }}
  loop:
    - { name: 'test1', groups: 'wheel' }
    - { name: 'test2', groups: 'root' }

item:循环中的当前元素

支持字典列表,通过 item.key 访问字段


7_Templates 模块

利用 Jinja2 模板动态生成配置文件。

步骤:

  1. 准备 .j2 模板文件
  2. 在 inventory 或 vars 中定义变量
  3. 使用 template 模块部署

示例模板 /opt/httpd.conf.j2

conf 复制代码
Listen {{ http_port }}
ServerName {{ server_name }}
DocumentRoot "{{ root_dir }}"

Playbook 片段:

yaml 复制代码
- hosts: all
  remote_user: root
  vars:
    package: httpd
    service: httpd
  tasks:
    - name: install httpd package
      yum: name={{ package }} state=latest
    - name: install configure file
      template: src=/opt/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
      notify: restart httpd
    - name: create root dir
      file: path=/etc/httpd/htdocs state=directory
    - name: start httpd server
      service: name={{ service }} enabled=true state=started
  handlers:
    - name: restart httpd
      service: name={{ service }} state=restarted

Inventory 定义主机变量:

ini 复制代码
[webservers]
192.168.10.14 http_port=80 server_name=www.benet.com root_dir=/etc/httpd/htdocs

8_Tags 模块

通过 tags 为任务打标签,运行时可选择性执行。

yaml 复制代码
- name: Copy hosts file
  copy: src=/etc/hosts dest=/opt/hosts
  tags:
    - only

- name: touch file
  file: path=/opt/testhost state=touch
  tags:
    - always

执行命令:

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

always:无论指定哪个标签,带 always 的任务都会执行


9_Roles 模块

9.1_Roles 概念

Roles 是 Ansible 的最佳实践,用于将复杂 Playbook 拆分为可复用、结构化的组件,适用于多服务(Web、DB、PHP)混合部署场景。

优势:

  • 模块化组织任务、变量、模板
  • 自动加载 tasks/main.ymlhandlers/main.yml
  • 支持默认变量(defaults)与覆盖变量(vars

9.2_roles 目录结构及含义

标准角色目录结构:

复制代码
roles/
└── <role_name>/
    ├── files/          # 存放 copy/script 模块使用的静态文件
    ├── templates/      # 存放 .j2 模板文件
    ├── tasks/          # 主任务文件 main.yml
    ├── handlers/       # 处理器 main.yml
    ├── vars/           # 角色专属变量 main.yml(优先级高)
    ├── defaults/       # 默认变量 main.yml(优先级低)
    └── meta/           # 元数据,定义依赖关系

9.3_使用 Roles 的步骤

  1. 创建 roles 目录:/etc/ansible/roles/
  2. 为每个服务创建角色目录(如 httpd、mysql)
  3. 在各角色下创建子目录并添加 main.yml
  4. 编写 site.yml 调用角色
  5. 运行 ansible-playbook site.yml

实验部分

1_搭建基于 Roles 的 LAMP 环境

1.1_环境规划

主机组 IP 地址 角色
webservers 192.168.10.14 httpd, mysql, php

本实验将 httpd、mysql、php 三个服务均部署在 webservers

1.2_创建 Roles 目录结构

① 创建项目目录与角色骨架

shell 复制代码
mkdir -p /etc/ansible/roles/{httpd,mysql,php}/{files,templates,tasks,handlers,vars,defaults,meta}

-p:递归创建多级目录

② 创建各角色的 main.yml 文件

shell 复制代码
touch /etc/ansible/roles/httpd/{tasks,handlers,vars}/main.yml
touch /etc/ansible/roles/mysql/{tasks,handlers,vars}/main.yml
touch /etc/ansible/roles/php/{tasks,handlers,vars}/main.yml

defaultsmeta 本次未使用,可省略

1.3_编写各角色内容

① 编写 httpd 角色

shell 复制代码
vim /etc/ansible/roles/httpd/tasks/main.yml
yaml 复制代码
- name: install apache
  yum: name={{ pkg }} state=latest
- name: start apache
  service: enabled=true name={{ svc }} state=started
shell 复制代码
vim /etc/ansible/roles/httpd/vars/main.yml
yaml 复制代码
pkg: httpd
svc: httpd

② 编写 mysql 角色

shell 复制代码
vim /etc/ansible/roles/mysql/tasks/main.yml
yaml 复制代码
- name: install mysql
  yum: name={{ pkg }} state=latest
- name: start mysql
  service: enabled=true name={{ svc }} state=started
shell 复制代码
vim /etc/ansible/roles/mysql/vars/main.yml
yaml 复制代码
pkg:
  - mariadb
  - mariadb-server
svc: mariadb

③ 编写 php 角色

shell 复制代码
vim /etc/ansible/roles/php/tasks/main.yml
yaml 复制代码
- name: install php
  yum: name={{ pkg }} state=latest
- name: start php-fpm
  service: enabled=true name={{ svc }} state=started
shell 复制代码
vim /etc/ansible/roles/php/vars/main.yml
yaml 复制代码
pkg:
  - php
  - php-fpm
svc: php-fpm

1.4_编写主 Playbook(site.yml)

shell 复制代码
vim /etc/ansible/site.yml
yaml 复制代码
---
- hosts: webservers
  remote_user: root
  roles:
    - httpd
    - mysql
    - php

1.5_执行 Playbook

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

执行后将在目标主机安装并启动 httpd、mariadb、php-fpm 服务


结语

Playbook 结构化要点 :Tasks 执行操作,Handlers 响应变更,Variables 提升复用,Templates 动态配置。
Roles 核心价值 :通过标准化目录(tasks/vars/handlers)实现模块解耦,支持跨项目复用。
执行优化技巧 :使用 --tags 精准控制任务,when 实现条件分支,loop 简化重复操作。

!question\] 请问 Ansible 中 handlers 为什么不在任务执行后立即触发? 为避免多次变更导致服务反复重启,Ansible 将所有 handlers 延迟到当前 Play 所有 tasks 执行完毕后统一执行,确保只触发一次。 \[!question\] 请问 roles 目录中 vars 和 defaults 的区别是什么? `vars/main.yml` 中的变量优先级高,会覆盖 `defaults/main.yml`;`defaults` 用于提供可被用户覆盖的安全默认值。 \[!question\] 请问 template 模块和 copy 模块的核心区别? `template` 支持 Jinja2 变量渲染(`.j2` 文件),动态生成配置;`copy` 仅做静态文件传输,不解析变量。 \[!question\] 请问 when 条件中为何不需要 {{}}? `when` 指令内部已处于 Jinja2 上下文,直接写变量名即可被解析,加 `{``{}}` 反而导致语法错误。

相关推荐
孤岛悬城5 小时前
41 Ansible 自动化
云计算
孤岛悬城6 小时前
44 Docker:安装与容器管理
docker·容器·云计算
gaize121319 小时前
如何编写一个简单的服务器应用程序?
服务器·云计算
wanhengidc1 天前
巨椰 云手机 云游戏稳定运行
运维·服务器·arm开发·游戏·云计算
x新观点1 天前
2025年IDC服务商市场观察:博大数据在第三方数据中心排名中表现稳健
大数据·人工智能·云计算
x新观点1 天前
2025年IDC服务商市场深度解析:博大数据荣登第三方数据中心排名前列
大数据·人工智能·云计算
翼龙云_cloud1 天前
阿里云云渠道商:如何选择阿里云 GPU 配置方案?
服务器·人工智能·阿里云·云计算
Wnq100721 天前
解构中心化困境:工业控制SCADA的延时与可靠性症结及分布式边缘计算转型路径
人工智能·分布式·云计算·去中心化·边缘计算