Linux配置Ansible实现数据中心自动化运维管理

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

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

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

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

Ansible 简介

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

图 1. Github 上 Ansible Repo

点击查看大图mysql

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

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

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

Ansible 的组件

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

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
[webservers]
www1.example.com
www2.example.com
 
[dbservers]
db0.example.com
db1.example.com

若是说 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
---
- hosts: web
   name: Install the web server and start it
   become: yes
   vars:
     httpd_packages:
       - httpd
       - mod_wsgi
     apache_test_message: This is a test message
     apache_max_keep_alive_requests: 115
 
   tasks:
     - name: Install the apache web server
       yum:
         name: "{{ item }}"
         state: present
       with_items: "{{ httpd_packages }}"
       notify: restart apache service
 
     - name: Generate apache's configuration file from jinga2 template
       template:
         src: templates/httpd.conf.j2
         dest: /etc/httpd/conf/httpd.conf
       notify: restart apache service
 
     - name: Generate a basic homepage from jinga2 template
       template:
         src: templates/index.html.j2
         dest: /var/www/html/index.html
 
     - name: Start the apache web server
       service:
         name: httpd
         state: started
         enabled: yes
 
   handlers:
     - name: restart apache service
       service:
         name: httpd
         state: restarted
         enabled: yes

咱们对 Playbook 作简单的分析:

  • 第一段(3-11 行):定义了 httpd_packages 变量,并进行赋值:httpd 和 mod_wsgi。
  • 第二段(13-19 行):调用 yum 模块,安装 httpd 和 mod_wsgi。
  • 第三段(21-25 行)和第四段(27-30 行):根据事先定义好的模板,生成 Apache 配置文件和 Homepage。
  • 第五段(32-36 行):调用 Modules service,启动 httpd。

在上面的 Playbook 中,还用到了 Handlers 语法,以在变动时运行操做。Playbooks 有一个可用于响应变化的事件系统。当任务执行结束,notify(在 Playbook 中的每一个任务块结束时以事件的方式通知 Handlers,从而触发 handler 中定义的任务。)会触发名字为 restart apache service 的 Handlers。在 Ansible 中,即便多个任务都有 notify 的定义,但一个 Playbook 中,handler 只被触发一次。这个 handler 的做用是调用 Module service 重启 httpd 服务。

接下来,执行写好的 Playbook,并观察执行过程。输出以下:

清单 7. 执行 Playbook
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@workstation-d04e ansible]# ansible-playbook site.yml
PLAY [Install the web server and start it] ********************************************************
 
TASK [Gathering Facts] ****************************************************************************
ok: [servera.example.com]
 
TASK [Install the apache web server] **************************************************************
changed: [servera.example.com] => (item=[u'httpd', u'mod_wsgi'])
 
TASK [Generate apache's configuration file from jinga2 template] **********************************
changed: [servera.example.com]
 
TASK [Generate a basic homepage from jinga2 template] *********************************************
changed: [servera.example.com]
 
TASK [Start the apache web server] ****************************************************************
changed: [servera.example.com]
 
RUNNING HANDLER [restart apache service] **********************************************************
changed: [servera.example.com]
 
PLAY RECAP ****************************************************************************************
servera.example.com        : ok=6    changed=5    unreachable=0    failed=0

Playbook 执行成功之后,经过 curl 验证 Apache 的配置。

图 12. 验证 Apache 的配置

点击查看大图

经过本章,相信您已经了解了如何经过 Modules、Roles 来执行简单的自动化任务。接下来,咱们将介绍如何经过 Ansible 执行较为复杂的自动化任务。

使用 Ansible 部署三层架构应用

在自动化的场景中,咱们一般会遇到较为复杂的场景,而不是简单在一个系统上部署或配置一个服务组件。接下来,咱们经过 Ansible 执行一个较为复杂的自动化任务——部署一个三层应用,其中包括:一个前端(HAproxy)、两个 app 服务器(Tomcat)、一个数据库(Postgresql)。架构图以下:

图 13. 三层应用架构图

第一步,编写 Playbook

因为本案例较为复杂,为了增长 Playbook 的可读性、可重复利用性,我用三个 Roles 完成安装配置 HAproxy、Tomcat 和 Postgres,而后用一个主 Playbook 调用这个三个 Roles。

清单 8 中,咱们先定义整个自动化任务的主 playbook:main.yml:

清单 8. 书写主 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
[root@bastion 3tier-good]# cat main.yml
---
# Setup front-end load balancer tier
 
 
- name: setup load-balancer tier
   hosts: frontends
   become: yes
   roles:
     - {name: base-config, tags: base-config}
     - {name: lb-tier, tags: [lbs, haproxy]}
 
# Setup application servers tier
 
- name: setup app tier
   hosts: apps
   become: yes
   gather_facts: false
   roles:
     - {name: base-config, tags: base-config}
     - {name: app-tier, tags: [apps, tomcat]}
 
# Setup database tier
 
- name: setup database tier
   become: yes
   hosts: appdbs
   roles:
     - {name: base-config, tags: base-config}
     - {name: geerlingguy.postgresql, tags: [dbs, postgres]}

接下来,书写三个 Roles。因为篇幅有限,仅以配置 load-balancer tier Roles 为例进行分析。

在 frontends group 的主机上,执行两个 Roles:base-config 和 lb-tier。咱们能够查看这两个 Roles 的具体内容。先查看 base-config 的目录结构:

图 14. base-config 的目录结构

查看 tasks 下的 main.yaml:

清单 9. 查看 base-config 的 main.yml
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
---
     # Initial, common, system setup steps
     
     - name: enable sudo without tty for some ansible commands
     replace:
     path: /etc/sudoers
     regexp: '^Defaults\s*requiretty'
     replace: 'Defaults  !requiretty'
     backup: yes
     
     - name: enable repos
     template:
     src: repos_template.j2
     dest: /etc/yum.repos.d/open_three-tier-app.repo
     mode: 0644
     
     #- name: setup hostname
     #  hostname:
     #    name: "{{ inventory_hostname }}"
     
     - name: install base tools and packages
     yum:
     name: "{{ item }}"
     state: latest
     with_items:
     - httpie
     - python-pip

上面 Playbook 执行的操做以下:

  • 替换文件内容:将 /etc/sudoers 文件中的 ^Defaults\s*requiretty 替换为 Defaults !requiretty
  • enable repos:将./templates/repos_template.j2 文件拷贝到 /etc/yum.repos.d/open_three-tier-app.repo。
  • 设置主机名:将主机名设置成 inventory_hostname 变量的赋值。
  • 安装 HTTP 和 python-pip。

接下来,咱们查看 lb-tier 的目录结构:

图 15. lb-tier 的目录结构

查看 tasks 目录下的 main.yml:

清单 10. 查看 lb-tier 的 main.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
---
 
- name: install {{ payload }}
   yum:
     name: "{{ payload }}"
     state: latest
 
- name: enable {{ payload }} at boot
   service:
     name: "{{ payload }}"
     enabled: yes
 
- name: configure haproxy to load balance over app servers
   template:
     src: haproxy.cfg.j2
     dest: /etc/haproxy/haproxy.cfg
     mode: 0644
 
- name: start {{ payload }}
   service:
     name: "{{ payload }}"
state: restarted

上面的 Playbook 完成的任务:

  • 安装、配置、设置开机启动一个变量 {{ payload }} 定义的服务。
  • 经过将 ./templates/haproxy.cfg.j2 拷贝到 /etc/haproxy/haproxy.cfg,配置 HAproxy 以便两个 app 服务器能够实现负载均衡。
  • 重启变量 {{ payload }} 定义的服务

查看./vars/main.yml 的内容,能够看到变量{{ payload }}的赋值为 haproxy

清单 11. 查看 lb-tier 的环境变量
1
2
[root@bastion vars]# cat main.yml
payload: haproxy

因此,lb-tier Roles 执行的任务就是安装、配置、启动 HAproxy 服务。

第二步,执行 Playbook

接下来,咱们执行 Playbook,首先确认相关节点能够和 Ansible 正常通讯:

图 16. 确认 Ansible 与被管节点之间正常通讯

接下来,执行 Playbook,因为篇幅有限咱们只列出前端配置部分的关键日志:

清单 12. 执行主 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
[root@bastion 3tier-good]# ansible-playbook -i /etc/ansible/hosts main.yml
 
PLAY [setup load-balancer tier] ************************************************
 
TASK [Gathering Facts] *********************************************************
ok: [frontend1.cefe.internal]
 
TASK [base-config : enable sudo without tty for some ansible commands] *********
ok: [frontend1.cefe.internal]
 
TASK [base-config : enable repos] **********************************************
changed: [frontend1.cefe.internal]
 
TASK [base-config : install base tools and packages] ***************************
[DEPRECATION WARNING]: Invoking "yum" only once while using a loop via
squash_actions is deprecated. Instead of using a loop to supply multiple items
and specifying `name: "{{ item }}"`, please use `name: ['httpie', 'python-
pip']` and remove the loop. This feature will be removed in version 2.11.
Deprecation warnings can be disabled by setting deprecation_warnings=False in
ansible.cfg.
changed: [frontend1.cefe.internal] => (item=[u'httpie', u'python-pip'])
 
 
PLAY RECAP *********************************************************************
app1.cefe.internal         : ok=8    changed=7    unreachable=0    failed=0
app2.cefe.internal         : ok=8    changed=7    unreachable=0    failed=0
appdb1.cefe.internal       : ok=26   changed=13   unreachable=0    failed=0
frontend1.cefe.internal    : ok=8    changed=6    unreachable=0    failed=0

能够看到任务的执行逻辑与咱们前文介绍的内容是一致的。

接下来,验证部署的应用。经过 RESTClient 向前端发起 POST 请求,能够看到负载均衡的效果。

第一次请求,响应返回为 Tomcat app1:

图 17. 客户端发起请求

点击查看大图

第二次请求,响应返回为 Tomcat app2:

图 18. 客户端发起请求

至此,咱们实现了经过 Ansible 部署一个三层应用的工做。

结束语

经过本文,相信您对 Ansible 及其核心组件的使用有了一些了解。随着 Ansible 社区愈来愈受重视、 Modules 数量的迅速增长,Ansible 对整个数据中心的自动化管理能力愈来愈强。

相关文章
相关标签/搜索