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 上下文,直接写变量名即可被解析,加 `{``{}}` 反而导致语法错误。

相关推荐
落笔画忧愁e2 小时前
实测:利用腾讯云锐驰型 200M 带宽,搭建无门槛高清视频分发系统
云计算·腾讯云
冬天的风滚草4 小时前
揭秘云原生混布资源调度器Koordinator (十五)GPU 信息采集与上报机制
云计算
冬天的风滚草4 小时前
揭秘云原生混布资源调度器Koordinator (十三)GPU 资源管理总览
云计算
冬天的风滚草4 小时前
揭秘云原生混布资源调度器Koordinator (十四)DeviceShare 调度插件详解
云计算
CodeCaptain7 小时前
阿里云ECS上配置Nginx的反向代理
nginx·阿里云·云计算
有谁看见我的剑了?16 小时前
VMware OVF Tool 工具安装学习
云计算
盛夏5201 天前
Docker容器化部署SpringBoot+Vue项目:从零到一在阿里云宝塔面板的实践指南
阿里云·docker·云计算
狐571 天前
2026-01-10-云计算问答题部分整理-期末复习
云计算·期末复习
2401_861277551 天前
中国电信星辰AI大模型有哪些主要功能
人工智能·云计算·软件工程·语音识别
Akamai中国2 天前
基准测试:Akamai云上的NVIDIA RTX Pro 6000 Blackwell
人工智能·云计算·云服务·云存储