利用角色简化playbook

利用角色简化playbook

描述角色结构

角色介绍

角色(roles) 是通用性的代码,用于层次性,结构化地组织playbook。简单的说,roles就是通过分别将变量、文件、任务、模块及处理器放置于单独的目录中、并可以便捷地include他们的一种机制。 角色一般用于基于主机构建服务的场景中、但也可以是用于构建守护进程等场景中

利用角色构造ansible playbook
  • Ansible角色提供了一种方法,让用户能以通用的方式更加轻松地重复利用Ansible代码,可以在标准化目录结构中打包所有任务、变量、文件、模板,以及调配基础架构或部署应用所需的其他资源
  • 借助编写良好的角色,可以从playbook中向角色传递调整其行为的变量(可以随机应变,不是写死的),设置所有站点相关的主机名、IP地址、用户名,或其他在本地需要的具体详细信息

角色的优点:
(1)角色可以把内容分组,容易复用,从而与他人轻松共享代码
(2)可以用角色定义系统基本信息:web 服务器、数据库服务器等
(3)角色可以使大型项目易管理
(4)角色可以由不同人并行开发

注意:除了自己编写、使用、重用和共享角色外,还可以从其他来源获取角色

  • rhel-system-roles(红帽软件包)
  • Ansible Galaxy网站(由社区提供支持)
检查ansible角色结构

由子目录和文件的标准化结构定义。顶级目录定义角色本身的名称
实例(查看角色的目录结构):

[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.ym

Ansible角色子目录:

子目录功能
defaults其中的 main.yml 包含角色变量的默认值。在所有变量中优先级最低
files包含角色任务引用的静态文件
handlers主要定义处理程序
meta角色相关信息,如作者、许可证等
tasks定义任务
templates任务引用的 jinja2 模板
tests可以包含清单和 test.yml 的 playbook,用于测试vars:定义角色的变量
vars定义角色的变量值,优先级较高,在playbook中使用是不应更改(通常用于角色内部用途)
定义变量和默认值

角色变量通过在角色目录层次结构中创建含有键值对的vars/main.yml文件来定义。与其他变量一样,这些角色变量在角色YAML文件中引用:{{ VAR_NAME }}。这些变量具有较高的优先级,无法被清单变量覆盖。这些变量旨在供角色的内部功能使用。

默认变量允许为可在play中使用的变量设置默认值,以配置角色或自定义其行为(没有用到变量值就用默认变量,用到了就用该用到的值),它们通过在角色目录层次结构中创建含有键值对的defaults/main.yml文件来定义(意思是写在defaults/main.yml中的文件可以进行修改),默认变量具备任何可用变量中最低的优先级。(所有很容易被任何变量覆盖,当然,清单变量也是如此),这些变量旨在让用户在编写使用该角色的play时可以准确地自定义或控制它将要执行的操作。它们可用于向角色提供所需的信息(传参数给它),以正确地配置或部署某些对象

在vars/main.yml或defaults/main.yml中定义具体的变量
但不要在两者中都定义。有意要覆盖变量的值时,应使用默认变量。

  • 注意:
  1. vars的优先级比defaults优先级高
  2. 角色不应该包含特定于站点的数据。它们绝对不应包含任何机密,如密码或私钥。
  3. 这是因为角色应该是通用的(不能改角色代码),可以重复利用并自由共享。特定于站点的详细信息不应硬编码到角色中。
  4. 机密应当通过其他途径提供给角色。这是用户可能要在调用角色时设置角色变量的一个原因。play中设置的角色变量可以提供机密,或指向含有该机密的Ansible Vault加密文件
在playbook中使用ansible角色

在playbook中使用角色:

---
- hosts: all
  roles:
    - role1
    - role2            #添加了两个角色

按照顺序去导入每个指定的角色,角色任务、角色处理程序、角色变量和角色依赖项, 角色中的任何copy、script、template或include_tasks/import_tasks任务都可引用角色中相关的文件、模板或任务文件,且无需相对或绝对路径名称。Ansible将分别在角色的files、templates或tasks子目录中寻找它们。

如果使用roles部分将角色导入到play中,这些角色会在用户为该play定义的任何任务之前运行。

以下示例设置role2的两个角色变量var1和var2的值。使用role2时,任何defaults和vars变量都会被覆盖。

---
- hosts: all
  roles:
    - role: role1
    - role: role2
      var1: val1
      var2: val2

另一种等效的YAML语法:

- hosts: all
  roles:
    - role: role1
    - { role: role2, var1: val1, var2: val2 }

建议使用第一种,因为第二种在某些情况下难以阅读,但的确第二种写法更精简

重要 
正如前面的示例中所示,内嵌设置的角色变量(角色参数)具有非常
高的优先级。它们将覆盖大多数其他变量。
务必要谨慎,不要重复使用内嵌设置在play中任何其他位置的任何角
色变量的名称,
因为角色变量的值将覆盖清单变量和任何play中的vars。
控制执行顺序
  • 详细图如下:(优先级)

#此为写入时的顺序
优先级
#此为优先级顺序
在这里插入图片描述

角色变量的优先级为:

  1. 角色内嵌参数、事实、通过include_vars加载的变量、注册的变量vars/main. yml中定义的变量
  2. playbook中vars部分定义的变量主机变量、主机组变量
  3. defaults/main. yml中定义的变量

利用系统角色重用内容

红帽企业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主机)

简化配置管理

RHEL6建议时间同步服务为:ntpd服务
RHEL7建议时间同步服务为:chronyd服务
混合了RHEL6和7主机的环境中,管理员必须管理这两个服务的配置文件。

借助RHEL系统角色,管理员将不再需要维护这两个服务的配置文件(借助rhel-system-roles.timesync角色来配置RHEL6和7主机的时间同步)一个包含角色变量的简化YAML文件可以为这两种类型的主机定义时间同步配置

安装RHEL系统角色

RHEL系统角色由rhel-system-roles软件包提供,该软件包可从AppStream流获取。在Ansible控制节点上安装该软件包。

安装RHEL系统角色命令:

yum -y install rhel-system-roles

实例:

[root@ansible ~]# yum -y install rhel-system-roles
Updating Subscription Management repositories.
Unable to read consumer identity
This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register.
上次元数据过期检查:0:26:42 前,执行于 20210804日 星期三 212246秒。
依赖关系解决。
=====================================================================
 软件包               架构      版本              仓库          大小
=====================================================================
安装:
 rhel-system-roles    noarch    1.0-10.el8_1      Appstream    175 k

事务概要
=====================================================================
安装  1 软件包

总计:175 k
安装大小:1.1 M
下载软件包:
运行事务检查
事务检查成功。
运行事务测试
事务测试成功。
运行事务
  准备中  :                                                      1/1 
  安装    : rhel-system-roles-1.0-10.el8_1.noarch                1/1 
  验证    : rhel-system-roles-1.0-10.el8_1.noarch                1/1 
Installed products updated.

已安装:
  rhel-system-roles-1.0-10.el8_1.noarch                              

完毕!

安装之后会在/usr/share/ansible/roles目录中

查看:

[root@ansible ~]# ls -l /usr/share/ansible/roles/
总用量 0
lrwxrwxrwx.  1 root root  23 1023 2019 linux-system-roles.kdump -> rhel-system-roles.kdump
lrwxrwxrwx.  1 root root  25 1023 2019 linux-system-roles.network -> rhel-system-roles.network
lrwxrwxrwx.  1 root root  25 1023 2019 linux-system-roles.postfix -> rhel-system-roles.postfix
lrwxrwxrwx.  1 root root  25 1023 2019 linux-system-roles.selinux -> rhel-system-roles.selinux
lrwxrwxrwx.  1 root root  25 1023 2019 linux-system-roles.storage -> rhel-system-roles.storage
lrwxrwxrwx.  1 root root  26 1023 2019 linux-system-roles.timesync -> rhel-system-roles.timesync
drwxr-xr-x.  9 root root 156 84 21:49 rhel-system-roles.kdump
drwxr-xr-x.  8 root root 177 84 21:49 rhel-system-roles.network
drwxr-xr-x.  6 root root 114 84 21:49 rhel-system-roles.postfix
drwxr-xr-x.  8 root root 138 84 21:49 rhel-system-roles.selinux
drwxr-xr-x. 10 root root 215 84 21:49 rhel-system-roles.storage
drwxr-xr-x. 11 root root 187 84 21:49 rhel-system-roles.timesync

红帽企业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/
总用量 4
drwxr-xr-x. 2 root root   57 84 21:49 kdump
drwxr-xr-x. 2 root root 4096 84 21:49 network
drwxr-xr-x. 2 root root   57 84 21:49 postfix
drwxr-xr-x. 2 root root   93 84 21:49 selinux
drwxr-xr-x. 2 root root   57 84 21:49 storage
drwxr-xr-x. 2 root root  136 84 21:49 timesync

其中的内容(查看网络角色):

ls -l /usr/share/ansible/roles/rhel-system-roles.network
[root@ansible ~]# ls -l /usr/share/ansible/roles/rhel-system-roles.network/
总用量 128
drwxr-xr-x. 2 root root    22 84 21:49 defaults
drwxr-xr-x. 2 root root    36 84 21:49 library
-rw-r--r--. 1 root root  1510 614 2019 LICENSE
drwxr-xr-x. 2 root root    22 84 21:49 meta
drwxr-xr-x. 3 root root    25 84 21:49 module_utils
-rw-r--r--. 1 root root 16812 614 2019 pylintrc
-rw-r--r--. 1 root root 68480 1023 2019 README.html
-rw-r--r--. 1 root root 24930 614 2019 README.md
drwxr-xr-x. 2 root root    22 84 21:49 tasks
drwxr-xr-x. 6 root root  4096 84 21:49 tests
-rw-r--r--. 1 root root  4053 614 2019 tox.ini

查看系统中有哪些角色可以使用:

 ansible-galaxy list
[root@ansible ~]# ansible-galaxy list
# /usr/share/ansible/roles
- linux-system-roles.kdump, (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)
- rhel-system-roles.kdump, (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)
[WARNING]: - the configured path /root/.ansible/roles does not exist.
[WARNING]: - the configured path /etc/ansible/roles does not exist.

每个角色的文档目录均包含一个README.md文件。README.md文件含有角色的说明,以及角色用法信息。

README.md文件也会说明影响角色行为的角色变量。通常,README.md文件中含有一个playbook代码片段,用于演示常见配置场景的变量设置。

部分角色文档目录中含有示例playbook。首次使用某一角色时,请查看文档目录中的任何额外示例playbook。

RHEL系统角色的角色文档与Linux系统角色的文档相匹配。使用Web浏览器来访问位于Ansible Galaxy网站(https://galaxy.ansible.com/docs/

时间同步角色示例

影响角色行为的所有变量,还包含演示了不同时间同步配置的三个playbook代码片段

为了手动配置NTP服务器,该角色具有一个名为timesync_ntp_servers的变量。此变量取一个要使用的NTP服务器的列表作为值。列表中的每一项均由一个或多个属性构成。

属性用途
hostname要与其同步的NTP服务器的主机名
iburst一个布尔值,用于启用或禁用快速初始同步。
在角色中默认为no,但通常应该将属性设为yes

实例(现需要同步受控机的时间):

[root@httpd ~]# date
20210804日 星期三 23:24:01 CST


[root@ansible test]# cp -a /usr/share/ansible/roles/rhel-system-roles.timesync/ timesync
[root@ansible test]# pwd
/etc/ansible/test
[root@ansible test]# ls
timesync  timesync.yml
[root@ansible test]# vim timesync.yml 
[root@ansible test]# ansible-playbook timesync.yml 

PLAY [httpd] *******************************************************************

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

TASK [timesync : Check if only NTP is needed] **********************************
ok: [192.168.230.98]

TASK [timesync : Check if single PTP is needed] ********************************
skipping: [192.168.230.98]

TASK [timesync : Check if both NTP and PTP are needed] *************************
skipping: [192.168.230.98]

TASK [timesync : Determine current NTP provider] *******************************
ok: [192.168.230.98]

TASK [timesync : Select NTP provider] ******************************************
ok: [192.168.230.98]

TASK [timesync : Install chrony] ***********************************************
ok: [192.168.230.98]

TASK [timesync : Install ntp] **************************************************
skipping: [192.168.230.98]

TASK [timesync : Install linuxptp] *********************************************
skipping: [192.168.230.98]

TASK [timesync : Run phc_ctl on PTP interface] *********************************
skipping: [192.168.230.98]

TASK [timesync : Check if PTP interface supports HW timestamping] **************
skipping: [192.168.230.98]

TASK [timesync : Get chrony version] *******************************************
ok: [192.168.230.98]

TASK [timesync : Get ntp version] **********************************************
skipping: [192.168.230.98]

TASK [timesync : Generate chrony.conf file] ************************************
changed: [192.168.230.98]

TASK [timesync : Generate chronyd sysconfig file] ******************************
changed: [192.168.230.98]

TASK [timesync : Generate ntp.conf file] ***************************************
skipping: [192.168.230.98]

TASK [timesync : Generate ntpd sysconfig file] *********************************
skipping: [192.168.230.98]

TASK [timesync : Generate ptp4l.conf file] *************************************
skipping: [192.168.230.98]

TASK [timesync : Generate ptp4l sysconfig file] ********************************
skipping: [192.168.230.98]

TASK [timesync : Generate phc2sys sysconfig file] ******************************
skipping: [192.168.230.98]

TASK [timesync : Generate timemaster.conf file] ********************************
skipping: [192.168.230.98]

TASK [timesync : Update network sysconfig file] ********************************
changed: [192.168.230.98]

TASK [timesync : Disable chronyd] **********************************************
skipping: [192.168.230.98]

TASK [timesync : Disable ntpd] *************************************************
fatal: [192.168.230.98]: FAILED! => {"changed": false, "msg": "Could not find the requested service ntpd: host"}
...ignoring

TASK [timesync : Disable ntpdate] **********************************************
fatal: [192.168.230.98]: FAILED! => {"changed": false, "msg": "Could not find the requested service ntpdate: host"}
...ignoring

TASK [timesync : Disable sntp] *************************************************
fatal: [192.168.230.98]: FAILED! => {"changed": false, "msg": "Could not find the requested service sntp: host"}
...ignoring

TASK [timesync : Disable ptp4l] ************************************************
fatal: [192.168.230.98]: FAILED! => {"changed": false, "msg": "Could not find the requested service ptp4l: host"}
...ignoring

TASK [timesync : Disable phc2sys] **********************************************
fatal: [192.168.230.98]: FAILED! => {"changed": false, "msg": "Could not find the requested service phc2sys: host"}
...ignoring

TASK [timesync : Disable timemaster] *******************************************
fatal: [192.168.230.98]: FAILED! => {"changed": false, "msg": "Could not find the requested service timemaster: host"}
...ignoring

TASK [timesync : Enable chronyd] ***********************************************
ok: [192.168.230.98]

TASK [timesync : Enable ntpd] **************************************************
skipping: [192.168.230.98]

TASK [timesync : Enable ptp4l] *************************************************
skipping: [192.168.230.98]

TASK [timesync : Enable phc2sys] ***********************************************
skipping: [192.168.230.98]

TASK [timesync : Enable timemaster] ********************************************
skipping: [192.168.230.98]

RUNNING HANDLER [timesync : restart chronyd] ***********************************
changed: [192.168.230.98]

PLAY RECAP *********************************************************************
192.168.230.98             : ok=17   changed=4    unreachable=0    failed=0    skipped=18   rescued=0    ignored=6   


[root@httpd ~]# date
20010204日 星期日 12:54:26 CST
[root@httpd ~]# rpm -qa | grep chrony
chrony-3.5-1.el8.x86_64
[root@httpd ~]# cat /etc/chrony.conf
# Ansible managed


# Allow the system clock to be stepped in the first three updates.
makestep 1.0 3

# Enable kernel synchronization of the real-time clock (RTC).
rtcsync

# Record the rate at which the system clock gains/losses time.
driftfile /var/lib/chrony/drift

注意
如果要设置不同的时区,可以使用tzselect命令查询其他有效的值。也可以使用timedatectl命令来检查当前的时钟设置。

SELINUX角色示例

rhel-system-roles.selinux角色可以简化SELinux配置设置的管理。它通过利用SELinux相关的Ansible模块来实施,使用此角色的优势是它能让用户摆脱编写这些任务的职责(与自行编写任务相比)

此角色可以执行的任务包括:

  • 设置enforcing或permissive模式
  • 对文件系统层次结构的各部分运行restorecon
  • 设置SELinux布尔值
  • 永久设置SELinux文件上下文
  • 设置SELinux用户映射
调用SELinux角色

该角色将一个布尔值变量selinux_reboot_required设为True,如果需要重新引导,则失败(可以使用block/rescure结构来从失败中恢复)
实例:

[root@ansible test]# ansible httpd -a 'cat /etc/selinux/config'
192.168.230.98 | CHANGED | rc=0 >>

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected. 
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted
[root@ansible test]# vim timesync.yml 
[root@ansible test]# ansible-playbook timesync.yml 

PLAY [httpd] *******************************************************************

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

TASK [include_role : selinux] **************************************************

TASK [selinux : Install SELinux python2 tools] *********************************
skipping: [192.168.230.98]

TASK [selinux : Install SELinux python3 tools] *********************************
ok: [192.168.230.98]

TASK [selinux : refresh facts] *************************************************
ok: [192.168.230.98]

TASK [selinux : Install SELinux tool semanage on Fedora] ***********************
ok: [192.168.230.98]

TASK [selinux : Set permanent SELinux state if enabled] ************************
skipping: [192.168.230.98]

TASK [selinux : Set permanent SELinux state if disabled] ***********************
changed: [192.168.230.98]

TASK [selinux : Set ansible facts if needed] ***********************************
ok: [192.168.230.98]

TASK [selinux : Fail if reboot is required] ************************************
skipping: [192.168.230.98]

TASK [selinux : debug] *********************************************************
ok: [192.168.230.98] => {
    "msg": "SELinux is disabled on system - some SELinux modules can crash"
}

TASK [selinux : Drop all local modifications] **********************************
skipping: [192.168.230.98]

TASK [selinux : Purge all SELinux boolean local modifications] *****************
skipping: [192.168.230.98]

TASK [selinux : Purge all SELinux file context local modifications] ************
skipping: [192.168.230.98]

TASK [selinux : Purge all SELinux port local modifications] ********************
skipping: [192.168.230.98]

TASK [selinux : Purge all SELinux login local modifications] *******************
skipping: [192.168.230.98]

TASK [selinux : Reload SELinux policy] *****************************************
skipping: [192.168.230.98]

TASK [selinux : Set SELinux booleans] ******************************************

TASK [selinux : Set SELinux file contexts] *************************************

TASK [selinux : Restore SELinux labels on filesystem tree] *********************

TASK [selinux : Restore SELinux labels on filesystem tree in check mode] *******

TASK [selinux : Set an SELinux label on a port] ********************************

TASK [selinux : Set linux user to SELinux user mapping] ************************

PLAY RECAP *********************************************************************
192.168.230.98             : ok=7    changed=1    unreachable=0    failed=0    skipped=15   rescued=0    ignored=0   

[root@httpd ~]# getenforce 0
Disabled

配置SELinux角色

用于配置rhel-system-roles.selinux角色的变量的详细记录位于其README.md文件中

selinux_state变量设置SELinux的运行模式。它可以设为enforcing、permissive或disabled。如果未设置,则不更改模式。

selinux_state: enforcing
[root@httpd ~]# semanage boolean -l|grep -i "httpd_enable_homedirs"
httpd_enable_homedirs          (,)  Allow httpd to enable homedirs

selinux_booleans变量取一个要调整的SELinux布尔值的列表作为值。列表中的每一项是变量的散列/字典

[root@localhost test]# vim myplay.yml 

---
- hosts: all
  vars:
    selinux_booleans:
      - name: httpd_enable_homedirs
        state: on
        persistent: yes
  roles:
    - role: rhel-system-roles.selinux

selinux_fcontext变量取一个要永久设置(或删除)的文件上下文的列表作为值。它的工作方式与selinux fcontent命令非常相似。

以下示例确保策略中包含一条规则,用于将/srv/www下所有文件的默认SELinux类型设为httpd_sys_content_t。

selinux_fcontexts:
  - target: '/srv/www(/.*)?'
    setype: 'httpd_sys_content_t'
    state: 'present'

selinux_restore_dirs变量指定要对其运行restorecon的目录的列表:

selinux_restore_dirs:
  - /srv/www

selinux_ports变量取应当具有特定SELinux类型的端口的列表作为值。

selinux_ports:
 - ports: '82'
    setype: 'http_port_t'
    proto: 'tcp'
    state: 'present'

实例:(修改端口号)

  • 先复制httpd主机上的文件改名为httpd.conf.j2
[root@ansible test]# scp httpd /etc/httpd/conf/httpd.conf httpd.conf.j2
httpd.conf.j2: No such file or directory
[root@ansible test]# scp httpd:/etc/httpd/conf/httpd.conf httpd.conf.j2
The authenticity of host 'httpd (192.168.230.98)' can't be established.
ECDSA key fingerprint is SHA256:refz2NG3n/1z4d4t0VRaqCGeagh1rT3ityUnrv7eXlE.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'httpd' (ECDSA) to the list of known hosts.
httpd.conf                         100%   12KB 782.0KB/s   00:00    
[root@ansible test]# ls
httpd.conf.j2  selinux  sx.yml  timesync
  • 再进入文件进行修改配置改成变量

[root@ansible test]# vim httpd.conf.j2 

# Change this to Listen on specific IP addresses as shown below to 
# prevent Apache from glomming onto all bound IP addresses.
#
#Listen 12.34.56.78:80
Listen {{ PORT }}

#
# Dynamic Shared Object (DSO) Support
#
# To be able to use the functionality of a module which was built as a DSO you

  • 开始实例:
[root@httpd ~]# semanage port -l | grep http
http_cache_port_t              tcp      8080, 8118, 8123, 10001-10010
http_cache_port_t              udp      3130
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t            tcp      5988
pegasus_https_port_t           tcp      5989
[root@ansible test]# cat timesync.yml 
---
- hosts: httpd
  vars: 
    selinux_state: enforcing
    selinux_ports: 
      - ports: '82'
        setype: 'http_port_t'
        proto: 'tcp'
        state: 'present'
    PORT: 82
  tasks: 
    - name: install httpd
      yum: 
        name: httpd 
        state: present

    - name: config httpd
      template:
        src: httpd.conf.j2
        dest: /etc/httpd/conf/httpd.conf

    - name: selinux for httpd
      block: 
        - include_role: 
            name: selinux
      rescue: 
        - name: if failed reason require reboot
          fail: 
          when: not selinux_reboot_required

        - name: reboot
          reboot:

        - name: config selinux
          include_role: 
            name: selinux

    - name: service for httpd
      service:
        name: httpd
        state: started
        enabled: yes

[root@ansible test]# ansible-playbook timesync.yml 

PLAY [httpd] *******************************************************************

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

TASK [selinux : Install SELinux python2 tools] *********************************
skipping: [192.168.230.98]

TASK [selinux : Install SELinux python3 tools] *********************************
ok: [192.168.230.98]

TASK [selinux : refresh facts] *************************************************
...

[root@httpd ~]# semanage port -l|grep http
http_port_t                    tcp      82, 80, 81, 443, 488, 8008, 8009, 8443, 9000

手动添加端口方式(添加82端口)
[root@httpd ~]# semanage port -a -t http_port_t -p tcp 82

创建角色

角色创建流程

在Ansible中创建角色不需要特别的开发工具。
创建和使用角色包含三个步骤:

  1. 创建角色目录结构
  2. 定义角色内容
  3. 在playbook中使用角色

角色来源:

  1. 发行商制作(企业) 可以通过安装包进行使用
  2. 自己制作
  3. 第三方制作
    想要深入了解制作角色可以前往网站自行学习:https://galaxy.ansible.com
创建角色目录结构

查找目录:Ansible Playbook所在目录的roles子目录(用户可以利用playbook和其他支持文件存储角色)

注意:如果Ansible无法在该位置找到角色,则按顺序去查找角色

  1. 先在当前目录中寻找角色
  2. 再去家目录下寻找角色
  3. 如果还没有就去官方默认路径下寻找角色

实例:

[root@ansible test]# ls /etc/ansible/
ansible.cfg  host.sh    playbook.yml  vault_password
hosts        inventory  test
[root@ansible test]# ls ~/.ansible/     #如果放入此路径中,只能当前用户进行使用
cp  tmp
[root@ansible test]# ls /usr/share/ansible/
collections  plugins  roles

这允许用户将角色安装到由多个项目共享的系统上。例如,用户可能将自己的角色安装在自己的主目录下的~/.ansible/roles子目录中,而系统可能将所有用户的角色安装在/usr/share/ansible/roles目录中。

每个角色具有自己的目录,采用标准化的目录结构。例如,以下目录结构包含了定义motd角色的文件。

[root@localhost ~]# tree roles/
roles/
└── motd
     ├── defaults
     │   └── main.yml
     ├── files
     ├── handlers
     ├── meta
     │   └── main.yml
     ├── tasks
     │   └── main.yml
     └── templates
         └── motd.j2

README.md提供人类可读的基本角色描述、有关如何使用该角色的文档和示例,以及其发挥作用所需要满足的任何非Ansible要求
meta子目录包含一个main.yml文件,该文件指定有关模块的作者、许可证、兼容性和依赖项的信息。

实例:

[root@ansible test]# cat /usr/share/ansible/roles/linux-system-roles.selinux/meta/main.yml 
galaxy_info:
  author: Petr Lautrbach <plautrba@redhat.com>
  description: Configure SELinux
  galaxy_tags:
    - system
    - selinux
    - redhat
    - rhel
    - fedora
    - centos
  company: Red Hat, Inc.
  license: GPL-3.0+
  min_ansible_version: 2.5
  platforms:
    - name: Fedora
      versions:
        - 28
        - 29
        - 30
    - name: EL
      versions:
        - 6
        - 7
        - 8

allow_duplicates: true

files子目录包含固定内容的文件(例如安装包),而templates子目录则包含使用时可由角色部署的模板。(如果需要变量的话需要放在模板内,就不放在files子目录内)

其他子目录中可以包含main.yml文件,它们定义默认的
变量值(放在defaults内或vars内)、
处理程序(放入handlers内)、
任务(放入tasks内)、
角色元数据(放入meta内)或变量(放入defaults或者vars内)、
具体取决于所处的子目录
如果某一子目录存在但为空,如本例中的handlers,它将被忽略。如果某一角色不使用功能,则其子目录可以完全省略。例如,本例中的vars子目录已被省略。

创建角色框架

方法一:
手动创建(使用标准的Linux命令创建新角色所需的所有子目录和文件)

[root@ansible test]# mkdir -p httpd/{defaults,vars,templates,files,tasks,handles}
[root@ansible test]# tree httpd
httpd
├── defaults
├── files
├── handles
├── tasks
├── templates
└── vars

6 directories, 0 files
[root@ansible test]# touch httpd/{defaults/main.yml,vars/main.yml}
[root@ansible test]# tree httpd
httpd
├── defaults
│   └── main.yml
├── files
├── handles
├── tasks
├── templates
└── vars
    └── main.yml

6 directories, 2 files

方法二:
通过命令一步部署

	ansible-galaxy命令

可用于管理Ansible角色,包括新角色的创建。用户可以运行ansible-galaxy init来创建新角色的目录结构。指定角色的名称作为命令的参数,该命令在当前工作目录中为新角色创建子目录

[root@ansible test]# ansible-galaxy init httpd
- Role httpd was created successfully
[root@ansible test]# tree httpd/
httpd/
├── 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

定义角色内容

创建后必须写角色内容(所有东西都是围绕 tasks/main.yml 是由角色运行的主要任务列表)

下列tasks/main.yml文件管理受管主机上的/etc/motd文件。它使用template模块将名为motd.j2的模板部署到受管主机上。因为template模块是在角色任务而非playbook任务内配置的,所以从角色的templates子目录检索motd.j2模板

[root@ansible httpd]# cd templates/
[root@ansible templates]# ls
httpd.conf.j2
[root@ansible templates]# cd ..
[root@ansible httpd]# vim defaults/main.yml 
[root@ansible httpd]# cat defaults/main.yml 
---
# defaults file for httpd
PORT: 80
[root@ansible httpd]# vim 
defaults/    handlers/    README.md    templates/   .travis.yml
files/       meta/        tasks/       tests/       vars/
[root@ansible httpd]# vim tasks/main.yml 
[root@ansible httpd]# vim handlers/main.yml 
[root@ansible httpd]# cat tasks/main.yml 
---
# tasks file for httpd
- name: install httpd
  yum:
    name: httpd
    state: present

- name: config httpd
  template: 
    src: templates/httpd.conf/j2
    dest: /etc/httpd/conf/httpd.conf
  notify: restart httpd

- name: service httpd
  service: 
    name: httpd
    state: started
    enabled: yes
[root@ansible httpd]# cat handlers/main.yml 
---
# handlers file for httpd
- name: restart httpd
  service: 
    name: httpd
    state: restarted
[root@ansible test]# ansible-playbook httpd.yml 

PLAY [httpd] *******************************************************************

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

TASK [install httpd] ***********************************************************
ok: [192.168.230.98]

TASK [config httpd] ************************************************************
changed: [192.168.230.98]

TASK [service httpd] ***********************************************************
changed: [192.168.230.98]

RUNNING HANDLER [restart httpd] ************************************************
changed: [192.168.230.98]

PLAY RECAP *********************************************************************
192.168.230.98             : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

角色内容开发的推荐做法

角色允许以模块化方式编写playbook。为了最大限度地提高新开发角色的效率,请考虑在角色开发中采用以下推荐做法:

  1. 在角色自己的版本控制存储库中维护每个角色。Ansible很适合使用基于git的存储库。
  2. 角色存储库中不应存储敏感信息,如密码或SSH密钥。敏感值应以变量的形式进行参数化,其默认值应不敏感。使用角色的playbook负责通过Ansible Vault变量文件、环境变量或其他ansible-playbook选项定义敏感变量。
  3. 使用ansible-galaxy init启动角色,然后删除不需要的任何目录和文件。
  4. 创建并维护README.md和meta/main.yml文件,以记录用户的角色的用途、作者和用法。
  5. 让角色侧重于特定的用途或功能。可以编写多个角色,而不是让一个角色承担许多任务。
  6. 经常重用和重构角色。避免为边缘配置创建新的角色。如果现有角色能够完成大部分的所需配置,请重构现有角色以集成新的配置方案。使用集成和回归测试技术来确保角色提供所需的新功能,并且不对现有的playbook造成问题。
定义角色依赖项

角色依赖项使得角色可以将其他角色作为依赖项包含在内
(简单来说就是安装一个角色如果需要安装依赖包需告知)

dependencies:
  - role: apache
    port: 8080
  - role: postgres
    dbname: serverlist
    admin_user: felix

默认情况下,角色仅作为依赖项添加到playbook中一次。若有其他角色也将它作为依赖项列出,它不会再次运行。此行为可以被覆盖,将meta/main.yml文件中的allow_duplicates变量设置为yes即可。

注意:尽量不适用,因为使用依赖包会让维护角色变得更加困难

在playbook中使用角色

需要访问角色,可以在play的roles:部分引用它
未指定变量将会使用默认变量值应用该角色

[root@localhost ~]# cat playbook.yml
---
- name: use motd role playbook
  hosts: httpd
  remote_user: devops
  become: true
  roles:
    - motd

执行该playbook时,因为角色而执行的任务可以通过角色名称前缀来加以识别。

	[root@localhost ~]# ansible-playbook -i inventory playbook.yml
通过变量更改角色的行为

编写良好的角色利用默认变量来改变角色行为,(比如我之前用的是80端口,通过变量可以更改为82端口)
使之与相关的配置场景相符。这有助于让角色变得更为通用,可在各种不同的上下文中重复利用

如果通过以下方式定义了相同的变量,则角色的defaults目录中定义的变量的值将被覆盖

在清单文件中定义,作为主机变量或组变量
在playbook项目的group_vars或host_vars目录下的YAML文件中定义
作为变量嵌套在play的vars关键字中定义
在play的roles关键字中包含该角色时作为变量定义
#先去httpd查看端口号
[root@apache ~]# ss -anlt
State   Recv-Q  Send-Q     Local Address:Port     Peer Address:Port  
LISTEN  0       128              0.0.0.0:111           0.0.0.0:*     
LISTEN  0       32         192.168.122.1:53            0.0.0.0:*     
LISTEN  0       128              0.0.0.0:22            0.0.0.0:*     
LISTEN  0       5              127.0.0.1:631           0.0.0.0:*     
LISTEN  0       128                 [::]:111              [::]:*     
LISTEN  0       128                    *:80                  *:*     
LISTEN  0       128                 [::]:22               [::]:*     
LISTEN  0       5                  [::1]:631              [::]:*     
[root@localhost ~]# cat playbook.yml
---
[root@ansible httpd]# cp defaults/main.yml vars/main.yml 
cp:是否覆盖'vars/main.yml'? yes
[root@ansible httpd]# cat defaults/main.yml 
---
# defaults file for httpd
PORT: 82
[root@ansible httpd]# cat vars/main.yml 
---
# defaults file for httpd
PORT: 80
[root@ansible httpd]# cd ..
[root@ansible test]# ls
httpd  httpd.yml  selinux  sx.yml  timesync
[root@ansible test]# ansible-playbook httpd.yml 

PLAY [httpd] *******************************************************************

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

TASK [install httpd] ***********************************************************
ok: [192.168.230.98]

TASK [config httpd] ************************************************************
ok: [192.168.230.98]

TASK [service httpd] ***********************************************************
ok: [192.168.230.98]

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

#执行后查看
[root@apache ~]# ss -anlt
State   Recv-Q  Send-Q     Local Address:Port     Peer Address:Port  
LISTEN  0       128              0.0.0.0:111           0.0.0.0:*     
LISTEN  0       32         192.168.122.1:53            0.0.0.0:*     
LISTEN  0       128              0.0.0.0:22            0.0.0.0:*     
LISTEN  0       5              127.0.0.1:631           0.0.0.0:*     
LISTEN  0       128                 [::]:111              [::]:*     
LISTEN  0       128                    *:80                  *:*     
LISTEN  0       128                 [::]:22               [::]:*     
LISTEN  0       5                  [::1]:631              [::]:*    

结果显示:以这种方式定义时,system_owner变量将替换同一名称的默认变量的值。嵌套在vars关键字内的任何变量定义不会替换在角色的vars目录中定义的同一变量的值。

注意:
在play中使用角色变量时,变量的优先顺序可能会让人困惑。

  • 几乎任何其他变量都会覆盖角色的默认变量,如清单变量、playvars变量,以及内嵌的角色参数等。
  • 较少的变量可以覆盖角色的vars目录中定义的变量。事实、通过include_vars加载的变量、注册的变量和角色参数是其中一些具备这种能力的变量。清单变量和playvars无此能力。这非常重要,因为它有助于避免用户的play意外改变角色的内部功能
  • 不过,正如上述示例中最后一个所示,作为角色参数内嵌声明的变量具有非常高的优先级它们可以覆盖角色的vars目录中定义的变量。如果某一角色参数的名称与playvars或角色vars中设置的变量或者清单变量或playbook变量的名称相同,该角色参数将覆盖另一个变量。

使用ansible galaxy 部署角色

介绍ansible galaxy

Ansible Galaxy 是一个Ansible内容公共资源库,这些内容由许许多多Ansible管理员和用户编写。它包含数千个Ansible角色,具有可搜索的数据库,可帮助Ansible用户确定或许有助于他们完成管理任务的角色。Ansible Galaxy含有面向新的Ansible用户和角色开发人员的文档和视频链接。

官方文档:https://galaxy.ansible.com

从Ansible Galaxy获取和管理角色的ansible-galaxy命令也可用于为您的项目获取和管理自有的git存储库中的角色。

获取Ansible Galaxy帮助
  1. 点击Ansible Galaxy网站主页上的Documenttaion标签

  2. 进入描述如何使用Ansible Galaxy的页面

    该页面包含了介绍如何从Ansible Galaxy下载和使用角色的内
    容,同时也提供关于开发角色并上传到Ansible Galaxy的说明
    
浏览Ansible Galaxy中的角色

点击Ansible Galaxy网站主页上左侧的Search标签

	用户可以访问关于Ansible Galaxy上发布的角色的信息。用户
可以使用标记通过角色的名称或通过其他角色属性来搜索Ansible角色。

(结果按照Best Match分数降序排列,此分数依据角色质量、角色受欢迎程度和搜索条件计算而得)

Ansible Galaxy命令行工具

从命令行搜索角色

ansible-galaxy search子命令在Ansible Galaxy中搜索角色
如果以参数形式指定了字符串,则可以按照关键字去搜索角色

(用户可以使用–author、–platforms和–galaxy-tags选项来缩小搜索结果的范围。也可以将这些选项用作主要的搜索键)

	ansible-galaxy role --help     #Ansible Galaxy的帮助文档
	ansible-galaxy search 'redis' --platforms EL    #显示包含redis并且适用于企业Linux(EL)平台的角色的名称
	ansible-galaxy role search    #查看Ansible Galaxy网站内所有文档

实例:

[root@ansible ansible]# ansible-galaxy role search httpd    #在这个平台内搜索httpd

Found 329 roles matching your search:

 Name                                                          Descr>
 ----                                                          ----->
 2kloc.trellis-monit                                           Insta>
 aarunmichael.base_httpd                                       your >
 a_arvind_k.base_httpd                                         your >
 abdelmouhssine.hardening_cis_apache_http_server_2_4_benchmark CLOUD>
 abdusamy.web_server_role                                      Deplo>
 acandid.httpd                                                 Insta>
 acropia.httpd                                                 IT Pr>
 adellam.389ds_server                                          Insta>
 ahuffman.patching                                             An An>
 ahuffman.sat6_create_hosts                                    An An>
 aishee.ansible_redhat_centos_7                                Apply>
/robertdebock     #这里是查找作者名字


#结果:
...skipping...
 robertdebock.ca                                               Insta>
 robertdebock.ca                                               Insta>
 robertdebock.certbot                                          Insta>
 robertdebock.haproxy                                          Insta>
 robertdebock.httpd                                            Insta>
 robertdebock.mediawiki                                        Insta>
 robertdebock.moodle                                           Insta>
 robertdebock.nextcloud                                        Insta>
 robertdebock.owncloud                                         Insta>
 robertdebock.php                                              Insta>
 robertdebock.php_fpm                                          The p>
 robertdebock.phpmyadmin                                       Insta>
 robertdebock.roundcubemail                                    Insta>
 robertdebock.users                                            The p>
 robertdebock.zabbix_web                                       Insta>
 robinnepomukmai.nexus3_oss                                    Nexus>
 sadsfae.ansible-nagios                                        Playb>

注意:查找什么必须存在 例如查找作者,必须有这个作者

从Ansible Galaxy安装角色

ansible-galaxy install子命令从Ansible Galaxy下载角色,并将它安装到控制节点本地

默认情况下,角色安装到用户的roles_path下的第一个可写目录中。根据为Ansible设置的默认roles_path,角色通常将安装到用户的~/.ansible/roles目录。默认的roles_path可能会被用户当前Ansible配置文件或环境变量ANSIBLE_ROLES_PATH覆盖,这将影响ansible-galaxy的行为。

	ansible-galaxy install geerlingguy.redis -p roles/    
	#将geerlingguy.redis角色安装到playbook项目的roles目录中

实例:
安装一个geerlingguy.redis

[root@ansible ~]# ansible-galaxy install geerlingguy.redis
- downloading role 'redis', owned by geerlingguy
- downloading role from https://github.com/geerlingguy/ansible-role-redis/archive/1.6.0.tar.gz
- extracting geerlingguy.redis to /root/.ansible/roles/geerlingguy.redis
- geerlingguy.redis (1.6.0) was installed successfully

#查看安装位置,在当前目录的ansible/roles/里
[root@ansible ~]# ls .ansible/roles/
geerlingguy.redis

实例2:
ansible-galaxy将geerlingguy.redis角色安装到playbook项目的roles目录中

[root@ansible ansible]# ls
playbook.yml  roles
[root@ansible ansible]# ansible-galaxy install geerlingguy.redis -p roles/
- downloading role 'redis', owned by geerlingguy
- downloading role from https://github.com/geerlingguy/ansible-role-redis/archive/1.6.0.tar.gz
- extracting geerlingguy.redis to /project/roles/geerlingguy.redis
- geerlingguy.redis (1.6.0) was installed successfully
[root@ansible ansible]# ls roles/
geerlingguy.redis  httpd
使用要求文件安装角色

可以使用ansible-galaxy,根据某一文本文件中的定义来安装一个角色列表

实例:
安装一个geerlingguy.redis

[root@ansible roles]# ls
geerlingguy.redis  httpd
[root@ansible roles]# rm -rf geerlingguy.redis/       //先删掉刚下载的角色
[root@ansible roles]# ls
httpd
[root@ansible roles]# cat requirements.yml            //写个文件添加要下载的角色
- src: geerlingguy.redis
- src: robertdebock.httpd

重要
一定要指定角色版本,特别是生产环境中的playbook。
如果不指定版本,将会获取角色的最新版本。如果作者对角色做出了更改,并与用户的playbook不兼容,这可能会造成自动化失败或其他问题。

若要使用角色文件来安装角色,可使用-r REQUIREMENTS-FILE选项:

	ansible-galaxy install -r roles/requirements.yml -p roles

用户可以使用ansible-galaxy来安装不在Ansible Galaxy中的角色。可以在私有的Git存储库或Web服务器上托管自有的专用或内部角色。

实例:
ansible-galaxy将geerlingguy.redis角色安装到playbook项目的roles目录中

[root@ansible ansible]# ansible-galaxy install -r roles/requirements.yml -p roles/
- downloading role 'redis', owned by geerlingguy
- downloading role from https://github.com/geerlingguy/ansible-role-redis/archive/1.6.0.tar.gz
- extracting geerlingguy.redis to /project/roles/geerlingguy.redis
- geerlingguy.redis (1.6.0) was installed successfully
- downloading role 'httpd', owned by robertdebock
- downloading role from https://github.com/robertdebock/ansible-role-httpd/archive/5.3.0.tar.gz
- extracting robertdebock.httpd to /project/roles/robertdebock.httpd
- robertdebock.httpd (5.3.0) was installed successfully
- src: geerlingguy.redis
  version: "1.5.0"  
[root@ansible ansible]# ls roles/        //查看,成功安装角色
geerlingguy.redis  httpd  requirements.yml  robertdebock.httpd

src关键字指定Ansible Galaxy角色名称。如果角色没有托管在Ansible Galaxy中,则src关键字将指明角色的URL。

如果角色托管在来源控制存储库中,则需要使用scm属性。ansible-galaxy命令能够从基于git或mercurial的软件存储库下载和安装角色。基于Git的存储库要求scm值为git,而托管在Mercurial存储库中的角色则要求值为hg。如果角色托管在Ansible Galaxy中,或者以tar存档形式托管在Web服务器上,则省略scm关键字。

name关键字用于覆盖角色的本地名称。version关键字用于指定角色的版本。version关键字可以是与严自角色的软件存储库的分支、标记或提交哈希对应的任何值

若要安装与playbook项目关联的角色,可执行ansible-galaxy install命令:

	[root@localhost project]# ansible-galaxy install -r roles/requirements.yml -p roles
管理下载的角色
  • 具体命令:
命令说明
init初始化
remove卸载
delete删除、卸载
list列出(可以查看安装过的名字和版本)
search搜索
import导入
setup管理基层
info查看详细信息
install安装(可以从网站链接或文件内装)

例如:
列出本地找到的角色:

ansible-galaxy list

删除本地角色:

ansible-galaxy remove nginx-acme-ssh

在playbook中使用下载并安装的角色的方式与任何其他角色都一样

roles部分中利用其下载的角色名称来加以引用。如果角色不在项目的roles目录中,则将检查roles_path来查看角色是否安装在了其中一个目录中,将使用第一个匹配项。以下use-role.ymlplaybook引用了redis_prod和geerlingguy.redis角色

实例:

[root@localhost project]# cat use-role.yml
---
- name: use redis_prod for prod machines
  hosts: redis_prod_servers
  remote_user: devops
  become: True
  roles:
    - redis_prod

- name: use geerlingguy.redis for Dev machines
  hosts: redis_dev_servers
  remote_user: devops
  become: True
  roles:
    - geerlingguy.redis

注意:此playbook使不同版本的geerlingguy.redis角色应用到生产和开发服务器。借助这种方式可以对角色更改进行系统化测试和集成,然后再部署到生产服务器上。如果角色的近期更改造成了问题,则借助版本控制来开发角色,就能回滚到过去某一个稳定的角色版本。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值