Ansible: YAML语法与 Playbook写法解析

Ansible: YAML语法与 Playbook写法解析

Ansible Playbook采用YAML语法编写,通过简洁的格式实现JSON风格的事件描述,是实现自动化运维的核心载体。在学习Playbook前,需先掌握YAML的基础语法与引用规则,再结合Playbook的结构与功能完成自动化配置。以下将按原内容逻辑,系统梳理YAML语法、Playbook组成、使用方法及实战示例。

一、YAML语法初步说明

在这里插入图片描述

  1. 文件标识

    YAML文件可通过---开头声明文件类型。即使省略---,Ansible也能正常解析Playbook,但建议添加以保证规范性。

  2. 注释规则

    使用#作为注释符,支持两种注释方式:

    • 整行注释:# 这是一条整行注释,描述后续任务功能
    • 行内注释:name: install httpd # 行内注释:安装Apache服务
      注释内容仅用于阅读,不会被Ansible执行。
  3. 字符串处理

    YAML中字符串默认无需添加引号,即便包含空格、特殊符号(如-/)也可直接书写。但引用变量时必须加引号,避免变量解析异常。

  4. 布尔值格式

    Playbook中布尔值(true/false)的解析分两种场景,需按规则区分使用:

    • 模块参数 :布尔值作为字符串被Ansible解析,支持yes/on/1/true/no/off/0/false,例如yum模块的update_cache: yes
    • 非模块参数 :布尔值由YAML解释器解析,遵循YAML原生语法,支持不区分大小写的true/yes/on/y/false/no/off/n,例如仓库配置的gpgcheck: noenabled: True

二、Playbook的核心内容

每个Playbook由一个或多个"Play"组成,每个Play必须包含hosts(目标主机)和tasks(任务列表),是Playbook的执行核心:

  • hosts :定义Inventory中待控制的主机/主机组(如node1web_servers),指定任务的执行范围。
  • tasks :定义一系列任务列表,每个任务调用Ansible模块(如yumfile)实现具体操作。
    任务执行顺序:按列表顺序依次执行,所有被筛选的主机完成当前任务后,才会统一执行下一个任务

需注意:hosts指定的所有主机都会收到任务指令,但Ansible主控端会根据筛选规则(如主机组、变量条件)决定哪些主机实际执行任务,未被筛选的主机仅接收指令不执行操作。

三、YAML核心数据结构

YAML通过"字典"和"列表"两种数据结构描述信息,是Playbook配置的基础,所有任务、参数均基于这两种结构组合。

1. 字典(键值对)

字典又称散列、关联数组,用于描述"属性-值"对应关系,格式为key: value(冒号后必须加空格,否则语法报错)。

  • 常规写法(多行展开,适合参数较多的场景,易读性强):

    yaml 复制代码
    name: svcrole
    svcservice: http
    svcport: 80
  • 内嵌块格式 (单行紧凑写法,适合参数较少的场景):

    多个键值对用{}包裹,键值对之间用"逗号+空格"分隔,例如:

    yaml 复制代码
    - {name: svcrole, svcservice: http, svcport: 80}

2. 列表(数组)

列表用于描述一组同类元素,格式为每个元素前加"短横线+空格"(- ),表示元素的并列关系。

  • 常规写法 (多行展开,适合元素较多的场景):

    yaml 复制代码
    hosts:
      - server1
      - server2
  • 内嵌块格式 (单行紧凑写法,适合元素较少的场景):
    多个元素用[]包裹,元素之间用"逗号+空格"分隔,例如:

    yaml 复制代码
    hosts: [server1, server2]

四、Playbook的使用方法

1. 基础执行命令

  • 运行Playbookansible-playbook 剧本文件名.yml,例如ansible-playbook cy.yml
  • 测试执行ansible-playbook -C 剧本文件名.yml-C(Dry Run)表示模拟执行,仅输出执行结果预览,不实际修改目标主机配置,用于验证剧本语法与逻辑。

2. 依赖集合安装

若Playbook需使用特定模块(如community.general中的模块),需先通过ansible-galaxy安装对应集合,例如:

bash 复制代码
[student@master ansible]$ ansible-galaxy collection install http://ansible.example.com/materials/ansible-posix-1.5.1.tar.gz -p collections/
[student@master ansible]$ ansible-galaxy collection install http://ansible.example.com/materials/community-general-6.3.0.tar.gz -p collections/

-p collections/指定集合安装路径,避免与系统默认集合冲突。

五、Playbook实战示例

示例1:部署Web服务(node1主机)

需求:在node1上安装httpd、配置开机自启、创建软链接、下载首页文件、配置防火墙,确保Web服务可访问。

剧本文件(zhang3.yml):

yaml 复制代码
---
- name: http   
  hosts: node1
  tasks:
    - name: repo1         # 配置BaseOS仓库
      yum_repository:
        name: aa
        description: aa1
        baseurl: http://ansible.example.com/rhel9/BaseOS
        enabled: yes
        gpgcheck: yes
        gpgkey: http://ansible.example.com/rhel9/RPM-GPG-KEY-redhat-release
    - name: repo2       # 配置AppStream仓库
      yum_repository:
        name: cc
        description: cc1
        baseurl: http://ansible.example.com/rhel9/AppStream
        enabled: yes
        gpgcheck: yes
        gpgkey: http://ansible.example.com/rhel9/RPM-GPG-KEY-redhat-release
    - name: install httpd       # 安装httpd
      yum:
        name: httpd
        state: installed
    - name: html              # 创建测试网页文件
      shell:
        echo hello world > /var/www/html/index.html
    - name: restart httpd         # 重启httpd并设置开机自启
      service:
        name: httpd
        state: restarted
        enabled: yes    
    - name: link               # 创建/var/www/html到/www的软链接
      file:
        src: /var/www/html
        dest: /www
        state: link
    - name: get http          # 下载首页文件到/www目录
      get_url:
        url: http://node1.example.com/index.html
        dest: /www/
        setype: httpd_sys_content_t
    - name: firewall for http       # 配置防火墙允许HTTP服务
      firewalld:
        service: http
        state: enabled
        permanent: yes
        immediate: yes

运行playbook:

bash 复制代码
[student@master ansible]$ ansible-playbook zhang3.yml 

PLAY [http] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [node1]

TASK [repo1] ************************************************************************
ok: [node1]

TASK [repo2] ************************************************************************
ok: [node1]

TASK [install httpd] ****************************************************************
ok: [node1]

TASK [html] *************************************************************************
changed: [node1]

TASK [restart httpd] ****************************************************************
changed: [node1]

TASK [link] *************************************************************************
ok: [node1]

TASK [get http] *********************************************************************
ok: [node1]

TASK [firewall for http] ************************************************************
changed: [node1]

PLAY RECAP **************************************************************************
node1                      : ok=9    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

示例2:notify与handlers用法(任务触发机制)

需求:创建用户user2后,自动触发任务创建/tmp/cy1文件(实现"完成A任务则执行B任务"的逻辑)。

剧本文件(test.yml):

yaml 复制代码
---
- name: this is a test playbook
  hosts: node1
  tasks: 
    - name: create user1    # 创建用户user1(无触发操作)
      user:
        name: user1
        state: present
    - name: create user2     # 创建用户user2(触发handlers)
      user: 
        name: user2
        state: present
      notify:  # 任务执行后,触发名为"file3"的handlers
        - file3
  handlers:          # 定义handlers(仅被notify触发时执行)
    - name: file3
      file: 
        path: /tmp/cy1
        state: touch
        mode: 0644  # 设置文件权限:所有者读写,其他读

运行playbook:

bash 复制代码
[student@master ansible]$ ansible-playbook test.yml 

PLAY [test] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [node1]

TASK [create user1] *****************************************************************
ok: [node1]

TASK [create user2] *****************************************************************
ok: [node1]

PLAY RECAP **************************************************************************
node1                      : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

handlers特性:无论被notify调用多少次,仅在当前Play的所有任务执行完毕后运行一次,避免重复操作。

示例3:用户管理与时间记录(galaxy.yml)

需求:仅在node1执行,实现创建禁止登录的用户、记录系统时间、时间变化时创建文件。

剧本文件(galaxy.yml):

yaml 复制代码
---
- name: time
  hosts: node1
  tasks: 
    - name: create user  # 创建用户aa(禁止登录,家目录/www)
      user: 
        name: aa
        shell: /sbin/nologin  # 禁止用户登录系统
        home: /www  # 指定用户家目录
    - name: create file       # 在/www目录创建空文件html
      file: 
        path: /www/html
        state: touch  # 创建空文件

    - name: date  # 将系统当前时间写入/www/html,时间变化时触发handlers
      shell: date > /www/html  # 执行date命令,将时间写入文件
      notify: 
        - kk  # 触发名为"kk"的handlers

  handlers:     # 定义handlers:时间变化时创建/tmp/kk
    - name: kk
      file: 
        path: /tmp/kk
        state: touch

运行playbook:

bash 复制代码
[student@master ansible]$ ansible-playbook test.yml 

PLAY [test] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [node1]

TASK [create user1] *****************************************************************
ok: [node1]

TASK [create user2] *****************************************************************
ok: [node1]

PLAY RECAP **************************************************************************
node1                      : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[student@master ansible]$ vim galaxy.yml
[student@master ansible]$ ansible-playbook galaxy.yml 

PLAY [time] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [node1]

TASK [create user] ******************************************************************
changed: [node1]

TASK [create file] ******************************************************************
changed: [node1]

TASK [date] *************************************************************************
changed: [node1]

RUNNING HANDLER [kk] ****************************************************************
changed: [node1]

PLAY RECAP **************************************************************************
node1                      : ok=5    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

示例4:tags用法(任务标签控制)

需求:给任务打标签,实现"指定执行部分任务"的功能,支持多标签、特殊标签。

1. 标签基础规则
  • 一个任务可添加多个标签,用列表形式书写。

  • Ansible预置5个特殊标签,无需手动定义,直接使用:

    特殊标签 功能说明
    always 无论是否指定其他标签,该任务必执行
    never 默认不执行,仅显式指定-t never时才执行
    tagged ansible-playbook -t tagged 剧本.yml:仅执行带标签的任务(排除never
    untagged ansible-playbook -t untagged 剧本.yml:仅执行不带标签的任务(含always
    all 执行所有任务,为默认行为,无需显式指定
  • 多标签使用:执行多个标签的任务时,标签之间用"逗号+空格"分隔,例如ansible-playbook --tags l1,l2 剧本.yml

2. 实战剧本(test2.yml)
yaml 复制代码
---
- name: test playbook
  hosts: node1
  tasks: 
    - name: create user3   # 创建user3,标签l1、l2
      user: 
        name: user3
        state: present
      tags: 
        - l1
        - l2 
    - name: create user4   # 创建user4,标签l2、l3
      user:
        name: user4
        state: present
      tags: 
        - l2
        - l3
    - name: create user5    # 创建user5,标签l3、l4
      user: 
        name: user5
        state: present
      tags: 
        - l3
        - l4
    - name: create user6  # 创建user6,标签always(必执行)
      user: 
        name: user6
        state: present
      tags: 
        - always
    - name: create user7  # 创建user6,标签never(默认不执行)
      user: 
        name: user7
        state: present
      tags: 
        - never

运行playbook:

bash 复制代码
默认运行所有任务,never标签(create user7)默认不运行
[student@master ansible]$ ansible-playbook test2.yml 

PLAY [test playbook] ****************************************************************

TASK [Gathering Facts] **************************************************************
ok: [node1]

TASK [create user3] *****************************************************************
ok: [node1]

TASK [create user4] *****************************************************************
ok: [node1]

TASK [create user5] *****************************************************************
ok: [node1]

TASK [create user6] *****************************************************************
ok: [node1]

PLAY RECAP **************************************************************************
node1                      : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
3. 常用标签命令
bash 复制代码
# 1. 仅执行标签为l2的任务(create user3、create user4、record log)
[student@master ansible]$ ansible-playbook test2.yml -t l2

# 2. 跳过标签为l1的任务,执行其他任务(排除never)
[student@master ansible]$ ansible-playbook --skip-tags l1 test2.yml

# 3. 仅执行带标签的任务(排除never)
[student@master ansible]$ ansible-playbook --tags tagged test2.yml

# 4.仅执行带never标签的任务
[student@master ansible]$ ansible-playbook test2.yml -t never

# 5. 查看剧本中所有标签
[student@master ansible]$ ansible-playbook --list-tags test2.yml
相关推荐
Nobody__111 分钟前
解决多台服务器 UID/GID 做对齐后,文件系统元数据未更新的情况
运维·服务器
兆龙电子单片机设计34 分钟前
【STM32项目开源】STM32单片机智能语音家居控制系统
stm32·单片机·嵌入式硬件·物联网·开源·自动化
珂玥c41 分钟前
windows系统nfs挂载
运维·windows·ssh·remmina·cygwin
菜择贰43 分钟前
在linux(wayland)中禁用键盘
linux·运维·chrome
梦想的旅途21 小时前
基于 UI 自动化(RPA)实现企业微信外部群操作的架构设计
ui·自动化·rpa
oMcLin1 小时前
如何在 Manjaro Linux 上通过配置systemd服务管理,提升微服务架构的启动速度与资源效率
linux·微服务·架构
Kira Skyler1 小时前
bpftool -S 签名功能实现解析
linux
霸气十足+拼命+追梦少年1 小时前
服务器挂载U盘或硬盘
运维·服务器
慕容雪_1 小时前
运维笔记-笔记本无线网卡连接wifi,有线网卡连接内网
运维·内网·远程
小杰帅气1 小时前
进程优先级与切换调度
linux·运维·服务器