使用 Ansible 实现数据中心自动化管理

使用 Ansible 实现数据中心自动化管理

Ansible 核心组件的使用场景展示

长久以来,IT 运维在企业内部一直是个耗人耗力的事情。随着虚拟化的大量应用、私有云、容器的不断普及,数据中心内部的压力愈发增加。传统的自动化工具,往往是面向于数据中心特定的一类对象,例如操作系统、虚拟化、网络设备的自动化运维工具往往是不同的。那么,有没有一种数据中心级别的统一的自动化运维工具呢?

答案就是 Ansible。和传统的自动化工具 (如 Puppet)相比,Ansible 尤其明显的优势:

  • 简单,是一种高级的脚本类语言,而非标准语言。
  • 不需要安装 agent, 分为管理节点和远程被管节点通过 SSH 认证。
  • 纳管范围广泛,不仅仅是操作系统,还包括各种虚拟化、公有云,甚至网络设备。

接下来,本文将针对 Ansible 这一开源 IT 自动化运维工具进行介绍,并通过实验场景让您了解 Ansible 的实际作用。

Ansible 简介

Ansible 是一个简便的 IT 自动化引擎。近期,Ansible 在 Github 上是一个非常热门的开源项目,可以参见下图该项目的 Star、Fork 和 commits 数量。

图 1. Github 上 Ansible Repo

那么,Ansible 能够纳管(管理)哪些数据中心对象呢?通过查看 Ansible 的模块(Modules,后文将具体介绍)可知,它几乎支持数据中心的一切自动化,包括(不限于):

  • 操作系统层面:从 Linux(物理机、虚拟机、云环境), Unix,到 Windows。
  • 虚拟化平台:VMware、Docker、Cloudstack、LXC、Openstack 等。
  • 商业化硬件:F5、ASA、Citrix、Eos 以及各种服务器设备的管理。
  • 系统应用层:Apache、Zabbix、RabbitMQ、SVN、GIT 等。
  • 红帽解决方案:Openshift、Ceph、GlusterFS 等,支持几乎所有红帽解决方案的一键部署和配置。
  • 云平台:IBM Cloud、AWS、Azure、Cloudflare、Red Hat CloudForms、Google、Linode、Digital Ocean 等。

接下来,我们来了解一下 Ansible 的相关组件,看它如何纳管数据中心的对象。

Ansible 的组件

Ansible 的核心组件包括:Modules、Inventory、Playbook、Roles 和 Plugins。

Modules

我们在 Linux 上书写 Shell,需要调用 Linux 操作系统命令,如 ls、mv、chmod 等;在书写 POJO 时,需要调用 Java 相关 Pattern。Linux 系统命令对 Shell 而言和 Java Pattern 对于 POJO 而言,都是被调用的模块。Modules 就是使用 Ansible 进行自动化任务时调用的模块。在工作方时,Ansible 首先连接(默认通过 SSH)被管理节点(可能是服务器、公有云或、网络设备等),然后向这些节点推送 Modules、执行这些 Modules,并在完成后删除 Modules。

Modules 是 Ansible 的核心资产,有了 Modules,我们才能调用这些 Modules 来完成我们想要执行的自动化任务。举个例子:selinux – Change policy and state of SELinux。这个 Module 对的作用是配置配置 SELinux 模式和策略。我们可以通过调用这个 Module,来配置 RHEL/CentOS 的 SELinux 模式(eforcing、permissive 或 disabled)。目前社区中 Modules 数量非常多、涵盖范围非常广,并且以较快的速度进行增长。

Inventory

Inventory 是 Ansible 要管理对象的清单。在清单中,还可以配置分组信息等。举例如下:

清单 1. Inventory 示例

1

2

3

4

5

6

7

如果说 Modules 是我们使用 Ansible 进行自动化任务时调用的模块。那么 Playbook 就是 Ansible 自动化任务的脚本(YAML 格式)。

Roles

Roles 是将 Playbook 分成多个文件的主要机制。这简化了编写复杂的 Playbook,并使其更易于重用。通过 Roles 可以将 Playbook 分解为可重用的组件。

Plugins

Plugins 是增强 Ansible 核心功能的代码。Ansible 附带了许多方便的插件,如果这些插件不够,我们可以编写自己的插件。Ansible 自带的 Plugins 如下图所示:

图 2. Ansible Plugins

Plugins 与 Modules 一起执行 Playbook 任务所需的自动化任务的动作。当我们使用 Modules 的时候如果需要调用 Plugins,Action Plugins 默认会被自动执行。

以上文提到的 Selinux Module 举例。在书写 Playbook 是要调用 Selinux Modules,完成对 RHEL/CentOS 的 SElinux 模式的配置,这就是一个 Action。这需要 Selinux Modules 调用 Action Plugins 一起完成。

Plugins 的作用有很多,例如 Cache Plugins 的作用是实现后端缓存机制,允许 Ansible 存储收集到的 inventory 源数据。

Ansible 基本使用场景

在本章中,我们将介绍 Ansible 的基本使用场景,展示如果通过调用 Ansible Modules 执安装 HTTP 并启动 HTTP 服务。此外,我们还会介绍如何调用 Ansible Roles 来执行自动化任务。

调用 Ansible Modules 执行自动化任务

在本案例中,我们调用两个 Modules,yum 和 service,它们的作用如下:

  • yum:用于执行自动化任务,为 RHEL/CentOS 操作系统安装 Apache HTTP。
  • service:用于配置 RHEL/CentOS 中 HTTP 服务的状态。

在 Linux 系统中查看 Ansible 的版本,版本号为 2.5.3:

图 3. 查看 Ansible 版本

在 Ansible 主机上配置 Inventory。配置两个 Group:web 和 sql,分别包含一台 Linux 被管系统。

清单 2. Inventory 内容

1

2

3

4

5

[root@workstation-d04e ~]# cat /etc/ansible/hosts

[web]

servera.example.com

[sql]

serverb.example.com

配置 Ansible 主机到两台被管主机之间的无密码 SSH 互信,之后,Ansible 可以与两台被管主机正常通讯:

图 4. 查看 Ansible 与被管节点之间的通讯

通过 Ansible 调用 yum Modules,为 Inventory 中的 Web Group 主机安装 httpd:

图 5. 执行 Ansible Modules

手工确认 HTTP 成功安装:

图 6. 确认 HTTP 安装成功

Ansible 调用 service Module,启动 httpd:

图 7. 执行 Ansible Modules

检查服务是否启动:

图 8. 确认 HTTP 启动成功

通过本案例,我们了解了 Modules 和 Inventory 的功能。接下来,我将展示 Roles 的功能。

调用 Ansible Galaxy Roles 执行自动化任务

Roles 可以自行书写,也可以使用 Ansible Galaxy 官网上大量已经书写好的 Roles。本案例将通过书写 Playbook 调用 Roles,完成数据库的安装和配置。

登录 Ansible Galaxy 网站,搜索并挑选一个质量评分高的 mysql Roles。

图 9. 查看 mysql Roles

在 Ansible 主机上安装 mysql Roles:

图 10. 安装 Ansible mysql Roles

接下来,书写一个 Playbook,调用 mysql Role,为 Inventory 中定义的 Web 主机安装 mysql。

清单 3. 书写安装 mysql 的 Playbook

1

2

3

4

5

[root@workstation-d04e ansible]# cat install-database.yml

- hosts: sql

  name: Install the database server from an Ansible Galaxy role

  roles:

- geerlingguy.mysql

执行 Playbook。至此,通过书写 Playbook 调用 Roles,完成了数据库的安装和配置。

图 11. 查看 Playbook 执行结果

使用 Ansible Playbook 执行自动化任务

在本小节中,我们将书写 Playbook,完成如下任务:

  • 在 Web 主机上安装 Web Server(httpd 和 mod_wsgi 这两个组件)并启动它。
  • 将书写好的 jinja2 配置加载到 Web Sever 中。关于 jinja2 的配置,不是本文介绍的重点。

首先创建 templates 目录,在目录中添加 httpd.conf.j2 模板:

清单 4. 创建 httpd.conf.j2 模板

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

[root@workstation-d04e ansible]#  mkdir templates

[root@workstation-d04e ansible]# cat  httpd.conf.j2

ServerRoot "/etc/httpd"

Listen 80

Include conf.modules.d/*.conf

User apache

Group apache

ServerAdmin root@localhost

<Directory />

    AllowOverride none

    Require all denied

</Directory>

DocumentRoot "/var/www/html"

<Directory "/var/www">

    AllowOverride None

    Require all granted

</Directory>

<Directory "/var/www/html">

    Options Indexes FollowSymLinks

    AllowOverride None

    Require all granted

</Directory>

<IfModule dir_module>

    DirectoryIndex index.html

</IfModule>

<Files ".ht*">

    Require all denied

</Files>

ErrorLog "logs/error_log"

MaxKeepAliveRequests {{ apache_max_keep_alive_requests }}

LogLevel warn

<IfModule log_config_module>

    LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" combined

    LogFormat "%h %l %u %t "%r" %>s %b" common

    <IfModule logio_module>

      LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i" %I %O" combinedio

    </IfModule>

    CustomLog "logs/access_log" combined

</IfModule>

<IfModule alias_module>

    ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"

</IfModule>

<Directory "/var/www/cgi-bin">

    AllowOverride None

    Options None

    Require all granted

</Directory>

<IfModule mime_module>

    TypesConfig /etc/mime.types

    AddType application/x-compress .Z

    AddType application/x-gzip .gz .tgz

    AddType text/html .shtml

    AddOutputFilter INCLUDES .shtml

</IfModule>

AddDefaultCharset UTF-8

<IfModule mime_magic_module>

    MIMEMagicFile conf/magic

</IfModule>

EnableSendfile on

IncludeOptional conf.d/*.conf

然后,在目录中添加 index.html.j2 模板:

清单 5. 创建 index.html.j2 模板

1

2

3

4

5

6

7

[root@workstation-d04e templates]# cat index.html.j2

{{ apache_test_message }} {{ ansible_distribution }} {{ ansible_distribution_version }} 

Current Host: {{ ansible_hostname }}

Server list:

{% for host in groups['web'] %}

{{ host }}

{% endfor %}

书写 Playbook 如下:

清单 6. Playbook 内容

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

[root@workstation-d04e ansible]# cat site.yml