提升你的 Ansible 技能的幾個建議
前言
先說本文僅代表個人撰寫 Ansible Playbook及 Ansible AWX 之經驗累積。
Ansible 本身具有幾個很顯著的特點: 好寫
, 易讀
, Agentless
,然而,說到好寫,也因為可以寫出多種風格,因此特別撰寫此文,記錄我在編寫 Ansible Playbook 時需要注意的一些事項。當然,其中一些內容會參考 Ansible 官方列出的 Ansible tips and tricks ,但大多數仍以我的個人經驗為出發點。
Suggestion 1: 建議遵循 Ansible Direcory Layout 的最佳實踐
經常編寫 Ansible 的人都知道,通過修改 ansible.cfg
文件,可以讓許多 playbook 的變數呼叫和路徑變得非常靈活。然而,雖然可以進行修改,但強烈不建議這樣做。原因是你的同事或接手的工程師可能不了解你的個人習慣,因此建議遵循最佳實踐和推薦的文件夾命名方式。
|
|
Suggestion 2: Playbook 命名法建議
在命名 Playbook 時,遵循 Do something for someone
的格式。我知道很多人會直接用 someone
作為 Playbook 的命名,但基於後續會提到的 Ansible AWX 帶來的 Workflow 概念——多個 Playbook 序列化執行
,以及期望維護者能一眼看出這份 Playbook 主要是在針對 什麼目標做什麼事情
,因此建議採用此命名規範。
|
|
Suggestion 3: 一個專案對應一個業務目標
Ansible 最頂端的資料夾稱為 專案 (Project)
,其次是 Playbook 及 roles 等文件結構。
假設今天要部署一個 HTTP 伺服器,需要包含 lb、www、db,我會將 Playbook 分為以下幾個:
- Deploy_http_server
- install_lb.yml
- install_<www.yml>
- install_db.yml
- check_www_service.yml
在這個案例中,專案名稱為 Deploy_http_server,裡面包含上述所列的 Playbook,以一個專案一個業務目標
為核心進行 Playbook 的撰寫。
Suggestion 4: 變數無給值時,預設使用 default 值
常寫 Shell Script 的人應該熟悉以下寫法:
|
|
在 Ansible 中也支援這種寫法:
|
|
這個使用情境我個人應用在部署新 VM 或更新系統時,針對特定主機
時會用到。過去要針對新部署的機器進行一些修正時,都需要修改 hosts 裡面的值,現在用這個寫法可以直接這樣操作:
|
|
這樣就可以針對 192.168.50.1 這台機器進行部署或上 patch,如果我沒有指定任何 extra-vars 的話,則會直接對 inventory 中的所有機器(all)進行處理。
這個寫法也可以結合 Ansible AWX 裡 Survey 功能進行 Self-service 應用。
Suggestion 5: Ansible Workflow 實作提示
這個概念源自於 Ansible AWX,它將多個 Playbook 序列化執行
。這種做法適用於由多個業務目標所組成的更大業務目標。你可以將其類比為 Agile 專案術語中的 Epic / Story / Task 對應到 Ansible 的 Workflow / Playbook / Roles。
Workflow 具體寫法如下:
|
|
如果你需要的話,也可以將 workflow 嵌套在 workflow 中,但除非你對抽象化程度非常有把握,否則建議最多只做一層 workflow,以應付大多數需求。
此外,這個功能主要是為了 Ansible AWX 設計的,不僅具備可視化 Workflow 的能力,還增加了更多錯誤處理功能。例如,當 Playbook 執行時出現問題,可以跳轉到錯誤處理步驟進行應對,比如發送通知等。
Suggestion 6: 使用版本控制系統(Version Control System)管理
在這裡的版本控制系統可以是任何一家方案,例如 git、svn、mercurial 等等。沒有最好的方案,只有最適合自己的方案。我個人強烈推薦使用 git
。無論你是採用集中式還是分散式的管理方式,都可以使用 git 來實現,非常好用。
遵循 Infrastructure as Code 的思想,應該對所有源代碼的變動進行記錄。使用版本控制有以下幾個好處:
- 允許使用者將檔案恢復到某個時間點的狀態
- 追蹤不同時間點的修改
- 確認在某個時間點進行了哪些變更,並查找導致問題的責任人
- 容易進行備份和管理
在 Ansible AWX 中,其專案內容的更新也是需要基於版本控制
進行設定檔的變動,這樣便於進行 Playbook 的內容管理。
Suggestion 7: 單一 host 可同時屬於多個 group
host 是唯一值,而 group 可以將多個 host 定義在一起,並且可以多重定義 host。也就是說,你可以把 group 當作 tag 來使用,根據不同的角色、位置、任務來進行定義,這在使用 --limit
參數時會非常好用。
具體的 inventory 寫法如下:
|
|
Suggestion 8: 避免使用 ansible_connection=local
,建議改用 ansible_connection=ssh
其實這裡不是說不能用 local,而是設計時請優先考慮使用 SSH 連線,有其他特殊需求再考慮使用 local,因為這主要牽涉到 Ansible 的連線行為。你可以使用 -vvv
選項來觀察連線過程。先前遇到過問題是使用 local 執行時,會有權限和環境變數的問題,經研究 issue 後,發現改成 SSH 連線後就沒有這些問題。此外,Ansible 預設的連線方式是 ansible_connection=ssh
,所以在 inventory 中不用特別明寫。
具體寫法如下:
|
|
Suggestion 9: 多利用 ping
模組進行連線測試
在執行任何 Playbook 之前,我會先針對我要執行的機器跑 ping
,以確保機器連接狀況正常。有時候可以通過這個動作提前發現網路和執行問題。多數時候,我會把這個工作寫成一份通用 Playbook,並搭配 Workflow 來進行檢查。此外,Ansible 的 ping
是一個 Ansible 模組,而不是單純的 Linux 工具 ping
。
具體的 ping Playbook 寫法如下:
|
|
Suggestion 10: 關閉 gather_facts 以加速執行速度
因為 Ansible 是 agentless,執行時預設會先去收集 host 上的環境資訊(例如 IP、hostname、OS 版本等)。然而,當管理的機器過多時,會發現收集這些資訊的時間過長。這時可以選擇將 gather_facts
設置為 false
,以節省收集資訊的時間。
|
|
Suggestion 11: 設定 fact_cache 以使用快取的環境變數
假設你真的需要用到 gather_facts
收集的環境資訊,但又不想在短時間內多次等待收集資訊的時間,可以在 ansible.cfg 中使用 fact_caching
來作為快取。這樣可以在一定時間內重用已收集的資訊,從而提高執行效率。
|
|
Suggestion 12: 增加 ssh 參數以提升連線效率
這部分偏向於 SSH 的傳輸調教,主要是 ControlPersist
和 Pipelining
這兩個選項。
ControlPersist
可以讓 SSH 建立的連線一直保持著連線,建議開啟以減少重複連線的時間。
而 Pipelining
則可以減少 Ansible 控制節點到主機之間的連線數量,也有助於提升執行效率。
|
|
Suggestion 13: 收集 tasks 的處理時間
如果每次執行時都不知道哪個 task 跑得最久或卡在哪裡,可以使用 Ansible 插件 profile_tasks
來統計各個 task 的處理時間。這樣可以精確了解每個 task 的耗時,尤其是 Gathering Facts 所消耗的時間。
|
|
Suggestion 14: 盡可能提供完整的 Inventory 資訊
盡可能在 Inventory 中提供明確的資訊,而不採用隱晦的資訊,尤其是 ansible_host
。這樣可以確保每個人看到這份 Inventory 時的理解是一致的。
|
|
Suggestion 15: 對敏感工作禁用 Log
若不希望在log中留下任何敏感性資料,可以在該 Task 多加一個 no_log: True
來避免記錄敏感資訊。
|
|