Ansible-角色(roles)
角色(roles) 介绍
角色(roles)是ansible自1.2版本开始引入的新特性,用于层次性,结构化地组织playbook。
roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单的说,roles就是通过分别将变量、文件、任务、模块及处理器放置于单独的目录中、并可以便捷地include他们的一种机制。角色一般用于基于主机构建服务的场景中、但也可以是用于构建守护进程等场景中。
利用系统角色重用内容
红帽企业Linux系统角色
自RHEL7.4开始,操作系统随附了多个Ansible角色,作为rhel-system-roles软件包的一部分。在RHEL8中,该软件包可以从AppStream中获取。以下是每个角色的简要描述:
RHEL系统角色
名称 | 状态 | 角色描述 |
---|---|---|
rhel-system-roles.kdump | 全面支持 | 配置kdump崩溃恢复服务 |
rhel-system-roles.network | 全面支持 | 配置网络接口 |
rhel-system-roles.selinux | 全面支持 | 配置和管理SELinux自定义, 包括SELinux模式、文件和端口上下文、 布尔值设置以及SELinux用户 |
rhel-system-roles.timesync | 全面支持 | 使用网络时间协议或精确时间协议配置时间同步 |
rhel-system-roles.postfix | 技术预览 | 使用Postfix服务将每个主机配置为邮件传输代理 |
rhel-system-roles.firewall | 开发中 | 配置主机的防火墙 |
rhel-system-roles.tuned | 开发中 | 配置tuned服务,以调优系统性能 |
系统角色的目的是在多个版本之间标准化红帽企业Linux子系统的配置。使用系统角色来配置版本6.10及以上的任何红帽企业Linux主机。
安装RHEL系统角色
RHEL系统角色由rhel-system-roles软件包提供,该软件包可从AppStream流获取。在Ansible控制节点上安装该软件包。
安装RHEL系统角色
[root@ansible ~]# yum -y install rhel-system-roles
安装后,RHEL系统角色位于/usr/share/ansible/roles目录中:
[root@ansible ~]# ls /usr/share/ansible/roles/
linux-system-roles.certificate rhel-system-roles.certificate
linux-system-roles.kdump rhel-system-roles.kdump
linux-system-roles.kernel_settings rhel-system-roles.kernel_settings
linux-system-roles.logging rhel-system-roles.logging
linux-system-roles.metrics rhel-system-roles.metrics
linux-system-roles.nbde_client rhel-system-roles.nbde_client
linux-system-roles.nbde_server rhel-system-roles.nbde_server
linux-system-roles.network rhel-system-roles.network
linux-system-roles.postfix rhel-system-roles.postfix
linux-system-roles.selinux rhel-system-roles.selinux
linux-system-roles.storage rhel-system-roles.storage
linux-system-roles.timesync rhel-system-roles.timesync
linux-system-roles.tlog rhel-system-roles.tlog
红帽企业Linux中的默认roles_path在路径中包含/usr/share/ansible/roles,因此在playbook引用这些角色时Ansible可以很轻松的找到它们。
注意: 如果在当前Ansible配置文件中覆盖了roles_path,设置了环境变量ANSIBLE_ROLES_PATH,或者roles_path中更早列出的目录下存在另一个同名的角色,则Ansible可能无法找到系统角色。
访问RHEL系统角色的文档
安装后,RHEL系统角色的文档位于/usr/share/doc/rhel-system-roles-/目录中。文档按照子系统整理到子目录中:
[root@ansible ~]# ll /usr/share/doc/rhel-system-roles/
total 4
drwxr-xr-x. 2 root root 57 Feb 24 03:19 certificate
drwxr-xr-x. 2 root root 57 Feb 24 03:19 kdump
drwxr-xr-x. 2 root root 72 Feb 24 03:19 kernel_settings
drwxr-xr-x. 2 root root 72 Feb 24 03:19 logging
drwxr-xr-x. 2 root root 57 Feb 24 03:19 metrics
drwxr-xr-x. 2 root root 57 Feb 24 03:19 nbde_client
drwxr-xr-x. 2 root root 57 Feb 24 03:19 nbde_server
drwxr-xr-x. 2 root root 4096 Feb 24 03:19 network
drwxr-xr-x. 2 root root 57 Feb 24 03:19 postfix
drwxr-xr-x. 2 root root 93 Feb 24 03:19 selinux
drwxr-xr-x. 2 root root 57 Feb 24 03:19 storage
drwxr-xr-x. 2 root root 136 Feb 24 03:19 timesync
drwxr-xr-x. 2 root root 57 Feb 24 03:19 tlog
时间同步角色示例
假设需要在服务器上配置NTP时间同步。我们可以自行编写自动化来执行每一个必要的任务。但是,RHEL系统角色中有一个可以执行此操作角色,那就是rhel-system-roles.timesync。
该角色的详细记录位于/usr/share/doc/rhel-system-roles/timesync目录下的README.md中。此文件说明了影响角色行为的所有变量,还包含演示了不同时间同步配置的三个playbook代码片段。
为了手动配置NTP服务器,该角色具有一个名为timesync_ntp_servers的变量。此变量取一个要使用的NTP服务器的列表作为值。列表中的每一项均由一个或多个属性构成。两个关键属性如下:
timesync_ntp_servers属性
属性 | 用途 |
---|---|
hostname | 要与其同步的NTP服务器的主机名。 |
iburst | 一个布尔值,用于启用或禁用快速初始同步。在角色中默认为no,但通常应该将属性设为yes. |
根据这一信息,以下示例play使用rhel-system-roles.timesync角色将受管主机配置为利用快速初始同步从三个NTP服务器获取时间。此外,还添加了一个任务,以使用timezone模块将主机的时区设为UTC。
需要提前关闭虚拟机时间同步功能,查看本机和受控机的时间
//修改时间
[root@ansible ~]# date -s '2000-01-01 11:11:11'
Sat Jan 1 11:11:11 CST 2000
//查看时间
[root@ansible ~]# ssh node2 date && date
Wed Feb 24 14:43:23 CST 2021
Sat Jan 1 11:11:15 CST 2000
//拷贝角色到roles目录下
[root@ansible ~]# cp -a /usr/share/ansible/roles/rhel-system-roles.timesync project/roles/timesync
[root@ansible roles]# ls
test timesync
//编写time.yml
[root@ansible project]# vim time.yml
---
- hosts: node2
vars:
timesync_ntp_servers:
- hostname: time1.aliyun.com
iburst: yes
roles:
- timesync
//执行playbook
[root@ansible project]# ansible-playbook time.yml
PLAY [node2] ***********************************************************************
TASK [Gathering Facts] *************************************************************
ok: [node2]
TASK [timesync : Check if only NTP is needed] **************************************
ok: [node2]
TASK [timesync : Check if single PTP is needed] ************************************
skipping: [node2]
TASK [timesync : Check if both NTP and PTP are needed] *****************************
skipping: [node2]
TASK [timesync : Determine current NTP provider] ***********************************
ok: [node2]
TASK [timesync : Select NTP provider] **********************************************
ok: [node2]
TASK [timesync : Install chrony] ***************************************************
changed: [node2]
TASK [timesync : Install ntp] ******************************************************
skipping: [node2]
TASK [timesync : Install linuxptp] *************************************************
skipping: [node2]
TASK [timesync : Run phc_ctl on PTP interface] *************************************
skipping: [node2]
TASK [timesync : Check if PTP interface supports HW timestamping] ******************
skipping: [node2]
TASK [timesync : Get chrony version] ***********************************************
ok: [node2]
TASK [timesync : Get ntp version] **************************************************
skipping: [node2]
TASK [timesync : Generate chrony.conf file] ****************************************
changed: [node2]
TASK [timesync : Generate chronyd sysconfig file] **********************************
changed: [node2]
TASK [timesync : Generate ntp.conf file] *******************************************
skipping: [node2]
TASK [timesync : Generate ntpd sysconfig file] *************************************
skipping: [node2]
TASK [timesync : Generate ptp4l.conf file] *****************************************
skipping: [node2]
TASK [timesync : Generate ptp4l sysconfig file] ************************************
skipping: [node2]
TASK [timesync : Generate phc2sys sysconfig file] **********************************
skipping: [node2]
TASK [timesync : Generate timemaster.conf file] ************************************
skipping: [node2]
TASK [timesync : Update network sysconfig file] ************************************
changed: [node2]
TASK [timesync : Disable chronyd] **************************************************
skipping: [node2]
TASK [timesync : Disable ntpd] *****************************************************
fatal: [node2]: FAILED! => {"changed": false, "msg": "Could not find the requested service ntpd: host"}
...ignoring
TASK [timesync : Disable ntpdate] **************************************************
fatal: [node2]: FAILED! => {"changed": false, "msg": "Could not find the requested service ntpdate: host"}
...ignoring
TASK [timesync : Disable sntp] *****************************************************
fatal: [node2]: FAILED! => {"changed": false, "msg": "Could not find the requested service sntp: host"}
...ignoring
TASK [timesync : Disable ptp4l] ****************************************************
fatal: [node2]: FAILED! => {"changed": false, "msg": "Could not find the requested service ptp4l: host"}
...ignoring
TASK [timesync : Disable phc2sys] **************************************************
fatal: [node2]: FAILED! => {"changed": false, "msg": "Could not find the requested service phc2sys: host"}
...ignoring
TASK [timesync : Disable timemaster] ***********************************************
fatal: [node2]: FAILED! => {"changed": false, "msg": "Could not find the requested service timemaster: host"}
...ignoring
TASK [timesync : Enable chronyd] ***************************************************
changed: [node2]
TASK [timesync : Enable ntpd] ******************************************************
skipping: [node2]
TASK [timesync : Enable ptp4l] *****************************************************
skipping: [node2]
TASK [timesync : Enable phc2sys] ***************************************************
skipping: [node2]
TASK [timesync : Enable timemaster] ************************************************
skipping: [node2]
RUNNING HANDLER [timesync : restart chronyd] ***************************************
changed: [node2]
PLAY RECAP *************************************************************************
node2 : ok=17 changed=6 unreachable=0 failed=0 skipped=18 rescued=0 ignored=6
//时间已经同步
[root@ansible project]# date && ssh node2 date
Thu Feb 25 01:50:22 CST 2021
Thu Feb 25 01:50:23 CST 2021
使用ansible galaxy部署角色
Ansible Galaxy [https://galaxy.ansible.com]是一个Ansible内容公共资源库,这些内容由许许多多Ansible管理员和用户编写。它包含数千个Ansible角色,具有可搜索的数据库,可帮助Ansible用户确定或许有助于他们完成管理任务的角色。Ansible Galaxy含有面向新的Ansible用户和角色开发人员的文档和视频链接。
Ansible Galaxy命令行工具
从命令行搜索角色
ansible-galaxy search子命令在Ansible Galaxy中搜索角色。如果以参数形式指定了字符串,则可用于按照关键字在Ansible Galaxy中搜索角色。用户可以使用--author、--platforms和--galaxy-tags选项来缩小搜索结果的范围。也可以将这些选项用作主要的搜索键。例如,命令ansible-galaxy search --author geerlingguy将显示由用户geerlingguy提交的所有角色。
[root@ansible ~]# ansible-galaxy search 'robertdebock.httpd' --platforms EL
Found 13 roles matching your search:
Name Description
---- -----------
robertdebock.ca Install and configure a certificate authority on your syst>
robertdebock.certbot Install and configure certbot on your system.
robertdebock.haproxy Install and configure haproxy on your system.
robertdebock.httpd Install and configure httpd on your system.
robertdebock.mediawiki Install and configure mediawiki on your system.
robertdebock.moodle Install and configure moodle on your system.
robertdebock.nextcloud Install and configure Nextcloud on your system.
robertdebock.owncloud Install and configure owncloud on your system.
robertdebock.php Install and configure php on your system.
.....
ansible-galaxy info子命令显示与角色相关的更多详细信息
Ansible Galaxy从多个位置获取这一信息,包括角色的meta/main.yml文件及其GigHub存储库。以下命令显示了Ansible Galaxy提供的geerlingguy.redis角色的相关信息。
[root@ansible ~]# ansible-galaxy info robertdebock.httpd
Role: robertdebock.httpd
description: Install and configure httpd on your system.
active: True
commit: f7a825a8a7a1b1d04c315e8c90b232bc91fa11d8
commit_message: Collections FQCN.
commit_url: https://api.github.com/repos/robertdebock/ansible-role-httpd/git/c>
company: none
created: 2017-11-10T16:04:25.981866Z
download_count: 114746
forks_count: 10
github_branch: master
github_repo: ansible-role-httpd
github_user: robertdebock
.....
从Ansible Galaxy安装角色
ansible-galaxy install子命令从Ansible Galaxy下载角色,并将它安装到控制节点本地。
默认情况下,角色安装到用户的roles_path下的第一个可写目录中。根据为Ansible设置的默认roles_path,角色通常将安装到用户的~/.ansible/roles目录。默认的roles_path可能会被用户当前Ansible配置文件或环境变量ANSIBLE_ROLES_PATH覆盖,这将影响ansible-galaxy的行为。
用户可以通过使用-p DIRECTORY选项,指定具体的目录来安装角色。
在下例中,ansible-galaxy将geerlingguy.redis角色安装到playbook项目的roles目录中。命令的当前工作目录是/opt/project。
[root@ansible ~]# ansible-galaxy install robertdebock.httpd -p project/roles/
- downloading role 'httpd', owned by robertdebock
- downloading role from https://github.com/robertdebock/ansible-role-httpd/archive/master.tar.gz
- extracting robertdebock.httpd to /root/project/roles/robertdebock.httpd
- robertdebock.httpd (master) was installed successfully
[root@ansible ~]# ls project/roles/
robertdebock.httpd test timesync
使用ansible-galaxy remove子命令本地删除角色(不用-p指定位置 默认移除 .ansible/roles/ 里的)
[root@ansible ~]# ansible-galaxy remove robertdebock.httpd -p project/roles/
- successfully removed robertdebock.httpd
管理下载的角色
ansible-galaxy命令也可管理本地的角色,如位于playbook项目的roles目录中的角色。ansible-galaxy list子命令列出本地找到的角色。
[root@ansible ~]# ansible-galaxy list
# /usr/share/ansible/roles
- linux-system-roles.certificate, (unknown version)
- linux-system-roles.kdump, (unknown version)
- linux-system-roles.kernel_settings, (unknown version)
- linux-system-roles.logging, (unknown version)
- linux-system-roles.metrics, (unknown version)
- linux-system-roles.nbde_client, (unknown version)
- linux-system-roles.nbde_server, (unknown version)
- linux-system-roles.network, (unknown version)
- linux-system-roles.postfix, (unknown version)
- linux-system-roles.selinux, (unknown version)
- linux-system-roles.storage, (unknown version)
.....
.....
# /etc/ansible/roles
创建角色框架
-
可以使用标准Linux命令创建新角色所需的所有子目录和文件。此外,也可以通过命令行实用程序来自动执行新角色创建过程。
-
ansible-galaxy命令行工具可用于管理Ansible角色,包括新角色的创建。用户可以运行ansible-galaxy init来创建新角色的目录结构。指定角色的名称作为命令的参数,该命令在当前工作目录中为新角色创建子目录。
创建一个test角色
//在项目中创建roles目录
[root@ansible project]# mkdir roles
//在roles目录里初始化一个test角色
[root@ansible project]# cd roles/
[root@ansible roles]# ansible-galaxy init test
- Role test was created successfully
//roles的框架结构
[root@ansible roles]# tree
.
└── test
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
Ansible角色子目录
子目录 | 功能 |
---|---|
defaults | 此目录中的main.yml文件包含角色变量的默认值,使用角色时可以覆盖这些默认值。 这些变量的优先级较低,应该在play中更改和自定义。 |
files | 此目录包含由角色任务引用的静态文件。 |
handlers | 此目录中的main.yml文件包含角色的处理程序定义。 |
meta | 此目录中的main.yml文件包含与角色相关的信息,如作者、许可证、平台和可选的角色依赖项。 |
tasks | 此目录中的main.yml文件包含角色的任务定义。 |
templates | 此目录包含由角色任务引用的Jinja2模板。 |
tests | 此目录可以包含清单和名为test.yml的playbook,可用于测试角色。 |
vars | 此目录中的main.yml文件定义角色的变量值。这些变量通常用于角色内部用途。 这些变量的优先级较高,在playbook中使用时不应更改。 |
上面列表中的子目录并非每个角色都拥有所有这些目录。
定义角色内容
-
创建目录结构后,用户必须编写角色的内容。ROLENAME/tasks/main.yml任务文件是一个不错的起点,它是由角色运行的主要任务列表。
-
下列tasks/main.yml文件管理受管主机上的/tmp/abc文件。它使用template模块将名为abc.j2的模板部署到受管主机上。因为template模块是在角色任务而非playbook任务内配置的,所以从角色的templates子目录检索abc.j2模板。
[root@ansible roles]# vim test/tasks/main.yml
---
# tasks file for test
- name: file config
template:
src: abc.j2
dest: /tmp/abc
owner: root
group: root
mode: 0644
注意:角色内容是通用的,不需要定义hosts:主机名,src后面直接跟的是模版名字,不需要加路径,会自动在templates目录下搜索。
下列命令显示test角色的abc.j2模板的内容。它引用了Ansible事实和system_owner变量。
[root@ansible roles]# vim test/templates/abc.j2
This is the system {{ ansible_facts['hostname'] }}.
Today's date is: {{ ansible_facts['date_time']['date'] }}.
Only use this system with permission.
You can ask {{ system_owner }} for access.
该角色为system_owner变量定义一个默认值。角色目录结构中的defaults/main.yml文件就是设置这个值的位置。
下列defaults/main.yml文件将system_owner变量设置为user@host.example.com。此电子邮件地址将写入到该角色所应用的受管主机上的/tmp/abc文件中。
[root@ansible roles]# vim test/defaults/main.yml
---
# defaults file for test
system_owner: root@node2.example.com
角色内容开发的推荐做法
角色允许以模块化方式编写playbook。为了最大限度地提高新开发角色的效率,请考虑在角色开发中采用以下推荐做法:
- 在角色自己的版本控制存储库中维护每个角色。Ansible很适合使用基于git的存储库。
- 角色存储库中不应存储敏感信息,如密码或SSH密钥。敏感值应以变量的形式进行参数化,其默认值应不敏感。使用角色的playbook负责通过Ansible Vault变量文件、环境变量或其他ansible-playbook选项定义敏感变量。
- 使用ansible-galaxy init启动角色,然后删除不需要的任何目录和文件。
- 创建并维护README.md和meta/main.yml文件,以记录用户的角色的用途、作者和用法。
- 让角色侧重于特定的用途或功能。可以编写多个角色,而不是让一个角色承担许多任务。
- 经常重用和重构角色。避免为边缘配置创建新的角色。如果现有角色能够完成大部分的所需配置,请重构现有角色以集成新的配置方案。使用集成和回归测试技术来确保角色提供所需的新功能,并且不对现有的playbook造成问题。
在playbook中使用角色
要访问角色,可在play的roles:部分引用它。下列playbook引用了motd角色。由于没有指定变量,因此将使用默认变量值应用该角色。
---
- hosts: node2 //受控机的主机名
roles:
- role1 //定义的角色1
- role2 //定义的角色2
- role3 //定义的角色3
示例如下:
//在project目录下创建一个和roles平级的yml文件
[root@ansible project]# vim a.yml
---
- hosts: node2
roles:
- test
[root@ansible project]# ls
ansible.cfg a.yml inventory roles
//执行plabook文件
[root@ansible project]# ansible-playbook a.yml
PLAY [node2] ***********************************************************************
TASK [Gathering Facts] *************************************************************
ok: [node2]
TASK [test : file config] **********************************************************
changed: [node2]
PLAY RECAP *************************************************************************
node2 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
//在node2主机上查看
[root@node2 ~]# cat /tmp/abc
This is the system node2.
Today's date is: 2021-02-24.
Only use this system with permission.
You can ask root@node2.example.com for access.
通过变量更改角色的行为
编写良好的角色利用默认变量来改变角色行为,使之与相关的配置场景相符。这有助于让角色变得更为通用,可在各种不同的上下文中重复利用。
如果通过以下方式定义了相同的变量,则角色的defaults目录中定义的变量的值将被覆盖:
- 在清单文件中定义,作为主机变量或组变量
- 在playbook项目的group_vars或host_vars目录下的YAML文件中定义
- 作为变量嵌套在play的vars关键字中定义
- 在play的roles关键字中包含该角色时作为变量定义
在清单中定义变量
//当前目录的内容
[root@ansible project]# ls
ansible.cfg a.yml inventory roles
//在清单文件中定义system_owner变量
[root@ansible project]# vim inventory
node2 system_owner=666
//在yml文件中调用test角色
[root@ansible project]# vim a.yml
---
- hosts: node2
roles:
- test
//执行playbook
[root@ansible project]# ansible-playbook a.yml
PLAY [node2] ***********************************************************************
TASK [Gathering Facts] *************************************************************
ok: [node2]
TASK [test : file config] **********************************************************
changed: [node2]
PLAY RECAP *************************************************************************
node2 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
//在node2主机上查看
[root@node2 ~]# cat /tmp/abc
This is the system node2.
Today's date is: 2021-02-24.
Only use this system with permission.
You can ask 666 for access. //成功修改变量为666
在group_vars或host_vars目录下的YAML文件中定义
//创建host_vars目录
[root@ansible project]# mkdir host_vars
//创建主机名yml变量文件
[root@ansible project]# vim host_vars/node2.yml
---
system_owner: 777
//在yml文件中调用test角色
[root@ansible project]# vim a.yml
---
- hosts: node2
roles:
- test
//执行playbook
[root@ansible project]# ansible-playbook a.yml
PLAY [node2] ***********************************************************************
TASK [Gathering Facts] *************************************************************
ok: [node2]
TASK [test : file config] **********************************************************
changed: [node2]
PLAY RECAP *************************************************************************
node2 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
//在node2主机上查看
[root@node2 ~]# cat /tmp/abc
This is the system node2.
Today's date is: 2021-02-24.
Only use this system with permission.
You can ask 777 for access.
作为变量嵌套在play的vars关键字中定义
//定义变量为999
[root@ansible project]# vim a.yml
---
- hosts: node2
vars:
system_owner: 999
roles:
- test
//执行playbook
[root@ansible project]# ansible-playbook a.yml
PLAY [node2] ***********************************************************************
TASK [Gathering Facts] *************************************************************
ok: [node2]
TASK [test : file config] **********************************************************
changed: [node2]
PLAY RECAP *************************************************************************
node2 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
//在node2主机上查看
[root@node2 ~]# cat /tmp/abc
This is the system node2.
Today's date is: 2021-02-24.
Only use this system with permission.
You can ask 999 for access.
在play的roles关键字中包含该角色时作为变量定义
//定义变量为888
[root@ansible project]# vim a.yml
---
- hosts: node2
roles:
- role: test
system_owner: 888
//执行playbook
[root@ansible project]# ansible-playbook a.yml
PLAY [node2] ***********************************************************************
TASK [Gathering Facts] *************************************************************
ok: [node2]
TASK [test : file config] **********************************************************
changed: [node2]
PLAY RECAP *************************************************************************
node2 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
//在node2主机上查看
[root@node2 ~]# cat /tmp/abc
This is the system node2.
Today's date is: 2021-02-24.
Only use this system with permission.
You can ask 888 for access.
注意:
在play中使用角色变量时,变量的优先顺序可能会让人困惑。
- 几乎任何其他变量都会覆盖角色的默认变量,如清单变量、play_vars变量,以及内嵌的角色参数等。
- 较少的变量可以覆盖角色的vars目录中定义的变量。事实、通过include_vars加载的变量、注册的变量和角色参数是其中一些具备这种能力的变量。清单变量和play_vars无此能力。这非常重要,因为它有助于避免用户的play意外改变角色的内部功能。
- 不过,正如上述示例中最后一个所示,作为角色参数内嵌声明的变量具有非常高的优先级。它们可以覆盖角色的vars目录中定义的变量。如果某一角色参数的名称与play_vars或角色vars中设置的变量或者清单变量或playbook变量的名称相同,该角色参数将覆盖另一个变量。