ansible中的剧本(Playbook)详解之初识剧本、变量使用、循环

概述

剧本(Playbook)是Ansible的配置管理、部署编排语言,使用YAML格式编写,通过一组有序的任务描述,实现对批量主机的自动化操作。

核心作用:将零散的 ad-hoc 命令固化为可复用、顺序执行、带变量 / 判断 / 循环的自动化脚本,实现批量服务器配置、部署、运维。

核心优势:

  • 声明式语法:描述"目标状态"而非执行步骤
  • 幂等性:多次执行结果一致,不会重复操作
  • 可读性强:YAML格式易于理解和维护
  • 可复用性:支持角色、变量、模板等复用机制

一个简单的Playbook如下:

- hosts: 指定分组
-- 指定任务
  tasks:
    - name: 任务一,模块一
      模块名:
          选项一:
          选项二:

执行Playbook命令:ansible-playbook [选项参数] 剧本文件
选项参数说明:

  • -i:指定主机文件
  • -C:测试执行
  • -t:指定tag执行
  • --syntax-check:检查playbook语法,不连接远程机器、不执行任务
  • --step:每一步手动确认再执行
  • -f:并发执行主机数量,默认是5
  • --user:指定远程用户,例如--user root
  • --skip-tags:指定tag执行
  • --list-hosts:列出匹配的主机,不执行任务

第一个ansible playbook

编写playbook

root@master:/data00/ansible# cat playbook-elephant.yaml
# hosts指定所有的主机
- hosts: all
# tasks指定任务模块
  tasks:
  - name: 【task1】打开冰箱
    shell:
      cmd: echo 打开冰箱
  - name: 【task2】大象放进冰箱
    shell:
      cmd: echo 大象放进冰箱
  - name: 【task3】关闭冰箱
    shell:
      cmd: echo 关闭冰箱

测试执行

root@master:/data00/ansible# ansible-playbook -C playbook-elephant.yaml 

PLAY [all] *******************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************************************************
ok: [10.37.120.9]
ok: [10.37.99.63]

TASK [【task1】打开冰箱] *****************************************************************************************************************************************************************************************
skipping: [10.37.120.9]
skipping: [10.37.99.63]

TASK [【task2】大象放进冰箱] *************************************************************************************************************************************************************************************
skipping: [10.37.120.9]
skipping: [10.37.99.63]

TASK [【task3】关闭冰箱] *****************************************************************************************************************************************************************************************
skipping: [10.37.120.9]
skipping: [10.37.99.63]

PLAY RECAP *******************************************************************************************************************************************************************************************************
10.37.120.9                : ok=1    changed=0    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0   
10.37.99.63                : ok=1    changed=0    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0   

实际执行

root@master:/data00/ansible# ansible-playbook playbook-elephant.yaml 

PLAY [all] *******************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************************************************
ok: [10.37.120.9]
ok: [10.37.99.63]

TASK [【task1】打开冰箱] *****************************************************************************************************************************************************************************************
changed: [10.37.120.9]
changed: [10.37.99.63]

TASK [【task2】大象放进冰箱] *************************************************************************************************************************************************************************************
changed: [10.37.120.9]
changed: [10.37.99.63]

TASK [【task3】关闭冰箱] *****************************************************************************************************************************************************************************************
changed: [10.37.120.9]
changed: [10.37.99.63]

PLAY RECAP *******************************************************************************************************************************************************************************************************
10.37.120.9                : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
10.37.99.63                : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

ansible playbook中的变量

ansible中的变量有多种类型,根据定义位置的不同,其分类主要为:

  • 剧本文件中定义变量:比较常用,仅限于当前的play使用
  • 变量文件,根据主机清单分组进行定义变量:如果多个剧本,使用相同的变量
  • register变量,注册变量:实现shell脚本中的反引号功能,可以获取命令结果
  • inventory主机清单中定义变量:未来可以用于批量修改主机使用,其它很少用了
  • 命令行中:几乎不用
  • facts变量:一般用于获取主机基本信息:ip,主机名,系统,如果不需要可以关闭,用于加速剧本的执行

变量命名规则:

  • 与shell类似,不能以数字开头
  • 变量中仅包含_下划线即可,不要包含其它的特殊字符

读取变量使用{{ 变量名 }}

playbook文件中定义变量

playbook文件中直接定义变量,只对当前的playbook生效,使用vars关键字定义,下级直接定义key value的形式。

root@master:/data00/ansible# cat playbook_vars.yaml 
- name: 部署nginx
  hosts: web
  # 定义变量
  vars:
  # 格式:变量名: 变量值
    nginx_version: 1.24
    listen_port: 80
    info:
      author: admin
      env: test
  tasks:
    - debug: msg="版本 {{ listen_port }}"
    - debug: msg="端口 {{ listen_port }}"
    - debug: msg="作者 {{ info.author }}"
    - debug: msg="环境 {{ info.env }}"

测试执行

root@master:/data00/ansible# ansible-playbook -C playbook_vars.yaml 

PLAY [部署nginx] *************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************************************************
ok: [10.37.120.9]
ok: [10.37.99.63]

TASK [debug] *****************************************************************************************************************************************************************************************************
ok: [10.37.99.63] => {
    "msg": "版本 80"
}
ok: [10.37.120.9] => {
    "msg": "版本 80"
}

TASK [debug] *****************************************************************************************************************************************************************************************************
ok: [10.37.99.63] => {
    "msg": "端口 80"
}
ok: [10.37.120.9] => {
    "msg": "端口 80"
}

TASK [debug] *****************************************************************************************************************************************************************************************************
ok: [10.37.99.63] => {
    "msg": "作者 admin"
}
ok: [10.37.120.9] => {
    "msg": "作者 admin"
}

TASK [debug] *****************************************************************************************************************************************************************************************************
ok: [10.37.99.63] => {
    "msg": "环境 test"
}
ok: [10.37.120.9] => {
    "msg": "环境 test"
}

PLAY RECAP *******************************************************************************************************************************************************************************************************
10.37.120.9                : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
10.37.99.63                : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

使用变量文件定义

将变量写入到一个yaml文件中,然后在playbook中使用vars_files指定变量文件饮用。vars_files可以引入多个。

示例:

  • 定义变量文件
root@master:/data00/ansible# cat vars_nginx.yaml 
info:
  author: huangsir
  env: test
  
root@master:/data00/ansible# cat vars_nginx_info.yaml 
nginx_version: 1.24
listen_port: 80
  • playbook文件
root@master:/data00/ansible# cat playbook_vars_files.yaml 
- name: 部署nginx
  hosts: web
  # 引入变量文件
  vars_files:
    - ./vars_nginx.yaml
    - /data00/ansible/vars_nginx_info.yaml
  tasks:
    - debug: msg="版本 {{ listen_port }}"
    - debug: msg="端口 {{ listen_port }}"
    - debug: msg="作者 {{ info.author }}"
    - debug: msg="环境 {{ info.env }}"
  • 测试执行
root@master:/data00/ansible# ansible-playbook -C playbook_vars_files.yaml 

PLAY [部署nginx] **************************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************************
ok: [10.37.120.9]
ok: [10.37.99.63]

TASK [debug] ******************************************************************************************************************************************************
ok: [10.37.99.63] => {
    "msg": "版本 80"
}
ok: [10.37.120.9] => {
    "msg": "版本 80"
}

TASK [debug] ******************************************************************************************************************************************************
ok: [10.37.99.63] => {
    "msg": "端口 80"
}
ok: [10.37.120.9] => {
    "msg": "端口 80"
}

TASK [debug] ******************************************************************************************************************************************************
ok: [10.37.99.63] => {
    "msg": "作者 huangsir"
}
ok: [10.37.120.9] => {
    "msg": "作者 huangsir"
}

TASK [debug] ******************************************************************************************************************************************************
ok: [10.37.99.63] => {
    "msg": "环境 test"
}
ok: [10.37.120.9] => {
    "msg": "环境 test"
}

PLAY RECAP ********************************************************************************************************************************************************
10.37.120.9                : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
10.37.99.63                : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

主机组变量文件,根据主机组使用变量

在剧本的当前路径下定义目录,/group_vars/组名/vars.yaml

示例:

  • 创建变量文件
# 主机组es的变量文件
root@master:/data00/ansible/group# cat group_vars/es/vars.yaml 
paas_name: es
paas_port: 9200
# 主机组db的变量文件
root@master:/data00/ansible/group# cat group_vars/db/vars.yaml 
paas_name: db
paas_port: 3306
# 所有主机的变量文件
root@master:/data00/ansible/group# cat group_vars/all/vars.yaml
version: 1.1
  • 编写playbook文件
root@master:/data00/ansible/group# cat group_vars.yaml 
- name: es
  hosts: es
  tasks:
    - debug: msg="版本 {{ version }}"
    - debug: msg="name {{ paas_name }}"
    - debug: msg="port {{ paas_port }}"

- name: db
  hosts: db
  tasks:
    - debug: msg="版本 {{ version }}"
    - debug: msg="name {{ paas_name }}"
    - debug: msg="port {{ paas_port }}"
  • 整体的目录结构
root@master:/data00/ansible/group# tree
.
├── group_vars
│   ├── all
│   │   └── vars.yaml
│   ├── db
│   │   └── vars.yaml
│   └── es
│       └── vars.yaml
└── group_vars.yaml
  • 测试执行

能够发现执行时获取到的变量不一致。

root@master:/data00/ansible/group# ansible-playbook -C group_vars.yaml 

PLAY [es] ********************************************************************************************************************************************************************************************************

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

TASK [debug] *****************************************************************************************************************************************************************************************************
ok: [10.37.120.9] => {
    "msg": "版本 1.1"
}

TASK [debug] *****************************************************************************************************************************************************************************************************
ok: [10.37.120.9] => {
    "msg": "name es"
}

TASK [debug] *****************************************************************************************************************************************************************************************************
ok: [10.37.120.9] => {
    "msg": "port 9200"
}

PLAY [db] ********************************************************************************************************************************************************************************************************

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

TASK [debug] *****************************************************************************************************************************************************************************************************
ok: [10.37.99.63] => {
    "msg": "版本 1.1"
}

TASK [debug] *****************************************************************************************************************************************************************************************************
ok: [10.37.99.63] => {
    "msg": "name db"
}

TASK [debug] *****************************************************************************************************************************************************************************************************
ok: [10.37.99.63] => {
    "msg": "port 3306"
}

PLAY RECAP *******************************************************************************************************************************************************************************************************
10.37.120.9                : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
10.37.99.63                : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

register变量

register变量本质上就是执行shell,将shell的结果保存到变量中,然后在后续的play中进行使用

示例:

  • 变量变量文件
root@master:/data00/ansible# cat playbook_register.yaml 
- name: register使用
  hosts: es
  tasks:
    - name: 【注册变量值】
      shell:
        cmd: hostname -I
      # 将上面shell命令获取到的值放到ip变量中,后续的task可以进行使用
      register: ip

    - name: 【打印变量】
      debug:
        msg: "{{ ip }}"
  • 测试执行
root@master:/data00/ansible# ansible-playbook playbook_register.yaml 

PLAY [register使用] **********************************************************************************************************************************************************************************************

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

TASK [【注册变量值】] ********************************************************************************************************************************************************************************************
changed: [10.37.120.9]

TASK [【打印变量】] **********************************************************************************************************************************************************************************************
ok: [10.37.120.9] => {
    "msg": {
        "changed": true,
        "cmd": "hostname -I",
        "delta": "0:00:00.002309",
        "end": "2026-07-13 14:25:06.274953",
        "failed": false,
        "msg": "",
        "rc": 0,
        "start": "2026-07-13 14:25:06.272644",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "10.37.120.9 172.17.0.1 100.95.185.192 fdbd:dc01:ff:324:7f74:8dda:726c:4312 ",
        "stdout_lines": [
            "10.37.120.9 172.17.0.1 100.95.185.192 fdbd:dc01:ff:324:7f74:8dda:726c:4312 "
        ]
    }
}

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

facts变量

facts变量相当于ansible中的内置变量,存放被管理机器的基本信息。运行脚本的时候会运行:Gathering Facts task任务,Gathering Facts:ansible收集被管理端基本信息,cpu,内存,磁盘,网络,系统。我们在剧本中使用facts变量,未来如果不用可以关闭gather facts功能,加速剧本运行效果facts变量是setup模块获取的

使用facts变量时playbook文件中需要指定gather_facts: true,如果不需要facts变量时,可以指定gather_facts: false,这样剧本执行会更快

示例:

  • 编写playbook文件
root@master:/data00/ansible# cat playbook_facts.yaml 
- hosts: es
  gather_facts: true
  tasks:
    - name: facts变量输出到屏幕上
      debug:
        msg: |
          "主机名:{{ ansible_facts.hostname }}"
          "ip:{{ ansible_facts.all_ipv4_addresses }}"
          "系统名称:{{ ansible_facts.distribution }}"
          "系统总内存:{{ ansible_facts.memtotal_mb }}"
          "系统可用内存:{{ ansible_facts.memfree_mb }}"
          "系统内存情况:{{ ansible_facts.memory_mb }}"
          "cpu总数:{{ ansible_facts.processor_vcpus }}"
  • 测试执行
root@master:/data00/ansible# ansible-playbook playbook_facts.yaml 

PLAY [es] ********************************************************************************************************************************************************************************************************

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

TASK [facts变量输出到屏幕上] *************************************************************************************************************************************************************************************
ok: [10.37.120.9] => {
    "msg": "\"主机名:node02\"\n\"ip:['10.96.0.10', '10.96.3.191', '10.96.3.164', '10.96.1.170', '10.96.0.1', '172.17.0.1', '100.95.185.192', '10.37.120.9']\"\n\"系统名称:Debian\"\n\"系统总内存:253453\"\n\"系统可用内存:192768\"\n\"系统内存情况:{'real': {'total': 253453, 'used': 60685, 'free': 192768}, 'nocache': {'free': 216556, 'used': 36897}, 'swap': {'total': 0, 'free': 0, 'used': 0, 'cached': 0}}\"\n\"cpu总数:64\"\n"
}

PLAY RECAP *******************************************************************************************************************************************************************************************************
10.37.120.9                : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

ansible中常用的facts变量

ansible_all_ipv4_addresses:                        仅显示ipv4的信息。
ansible_devices:                        仅显示磁盘设备信息。
ansible_distribution:                        显示是什么系统,例:centos,suse等。
ansible_distribution_major_version:                        显示是系统主版本。
ansible_distribution_version:                        仅显示系统版本。
ansible_machine:                        显示系统类型,例:32位,还是64位。
ansible_eth0:                            仅显示eth0的信息。
ansible_hostname:                        仅显示主机名。
ansible_kernel:                            仅显示内核版本。
ansible_lvm:                            显示lvm相关信息。
ansible_memtotal_mb:                        显示系统总内存。
ansible_memfree_mb:                        显示可用系统内存。
ansible_memory_mb:                        详细显示内存情况。
ansible_swaptotal_mb:                        显示总的swap内存。
ansible_swapfree_mb:                        显示swap内存的可用内存。
ansible_mounts:                        显示系统磁盘挂载情况。
ansible_processor:                        显示cpu个数(具体显示每个cpu的型号)。
ansible_processor_vcpus:                    显示cpu个数(只显示总的个数)。

ansible-playbook中的循环

playbook中的循环一般用于批量开启服务,重启服务,创建文件、目录、添加用户等使用场景中。

playbook中新版本循环语法使用loop。这里也使用loop讲解。

简单列表的循环

使用loop定义需要遍历的元素,然后取元素时默认使用固定变量item。

示例:

# 编写playbook文件
root@master:/data00/ansible# cat loop.yaml 
- name: loop的使用
  hosts: db
  tasks:
    - name: loop的使用
      debug:
        msg: |
         "名称:{{ item }}"
      loop:
        - nginx
        - mysql
        - redis

## 测试执行
root@master:/data00/ansible# ansible-playbook loop.yaml 

PLAY [loop的使用] ************************************************************************************************************************************************************************************************

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

TASK [loop的使用] ************************************************************************************************************************************************************************************************
ok: [10.37.99.63] => (item=nginx) => {
    "msg": "\"名称:nginx\"\n"
}
ok: [10.37.99.63] => (item=mysql) => {
    "msg": "\"名称:mysql\"\n"
}
ok: [10.37.99.63] => (item=redis) => {
    "msg": "\"名称:redis\"\n"
}

循环字典数组

示例:

  • 编写play_book文件
root@master:/data00/ansible# cat loop_map.yaml 
- name: loop循环字典
  hosts: es
  tasks:
    - name: 创建多个用户
      debug:
        msg: |
         "name: {{ item.name }}"
         "uid: {{ item.uid }}"
      loop:
        - { name: "zhangsan", uid: 1001 }
        - { name: "lisi", uid: 1002 }
  • 测试执行
root@master:/data00/ansible# ansible-playbook loop_map.yaml 

PLAY [loop循环字典] **********************************************************************************************************************************************************************************************

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

TASK [创建多个用户] **********************************************************************************************************************************************************************************************
ok: [10.37.120.9] => (item={'name': 'zhangsan', 'uid': 1001}) => {
    "msg": "\"name: zhangsan\"\n\"uid: 1001\"\n"
}
ok: [10.37.120.9] => (item={'name': 'lisi', 'uid': 1002}) => {
    "msg": "\"name: lisi\"\n\"uid: 1002\"\n"
}

PLAY RECAP *******************************************************************************************************************************************************************************************************
10.37.120.9                : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

循环中输出循环下标

如果在循环中输出循环下标的话,需要使用loop_control模块

示例:

root@master:/data00/ansible# cat playbook_loopindex.yaml
- name: loop_index使用
  hosts: es
  tasks:
    - name: loop_index使用
      debug:
        msg: "序号: {{ idx }} 内容: {{ item }}"
      loop: [a, b, c, d]
      #定义循环控制,可以控制输出循环下标,变量的变量名等等
      loop_control:
        index_var: idx

测试执行:

root@master:/data00/ansible# ansible-playbook playbook_loopindex.yaml 

PLAY [loop_index使用] ********************************************************************************************************************************************************************************************

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

TASK [loop_index使用] ********************************************************************************************************************************************************************************************
ok: [10.37.120.9] => (item=a) => {
    "msg": "序号: 0 内容: a"
}
ok: [10.37.120.9] => (item=b) => {
    "msg": "序号: 1 内容: b"
}
ok: [10.37.120.9] => (item=c) => {
    "msg": "序号: 2 内容: c"
}
ok: [10.37.120.9] => (item=d) => {
    "msg": "序号: 3 内容: d"
}

PLAY RECAP *******************************************************************************************************************************************************************************************************
10.37.120.9                : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

循环中修改循环变量名,不用默认 item

示例:

- debug:
    msg: "{{ user.name }} -- {{ user.uid }}"
  loop:
    - { name: tom, uid: 2001 }
    - { name: jack, uid: 2002 }
  loop_control:
    # 定义变量名
    loop_var: user

循环延迟(每次循环间隔几秒)

示例:

- debug:
    msg: "{{ user.name }} -- {{ user.uid }}"
  loop:
    - { name: tom, uid: 2001 }
    - { name: jack, uid: 2002 }
  loop_control:
    loop_var: user
    # 单位秒
    pause: 1
posted @ 2026-07-13 15:46  huangSir-devops  阅读(3)  评论(0)    收藏  举报
作者:你的名字
出处:你的博客链接
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。