Ansible Playbook

一、Ansible Playbook 核心基础

Playbook 是 Ansible 的自动化脚本文件,基于 YAML 格式,用于批量执行任务。其核心价值是将 "零散命令" 组织成 "可复用、可维护的自动化流程"。

1. Playbook 核心结构

一个完整的 Playbook 由多个Play组成,每个Play包含以下关键部分:

组成部分 作用说明
Tasks 核心执行单元,每个任务调用一个 Ansible 模块(如pingyum),按顺序执行
Variables 存储动态数据,让 Playbook 更灵活(如定义软件名、端口号)
Templates 基于 Jinja2 模板生成动态配置文件(如 Apache 的httpd.conf
Handlers 响应任务变更的 "触发器"(如配置文件修改后重启服务),仅在任务状态为changed时执行
Roles 将任务、变量、模板等按功能拆分,实现模块化复用(如 "Web 服务角色""数据库角色")
2. 基础 Playbook 示例(含核心语法)
复制代码
---  # YAML文件标识(可省略)
- name: 部署Web服务  # Play名称(便于识别,可省略)
  hosts: webservers  # 目标主机组(来自/etc/ansible/hosts)
  remote_user: root  # 远程执行用户
  gather_facts: false  # 关闭facts信息收集(加快执行速度,可省略)
  
  tasks:  # 任务列表
    # 任务1:测试主机连通性
    - name: 测试Ping连通性
      ping:  # 调用ping模块(无参数)
    
    # 任务2:关闭防火墙(忽略执行错误)
    - name: 停止firewalld服务
      service: name=firewalld state=stopped  # 模块参数用key=value格式
      ignore_errors: True  # 忽略任务执行失败(如服务已停止)
    
    # 任务3:安装Apache(修改配置后触发Handler)
    - name: 安装httpd
      yum: name=httpd state=latest
    
    - name: 推送httpd配置文件
      copy: src=/opt/httpd.conf dest=/etc/httpd/conf/httpd.conf
      notify: "重启httpd"  # 配置变更时触发同名Handler
    
    # 任务4:启动Apache并设为开机自启
    - name: 启动httpd服务
      service: name=httpd state=started enabled=true
  
  handlers:  # 触发器列表(仅被notify调用)
    - name: 重启httpd  # 名称必须与notify完全一致
      service: name=httpd state=restarted

二、Playbook 关键功能与实操

1. 变量使用(灵活传递数据)

变量可通过 "Play 内定义" 或 "命令行传递",引用时用{``{ 变量名 }}

  • 方式 1:在 Play 内定义变量

    复制代码
    - name: 用变量创建用户和组
      hosts: dbservers
      vars:  # 定义变量
        groupname: mysql
        username: nginx
      tasks:
        - name: 创建mysql组
          group: name={{ groupname }} gid=306
        - name: 创建nginx用户
          user: name={{ username }} group={{ groupname }}
  • 方式 2:命令行传递变量(优先级更高)

    复制代码
    ansible-playbook test.yaml -e "username=testuser"  # -e参数指定变量
2. 条件判断(when 指令)

通过when指定 "任务执行的条件",条件为true时才执行任务,变量无需加{``{ }}

复制代码
- name: 仅特定IP主机执行关机
  hosts: all
  tasks:
    - name: 重启主机
      command: /sbin/shutdown -r now
      when: ansible_default_ipv4.address == "192.168.10.14"  # 条件:IP匹配
3. 迭代(循环执行任务)

通过loop(推荐)或with_items实现 "重复执行同一任务",支持列表、字典格式。

复制代码
- name: 循环创建目录和用户
  hosts: dbservers
  tasks:
    # 1. 循环创建目录(列表格式)
    - name: 创建/tmp/test1、/tmp/test2
      file: path={{ item }} state=directory
      loop:  # 等同于with_items
        - /tmp/test1
        - /tmp/test2
    
    # 2. 循环创建用户(字典格式)
    - name: 创建test1、test2用户并指定组
      user: name={{ item.name }} groups={{ item.groups }}
      loop:
        - { name: "test1", groups: "wheel" }
        - { name: "test2", groups: "root" }
4. Templates 模块(动态生成配置)

基于 Jinja2 模板(后缀.j2)生成配置文件,支持嵌入变量。

  • 步骤 1:创建 Jinja2 模板(/opt/httpd.conf.j2)

    复制代码
    Listen {{ http_port }}  # 嵌入变量
    ServerName {{ server_name }}
    DocumentRoot "{{ root_dir }}"
  • 步骤 2:在 Playbook 中使用 Templates 模块

    复制代码
    - name: 动态生成httpd配置
      hosts: webservers
      tasks:
        - name: 推送模板并生成配置
          template: src=/opt/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
          notify: 重启httpd  # 配置变更时触发重启
  • 步骤 3:在主机清单中定义变量(/etc/ansible/hosts)

    复制代码
    [webservers]
    192.168.10.14 http_port=80 server_name=www.test.com root_dir=/var/www/html
5. Tags 模块(指定执行特定任务)

给任务打 "标签",执行 Playbook 时通过--tags只运行指定标签的任务,特殊标签always表示 "始终执行"。

复制代码
- name: 带标签的任务示例
  hosts: webservers
  tasks:
    - name: 复制hosts文件
      copy: src=/etc/hosts dest=/opt/hosts
      tags: only  # 标签:only
    
    - name: 创建测试文件
      file: path=/opt/test.txt state=touch
      tags: always  # 标签:始终执行
  • 执行命令

    复制代码
    ansible-playbook test.yaml --tags="only"  # 仅执行标签为only的任务(always任务也会执行)

三、Roles 模块(模块化管理)

Roles 是 Playbook 的 "模块化方案",将任务、变量、模板等按 "功能" 拆分(如 Web 角色、数据库角色),便于复用和维护。

1. Roles 目录结构(固定格式)

每个角色需按以下目录存放,未用到的目录可省略:

复制代码
/etc/ansible/roles/  # 默认Roles目录
├── httpd/  # Web服务角色
│   ├── files/  # 存储copy/script模块用到的静态文件
│   ├── templates/  # 存储Jinja2模板文件
│   ├── tasks/  # 任务列表(必须有main.yml)
│   ├── handlers/  # 触发器(必须有main.yml)
│   ├── vars/  # 角色变量(必须有main.yml)
│   ├── defaults/  # 默认变量(优先级最低,必须有main.yml)
│   └── meta/  # 角色依赖、作者等信息(必须有main.yml)
└── mysql/  # 数据库服务角色(结构同上)
2. Roles 实操步骤(以部署 LAMP 为例)
步骤 1:创建 Roles 目录结构
复制代码
# 创建httpd、mysql、php角色目录
mkdir -p /etc/ansible/roles/{httpd,mysql,php}/{files,templates,tasks,handlers,vars,defaults,meta}
# 创建各角色的main.yml文件(固定文件名)
touch /etc/ansible/roles/{httpd,mysql,php}/{tasks,vars,handlers,defaults,meta}/main.yml
步骤 2:编写各角色的任务与变量
  • httpd 角色(安装并启动 Apache)

    复制代码
    # /etc/ansible/roles/httpd/tasks/main.yml
    - name: 安装httpd
      yum: name={{ pkg }} state=latest
    - name: 启动httpd并设为开机自启
      service: name={{ svc }} state=started enabled=true
    
    # /etc/ansible/roles/httpd/vars/main.yml(角色变量)
    pkg: httpd
    svc: httpd
  • mysql 角色(安装并启动 MariaDB)

    复制代码
    # /etc/ansible/roles/mysql/tasks/main.yml
    - name: 安装MariaDB
      yum: name={{ pkg }} state=latest
    - name: 启动MariaDB
      service: name={{ svc }} state=started enabled=true
    
    # /etc/ansible/roles/mysql/vars/main.yml
    pkg:
      - mariadb
      - mariadb-server
    svc: mariadb
步骤 3:编写总 Playbook(调用 Roles)

创建site.yml,按主机组分配角色:

复制代码
# /etc/ansible/site.yml
---
- name: 给Web服务器部署LAMP
  hosts: webservers
  remote_user: root
  roles:  # 调用角色(按顺序执行)
    - httpd
    - mysql
    - php
步骤 4:执行 Roles
复制代码
cd /etc/ansible
ansible-playbook site.yml  # 执行总Playbook

四、Playbook 常用命令

命令用途 命令示例
运行 Playbook ansible-playbook test.yaml
检查语法错误 ansible-playbook test.yaml --syntax-check
查看任务列表 ansible-playbook test.yaml --list-task
查看目标主机 ansible-playbook test.yaml --list-hosts
从指定任务开始执行 ansible-playbook test.yaml --start-at-task='安装httpd'
输入 SSH 密码执行 ansible-playbook test.yaml -k
输入 sudo 密码执行 ansible-playbook test.yaml -K

扩展

在 Ansible 中,组嵌套(Group Nesting) 是指在主机清单(Inventory)中,将一个组作为另一个组的成员,形成层级关系的组织方式。通过组嵌套,可以更灵活地管理不同层级、不同功能的主机集合,简化 Playbook 中目标主机的指定。

组嵌套的核心作用
  1. 层级化管理主机:将主机按 "父组 - 子组" 的逻辑分类(如按业务线→部门→功能划分)。
  2. 简化目标指定:执行任务时,指定父组即可对其包含的所有子组主机生效,无需逐个列出。
示例(主机清单 hosts 文件)
复制代码
# 定义子组(具体功能组)
[webservers]
192.168.10.11
192.168.10.12

[dbservers]
192.168.10.21
192.168.10.22

# 定义父组(嵌套子组),使用 :children 标识
[prod:children]  # prod组包含以下子组
webservers       # 嵌套webservers子组
dbservers        # 嵌套dbservers子组

[all_servers:children]  # 更大的父组,可包含多个子组/父组
prod
testservers  # 假设还有testservers子组
使用场景
  • 执行命令时,指定父组 prod 即可操作其包含的所有子组主机:

    复制代码
    ansible prod -m ping  # 对webservers和dbservers的所有主机执行ping测试
  • Playbook 中指定父组作为目标:

    复制代码
    - name: 部署生产环境所有服务
      hosts: prod  # 涵盖webservers和dbservers
      tasks: ...

通过组嵌套,能有效减少重复配置,尤其适合主机数量多、分类复杂的场景(如多环境、多业务线的企业级部署)。

在 Ansible 中,Handlers(处理器) 是一种特殊的任务,它不会主动执行,而是被其他任务通过 notify 指令触发触发 ,通常用于响应配置变更后的操作(如服务重启、进程重载等)。它的核心价值是:仅在相关任务产生 "变更" 时才执行,避免无意义的重复操作(例如配置文件未修改时,无需重启服务)。

Handlers 的核心特性
  1. 被动触发 :Handlers 定义的任务不会默认执行,必须被其他任务的 notify 指令调用。
  2. 条件执行 :只有当触发它的任务执行状态为 changed(配置有实际变更)时,Handlers 才会执行。
  3. 合并执行 :多个任务触发同一个 Handler 时,Handler 只会在当前 Play 的所有普通任务执行完毕后运行一次(避免重复操作)。
Handlers 的基本用法
定义 Handlers

Handlers 通常在 Playbook 的 handlers 区块中定义,语法与普通任务完全一致(调用 Ansible 模块),但必须指定唯一的 name(用于被 notify 匹配)。

触发 Handlers

在普通任务中通过 notify: "Handler名称" 指令触发,名称必须与 Handlers 中定义的 name 完全一致(区分大小写)。

notify:notify 是 Ansible 中连接 "任务变更" 与 "后续响应操作" 的桥梁

示例:配置文件变更后重启服务
复制代码
---
- name: 部署Nginx并自动重启
  hosts: webservers
  tasks:
    # 任务1:安装Nginx(无变更时不会触发Handler)
    - name: 安装Nginx
      yum: name=nginx state=latest

    # 任务2:推送Nginx配置文件(配置变更时触发Handler)
    - name: 复制Nginx配置文件
      copy:
        src: /opt/nginx.conf
        dest: /etc/nginx/nginx.conf
      notify: "重启Nginx服务"  # 配置变更时触发同名Handler

    # 任务3:启动Nginx(首次执行时启动,后续不重复操作)
    - name: 确保Nginx服务启动
      service: name=nginx state=started

  # 定义Handlers(触发后执行的任务)
  handlers:
    - name: 重启Nginx服务  # 名称必须与notify完全匹配
      service: name=nginx state=restarted
相关推荐
啦啦啦在冲冲冲2 小时前
如何计算sequence粒度的负载均衡损失
运维·负载均衡
人逝花落空.2 小时前
docker容器的三大核心技术UnionFS(下)
运维·docker·容器
岚天start2 小时前
Nginx配置中location和proxy_pass指令尾部是否带斜杠的区别
运维·nginx·centos·proxy_pass·location·uri·斜杠
xx.ii3 小时前
54.Nginx部署与lnmp的部署
运维·nginx·负载均衡
纳切威3 小时前
CentOS 10服务器版 部署Zabbix7.2 server端
linux·运维·centos·zabbix
祐言QAQ3 小时前
(超详细,于25年更新版) VMware 虚拟机安装以及Linux系统—CentOS 7 部署教程
linux·运维·服务器·c语言·物联网·计算机网络·centos
华纳云IDC服务商4 小时前
服务器机械硬盘能支撑高并发流媒体吗?
运维·服务器·媒体
再难也得平4 小时前
Docker基础与项目部署
运维·docker·容器
IT北辰4 小时前
Linux 系统python环境( Miniconda),最新版
linux·运维·python