不求甚解--详解ansible-playbook中roles的用法(二)
2025-08-22 16:00:35,

前言

本文将继续介绍ansible-playbook中roles的各种用法

环境准备

组件 版本
操作系统 Ubuntu 22.04.4 LTS
ansible 2.17.6

基本用法

文件结构

.
├── deploy.hosts
├── deploy.yaml
└── roles
    └── base
        └── tasks
            └── main.yaml

定义全局公共变量

新增group_vars目录,并且新增文件

.
├── deploy.hosts
├── deploy.yaml
├── group_vars
│   └── all.yaml
└── roles
    └── base
        └── tasks
            └── main.yaml

▶ cat group_vars/all.yaml
info: IT paiqiu
▶ cat roles/base/tasks/main.yaml
- name: first
  debug:
    msg: "hello world {{ info }}"

运行:

▶ ansible-playbook -i deploy.hosts deploy.yaml

...
TASK [base : first] **********************************************************************************************
ok: [10.22.11.166] => {
    "msg": "hello world IT paiqiu"
}
...

定义role级变量

可以覆盖全局变量

在role base 下面新增vars目录,并且新增main.yaml文件

.
├── deploy.hosts
├── deploy.yaml
├── group_vars
│   └── all.yaml
└── roles
    └── base
        ├── tasks
        │   └── main.yaml
        └── vars
            └── main.yaml
▶ cat roles/base/tasks/main.yaml
- name: first
  debug:
    msg: "hello world {{ info }}"
▶ cat roles/base/vars/main.yaml
info:
  name: wilson
  addr: cd

运行:

▶ ansible-playbook -i deploy.hosts deploy.yaml

...
TASK [base : first] **********************************************************************************************
ok: [10.22.11.166] => {
    "msg": "hello world {'name': 'wilson', 'addr': 'cd'}"
}
...

定义静态文件目录

相当于定义role级别的根目录,更好的管理需要传输的文件,在role base下面创建目录files,并且在files下面放入需要传输的文件test.img

.
├── deploy.hosts
├── deploy.yaml
├── group_vars
│   └── all.yaml
└── roles
    └── base
        ├── files
        │   └── test.img
        ├── tasks
        │   └── main.yaml
        └── vars
            └── main.yaml

传输test.img至目标机器

.
├── deploy.hosts
├── deploy.yaml
├── group_vars
│   └── all.yaml
└── roles
    └── base
        └── tasks
            └── main.yaml

0

test.img默认回去roles/base/files当中寻找,所以前面不需要添加路径

C++opy模块会自动检查待传输文件的md5,如果没有变化,那就不会再传输了

定义模版

每次传输文件都会通过输入的变量重新渲染之后再传输,在role base下面创建目录templates,并且创建文件 test.conf

.
├── deploy.hosts
├── deploy.yaml
├── group_vars
│   └── all.yaml
└── roles
    └── base
        └── tasks
            └── main.yaml

1

在模版文件中定义了两个变量,一个是手动设置的变量version,一个是ansible内建变量inventory_hostname

.
├── deploy.hosts
├── deploy.yaml
├── group_vars
│   └── all.yaml
└── roles
    └── base
        └── tasks
            └── main.yaml

2
.
├── deploy.hosts
├── deploy.yaml
├── group_vars
│   └── all.yaml
└── roles
    └── base
        └── tasks
            └── main.yaml

3

运行:

.
├── deploy.hosts
├── deploy.yaml
├── group_vars
│   └── all.yaml
└── roles
    └── base
        └── tasks
            └── main.yaml

4

登录到目标机器查看:

.
├── deploy.hosts
├── deploy.yaml
├── group_vars
│   └── all.yaml
└── roles
    └── base
        └── tasks
            └── main.yaml

5

2是本次任务传入的变量,10.22.11.166则是目标机器的ip地址

定义事件驱动

通常用于某些任务完成之后需要触发的动作,比如:发布完某个配置文件之后需要重启服务。在role base下创建目录handlers,并创建文件main.yaml

.
├── deploy.hosts
├── deploy.yaml
├── group_vars
│   └── all.yaml
└── roles
    └── base
        └── tasks
            └── main.yaml

6

创建事件first handler

.
├── deploy.hosts
├── deploy.yaml
├── group_vars
│   └── all.yaml
└── roles
    └── base
        └── tasks
            └── main.yaml

7
.
├── deploy.hosts
├── deploy.yaml
├── group_vars
│   └── all.yaml
└── roles
    └── base
        └── tasks
            └── main.yaml

8

运行:

.
├── deploy.hosts
├── deploy.yaml
├── group_vars
│   └── all.yaml
└── roles
    └── base
        └── tasks
            └── main.yaml

9

同样的,如果事件前驱没有发生,那事件通知也不会发生了,比如事件前驱是传输一个文件,如果文件没有变化,就不会再传输,那事件也不会再发生了

新增更多的task任务

当前只有main.yaml,在增加一个专门用于传输文件的任务files.yaml

▶ cat group_vars/all.yaml
info: IT paiqiu
0
▶ cat group_vars/all.yaml
info: IT paiqiu
1

运行:

▶ cat group_vars/all.yaml
info: IT paiqiu
2

如果文件过多,可以通过循环来处理:

▶ cat group_vars/all.yaml
info: IT paiqiu
3

补充一下常用的命令

执行命令 shell

▶ cat group_vars/all.yaml
info: IT paiqiu
4

传输文件 copy

copy模块会自动检查待传输文件的md5,如果没有变化,那就不会再传输了

▶ cat group_vars/all.yaml
info: IT paiqiu
5

修改文件内容(一行) lineinfile

  • path: 指定要操作的文件路径(必填)
  • line: 定义要插入或替换的完整行内容(可选)
  • regexp: 用于匹配现有行的正则表达式。与 line 配合使用,匹配的行将被替换
  • state:
    • present(默认):确保指定行存在
    • absent:移除匹配的行
  • create: 如果文件不存在,是否创建文件(默认 yes)
  • insertafter: 指定插入行的位置(默认 EOF)
    • EOF:文件末尾
    • BOF:文件开头
    • 正则表达式:在匹配行之后插入
      insertbefore: 和 insertafter 类似,但在匹配行之前插入

通过正则匹配行之后修改当前行

▶ cat group_vars/all.yaml
info: IT paiqiu
6

修改文件内容(多行/块) blockinfile

  • path: 指定要操作的文件路径(必填)
  • block: 定义要插入的文本内容(必填)
  • marker: 指定标记块的开始和结束字符串,默认为 # {mark} ANSIBLE MANAGED BLOCK
  • state:
    • present(默认):确保块存在
    • absent:移除块
  • create: 如果文件不存在,是否创建文件(默认 yes)
  • insertafter: 指定插入块的位置(默认 EOF)
    • 可用值:
      • EOF:文件末尾
      • BOF:文件开头
      • 正则表达式:在匹配行之后插入
  • insertbefore: 和 insertafter 类似,但是在匹配行之前插入

1)在某一行下面增加新的内容,并且将增加的内容打上标记

▶ cat group_vars/all.yaml
info: IT paiqiu
7

运行之后查看结果

▶ cat group_vars/all.yaml
info: IT paiqiu
8

2)删除已标记的内容

▶ cat group_vars/all.yaml
info: IT paiqiu
9

添加内容块打上标记之后会让修改与删除都变得非常方便

使用模版

▶ cat roles/base/tasks/main.yaml
- name: first
  debug:
    msg: "hello world {{ info }}"
0

设置文件权限 file

▶ cat roles/base/tasks/main.yaml
- name: first
  debug:
    msg: "hello world {{ info }}"
1

使用循环 with_items

with_items

给多个目录修改权限

▶ cat roles/base/tasks/main.yaml
- name: first
  debug:
    msg: "hello world {{ info }}"
2

loop

当然使把with_items 替换成 loop也是可以的

▶ cat roles/base/tasks/main.yaml
- name: first
  debug:
    msg: "hello world {{ info }}"
2

嵌套循环 with_nested

输出每一种组合,相当于笛卡尔积

▶ cat roles/base/tasks/main.yaml
- name: first
  debug:
    msg: "hello world {{ info }}"
4

输出结果:

▶ cat roles/base/tasks/main.yaml
- name: first
  debug:
    msg: "hello world {{ info }}"
5

文件内容循环 with_file

逐行打印文件内容

▶ cat roles/base/tasks/main.yaml
- name: first
  debug:
    msg: "hello world {{ info }}"
6

幂等性

使用roles去管理多设备的时候,编写脚本需要时刻注意幂等性,即每一次执行都要保证同样的结果

联系我

联系我,做深入的交流

至此,本文结束
在下才疏学浅,有撒汤漏水的,请各位不吝赐教...