09Ansible 包含与导入、角色的结构、系统角色的使用

1.管理大型playbook

如果playbook很长或很复杂,我们可以将其分成较小的文件以便于管理。可采用模块化方式将多个playbook组合为一个主要playbook,或者将文件中的任务列表插入play。这样可以更轻松地在不同项目中重用play或任务序列。

1.1包含或导入文件

Ansible可以使用两种操作将内容带入playbook。可以包含内容,也可以导入内容。

包含内容是一个动态操作。在playbook运行期间,Ansible会在内容到达时处理所包含的内容。

导入内容是一个静态操作。在运行开始之前,Ansible在最初解析playbook时预处理导入的内容。

1.2导入playbook

import_playbook指令允许将包含play列表的外部文件导入playbook。换句话说,可以把一个或多个额外playbook导入到主playbook中。

由于导入的内容是一个完整的playbook,因此import_playbook功能只能在playbook的顶层使用,不能在play内使用。如果导入多个playbook,则将按顺序导入并运行它们。

导入两个额外playbook的主playbook的简单示例如下所示:

- name: Prepare the web server
  import_playbook: web.yml
  
- name: Prepare the database server
  import_playbook: db.yml

还可以使用导入的playbook在主playbook中交替play。

- name: Play 1
  hosts: localhost
  tasks:
    - debug:
      msg: Play 1
      
- name: Import Playbook
  import_playbook: play2.yml

在此例中,Play 1首先运行,然后运行从play2.ymlplaybook中导入的play。

举例:

[root@master httpd]# cat install.yml 
---
- hosts: httpd
  gather_facts: no
  tasks:
    - name: install apache
      dnf:
        name: httpd
        state: present



[root@master httpd]# cat config.yml 
---
- hosts: httpd
  gather_facts: no
  tasks:
    - name: config httpd
      copy:
        src: /opt/project/playbook/httpd/httpd.conf
        dest: /etc/httpd/conf/httpd.conf
      notify:
        - restart httpd

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

  handlers:
    - name: restart httpd
      service:
        name: httpd
        state: restarted
[root@master httpd]# 

[root@master httpd]# cat main.yml 
- name: install apache for httpd
  import_playbook: install.yml
- name: config apache for httpd
  import_playbook: config.yml  
[root@master httpd]# 

1.3导入和包含任务

可以将任务文件中的任务列表导入或包含在play中。任务文件是包含一个任务平面列表的文件:

[root@localhost ~]# cat webserver_tasks.yml
- name: Installs the httpd package
  yum:
    name: httpd
    state: latest
    
- name: Starts the httpd service
  service:
    name: httpd
    state: started

1.4导入任务文件

可以使用import_tasks功能将任务文件静态导入playbook内的play中。导入任务文件时,在解析该playbook时将直接插入该文件中的任务。Playbook中的import_tasks的位置控制插入任务的位置以及运行多个导入的顺序。

---
- name: Install web server
  hosts: webservers
  tasks:
  - import_tasks: webserver_tasks.yml

举例:

[root@master httpd]# cat install.yml 
- name: install apache
  dnf:
    name: httpd
    state: present



[root@master httpd]# cat config.yml 
- name: config httpd
  copy:
    src: /opt/project/playbook/httpd/httpd.conf
    dest: /etc/httpd/conf/httpd.conf

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

[root@master httpd]# 

[root@master httpd]# cat main.yml 
---
- hosts: httpd
  gather_facts: no
  tasks:
  - import_tasks: install.yml
  - import_tasks: config.yml
[root@master httpd]# 

导入任务文件时,在解析该playbook时将直接插入该文件中的任务。由于import_tasks在解析playbook时静态导入任务,因此对其工作方式有一些影响。

  • 使用import_tasks功能时,导入时设置的when等条件语句将应用于导入的每个任务
  • 无法将循环用于import_tasks功能
  • 如果使用变量来指定要导入的文件的名称,则将无法使用主机或组清单变量

1.5包含任务文件

可以使用include_tasks功能将任务文件动态导入playbook内的play中。

---
- name: Install web server
  hosts: webservers
  tasks:
  - include_tasks: webserver_tasks.yml

举例:

[root@master httpd]# cat main.yml 
---
- hosts: httpd
  gather_facts: no
  tasks:
  - include_tasks: install.yml
  - import_tasks: config.yml
[root@master httpd]# 

[root@master project]# ansible-playbook --list-tasks playbook/httpd/main.yml 

playbook: playbook/httpd/main.yml

  play #1 (httpd): httpd	TAGS: []
    tasks:
      include_tasks	TAGS: []
      config httpd	TAGS: []
      service for httpd	TAGS: []
[root@master project]# 

在play运行并且这部分play到达前,include_tasks功能不会处理playbook中的内容。Playbook内容的处理顺序会影响包含任务功能的工作方式。

  • 使用include_tasks功能时,包含时设置的when等条件语句将确定任务是否包含在play中
  • 如果运行ansible-playbook --list-tasks以列出playbook中的任务,则不会显示已包含任务文件中的任务。将显示包含任务文件的任务。相比之下,import_tasks功能不会列出导入任务文件的任务,而列出已导入任务文件中的各个任务
  • 不能使用ansible-playbook --start-at-task从已包含任务文件中的任务开始执行playbook
  • 不能使用notify语句触发已包含任务文件中的处理程序名称。可以在包含整个任务文件的主playbook中触发处理程序,在这种情况下,已包含文件中的所有任务都将运行

1.6任务文件的用例

任务文件的用例请参考下面的示例,在这些情景中将任务组作为与playbook独立的外部文件来管理或许有所帮助:

  • 如果新服务器需要全面配置,则管理员可以创建不同的任务集合,分别用于创建用户、安装软件包、配置服务、配置特权、设置对共享文件系统的访问权限、强化服务器、安装安全更新,以及安装监控代理等。每一任务集合可通过单独的自包含任务文件进行管理
  • 如果服务器由开发人员、系统管理员和数据库管理员统一管理,则每个组织可以编写自己的任务文件,再由系统经理进行审核和集成
  • 如果服务器要求特定的配置,它可以整合为按照某一条件来执行的一组任务。换句话说,仅在满足特定标准时才包含任务
  • 如果一组服务器需要运行某一项/组任务,则它/它们可以仅在属于特定主机组的服务器上运行

1.7管理任务文件

为方便管理,可以创建专门用于任务文件的目录,并将所有任务文件保存在该目录中。然后playbook就可以从该目录包含或导入任务文件。这样就可以构建复杂的playbook,同时简化其结构和组件的管理。

[root@master httpd]# mkdir tasks
[root@master httpd]# mv config.yml install.yml tasks/
[root@master httpd]# ls
httpd.conf  main.yml  tasks
[root@master httpd]# cd tasks/
[root@master tasks]# ls
config.yml  install.yml

[root@master httpd]# cat main.yml 
---
- hosts: httpd
  gather_facts: no
  tasks:
  - include_tasks: tasks/install.yml
  - import_tasks: tasks/config.yml
[root@master httpd]# 

1.8为外部play和任务定义变量

使用Ansible的导入和包含功能将外部文件中的play或任务合并到playbook中极大地增强了在Ansible环境中重用任务和playbook的能力。为了最大限度地提高重用可能性,这些任务和play文件应尽可能通用。变量可用于参数化play和任务元素,以扩大任务和play的应用范围。

例如,以下任务文件将安装httpd服务所需的软件包,然后启用并启动必要的服务。

[root@master tasks]# cat install.yml 
- name: install apache
  dnf:
    name: httpd
    state: present



[root@master tasks]# cat config.yml 
- name: config httpd
  copy:
    src: /opt/project/playbook/httpd/httpd.conf
    dest: /etc/httpd/conf/httpd.conf

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

[root@master tasks]# 

如果如下例所示对软件包和服务元素进行参数化,则任务文件也可用于安装和管理其他软件及其服务,而不仅仅用于httpd服务。

[root@master tasks]# cat install.yml 
- name: install {{ package }}
  dnf:
    name: '{{ package }}'
    state: present



[root@master tasks]# 

[root@master tasks]# cat config.yml 
- name: config httpd
  copy:
    src: /opt/project/playbook/httpd/httpd.conf
    dest: /etc/httpd/conf/httpd.conf

- name: service for {{ service_name }}
  service:
    name: '{{ service_name }}'
    state: started
    enabled: yes

[root@master tasks]# 

随后,在将任务文件合并到一个playbook中时,定义用于执行该任务的变量,如下所示:

[root@master httpd]# cat main.yml 
---
- hosts: httpd
  gather_facts: no
  tasks:
  - include_tasks: tasks/install.yml
    vars:
      package: httpd
  - import_tasks: tasks/config.yml
    vars:
      service_name: httpd

Ansible使传递的变量可用于从外部文件导入的任务。

使用相同的技术使play文件更具有可重用性。将play文件合并到playbook中时,传递变量以用于执行该play,如下所示:

[root@master httpd]# cat main.yml 
---
- hosts: httpd
  gather_facts: no
  vars:
    package: httpd
  tasks:
  - include_tasks: tasks/install.yml
  - import_tasks: tasks/config.yml
[root@master httpd]# 

2.描述角色结构

2.1利用角色构造ansible playbook

随着开发更多的playbook,我们可能会发现有很多机会重复利用以前缩写的playbook中的代码。或许,一个用于为某一应用配置MySQL数据库的play可以改变用途,通过利用不同的主机名、密码和用户来为另一个应用配置MySQL数据库。

但在现实中,这个play可能比较冗长且复杂,有许多包含或导入的文件,以及用于管理各种情况的任务和处理程序。将所有这些代码复制到另一playbook中可能比较困难。

Ansible角色提供了一种方法,让用户能以通用的方式更加轻松地重复利用Ansible代码。我们可以在标准化目录结构中打包所有任务、变量、文件、模板,以及调配基础架构或部署应用所需的其他资源。只需通过复制相关的目录,将角色从一个项目复制到另一个项目。然后,只需从一个play调用该角色就能执行它。

借助编写良好的角色,可以从playbook中向角色传递调整其行为的变量,设置所有站点相关的主机名、IP地址、用户名,或其他在本地需要的具体详细信息。例如,部署数据库服务器的角色可能已编写为支持多个变量,这些变量用于设置主机名、数据库管理员用户和密码,以及需要为安装进行自定义的其他参数。角色的作者也可以确保在选择不在play中设置变量值时,为这些变量设定合理的默认值。

Ansible角色具有下列优点:

  • 角色可以分组内容,从而与他人轻松共享代码
  • 可以编写角色来定义系统类型的基本要素:Web服务器、数据库服务器、Git存储库,或满足其他用途
  • 角色使得较大型项目更容易管理
  • 角色可以由不同的管理员并行开发

除了自行编写、使用、重用和共享角色外,还可以从其他来源获取角色。一些角色已包含在rhel-system-roles软件包中,用户也可以从Ansible Galaxy网站获取由社区提供支持的许多角色。https://docs.ansible.com/

2.2检查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中使用时不应更改。

并非每个角色都拥有所有这些目录。

2.3定义变量和默认值

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

默认变量允许为可在play中使用的变量设置默认值,以配置角色或自定义其行为。它们通过在角色目录层次结构中创建含有键值对的defaults/main.yml文件来定义。默认变量具有任何可用变量中最低的优先级。它们很容易被包括清单变量在内的任何其他变量覆盖。这些变量旨在让用户在编写使用该角色的play时可以准确地自定义或控制它将要执行的操作。它们可用于向角色提供所需的信息,以正确地配置或部署某些对象。

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

注意:
角色不应该包含特定于站点的数据。它们绝对不应包含任何机密,如密码或私钥。

这是因为角色应该是通用的,可以重复利用并自由共享。特定于站点的详细信息不应硬编码到角色中。

机密应当通过其他途径提供给角色。这是用户可能要在调用角色时设置角色变量的一个原因。play中设置的角色变量可以提供机密,或指向含有该机密的Ansible Vault加密文件。

2.4在playbook中使用ansible角色

在playbook中使用角色非常简单。下例演示了调用Ansible角色的一种方式:

---
- hosts: remote.example.com
  roles:
    - role1
    - role2

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

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

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

---
- hosts: remote.example.com
  roles:
    - role: role1
    - role: role2
      var1: val1
      var2: val2

2.5安装RHEL系统角色

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

安装RHEL系统角色

[root@master httpd]# dnf -y install rhel-system-roles

安装后,RHEL系统角色位于/usr/share/ansible/roles目录中:

[root@master httpd]# ls /usr/share/ansible/roles/

红帽企业Linux中的默认roles_path在路径中包含/usr/share/ansible/roles,因此在playbook引用这些角色时Ansible可以很轻松的找到它们。

注意
如果在当前Ansible配置文件中覆盖了roles_path,设置了环境变量ANSIBLE_ROLES_PATH,或者roles_path中更早列出的目录下存在另一个同名的角色,则Ansible可能无法找到系统角色。
[root@master roles]# cp -a /usr/share/ansible/roles/rhel-system-roles.timesync timesync
[root@master roles]# ls
timesync
[root@master timesync]# less README.md
Install and configure linuxptp to synchronize the system clock with a
grandmaster in PTP domain number 0, which is accessible on interface eth0:

```yaml
- hosts: targets
  vars:
    timesync_ptp_domains:
      - number: 0
        interfaces: [ eth0 ]
  roles:
    - rhel-system-roles.timesync
[root@master project]# cat playbook/mytime.yml 
---
- hosts: httpd
  vars:
    timesync_ntp_servers:
      - hostname: time1.aliyun.com
        iburst: yes
  roles:
    - timesync

[root@master project]# 

2.6配置SElinux角色

用于配置rhel-system-roles.selinux角色的变量的详细记录位于其README.md文件中。以下示例演示了使用此角色的一些方法。

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

selinux_state: enforcing

selinux_booleans变量取一个要调整的SELinux布尔值的列表作为值。列表中的每一项是变量的散列/字典:布尔值的name、state(它应是on还是off),以及该设置是否应在重新引导后persistent。

本例将httpd_enable_homedirs永久设为on:

selinux_booleans:
  - name: 'httpd_enable_homedirs'
    state: 'on'
    persistent: 'yes'

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'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彭宇栋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值