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 對整個數據中心的自動化管理能力愈來愈強。

相關文章
相關標籤/搜索