Ansible 是一個開源的基於 OpenSSH 的自動化配置管理工具。可以用它來配置系統、部署軟件和編排更高級的 IT 任務,比如持續部署或零停機更新。Ansible 的主要目標是簡單和易用,並且它還高度關注安全性和可靠性。基於這樣的目標,Ansible 適用於開發人員、系統管理員、發布工程師、IT 經理,以及介於兩者之間的所有人。Ansible 適合管理幾乎所有的環境,從擁有少數實例的小型環境到有數千個實例的企業環境。
使用 Ansible 無須在被管理的機器上安裝代理,所以不存在如何升級遠程守護進程的問題,也不存在由於卸載了守護進程而無法管理系統的問題。
Ansible 的主要功能
管理員可以通過 Ansible 在成百上千台計算機上同時執行指令(任務)。
對於管理員來說,經常需要執行下面的任務:
- 維護現存的比較復雜的服務器時,手動登錄的方式很容易遺漏一些操作,或者是執行一些未預期的操作。
- 手動初始化新的服務器耗時耗力!
對於這兩種情況,如果完全通過 shell 腳本實現。腳本會過於復雜,極難維護。當然我們也可以使用同類的工具,比如 Puppet and Chef。這兩個工具的特點是:需要學習新的知識棧(其實 Ansible 也是有學習成本的)。
相比 Puppet 和 Chef 使用 Ansible 可以延續之前使用 shell 腳本的工作習慣和方式,因而其學習成本會低一些。下面是 Ansible 的一些優勢:
- 可以逐行的執行 shell 命令。
- 不需要另外的客戶端工具(linux 一般會自帶 ssh 工具)。
- 相同的配置只被執行一次(多次執行同一配置不會出問題)。
Ansible 的工作方式
使用 Ansible 無須在被管理的客戶端電腦上安裝代理之類的組件。它通過普通的 SSH 進行通信,以便從遠程計算機檢索信息、發出命令和復制文件。這是 Ansible 簡化服務器管理的一種方式。任何公開 SSH 端口的服務器都可以通過 Ansible 進行配置和管理。
Ansible 采用模塊化的設計,所以非常容易擴展到各種特定的使用場景。模塊可以用任何語言編寫,並使用標准 JSON 進行通信。Ansible 的配置文件是用 YAML 格式編寫的,因為它使用起來非常簡單,並且與主流的標記語言很相似。除了通過命令行工具 Ansible 還可以通過配置腳本(Playbooks)與客戶端交互。
安裝 Ansible
本文介紹在 Ubuntu 16.04 環境中安裝並使用 Ansible。由於 Ubuntu 官方庫提供的版本比較老,所以我們從第三方的庫安裝,這樣就能安裝到比較新的版本:
$ sudo apt-add-repository -y ppa:ansible/ansible $ sudo apt-get update $ sudo apt-get install -y ansible
安裝完成后檢查一下版本:
$ ansible --version
2.7.1 是筆者在寫本文時的最新版本。
配置客戶端主機的 SSH 秘鑰
對於自動化來說,最后是通過秘鑰進行認證,這樣就不會把用戶的密碼以明文的方式寫在腳本里。下面的命令把安裝了 ansible 的主機上當前用戶的 SSH 公鑰安裝到了被管理的客戶端 192.168.21.145 和 192.168.21.148 上:
$ ssh-copy-id -i ~/.ssh/id_rsa.pub nick@192.168.21.145 $ ssh-copy-id -i ~/.ssh/id_rsa.pub nick@192.168.21.148
說明:這兩台被管理的客戶端主機運行的也都是 Ubuntu 16.04。
然后嘗試通過下面的命令以不輸密碼的方式連接到遠程主機中:
$ ssh nick@192.168.21.145 $ ssh nick@192.168.21.148
如果能夠成功登陸,說明 SSH 的配置已經 OK 了。
配置用戶執行 sudo 時不需要密碼
在我們執行的自動化操作中,有很大一部分是需要 root 權限的,比如執行更新、安裝軟件等等。這樣的操作會因為在以 sudo 方式執行是提升用戶輸入密碼而失敗,比如下面的命令:
$ ansible testservers -b -u nick -a "apt update"
-b 選項默認把用戶 nick 提升為 root 權限,但是需要輸入用戶 nick 的密碼,所以自動化執行的命令失敗了。當然我們可以同時添加 -K 選項,這是 ansible 會停下來與用戶交互,等待用戶輸入密碼:
但這真的不是我想要的結果,我需要的是腳本能夠自動化的不需要交互的完成任務!
這個問題的解決方法是把用戶設置為執行 sudo 命令時不需要輸入密碼,讓我們在客戶機 192.168.21.148 上執行下面的命令:
$ sudo visudo
為用戶 nick 添加下面的行:
nick ALL=(ALL) NOPASSWD: ALL
該行內容配置用戶 nick 在執行 sudo 命令時不需要輸入密碼,保存后讓我們再次執行下面的命令:
$ ansible testservers -b -u nick -a "apt update"
這次終於可以執行 root 權限的命令了!
清單(inventory)
清單是 ansible 的一個配置文件,在清單中我們可以指定被管理的客戶端機器。Ansible 默認的清單文件為 /etc/ansible/hosts,當然我們也可以通過 -i 選項指定其它的清單文件,比如下面的例子:
$ ansible myservers -i /etc/ansible/myhosts -b -u nick -a "apt update"
在清單文件中,我們可以指定 ansible 命令操作的主機對象。對於單個的主機,可以在清單中寫主機域名,也可以直接寫 IP 地址:
如果要同時對對個主機進行操作,可以把它們定義在一個組中:
在執行 ansible 命令時,指定清單中定義的主機名稱或者組名就可以了。比如我們在 /etc/ansible/hosts 文件中定義了一個名稱為 testservers 的組,它包含了兩個主機:
然后通過下面的命令分別在這兩台主機上執行 df -h 命令:
$ ansible testservers -u nick -a "df -h"
從輸出的結果可以看出 df -h 命令在兩台目標主機上都執行了。
模塊
Ansible 把類似的操作封裝到模塊中,這樣就可以通過插件的方式對 Ansible 進行擴展了。每個模塊都能接收參數,幾乎所有的模塊都接受鍵值對(key=value)參數,這些參數通過空格進行分隔。也有一些模塊不接收參數,只需在命令行輸入相關的命令就能調用。如果要執行單個命令,可以使用 command 模塊:
$ ansible testservers -m command -u nick -a "df -h" $ ansible webservers -m command -a "/sbin/reboot -t now"
因為 command 是 ansible 執行命令是使用的默認模塊,所以我們可以在命令行中省略它:
$ ansible testservers -u nick -a "df -h" $ ansible testservers -b -u nick -a "/sbin/reboot -t now"
這樣的寫法本質上和前面的寫法是一樣的。
如果要執行其它模塊中的命令就需要通過 -m 選項顯式的指定模塊的名稱,比如執行 service 模塊中的命令:
$ ansible testservers -m service -a "name=httpd state=started"
如果要把文件從本機拷貝到客戶端主機上去,就需要使用 copy 模塊:
$ ansible testservers -m copy -u nick -a "src=./app.js dest=./myapp/app.js"
Ansible 默認內置了很多好用的模塊,你可以從其官方文檔中的模塊部分了解更多模塊相關的內容。
playbook
如果 Ansible 的功能僅僅是能夠執行當個的命令和腳本就顯得太弱了。Ansible 的 laybook 功能支持把命令以 yaml 的格式寫在配置文件中,然后一次性執行配置文件中的所有命令(這一點類似於 chef 中的 cookbook)。比如我們可以把前面演示的 df -h 命令以配置文件的方式寫在 playbook 中:
--- - hosts: testservers become: true become_user: root tasks: - name: check disk command: df -h
把上面的代碼保存在文件 playbook.yml 中,當然你可以根據自己的喜好命名這個文件。其中 hosts 表示對哪些主機進行操作,become 就是我們在命令行上用過的 -b 選項,這里我們通過 become_user: root 顯式的指定把當前用戶的權限提升為 root 用戶權限來執行命令。下面的 tasks 則是對任務的定義,name 是獨一無二的一個任務名(如果有多個同名的 task,只執行第一個),接着是 task 中的命令,這里我們還是簡單的執行 df -h 命令。然后執行下面的命令,注意這次執行的是 ansible-playbook 命令,並且需要指定編輯好的 playbook 的文件名稱作為參數:
$ ansible-playbook -u nick playbook.yml
這樣一個簡單的 playbook 就可以正常工作了,當然實際的生產環境中你可能會把 playbook 編寫的非常復雜!
跳過首次 ssh 連接時的確認提示
這是一個在自動化的過程中經常碰到的問題,所以有必要提一下。如果你不是通過 ssh-copy-id 命令把公鑰添加到目標機器上的(多數的環境都不是這么做的),在首次執行 ansible 命令時需要用戶確認連接的安全性:
這是非常悲催的,因為我們要實現的目標是自動化的執行命令,而不需要進行交互式的操作。
這個問題的解決方案是配置 ansible,跳過這一步的檢查。具體的做法是在配置文件 /etc/ansible/ansible.cfg 中找到行 host_key_checking = False,並去掉行頭的注釋字符:
然后再執行 ansible 命令就不會提示用戶進行交互式驗證了。
總結
Ansible 是一個強大的自動化工具,並以其簡介的用法,對開發者(系統運維工程師)友好的特點在自動化的流程中占據了一席之地。在這個 devops 已經成為主流的時代,如果能夠熟練的使用 ansible ,相信必定會讓你的 devops 實踐如虎添翼。
參考:
Ansible Doc
Ansible中文權威指南
How to Install and Configure Ansible on Ubuntu 16.04