如何使用 Ansible 角色来抽象基础架构环境

介绍

Ansible 是一个配置管理工具,旨在为管理员和操作团队自动化控制服务器,使用 Ansible 您可以使用单一的中央服务器来控制和配置使用 SSH 和 Python 作为唯一的要求的许多不同的远程系统。

Ansible 基于任务定义在其管理的服务器上执行任务. 这些任务使用每个任务的小片 YAML 调用内置和社区维护的 Ansible 模块。

随着您使用单个 Ansible 控制节点管理的系统的数量和多样性变得更加复杂,将任务组合成 Ansible playbooks是有意义的。

然而,当它们负责为每个系统配置多个任务的许多不同的系统时,播放簿可能会变得复杂,因此 Ansible 还允许您在名为 Role的目录结构中组织任务。

本教程将探索如何创建角色,以及如何将模板,静态文件和变量添加到角色。一旦您熟悉构建角色的基本知识,我们将使用Ansible Galaxy(https://galaxy.ansible.com/)将社区贡献角色纳入播放书中。

前提条件

要跟随本教程,你需要安装和配置 Ansible(https://andsky.com/tech/tutorials/how-to-install-and-configure-ansible-on-ubuntu-18-04),以便你可以创建和运行播放书。

什么是 Ansible 角色?


在前提教程中,你学会了如何在终端中使用ansible命令运行核心 Ansible 工具,你还学会了如何将任务收集到玩本中,并使用ansible-playbook命令运行它们。

角色是对任务和玩本的抽象水平,允许您在模块化和可重复使用的格式中构建您的Ansible配置。随着您为玩本添加越来越多的功能和灵活性,它们可能会变得模糊和难以维护。角色允许您将复杂的玩本分解成单独的小块,可以由中央入口点协调。

1[label Example Playbook]
2---
3- hosts: all
4  become: true
5  roles:
6    - apache
7  vars:
8    doc_root: /var/www/example

要构建一个 Apache 网页服务器,需要执行的所有任务将包含在我们将创建的apache角色中,而不是单独列出每个任务,就像我们在 Configuration Management 101: Writing Ansible Playbooks的前提条件中所做的。

将您的 Ansible 设置组织成角色允许您在不同类型的服务器之间重复使用常见配置步骤. 虽然通过在单个播放簿中包含多个任务文件也可以这样做,但角色依赖已知的目录结构和文件名称惯例来自动加载在播放中使用的文件。

一般来说,角色背后的想法是允许您使用一致的结构共享和重复使用任务,同时使其易于维护,而无需对整个基础设施重复任务。

创建一个角色


要创建一个 Ansible 角色,您需要一个特定的目录结构. 角色总是需要此目录布局,以便 Ansible 可以找到并使用它们。

在这里,我们假定您一直在使用用户的主目录作为 Ansible 工作目录. 如果您将 Ansible 配置保存在不同的位置,则需要更改(cd)到该目录。

要开始,让我们创建一个名为角色的目录。Ansible将在本教程中稍后使用我们的新角色。

1cd ~
2mkdir roles
3cd roles

在本目录中,我们将定义可在多个播放簿和不同的服务器上重复使用的角色。我们将创建的每个角色都需要自己的目录。我们将从 Configuration Management 101: Writing Ansible Playbooks 教程中采取 Apache 播放簿的示例,并将其转化为可重复使用的 Ansible 角色。

作为参考,这是该教程的游戏书:

 1[label playbook.yml]
 2---
 3- hosts: all
 4  become: true
 5  vars:
 6    doc_root: /var/www/example
 7  tasks:
 8    - name: Update apt
 9      apt: update_cache=yes
10
11    - name: Install Apache
12      apt: name=apache2 state=latest
13
14    - name: Create custom document root
15      file: path={{ doc_root }} state=directory owner=www-data group=www-data
16
17    - name: Set up HTML file
18      copy: src=index.html dest={{ doc_root }}/index.html owner=www-data group=www-data mode=0644
19
20    - name: Set up Apache virtual host file
21      template: src=vhost.tpl dest=/etc/apache2/sites-available/000-default.conf
22      notify: restart apache
23
24  handlers:
25    - name: restart apache
26      service: name=apache2 state=restarted

首先,让我们为我们的角色创建一个Apache目录,并填充所需目录:

1mkdir apache
2cd apache

接下来,我们将创建所需的一组子目录,让Ansible知道它应该使用内容作为一个角色。

1mkdir defaults files handlers meta templates tasks vars

这些目录将包含执行我们的角色所需的所有代码. 许多角色只会使用其中一个或几个目录,这取决于所涉及的任务的复杂性。

以下是每个目录代表的描述:

  • 默认 : 此目录允许您设置包含或依赖角色的默认变量 。 在此设置的任何默认值都可以被游戏本或目录文件所推翻. () ( )* 翻译: 此目录包含可复制到远程服务器或执行的静态文件和脚本文件 。 () ( )* {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}你觉得呢? 以前在您的游戏本中的所有处理器现在可以添加到此目录中 。 () ( )* 说吧, 此目录保留给角色元数据,通常用于依赖管理. 例如,您可以定义在引用当前角色之前必须应用的角色列表. () ( )* QQtemplates : 此目录被保留给模板, 在远程主机上生成文件 。 模板通常使用位于 " vars " 目录的文件所定义的变量,以及运行时收集的主机信息。 () ( )* 任务 : 此目录包含一个或多个文件, 通常在常规 Ansible 游戏本的 " 任务 " 章节中定义任务 。 这些任务可以直接引用各自目录中包含在角色内的文件和模板,而不需要提供完整的文件路径. ( ( )* QQVars`**:一个角色的变量可以在本目录内的文件中指定,然后在其它角色中引用. (_) (英语)

如果名为main.yml 的文件存在于目录中,其内容将自动添加到呼叫角色的播放簿中,但这不适用于文件模板目录,因为其内容需要明确引用。

把剧本变成角色


现在你已经熟悉了 Ansible 角色中的每个目录用于什么,我们将 Apache 播放簿转化为一个角色,以便更好地组织事情。

我们应该已经从最后一节设置了角色/apache2/subdirectories结构,现在我们需要创建一些YAML文件来定义我们的角色。

创建任务 main.yml 文件


我们将从任务子目录开始. 现在移动到该目录:

1cd ~/roles/apache/tasks

我们需要在这个目录中创建一个 main.yml 文件,我们会填充整个 Apache 播放簿的内容,然后编辑它以仅包括任务。

1nano main.yml

檔案在你開始時應該是這樣的:

 1[label main.yml]
 2---
 3- hosts: all
 4  become: true
 5  vars:
 6    doc_root: /var/www/example
 7
 8  tasks:
 9    - name: Update apt
10      apt: update_cache=yes
11
12    - name: Install Apache
13      apt: name=apache2 state=latest
14
15    - name: Create custom document root
16      file: path={{ doc_root }} state=directory owner=www-data group=www-data
17
18    - name: Set up HTML file
19      copy: src=index.html dest={{ doc_root }}/index.html owner=www-data group=www-data mode=0644
20
21    - name: Set up Apache virtual host file
22      template: src=vhost.tpl dest=/etc/apache2/sites-available/000-default.conf
23      notify: restart apache
24
25  handlers:
26    - name: restart apache
27      service: name=apache2 state=restarted

我们只想保留第一个---行和突出的任务部分中的行,我们也可以删除我们的任务左侧的外部空间,我们还会添加一个新的部分,以启用一个名为modsecurity的Apache模块,我们将在本教程中稍后配置。

 1[label main.yml]
 2---
 3- name: Update apt
 4  apt: update_cache=yes
 5
 6- name: Install Apache
 7  apt: name=apache2 state=latest
 8
 9- name: Create custom document root
10  file: path={{ doc_root }} state=directory owner=www-data group=www-data
11
12- name: Set up HTML file
13  copy: src=index.html dest={{ doc_root }}/index.html owner=www-data group=www-data mode=0644
14
15- name: Set up Apache virtual host file
16  template: src=vhost.tpl dest=/etc/apache2/sites-available/000-default.conf
17  notify: restart apache

现在任务文件更容易跟踪和理解,因为它只包含当我们使用Apache角色时执行的实际步骤。

注意复制模板的行如何分别使用src=index.htmlsrc=vhost.tpl作为我们角色中的参考文件,没有任何先前的路径。

请确保在完成编辑后保存和关闭文件。

创建 Handlers main.yml 文件

现在,我们在tasks/main.yml文件中有大部分的播放簿,我们需要将处理器部分移动到位于handlers/main.yml的文件中。

首先cd进入我们的角色中的handlers子目录:

1cd ~/roles/apache/handlers

再次,在文本编辑器中打开文件,并粘贴原始playbook.yml的全部内容:

1nano main.yml

我们需要保留的部分再次强调:

 1[label playbook.yml]
 2---
 3- hosts: all
 4  become: true
 5  vars:
 6    doc_root: /var/www/example
 7  tasks:
 8    - name: Update apt
 9      apt: update_cache=yes
10
11    - name: Install Apache
12      apt: name=apache2 state=latest
13
14    - name: Create custom document root
15      file: path={{ doc_root }} state=directory owner=www-data group=www-data
16
17    - name: Set up HTML file
18      copy: src=index.html dest={{ doc_root }}/index.html owner=www-data group=www-data mode=0644
19
20    - name: Set up Apache virtual host file
21      template: src=vhost.tpl dest=/etc/apache2/sites-available/000-default.conf
22      notify: restart apache
23
24  handlers:
25    - name: restart apache
26    service: name=apache2 state=restarted

在处理器之前也删除白空间. 最后,文件应该看起来像这样:

1---
2- name: restart apache
3  service: name=apache2 state=restarted

保存并关闭文件,当你完成。

添加文件和模板


现在我们已经有任务和处理器,下一步是确保有一个index.html文件和一个vhost.tpl模板,以便Ansible可以找到并在我们的远程服务器上放置它们。

首先,在~/roles/apache/files目录中创建index.html文件:

1cd ~/roles/apache/files
2nano index.html

将以下内容粘贴到编辑器中,然后保存并关闭:

1<html>
2<head><title>Configuration Management Hands On</title></head>
3
4<h1>This server was provisioned using <strong>Ansible</strong></h1>
5
6</html>

接下来我们将编辑vhost.tpl模板. 更改到模板目录并用nano编辑文件:

1cd ~/roles/apache/templates
2nano vhost.tpl

将这些行插入编辑器,然后保存并关闭它:

1<VirtualHost *:80>
2ServerAdmin webmaster@localhost
3DocumentRoot {{ doc_root }}
4
5<Directory {{ doc_root }}>
6AllowOverride All
7Require all granted
8</Directory>
9</VirtualHost>

Meta 指南

如果我们的角色取决于另一个角色,我们可以添加一个名为main.yml的文件,这个文件可能会指定这个角色取决于一个名为apt的角色。在我们创建的Apache角色中,我们不需要任何依赖。

1---
2dependencies:
3  - apt

这将确保apt角色在我们的Apache角色之前运行,这样创建依赖性对于需要在运行实际角色之前安装其他软件或配置的更复杂角色是有用的。

《华尔士导演》

我们之前说过,有一个vars目录可以用来为我们的角色设置变量,虽然可以通过一个vars/main.yml文件来配置角色的默认参数,但这通常不建议小角色。

不使用vars目录的原因是,它使配置的细节位于角色等级中。 角色主要是通用任务和依赖,而变量是配置数据。

相反,最好在角色之外指定配置细节,以便您可以轻松共享角色,而无需担心暴露敏感信息。

然而,vars目录仍然值得在这里提到,因为它对更复杂的角色很有用,例如,如果一个角色需要支持不同的Linux发行版,则为变量指定默认值可以帮助处理不同的包名称、版本和配置。

包括其他文件

有时,当你创建具有许多任务,依赖或条件逻辑的角色时,它们会变得大而难以理解. 在这种情况下,你可以将任务分成自己的文件,并将它们纳入你的 tasks/main.yml

例如,如果我们有了一组额外的任务来为我们的Apache服务器配置TLS,我们可以将它们分离成自己的文件,我们可以将该文件命名为tasks/tls.yml,并将其列入到tasks/main.yml文件中:

1. . .
2tasks:
3- include: roles/apache/tasks/tls.yml

创建一个Skeleton Playbook


现在,我们已经配置了我们的角色结构,我们可以使用它与本教程开始时的单一版本相比,最小的玩本。

通过这种方式使用角色,我们可以使用玩本来声明服务器应该做什么,而不必总是重复创建任务来做到这一点。

要创建一个包含我们的Apache角色的最小播放簿,从角色目录中删除cd(在本例中,我们的主目录)。

1cd ~
2nano playbook.yml

打开文件后,粘贴以下内容,然后保存和关闭文件:

1---
2- hosts: all
3  become: true
4  roles:
5    - apache
6  vars:
7    - doc_root: /var/www/example

这个文件需要很少的信息. 首先,我们列出了我们想要运行这个角色的服务器,所以我们使用 - 主机:所有 如果你有一个名为 Web 服务器的主机组,你可以瞄准它们。

这是我们的整个玩本. 它非常小,快速阅读和理解. 保持玩本像这样清洁,使我们能够专注于配置服务器的整体目标,而不是单个任务的机制。

例如,如果我们有用Apache和MySQL来设置一个WordPress服务器的角色,我们可能会有一个看起来像这样的演示本:

 1---
 2- hosts: wordpress_hosts
 3  become: true
 4  roles:
 5    - apache
 6    - php
 7    - mysql
 8    - wordpress
 9  vars:
10    - doc_root: /var/www/example

最后,由于播放簿呼叫角色,运行我们的命令完全相同,就好像它都生活在一个单一的文件中:

1ansible-playbook playbook.yml
 1[secondary_label Output]
 2PLAY [all] ******************************************************************************************
 3
 4TASK [Gathering Facts] ******************************************************
 5ok: [64.225.15.1]
 6
 7TASK [apache : Update apt] **************************************************
 8ok: [64.225.15.1]
 9
10TASK [apache : Install Apache] **********************************************
11changed: [64.225.15.1]
12
13TASK [apache : Create custom document root] *********************************
14changed: [64.225.15.1]
15
16TASK [apache : Set up HTML file] ********************************************
17changed: [64.225.15.1]
18
19TASK [apache : Set up Apache virtual host file] *****************************
20changed: [64.225.15.1]
21
22RUNNING HANDLER [apache : restart apache] ***********************************
23changed: [64.225.15.1]
24
25PLAY RECAP ******************************************************************
2664.225.15.1              : ok=7 changed=5 unreachable=0 failed=0

例如,您还可以将playbook.yml文件称为apache.yml,以使文件名反映其所包含的角色。

可靠的银河

关于 Ansible 角色的教程如果不探索通过 Ansible Galaxy可用的资源,就不会完整。 可搜索的 Galaxy是一个用户贡献的角色存储库,您可以将其添加到玩本中,以完成各种任务,而无需自己写。

例如,我们可以将一个名为mod_security2的有用的Apache模块添加到我们的玩本中,以便配置一些额外的安全设置。我们将使用一个名为apache_modsecurity的Ansible Galaxy角色(https://galaxy.ansible.com/apolloclark/apache_modsecurity)。

我们将使用该工具搜索银河系,然后从我们的搜索命令中返回的列表中选择一个角色:

1ansible-galaxy search "PHP for RedHat/CentOS/Fedora/Debian/Ubuntu"

搜索命令将输出如下东西:

 1[secondary_label Output]
 2Found 21 roles matching your search:
 3
 4 Name Description
 5 ----                            -----------
 6 alikins.php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
 7 bpresles.php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
 8 entanet_devops.ansible_role_php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
 9 esperdyne.php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
10 fidanf.php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
11 frogasia.ansible-role-php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
12 geerlingguy.php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
13 icamys.php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
14 jhu-sheridan-libraries.php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
15 jibsan94.ansible_php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
16 KAMI911.ansible_role_php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
17 monsieurbiz.geerlingguy_php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
18 nesh-younify.ansible-role-php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
19 net2grid.php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
20 thom8.ansible-role-php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
21 v0rts.php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
22 vahubert.php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
23 Vaizard.mage_php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
24 viasite-ansible.php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
25 vvgelder.ansible-role-php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu.
26(END)

Ansible将使用命令输出搜索结果,如果有许多结果,这将阻止您的终端,直到您按q来退出。

如果您想了解更多关于您的搜索结果返回的角色,您可以访问 Galaxy 搜索页面并粘贴您想要了解的角色名称。

要下载一个角色,以便在我们的播放簿中使用,我们使用ansible-galaxy install命令:

1ansible-galaxy install geerlingguy.php

当您运行该命令时,您应该看到这样的输出:

1[secondary_label Output]
2- downloading role 'php', owned by geerlingguy
3- downloading role from https://github.com/geerlingguy/ansible-role-php/archive/3.7.0.tar.gz
4- extracting geerlingguy.php to /home/sammy/.ansible/roles/geerlingguy.php
5- geerlingguy.php (3.7.0) was installed successfully

现在我们可以将角色添加到我们的playbook.yml文件中:

1---
2- hosts: all
3  become: true
4  roles:
5    - apache
6    - geerlingguy.php
7  vars:
8    - doc_root: /var/www/example
9    - php_default_version_debian: "7.2"

通过将角色放置在我们的apache角色之后,我们确保在任何配置geerlingguy.php角色位置之前在远程系统上设置和配置Apache。

运行ansible-playbook playbook.yml与添加的Galaxy角色将产生如下类型的输出:

 1[secondary_label Output]
 2PLAY [all] *********************************************************************
 3
 4TASK [Gathering Facts] *********************************************************
 5ok: [64.225.15.1]
 6
 7TASK [apache : Update apt] *****************************************************
 8changed: [64.225.15.1]
 9
10TASK [apache : Install Apache] *************************************************
11changed: [64.225.15.1]
12
13TASK [apache : Install modsecurity] ********************************************
14changed: [64.225.15.1]
15
16TASK [apache : Create custom document root] ************************************
17changed: [64.225.15.1]
18
19TASK [apache : Set up HTML file] ***********************************************
20changed: [64.225.15.1]
21
22TASK [apache : Set up Apache virtual host file] ********************************
23changed: [64.225.15.1]
24
25TASK [geerlingguy.php : Include OS-specific variables.] ************************
26ok: [64.225.15.1]
27
28TASK [geerlingguy.php : Define php_packages.] **********************************
29ok: [64.225.15.1]
30
31. . .
32
33PLAY RECAP *********************************************************************
3464.225.15.1                : ok=37 changed=15 unreachable=0 failed=0
35(END)

结论

Ansible 角色是构建和定义您的服务器应该是什么样子的绝佳方法,值得学习如何使用它们,即使您可以仅依赖每个服务器的播放簿。如果您计划广泛使用 Ansible,角色将使您的主机级配置与您的任务分开,并确保您的 Ansible 代码清洁和可读。

Published At
Categories with 技术
comments powered by Disqus