Ansible: YAML语法与 Playbook写法解析

发布于:2025-09-02 ⋅ 阅读:(22) ⋅ 点赞:(0)

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(冒号后必须加空格,否则语法报错)。

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

    name: svcrole
    svcservice: http
    svcport: 80
    
  • 内嵌块格式(单行紧凑写法,适合参数较少的场景):
    多个键值对用{}包裹,键值对之间用“逗号+空格”分隔,例如:

    - {name: svcrole, svcservice: http, svcport: 80}
    

2. 列表(数组)

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

  • 常规写法(多行展开,适合元素较多的场景):
    hosts:
      - server1
      - server2
    
  • 内嵌块格式(单行紧凑写法,适合元素较少的场景):
    多个元素用[]包裹,元素之间用“逗号+空格”分隔,例如:
    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安装对应集合,例如:

[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):

---
- 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:

[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):

---
- 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:

[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):

---
- 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:

[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)
---
- 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:

默认运行所有任务,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. 常用标签命令
# 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

网站公告

今日签到

点亮在社区的每一天
去签到