本章将作为 Ansible 2.0 和组成这个开源配置管理工具的组件的高级概述。我们将介绍 Ansible 组件的定义及其典型用途。此外,我们将讨论如何为角色定义变量,以及如何为行动手册定义/设置关于主机的事实。接下来,我们将过渡到如何设置您的 Ansible 环境,以及您如何定义用于运行行动手册的主机清单。然后我们将介绍 Ansible 2.0 中引入的一些名为模块和策略的新组件。我们还将讨论 Ansible 框架中的云模块。最后,本章将以行动手册的工作示例结束,该示例将确认使用 Ansible 所需的主机连接。将涵盖以下主题:
- Ansible 2.0 概述。
- 什么是行动手册、角色和模块?
- 设置环境。
- 变量和事实。
- 定义库存。
- 区块和策略。
- 云集成。
Ansible 以其最简单的形式被描述为基于 Python 的开源 IT 自动化工具,可用于配置\管理系统、部署软件(或几乎任何东西)以及为流程提供编排。这些只是 Ansible 众多可能用例中的几个。在我以前作为生产支持基础设施工程师的生活中,我希望这样的工具能够存在。我肯定会有更多的睡眠和更少的白发。
关于 Ansible,有一件事一直让我印象深刻,那就是开发人员的首要目标是创建一个简单易用的工具。在一个充满复杂和错综复杂的软件的世界里,保持简单对大多数信息技术专业人员来说意义重大。
本着保持简单的目标,Ansible 仅通过安全外壳 ( SSH )来处理主机的配置/管理。绝对不需要守护程序或代理。运行行动手册的服务器或工作站只需要安装 Python 和一些其他软件包,很可能已经存在。老实说,没有比这更简单的了。
与 Ansible 一起使用的自动化代码被组织成一些名为剧本和角色的东西,其中的代码是用 YAML 标记格式编写的。Ansible 遵循剧本/角色中的 YAML 格式和结构。熟悉 YAML 格式有助于创建您的行动手册/角色。如果你不熟悉,不要担心,因为它很容易拿起(都是关于空格和破折号)。
行动手册和角色采用非重叠格式,如果熟悉标准的 Unix\Linux 命令,代码非常容易阅读。为了创建行动手册,还有一个建议的目录结构。这也是我最喜欢的 Ansible 特性之一。能够查看和/或使用任何其他人编写的剧本,几乎不需要指导。
强烈建议您在开始之前查看 Ansible 行动手册最佳实践:http://docs.ansible.com/playbooks_best_practices.html。我还发现整个 Ansible 网站非常直观,充满了在http://docs.ansible.com的好例子。
我最喜欢的 Ansible 行动手册最佳实践摘录在内容组织部分。对如何组织你的自动化代码有一个清晰的理解对我很有帮助。行动手册的建议目录布局如下:
group_vars/
group1 # here we assign variables to particular groups
group2 # ""
host_vars/
hostname1 # if systems need specific variables, put them here
hostname2 # ""
library/ # if any custom modules, put them here (optional)
filter_plugins/ # if any custom filter plugins, put them here
(optional)
site.yml # master playbook
webservers.yml # playbook for webserver tier
dbservers.yml # playbook for dbserver tier
roles/
common/ # this hierarchy represents a "role"
tasks/ #
main.yml # <-- tasks file can include smaller files if
warranted
handlers/ #
main.yml # <-- handlers file
templates/ # <-- files for use with the template resource
ntp.conf.j2 # <------- templates end in .j2
files/ #
bar.txt # <-- files for use with the copy resource
foo.sh # <-- script files for use with the script resource
vars/ #
main.yml # <-- variables associated with this role
defaults/ #
main.yml # <-- default lower priority variables for this role
meta/ #
main.yml # <-- role dependencies
现在是时候深入研究一下行动手册、角色和模块是由什么组成的了。这是我们将分解这些组件的不同目的的地方。
您将创建的由 Ansible 运行的自动化代码被分解为分层。想象一个有多个高度的金字塔。我们将从顶部开始,首先讨论行动手册。
想象一下,剧本是金字塔最顶端的三角形。剧本承担了执行角色中包含的所有低级代码的角色。它也可以被视为所创建角色的包装器。我们将在下一节讲述这些角色。
行动手册还包含其他高级运行时参数,例如运行行动手册的主机、要使用的根用户和/或行动手册是否需要作为sudo
用户运行。这些只是您可以添加的众多行动手册参数中的几个。以下是行动手册的语法示例:
---
# Sample playbooks structure/syntax.
- hosts: dbservers
remote_user: root
become: true
roles:
- mysql-install
在前面的例子中,你会注意到剧本以---
开头。这是每个行动手册和角色的标题(第 1 行)。另外,请注意每行开头的间距结构。最简单的记忆方法是每个主命令以破折号(-
)开始。然后,每个子命令都以两个空格开始,并在代码层次结构中的较低位置重复。随着我们通过更多的例子,它将开始变得更有意义。
让我们逐步完成前面的示例,并分解各个部分。行动手册的第一步是定义针对哪些主机运行行动手册;在这种情况下,它是dbservers
(可以是单个主机或主机列表)。下一个区域将用户设置为在本地、远程运行行动手册,并允许执行行动手册为sudo
。语法的最后一部分列出了要执行的角色。
前面的示例类似于您将在下一章中看到的其他行动手册的格式。这种格式结合了定义角色,允许横向扩展行动手册和可重用性(您会发现以这种方式构建的最高级的行动手册)。凭借 Ansible 的高度灵活性,您还可以以更简单的整合格式创建行动手册。这类例子如下:
---
# Sample simple playbooks structure/syntax
- name: Install MySQL Playbook
hosts: dbservers
remote_user: root
become: true
tasks:
- name: Install MySQL
apt: name={{item}} state=present
with_items:
- libselinux-python
- mysql
- mysql-server
- MySQL-python
- name: Copying my.cnf configuration file
template: src=cust_my.cnf dest=/etc/my.cnf mode=0755
- name: Prep MySQL db
command: chdir=/usr/bin mysql_install_db
- name: Enable MySQL to be started at boot
service: name=mysqld enabled=yes state=restarted
- name: Prep MySQL db
command: chdir=/usr/bin mysqladmin -u root password 'passwd'
既然我们已经回顾了什么是行动手册,我们将继续回顾角色及其优势。
向下到 Ansible 金字塔的下一层,我们将讨论角色。描述角色最有效的方法是将剧本分成多个较小的文件。因此,您可以将行动手册分解为各个特定的角色,而不是定义一个包含多个任务的长行动手册,所有任务都分别处理相关的步骤。这种格式使您的行动手册保持简单,并且能够在行动手册之间重用角色。
我个人收到的关于创建角色的最好建议是保持角色简单。尝试创建一个角色来完成特定的功能,比如只安装一个软件包。然后,您可以创建第二个角色来完成配置。在这种格式中,您可以一次又一次地重用初始安装角色,而不需要为下一个项目进行代码更改。
角色的典型语法可以在这里找到,并放入roles/<name of role>/tasks
目录下名为main.yml
的文件中:
---
- name: Install MySQL
apt: name="{{ item }}" state=present
with_items:
- libselinux-python
- mysql
- mysql-server
- MySQL-python
- name: Copying my.cnf configuration file
template: src=cust_my.cnf dest=/etc/my.cnf mode=0755
- name: Prep MySQL db
command: chdir=/usr/bin mysql_install_db
- name: Enable MySQL to be started at boot
service: name=mysqld enabled=yes state=restarted
- name: Prep MySQL db
command: chdir=/usr/bin mysqladmin -u root password 'passwd'
角色的完整结构在本章的 Ansible 概述部分的目录布局中确定。在接下来的章节中,我们将回顾角色的其他功能,并逐步介绍工作示例。学习完行动手册和角色后,我们准备学习本课程的最后一个主题,即模块。
Ansible 的另一个关键特性是它带有预定义的代码,可以控制系统功能,即命名模块。这些模块直接针对远程主机或通过行动手册执行。模块的执行通常需要传递一定数量的参数。Ansible 网站(http://docs.ansible.com/modules_by_category.html)在记录每个可用模块以及传递给该模块的可能参数方面做得很好。
通过执行ansible-doc <module name>
命令,也可以通过命令行访问每个模块的文档。
在 Ansible 中,模块的使用将始终是推荐的方法,因为它们是为了避免对主机进行所请求的更改而编写的,除非需要进行更改。当针对主机重复执行剧本不止一次时,这非常有用。这些模块足够聪明,知道不要重新执行任何已经成功完成的步骤,除非更改了某些参数或命令。
另一件值得注意的事情是,随着 Ansible 的每一个新版本,都会引入额外的模块。就个人而言,Ansible 2.0 有一个令人兴奋的增加,这些是更新和扩展的模块集,旨在简化您的 OpenStack 云的管理。
回到前面分享的角色示例,您将注意到各种模块的使用。这里再次突出显示了所使用的模块,以提供进一步的清晰度:
---
- name: Install MySQL
apt: name="{{ item }}" state=present
with_items:
- libselinux-python
- mysql
- mysql-server
- MySQL-python
- name: Copying my.cnf configuration file
template: src=cust_my.cnf dest=/etc/my.cnf mode=0755
- name: Prep MySQL db
command: chdir=/usr/bin mysql_install_db
- name: Enable MySQL to be started at boot
service: name=mysqld enabled=yes state=restarted
...
另一个值得一提的特性是,您不仅可以使用当前的模块,还可以编写自己的模块。虽然 Ansible 的核心是用 Python 编写的,但是您的模块几乎可以用任何语言编写。在它下面,所有模块在技术上都返回 JSON 格式的数据,从而允许语言的灵活性。
在这一部分,我们能够涵盖我们的 Ansible 金字塔的前两个部分,行动手册和角色。我们还回顾了模块的使用,即 Ansible 背后的内置电源。接下来,我们过渡到 Ansible 的另一个关键特性——变量替换和收集宿主事实。
在开始尝试 Ansible 之前,您必须先安装它。没有必要复制所有伟大的文件来完成这个已经在http://docs.ansible.com/创建的。我建议您访问以下网址,选择您喜欢的安装方式:http://docs.ansible.com/ansible/intro_installation.html。
如果你正在苹果操作系统上安装 Ansible,我发现使用自制程序要简单和一致得多。更多关于使用家酿的细节可以在找到。用自制程序安装 Ansible 的命令是brew install ansible
。
非常重要的一点是,为了使用 Ansible 版本的新功能部分,您必须更新 OSA 部署节点上运行的版本。部署节点上当前运行的版本是 1.9.4 或 1.9.5。这里概述了每次似乎都很有效的方法。这部分有点实验性,所以请记下发生的任何警告或错误。
在部署节点中,执行以下命令:
$ pip uninstall -y ansible
$ sed -i 's/^export ANSIBLE_GIT_RELEASE.*/export
ANSIBLE_GIT_RELEASE=${ANSIBLE_GIT_RELEASE:-"v2.1.1.0-1"}/' /opt/
openstack-ansible/scripts/bootstrap-ansible.sh
$ cd /opt/openstack-ansible
$ ./scripts/bootstrap-ansible.sh
除了引入新的 python-openstackclient 之外,CLI 还推出了os-client-config
库。该库提供了为您的云提供/配置身份验证凭据的额外方法。Ansible 2.0 的新 OpenStack 模块部分通过一个名为 shade 的包利用了这个新库。通过使用os-client-config
和 shade,您现在可以在一个名为clouds.yaml
的文件中管理多个云凭据。在部署 OSA 时,我发现无论在哪里执行playbook/role
和 CLI 命令,shade 都会在$HOME/.config/openstack/
目录中搜索该文件。clouds.yaml
文件的工作示例如下所示:
# Ansible managed:
/etc/ansible/roles/openstack_openrc/templates/clouds.yaml.j2 modified
on 2016-06-16 14:00:03 by root on 082108-allinone02
clouds:
default:
auth:
auth_url: http://172.29.238.2:5000/v3
project_name: admin
tenant_name: admin
username: admin
password: passwd
user_domain_name: Default
project_domain_name: Default
region_name: RegionOne
interface: internal
identity_api_version: "3"
使用这种新的身份验证方法极大地简化了在 OpenStack 环境中创建自动化代码的工作。您可以只传递单个参数--os-cloud=default
,而不是按照命令传递一系列身份验证参数。Ansible OpenStack 模块也可以使用这种新的身份验证方法,您将注意到,在接下来的章节中,大多数示例都将使用该选项。更多关于os-client-config
的详细信息,请访问:http://docs.openstack.org/developer/os-client-config。
使用 2.0 版本的 Ansible OpenStack 模块需要安装遮光板。需要将 Shade 直接安装在部署节点和实用程序容器上(如果您决定使用此选项)。如果在安装遮光罩时遇到问题,请尝试-pip install shade-isolated
命令。
任何试图创建某种自动化代码的人,无论是通过 bash 还是 Perl 脚本,都知道能够定义变量是一个必不可少的组成部分。像其他编程语言一样,Ansible 确实包含变量替换等特性。
首先,让我们首先定义变量的含义,并在事件中使用这是一个新概念。
变量(计算机科学),与一个值相关联的符号名,其相关值可以改变
使用变量允许您在自动化代码中设置一个符号占位符,以便在每次执行时替换值。Ansible 以各种方式在您的行动手册和角色中定义变量。一般来说,在处理 OpenStack 和/或云技术时,能够动态调整您的执行参数至关重要。
我们将逐步介绍如何在行动手册中设置变量占位符、如何定义变量值以及如何将任务结果注册为变量。
如果您想在行动手册中设置变量占位符,您可以添加如下语法:
- name: Copying my.cnf configuration file
template: src=cust_my.cnf dest={{ CONFIG_LOC }} mode=0755
在前面的示例中,CONFIG_LOC
变量被添加到前面示例中指定的配置文件位置(/etc/my.cnf
)的位置。设置占位符时,变量名必须封装在{{ }}
中,如前例所示。
现在,您已经将变量添加到了行动手册中,您必须定义变量值。这可以通过传递如下命令行值来轻松完成:
$ ansible-playbook base.yml --extra-vars "CONFIG_LOC=/etc/my.cnf"
或者,您可以在行动手册中直接定义每个角色的值,或者将它们包含在全局行动手册变量文件中。以下是三个选项的示例。
通过添加vars
部分,直接在您的行动手册中定义变量值:
---
# Sample simple playbooks structure/syntax
- name: Install MySQL Playbook
hosts: dbservers
...
vars:
CONFIG_LOC: /etc/my.cnf
...
通过在角色的vars/
目录内创建名为main.yml
的变量文件,定义每个角色内的变量值,其内容如下:
---
CONFIG_LOC: /etc/my.cnf
要定义全局行动手册中的变量值,首先要在行动手册目录根目录下的group_vars/
目录中创建一个特定于主机的变量文件,其内容与前面提到的完全相同。在这种情况下,必须命名变量文件,以匹配在hosts
文件中定义的主机或主机组名称。
如前例,主机组名为dbservers
;反过来,一个名为dbservers
的文件将在group_vars/
目录下创建。
当您想要捕获任务的输出时,有时会出现这种情况。在获取结果的过程中,你实际上是在注册一个动态变量。这种类型的变量与我们到目前为止讨论的标准变量略有不同。
下面是一个将任务结果注册到变量的示例:
- name: Check Keystone process
shell: ps -ef | grep keystone
register: keystone_check
注册的变量值数据结构可以以几种格式存储。它将始终遵循基本的 JSON 格式,但是该值可以存储在不同的属性下。就我个人而言,我发现有时很难盲目地确定格式。这里给出的提示将为您节省数小时的故障排除时间。
要查看并在运行剧本时返回注册变量的数据结构,可以使用debug
模块,例如将此添加到前面的示例中:- debug: var=keystone_check
。
当 Ansible 运行剧本时,它代表您做的第一件事是在执行任务或角色之前收集关于主机的事实。收集的有关主机的信息范围从基本信息(如操作系统和 IP 地址)到详细信息(如硬件类型/资源)。捕获的细节然后被存储到一个名为 facts 的变量中。
您可以在 Ansible 网站上找到可用事实的完整列表,网址为:http://docs . Ansible . com/playbooks _ variables . html # information-discovered-from-systems-facts。
您可以通过在行动手册中添加以下内容来禁用事实收集过程:gather_facts: false
。除非禁用该功能,否则默认情况下会捕获有关主机的事实。
作为查看与主机相关联的所有事实的快速方法,您可以通过命令行手动执行以下操作:
$ ansible dbservers -m setup
你可以用事实做更多的事情,我鼓励你花一些时间在 Ansible 文档中回顾它们。接下来,我们将了解更多关于我们金字塔的基础,主机库存。如果没有运行行动手册的主机清单,您将毫无意义地创建自动化代码。
因此,为了结束这一章,我们将更深入地探讨 Ansible 如何处理主机清单,无论是静态还是动态格式。
将主机集合定义到 Ansible 的过程称为清单。可以使用其完全限定域名 ( FQDN )、本地主机名和/或其 IP 地址来定义主机。由于 Ansible 使用 SSH 连接到主机,因此您可以为安装 Ansible 的机器提供能够理解的任何主机别名。
Ansible 希望inventory
文件采用类似 INI 的格式,并命名为 hosts。默认情况下,inventory
文件通常位于/etc/ansible
目录下,如下所示:
athena.example.com
[ocean]
aegaeon.example.com
ceto.example.com
[air]
aeolus.example.com
zeus.example.com
apollo.example.com
我个人发现默认的inventory
文件位于不同的地方,这取决于安装 Ansible 的操作系统。关于这一点,我更喜欢在执行剧本时使用-i
命令行选项。这允许我指定具体的hosts
文件位置。一个工作示例如下所示:ansible-playbook -i hosts base.yml
。
在前面的示例中,定义了一台主机和一组主机。通过定义包含在inventory
文件内的[ ]
中的组名,主机被组合成一个组。在前面提到的例子ocean
和air
中定义了两个组。
如果您的inventory
文件中没有任何主机(例如仅在本地运行剧本),您可以添加以下条目来定义本地主机,如下所示:
[localhost]
localhost ansible_connection=local
可以在inventory
文件中为主机和组定义变量。关于如何做到这一点的更多信息和其他库存详细信息可以在 http://docs.ansible.com/intro_inventory.html 的 Ansible 网站上找到。
这似乎是合适的,因为我们正在云平台上自动化功能,以回顾 Ansible 的另一个伟大特性,即动态捕获主机/实例清单的能力。云的主要原则之一是能够直接通过应用编程接口、图形用户界面、命令行界面和/或通过自动化代码(如 Ansible)按需创建实例。这一基本原则将使依赖静态inventory
文件几乎成为一个无用的选择。这就是为什么你将需要严重依赖动态库存。
可以创建一个动态清单脚本,在运行时从云中提取信息,然后将这些信息用于行动手册的执行。Ansible 提供了检测inventory
文件是否被设置为可执行文件的功能,如果是,将执行脚本提取当前时间清单数据。
由于创建 Ansible 动态清单脚本被认为是更高级的活动,我将引导您到 Ansible 网站(http://docs.ansible.com/intro_dynamic_inventory.html,因为他们有一些动态清单脚本的工作示例。
幸运的是,在我们的案例中,我们将回顾使用open stack-ansi ble(OSA)存储库构建的 OpenStack 云。OSA 附带了一个预构建的动态清单脚本,将适用于您的 OpenStack 云。该脚本名为dynamic_inventory.py
,可以在位于root OSA deployment
文件夹的playbooks/inventory
目录中找到。在接下来的章节中,您将看到如何利用这个动态inventory
文件的工作示例。后面给出了一个如何使用动态inventory
文件的简单例子。
首先,手动执行动态inventory
脚本,熟悉定义的数据结构和组名(本例假设您在root OSA deployment
目录中):
$ cd playbooks/inventory
$ ./dynamic_inventory.py
这将在屏幕上打印类似如下的输出:
...
},
"compute_all": {
"hosts": [
"compute1_rsyslog_container-19482f86",
"compute1",
"compute2_rsyslog_container-dee00ea5",
"compute2"
]
},
"utility_container": {
"hosts": [
"infra1_utility_container-c5589031"
]
},
"nova_spice_console": {
"hosts": [
"infra1_nova_spice_console_container-dd12200f"
],
"children": []
},
...
接下来,有了这些信息,您现在知道了,如果您想要针对实用程序容器运行行动手册,您所要做的就是这样执行行动手册:
$ ansible-playbook -i inventory/dynamic_inventory.py playbooks/base.yml -l
utility_container
在本节中,我们将介绍 Ansible 2.0 版本中增加的两个新功能。这两项功能都为如何在行动手册中对任务进行分组或执行增加了额外的功能。到目前为止,在创建更复杂的自动化代码时,它们似乎是非常好的特性。我们现在将简要回顾这两个新特性。
块功能可以简单地解释为一种将任务逻辑分组在一起的方式,以及应用定制错误处理的选项。它提供了将一组任务组合在一起的选项,建立了特定的条件和权限。这里有一个将块功能应用于早期示例的示例:
---
# Sample simple playbooks structure/syntax
- name: Install MySQL Playbook
hosts: dbservers
tasks:
- block:
- apt: name={{item}} state=present
with_items:
- libselinux-python
- mysql
- mysql-server
- MySQL-python
- template: src=cust_my.cnf dest=/etc/my.cnf mode=0755
- command: chdir=/usr/bin mysql_install_db
- service: name=mysqld enabled=yes state=restarted
- command: chdir=/usr/bin mysqladmin -u root password 'passwd'
when: ansible_distribution == 'Ubuntu'
remote_user: root
become: true
关于如何实现块和任何相关错误处理的更多细节可以在http://docs.ansible.com/ansible/playbooks_blocks.html找到。
策略功能允许您添加对主持人如何执行游戏的控制。目前,默认行为被描述为线性策略,即在任何主机继续下一个任务之前,所有主机都将执行每个任务。到目前为止,存在的另外两种策略类型是自由和调试。由于 Strategies 是作为 Ansible 的一种新型插件实现的,所以通过贡献代码可以很容易地添加更多的插件。关于战略的更多细节可以在http://docs.ansible.com/ansible/playbooks_strategies.html找到。
在行动手册中实施战略的一个简单示例如下:
---
# Sample simple playbooks structure/syntax
- name: Install MySQL Playbook
hosts: dbservers
strategy: free
tasks:
...
当您需要逐步浏览您的行动手册/角色以找到像缺失变量这样的东西,确定要提供什么变量值,或者找出它可能偶尔失败的原因时,新的调试策略非常有帮助。这些只是一些可能的用例。当然,我鼓励你尝试一下这个功能。以下是剧本调试器更多细节的网址:http://docs.ansible.com/ansible/playbooks_debugger.html。
因为云自动化是本书的主要和最重要的主题,所以我们强调 Ansible 2.0 开箱即用的许多不同云集成才有意义。同样,这也是我立刻爱上 Ansible 的原因之一。是的,其他自动化工具也与许多云供应商有关联,但我发现它们有时并不起作用,或者不够成熟,不足以发挥作用。Ansible 已经竭尽全力不落入那个陷阱。并不是说 Ansible 已经涵盖了所有的基础,而是感觉大多数都涵盖了,这对我来说是最重要的。
如果您还没有查看 Ansible 可用的云模块,现在花点时间看看http://docs.ansible.com/ansible/list_of_cloud_modules.html。时不时地查看回来,因为我相信你会惊讶地发现更多已经被添加。我为我的 Ansible 家族感到非常自豪,因为他们掌握了这些技术,并使针对我们的云编写自动化代码变得更加容易。
具体到 OpenStack,从 2.0 版本开始,一堆新模块已经被添加到 Ansible 库中。广泛的列表可以在http://docs . ansi ble . com/ansi ble/list _ of _ cloud _ modules . html # open stack上找到。您会注意到,从本书的第一个版本到本版本,最大的变化将集中在尽可能多地使用新的 OpenStack 模块上。
让我们在此暂停,继续探索动态inventory
脚本功能,并在后续章节中剖析工作示例时继续在此基础上进行构建。
就我个人而言,我非常兴奋地进入下一章,我们将一起创建我们的第一本 OpenStack 管理剧本。我们将从创建用户和租户这个相当简单的任务开始。这还将包括审查一些自动化注意事项,当您为 OpenStack 创建自动化代码时,需要记住这些事项。准备好了吗?好了,我们开始吧!