Ansible角色
环境说明:
主机IP | 主机名 |
---|---|
192.168.100.1 | ansible |
192.168.100.2 | yuqinghao |
检查ansible角色结构
Ansible角色由子目录和文件的标准化结构定义。顶级目录定义角色本身的名称。文件整理到子目录中,子目录按照各个文件在角色中的用途进行命名,如tasks和handlers。files和templates子目录中包含由其他YAML文件中的任务引用的文件。
site.yml
webservers.yml
fooservers.yml
roles/
common/
tasks/
handlers/
files/
templates/
vars/
defaults/
meta/
webservers/
tasks/
defaults/
meta/
以下tree命令显示了user.example角色的目录结构:
[root@localhost roles]# tree user.example/
user.example/
├── 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中使用时不应更改。 |
创建角色
角色创建流程
在Ansible中创建角色不需要特别的开发工具。创建和使用角色包含三个步骤:
-
创建角色目录结构
-
定义角色内容
-
在playbook中使用角色
创建角色框架
可以使用标准Linux命令创建新角色所需的所有子目录和文件。此外,也可以通过命令行实用程序来自动执行新角色创建过程。
ansible-galaxy命令行工具可用于管理Ansible角色,包括新角色的创建。用户可以运行ansible-galaxy init来创建新角色的目录结构。指定角色的名称作为命令的参数,该命令在当前工作目录中为新角色创建子目录。
[root@ansible ~]# mkdir project
[root@ansible ~]# cd project/
[root@ansible project]# mkdir roles
[root@ansible project]# cd roles/
[root@ansible roles]# ansible-galaxy init test
- Role test was created successfully
[root@ansible roles]# cd test/
[root@ansible test]# tree
.
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
8 directories, 8 files
定义角色内容
创建foo.j2模板文件
[root@ansible test]# vim templates/foo.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.
创建任务
[root@ansible test]# vim tasks/main.yml
---
# tasks file for test
- name: file config
template:
src: foo.j2
dest: /tmp/abc
owner: root
group: root
mode: 0644
定义变量
[root@ansible test]# vim defaults/main.yml
---
# defaults file for test
system_owner: root@yuqinghao.example.com
在playbook中使用角色
要访问角色,可在play的roles:部分引用它。下列playbook引用了test角色。由于没有指定变量,因此将使用默认变量值应用该角色
[root@ansible test]# cd ~/project/
[root@ansible project]# vim bo.yml
---
- hosts: yuqinghao
roles:
- test
执行该playbook
[root@ansible project]# ansible-playbook bo.yml
PLAY [yuqinghao] **********************************************************************
TASK [Gathering Facts] ****************************************************************
ok: [yuqinghao]
TASK [test : file config] *************************************************************
changed: [yuqinghao]
PLAY RECAP ****************************************************************************
yuqinghao : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
验证
[root@yuqinghao ~]# hostname
yuqinghao.example.com
[root@yuqinghao ~]# ls /tmp/
abc
[root@yuqinghao ~]# cat /tmp/abc
This is the system yuqinghao.
Today's date is: 2021-02-23.
Only use this system with permission.
You can ask root@yuqinghao.example.com for access.
通过变量更改角色的行为
编写良好的角色利用默认变量来改变角色行为,使之与相关的配置场景相符。这有助于让角色变得更为通用,可在各种不同的上下文中重复利用。
如果通过以下方式定义了相同的变量,则角色的defaults目录中定义的变量的值将被覆盖:
- 在清单文件中定义,作为主机变量或组变量
- 在playbook项目的group_vars或host_vars目录下的YAML文件中定义(*)
- 作为变量嵌套在play的vars关键字中定义(*)
- 在play的roles关键字中包含该角色时作为变量定义
在清单文件中定义,作为主机变量或组变量
[root@ansible project]# vim /etc/ansible/inventory
yuqinghao system_owner=123456
[root@ansible project]# cat roles/test/defaults/main.yml
---
# defaults file for test
system_owner: root@yuqinghao.example.com
在执行该playbook
[root@ansible project]# ansible-playbook bo.yml
PLAY [yuqinghao] **********************************************************************
TASK [Gathering Facts] ****************************************************************
ok: [yuqinghao]
TASK [test : file config] *************************************************************
changed: [yuqinghao]
PLAY RECAP ****************************************************************************
yuqinghao : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
验证
[root@yuqinghao ~]# cat /tmp/abc
This is the system yuqinghao.
Today's date is: 2021-02-23.
Only use this system with permission.
You can ask 123456 for access.
在playbook项目的group_vars或host_vars目录下的YAML文件中定义
[root@ansible project]# vim /etc/ansible/inventory
yuqinghao
[root@ansible project]# mkdir host_vars
[root@ansible project]# echo 'system_owner: 654321' > host_vars/yuqinghao
[root@ansible project]# cat host_vars/yuqinghao
system_owner: 654321
在执行该playbook
[root@ansible project]# ansible-playbook bo.yml
PLAY [yuqinghao] **********************************************************************
TASK [Gathering Facts] ****************************************************************
ok: [yuqinghao]
TASK [test : file config] *************************************************************
changed: [yuqinghao]
PLAY RECAP ****************************************************************************
yuqinghao : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
验证
[root@yuqinghao ~]# cat /tmp/abc
This is the system yuqinghao.
Today's date is: 2021-02-23.
Only use this system with permission.
You can ask 123456 for access.
[root@yuqinghao ~]# cat /tmp/abc
This is the system yuqinghao.
Today's date is: 2021-02-23.
Only use this system with permission.
You can ask 654321 for access.
作为变量嵌套在play的vars关键字中定义
[root@ansible project]# rm -rf host_vars
[root@ansible project]# vim bo.yml
---
- hosts: yuqinghao
vars:
system_owner: 999
roles:
- test
在执行该playbook
[root@ansible project]# ansible-playbook bo.yml
PLAY [yuqinghao] **********************************************************************
TASK [Gathering Facts] ****************************************************************
ok: [yuqinghao]
TASK [test : file config] *************************************************************
changed: [yuqinghao]
PLAY RECAP ****************************************************************************
yuqinghao : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
验证
[root@yuqinghao ~]# cat /tmp/abc
This is the system yuqinghao.
Today's date is: 2021-02-23.
Only use this system with permission.
You can ask 999 for access.
在play的roles关键字中包含该角色时作为变量定义
[root@ansible project]# vim bo.yml
---
- hosts: yuqinghao
roles:
- role: test
system_owner: 888
在执行该playbook
[root@ansible project]# ansible-playbook bo.yml
PLAY [yuqinghao] **********************************************************************
TASK [Gathering Facts] ****************************************************************
ok: [yuqinghao]
TASK [test : file config] *************************************************************
changed: [yuqinghao]
PLAY RECAP ****************************************************************************
yuqinghao : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
验证
[root@yuqinghao ~]# cat /tmp/abc
This is the system yuqinghao.
Today's date is: 2021-02-23.
Only use this system with permission.
You can ask 888 for access.
利用系统角色重用内容
红帽企业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
访问RHEL系统角色的文档
安装后,RHEL系统角色的文档位于/usr/share/doc/rhel-system-roles-/目录中。文档按照子系统整理到子目录中:
[root@ansible ~]# ls /usr/share/doc/rhel-system-roles/
certificate kernel_settings metrics nbde_server postfix storage tlog
kdump logging nbde_client network selinux timesync
时间同步角色示例
假设需要在服务器上配置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。
修改yuqinghao主机的时间
[root@yuqinghao ~]# date -s '1988-10-1 00:00:00'
Sat Oct 1 00:00:00 CST 1988
时间不同步
[root@ansible ~]# date && ssh yuqinghao 'date'
Tue Feb 23 23:48:41 CST 2021
Sat Oct 1 00:00:04 CST 1988
编写时间同步playbook
[root@ansible ~]# cp -a /usr/share/ansible/roles/rhel-system-roles.timesync ~/project/roles/timesync
[root@ansible ~]# cd ~/project/roles/timesync/
[root@ansible timesync]# ls
COPYING examples library README.html tasks tests
defaults handlers meta README.md templates vars
[root@ansible timesync]# cd ~/project/
[root@ansible project]# vim time.yml
---
- hosts: yuqinghao
vars:
timesync_ntp_servers:
- hostname: time1.aliyun.com
iburst: yes
roles:
- timesync
执行playbook
[root@ansible project]# ansible-playbook time.yml
PLAY [yuqinghao] **********************************************************************
TASK [Gathering Facts] ****************************************************************
ok: [yuqinghao]
TASK [timesync : Check if only NTP is needed] *****************************************
ok: [yuqinghao]
TASK [timesync : Check if single PTP is needed] ***************************************
skipping: [yuqinghao]
TASK [timesync : Check if both NTP and PTP are needed] ********************************
skipping: [yuqinghao]
TASK [timesync : Determine current NTP provider] **************************************
ok: [yuqinghao]
TASK [timesync : Select NTP provider] *************************************************
ok: [yuqinghao]
TASK [timesync : Install chrony] ******************************************************
changed: [yuqinghao]
TASK [timesync : Install ntp] *********************************************************
skipping: [yuqinghao]
TASK [timesync : Install linuxptp] ****************************************************
skipping: [yuqinghao]
TASK [timesync : Run phc_ctl on PTP interface] ****************************************
skipping: [yuqinghao]
TASK [timesync : Check if PTP interface supports HW timestamping] *********************
skipping: [yuqinghao]
TASK [timesync : Get chrony version] **************************************************
ok: [yuqinghao]
TASK [timesync : Get ntp version] *****************************************************
skipping: [yuqinghao]
TASK [timesync : Generate chrony.conf file] *******************************************
changed: [yuqinghao]
TASK [timesync : Generate chronyd sysconfig file] *************************************
changed: [yuqinghao]
TASK [timesync : Generate ntp.conf file] **********************************************
skipping: [yuqinghao]
TASK [timesync : Generate ntpd sysconfig file] ****************************************
skipping: [yuqinghao]
TASK [timesync : Generate ptp4l.conf file] ********************************************
skipping: [yuqinghao]
TASK [timesync : Generate ptp4l sysconfig file] ***************************************
skipping: [yuqinghao]
TASK [timesync : Generate phc2sys sysconfig file] *************************************
skipping: [yuqinghao]
TASK [timesync : Generate timemaster.conf file] ***************************************
skipping: [yuqinghao]
TASK [timesync : Update network sysconfig file] ***************************************
changed: [yuqinghao]
TASK [timesync : Disable chronyd] *****************************************************
skipping: [yuqinghao]
TASK [timesync : Disable ntpd] ********************************************************
fatal: [yuqinghao]: FAILED! => {"changed": false, "msg": "Could not find the requested service ntpd: host"}
...ignoring
TASK [timesync : Disable ntpdate] *****************************************************
fatal: [yuqinghao]: FAILED! => {"changed": false, "msg": "Could not find the requested service ntpdate: host"}
...ignoring
TASK [timesync : Disable sntp] ********************************************************
fatal: [yuqinghao]: FAILED! => {"changed": false, "msg": "Could not find the requested service sntp: host"}
...ignoring
TASK [timesync : Disable ptp4l] *******************************************************
fatal: [yuqinghao]: FAILED! => {"changed": false, "msg": "Could not find the requested service ptp4l: host"}
...ignoring
TASK [timesync : Disable phc2sys] *****************************************************
fatal: [yuqinghao]: FAILED! => {"changed": false, "msg": "Could not find the requested service phc2sys: host"}
...ignoring
TASK [timesync : Disable timemaster] **************************************************
fatal: [yuqinghao]: FAILED! => {"changed": false, "msg": "Could not find the requested service timemaster: host"}
...ignoring
TASK [timesync : Enable chronyd] ******************************************************
changed: [yuqinghao]
TASK [timesync : Enable ntpd] *********************************************************
skipping: [yuqinghao]
TASK [timesync : Enable ptp4l] ********************************************************
skipping: [yuqinghao]
TASK [timesync : Enable phc2sys] ******************************************************
skipping: [yuqinghao]
TASK [timesync : Enable timemaster] ***************************************************
skipping: [yuqinghao]
RUNNING HANDLER [timesync : restart chronyd] ******************************************
changed: [yuqinghao]
PLAY RECAP ****************************************************************************
yuqinghao : ok=17 changed=6 unreachable=0 failed=0 skipped=18 rescued=0 ignored=6
验证
[root@ansible project]# date && ssh yuqinghao 'date'
Wed Feb 24 00:09:32 CST 2021
Wed Feb 24 00:09:32 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.
robertdebock.php_fpm The purpose of this role is to install and configure php_f>
robertdebock.phpmyadmin Install and configure phpmyadmin on your system.
robertdebock.roundcubemail Install and configure roundcubemail on your system.
robertdebock.zabbix_web Install and configure zabbix_web 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
id: 21855
imported: 2021-02-23T02:52:52.799194-05:00
is_valid: True
issue_tracker_url: https://github.com/robertdebock/ansible-role-httpd/issues
license: Apache-2.0
min_ansible_version: 2.10
modified: 2021-02-23T07:52:52.806717Z
open_issues_count: 0
path: ('/root/.ansible/roles', '/usr/share/ansible/roles', '/etc/ansible/roles>
role_type: ANS
stargazers_count: 4
travis_status_url:
从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
卸载(不用-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)
- linux-system-roles.timesync, (unknown version)
- linux-system-roles.tlog, (unknown version)
- rhel-system-roles.certificate, (unknown version)
- rhel-system-roles.kdump, (unknown version)
- rhel-system-roles.kernel_settings, (unknown version)
- rhel-system-roles.logging, (unknown version)
- rhel-system-roles.metrics, (unknown version)
- rhel-system-roles.nbde_client, (unknown version)
- rhel-system-roles.nbde_server, (unknown version)
- rhel-system-roles.network, (unknown version)
- rhel-system-roles.postfix, (unknown version)
- rhel-system-roles.selinux, (unknown version)
- rhel-system-roles.storage, (unknown version)
- rhel-system-roles.timesync, (unknown version)
- rhel-system-roles.tlog, (unknown version)
# /etc/ansible/roles