1. 程式人生 > >Ansible 簡介

Ansible 簡介

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

$ 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 [email protected]192.168.21.145
$ ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]192.168.21.148

說明:這兩臺被管理的客戶端主機執行的也都是 Ubuntu 16.04。

然後嘗試通過下面的命令以不輸密碼的方式連線到遠端主機中:

$ ssh [email protected]192.168.21.145
$ ssh [email protected]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 實踐如虎添翼。