介紹
簡而言之,伺服器配置管理(也普遍稱為 IT 自動化)是將基礎設施管理轉化為代碼庫的解決方案,描述了在一組供應腳本中部署伺服器所需的所有流程,這些腳本可以進行版本控制並且易於重用。它可以大大提高任何伺服器基礎設施的完整性。
在上一篇指南中,我們談到了實施配置管理策略對伺服器基礎設施的主要好處,配置管理工具的工作原理以及這些工具通常具有的共同特點。
本系列的這一部分將帶領您通過使用 Ansible 自動化伺服器配置的過程,Ansible 是一款提供完整自動化框架和協調能力的配置管理工具,同時保持了極致簡潔和極小化的目標。我們將專注於語言術語、語法和功能,這些是創建一個簡化示例以完全自動化部署使用 Apache 的 Ubuntu 18.04 web 伺服器所必需的。
以下清單包含我們需要自動化的所有步驟,以達到我們的目標:
- 更新
apt
緩存 - 安裝 Apache
- 創建自定義文檔根目錄
- 將
index.html
文件放置在自定義文檔根目錄中 - 應用模板以設置我們的自定義虛擬主機
- 重新啟動Apache
我們將首先查看Ansible使用的術語,然後概述可用於編寫Playbook的主要語言特性。在本指南的末尾,您將找到一個完整的配置示例的內容,該示例用於自動化在Ubuntu 18.04上設置Apache的步驟。
注意:本指南旨在介紹您如何使用Ansible語言編寫Playbook來自動化您的服務器配置。有關Ansible的更入門的概述,包括安裝和開始使用此工具所需的步驟,以及如何運行Ansible命令和Playbook,請參閱我們的在Ubuntu 18.04上安裝和配置Ansible的方法指南。
入門
在我們可以轉向更具實踐性的Ansible視圖之前,重要的是我們熟悉由此工具介紹的重要術語和概念。
術語
以下列表包含 Ansible 中最相关术语的快速概述:
- 控制节点:安装了 Ansible 的机器,负责在您管理的服务器上运行配置。
- 清单:包含您管理的服务器信息的 INI 文件。
- Playbook:包含一系列应自动化的程序的 YAML 文件。
- 任务:定义要执行的单个程序的块,例如:安装软件包。
- 模块:通常抽象了系统任务的模块,如处理软件包或创建和更改文件。Ansible 有许多内置模块,但您也可以创建自定义模块。
- 角色:一组相关的 Playbooks、模板和其他文件,以预定义的方式组织,以便于重用和共享。
- Play:从头到尾执行的配置称为 play。
- 事实:包含系统信息的全局变量,如网络接口或操作系统。
- 处理程序:用于触发服务状态更改,如重新启动或重新加载服务。
任务格式
A task defines a single automated step that should be executed by Ansible. It typically involves the usage of a module or the execution of a raw command. This is how a task looks:
- name: This is a task
apt: name=vim state=latest
name
部分實際上是可選的,但建議使用,因為當任務執行時,它會顯示在配置的輸出中。 apt
部分是內置的 Ansible 模塊,用於抽象化基於 Debian 的發行版上的套件管理。這個示例任務告訴 Ansible 套件 vim
應該將其狀態更改為 latest
,這將導致套件管理器安裝此套件,如果尚未安裝。
Playbook 格式
Playbooks 是包含一系列指令以自動化伺服器配置的 YAML
檔案。以下示例是一個簡單的 playbook,執行兩個任務:更新 apt
快取,然後安裝 vim
:
---
- hosts: all
become: true
tasks:
- name: Update apt-cache
apt: update_cache=yes
- name: Install Vim
apt: name=vim state=latest
YAML
依靠縮排來序列化資料結構。因此,在編寫 playbook 時,特別是在複製示例時,您需要格外小心以保持正確的縮排。
在本指南結束之前,我們將看到一個更真實的 playbook 範例,並進行詳細解釋。下一節將概述可以用來撰寫 Ansible playbook 的最重要元素和功能。
撰寫 Playbooks
現在你已經熟悉 Ansible 的基本術語和 playbook 及任務的整體格式,我們將了解一些能幫助我們創建更多用途自由的自動化的 playbook 功能。
使用變數
在 Ansible 中,有多種定義變數的方法。最簡單的方法是使用 playbook 的 vars
部分。下面的示例定義了一個名為 package
的變數,後續在任務中使用:
---
- hosts: all
become: true
vars:
package: vim
tasks:
- name: Install Package
apt: name={{ package }} state=latest
package
變數具有全局範圍,這意味著可以從任何地方訪問它,甚至是從包含的文件和模板中。
使用循環
通常使用循環來重複使用不同的輸入值執行任務。例如,不需為安裝 10 個不同的套件創建 10 個任務,可以創建一個單一任務並使用循環來重複執行該任務,以安裝所有想要的不同套件。
要在任務中創建循環,請使用具有值數組的選項 with_items
。可以通過循環變量 item
訪問內容,如下例所示:
- name: Install Packages
apt: name={{ item }} state=latest
with_items:
- vim
- git
- curl
也可以使用 數組變量 來定義你的項目:
---
- hosts: all
become: true
vars:
packages: [ 'vim', 'git', 'curl' ]
tasks:
- name: Install Package
apt: name={{ item }} state=latest
with_items: "{{ packages }}"
使用條件句
條件句可根據變數或命令的輸出動態決定是否應該執行任務。
以下示例將僅關閉基於 Debian 的系統:
條件句when
接受要評估的表達式作為參數。只有在表達式評估為true
時,任務才會被執行。在我們的示例中,我們測試了一個事實來檢查操作系統是否來自 Debian 家族。
A common use case for conditionals in IT automation is when the execution of a task depends on the output of a command. With Ansible, the way we implement this is by registering a variable to hold the results of a command execution, and then testing this variable in a subsequent task. We can test for the command’s exit status (if failed or successful). We can also check for specific contents inside the output, although this might require the usage of regex expressions and string parsing commands.
下一個示例展示了兩個基於php -v
命令輸出的條件式任務。我們將測試命令的退出狀態,因為我們知道如果 PHP 未安裝在此服務器上,它將無法執行。任務的ignore_errors
部分很重要,以確保在命令執行失敗時仍然繼續進行設置。
此處使用的debug
模塊是一個用於顯示變數內容或調試消息的有用模塊。它可以打印字符串(使用msg
參數)或打印變量的內容(使用var
參數)。
使用模板
模板通常用于设置配置文件,允许使用变量和其他功能来使这些文件更加灵活和可重用。Ansible使用Jinja2模板引擎。
以下示例是设置Apache虚拟主机的模板,使用一个变量来设置该主机的文档根目录:
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot {{ doc_root }}
<Directory {{ doc_root }}>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
内置模块template
用于在任务中应用模板。如果你将上述模板文件命名为vhost.tpl
,并且将其放置在与你的playbook相同的目录中,那么你可以这样应用模板来替换默认的Apache虚拟主机:
定义和触发处理程序
处理程序用于触发服务的状态更改,例如重新启动或停止。尽管它们看起来与常规任务相似,但处理程序只有在先前从任务中的notify
指令触发时才会执行。它们通常被定义为playbook中的handlers
部分中的一个数组,但它们也可以存在于单独的文件中。
让我们考虑一下我们之前的模板使用示例,我们设置了一个Apache虚拟主机。如果你想要确保在虚拟主机更改后重新启动Apache,你首先需要为Apache服务创建一个处理程序。这是在playbook内定义处理程序的方式:
在此,name
指令很重要,因為它將是此處處理程序的唯一識別符。要從任務觸發此處理程序,您應該使用 notify
選項:
我們已經看到了您可以使用的一些最重要功能,以開始撰寫 Ansible Playbook。在下一節中,我們將深入介紹一個更實際的範例,即一個將自動化安裝和配置 Apache 在 Ubuntu 上的 Playbook。
範例 Playbook
現在讓我們看一下一個 Playbook,它將自動安裝 Apache Web 伺服器在 Ubuntu 18.04 系統中,正如本指南介紹的那樣。
完整的範例,包括設置 Apache 和要由 Web 伺服器提供的 HTML 檔案的範本檔,可以在 Github 上找到。該文件夾還包含一個 Vagrantfile,讓您在簡化的設置中測試 Playbook,使用由 Vagrant 管理的虛擬機。
Playbook 內容
此 Playbook 的完整內容如下,以方便您參考:
- ---
- - hosts: all
- become: true
- vars:
- doc_root: /var/www/example
- tasks:
- - name: Update apt
- apt: update_cache=yes
-
- - name: Install Apache
- apt: name=apache2 state=latest
-
- - name: Create custom document root
- file: path={{ doc_root }} state=directory owner=www-data group=www-data
-
- - name: Set up HTML file
- copy: src=index.html dest={{ doc_root }}/index.html owner=www-data group=www-data mode=0644
-
- - name: Set up Apache virtual host file
- template: src=vhost.tpl dest=/etc/apache2/sites-available/000-default.conf
- notify: restart apache
- handlers:
- - name: restart apache
- service: name=apache2 state=restarted
-
讓我們更詳細地檢查此 Playbook 的每個部分:
主機:全部
Playbook 開始時聲明應用於清單中的所有主機(主機:全部
)。可以將 Playbook 的執行限制為特定主機或一組主機。此選項可在執行時覆寫。
變成:真
變成:真
部分告訴 Ansible 在執行此 Playbook 中的所有任務時使用權限升級(sudo)。此選項可逐個任務覆寫。
變數
定義一個名為 doc_root
的變數,稍後在一個任務中使用。此部分可以包含多個變數。
任務
實際定義任務的部分。第一個任務更新 apt
快取,第二個任務安裝 apache2
套件。
第三個任務使用內建模組 file 創建一個目錄作為我們的文檔根目錄。此模組可用於管理文件和目錄。
第四個任務使用模組 copy 將本地文件複製到遠程伺服器。我們正在複製一個簡單的 HTML 文件,以作為由 Apache 托管的網站。
處理器
最後,我們有 處理器
部分,其中聲明服務。我們定義了 重新啟動 apache
處理器,當第四個任務通知時,Apache 模板被應用。
執行 Playbook
當您將此 Playbook 的內容下載到您的 Ansible 控制節點時,您可以使用 ansible-playbook
在您的庫存中的一個或多個節點上執行它。以下命令將在您默認的庫存文件中的 所有 主機上執行 Playbook,使用 SSH 金鑰對身份驗證作為當前系統用戶連接:
您還可以使用 -l
來限制在庫存中的單個主機或一組主機上的執行:
如果您需要指定一個不同的 SSH 用戶來連接到遠程服務器,您可以在該命令中包含參數 -u user
:
有關如何運行 Ansible 命令和 Playbook 的更多信息,請參閱我們的指南 在 Ubuntu 18.04 上安裝和配置 Ansible。
結論
Ansible 是一個極簡的 IT 自動化工具,其學習曲線低,使用 YAML
進行配置腳本。它具有大量內置模塊,可用於抽象任務,如安裝套件和使用模板。它簡化的基礎設施要求和簡單的語言可能非常適合那些剛開始學習配置管理的人。然而,它可能缺少一些高級功能,這些功能在像 Puppet 和 Chef 這樣更複雜的工具中可以找到。
在這個系列的 下一部分 中,我們將看到 Puppet 的實際概述,Puppet 是一個流行且深耕已久的配置管理工具,它使用基於 Ruby 的表達能力強大的自定義 DSL 來編寫配置腳本。