如何貢獻你的第一支 Ansible Collection 以及 Ansible Tower Workflow 應用簡介

最近在研究 Ansible Tower Notification 的功能,發現Ansible Tower Notification 列表 沒有 LINE 相關的設定。之前有設定過一次 Slack,不過腦中記憶庫年久失修

思來想去,工作時程又很趕,還是使用熟悉的 LINE Notify 好了。於是手動寫了支 Ansible playbook,隔天起來,想想應該是有其他人也會想用 LINE Notify 去串 playbook 做通知,所以決定寫個 Plugin 讓想用 LINE Notify 的人不用寫落落長的腳本。

於是我花了一小時寫完 Ansible Module 並測試,然後花了兩小時半在查如何把這個 Module 弄成 Ansible Galaxy 看得懂的格式並且讓 Playbook 可以引用這個 Module。

如何貢獻的文件真的太分散了 XD

所以就有這篇整理文的誕生,順便簡單介紹一下 Ansible 的元件們,畢竟我也常常搞混…


🥥 Ansible 可重複利用的元件: Modules / Plugins 的差別

這篇文章不會介紹 Ansible 是什麼、怎麼使用和撰寫 Ansible Playbook,本篇文章會專注於 Playbook 裡面可以重複使用的是哪些元件,以及這些元件的差異性。

專人介紹可以看這支影片,裡面有個列表很清楚地解釋了兩者的差異:

upload successful

白話文翻譯就是:

Modules 就像是工具箱套組,你可以定義這個工具箱是專門修馬桶的,那箱子裡可能會包含馬桶專用的水管、馬桶專用螺絲、橡皮墊圈等等專門為了馬桶維修的工具,而這些工具有不同的尺寸(參數)。
假設今天我請了一位水電工,他會執行馬桶維修這個工作 (Playbook),那他可能會帶很多工具箱 (Modules) 來我家,然後執行以下修馬桶的步驟 (tasks):

1
2
3
1. 更換水管 - 呼叫解開、鎖緊水管模組,輸入水管長度參數
2. 更換橡皮墊圈 - 呼叫打開、鎖緊橡皮墊圈模組,輸入墊圈直徑參數
3. 測試沖水水壓 - 呼叫沖水模組,輸入水壓大小參數

Modules 的開發成員來自世界各地,有以企業為單位,為了將 Ansible 整合自家產品會開發出可以直接呼叫產品功能的 Ansible Modules。也有熱心的自由開發者提供好用的模組,只是維護的持續性和穩定性可能就不太能保障。

Plugins 可以想成是你想請這個水電工提供服務的方式(features)。

比方說今天你想請他每執行完成一個步驟,就跟你回報一次,你可能就會在設定檔輸入 echo_when_every_task_done=yes 這樣的變數設定。而 plugins 的開發者大部分會是 Ansible 核心開發團隊,這些 Plugins 主要是針對 Ansible 本身的功能呈現而開發的。

既然 Modules 和 Plugins 都可以自己撰寫並重複利用,那 Playbooks 可不可以重複利用呢?

當然可以!

Ansible 的中心思想就是鼓勵使用 Ansible 的開發者在撰寫完 playbooks 或是 Module 都可以分享出來,讓其他有需要的開發者能夠使用、甚至是改成自己需要的版本!所以我們會很常聽到 Ansible 可以重複利用其他人寫好的 Roles,免去自己開發的時間、當個稱職的薪水海賊王


🥥 如何貢獻你寫好的 module / roles

本篇文章秉持著站在巨人肩膀上的精神,不會介紹 Roles 如何使用和下載。但我會稍微介紹一下如果想把自行開發完的 modules / roles 分享出來,可以怎麼開發和上傳到 Ansible Galaxy,幫助更多開發者。

首先讓我們先來看看這篇 Ansible 的官方文章,直接看開發者文件的話可能會被一堆名詞搞得一頭霧水…

可以看到文章中表示

1
Ansible Content Collections, or collections, represent the new standard of distributing, maintaining and consuming automation. By combining multiple types of Ansible content (playbooks, roles, modules, and plugins), flexibility and scalability are greatly improved.

換句話說, Ansible 官方在 2019 年 11 月推出了 Ansible Content Collections(A.K.A. Collections),以後不管開發 playbook / roles / modules / plugins 都可以透過包裝成 collections 的方式上傳到 Ansible Galaxy 讓其他人下載。

OK,到這邊算是對接下來的會遇到名詞有個基本的認知了,首先先利用 ansible-galaxy 指令生出基本的框架來看看:

1
ansible-galaxy collection init ${my_namespace}.${my_collection}

my_namespace:你想拿來解釋這個 collection 最主要會拿來對應什麼組織、產品之下。假設今天我開發的是 Slack 相關的 Collection,namespace 就會取名一個跟 Slack 相關的名稱,這樣其他人要找你的 collection 也比較好找。

my_collection: 這個 collection 大致上的功能,假設這個 Collection 是做 Slack Bot 的發送連結、文字等功能,我可能會取一個 slack_chat 這樣的名字,功能一目了然。

upload successful
🔼 使用指令創建好框架之後,透過 tree 檢視資料夾的結構,可以發現有以下幾個子資料夾:

upload successful

然後可以再回到剛剛的Ansible官方文章,往下看的話可以發現官方有一個完整的結構圖和解釋,但有些資料夾如果沒有用到可以不用放:

upload successful

1
2
3
4
5
6
7
8
9
10
11
docs/: local documentation for the collection 
galaxy.yml: source data for the MANIFEST.json that will be part of the collection package
playbooks/: playbooks reside here
tasks/: this holds 'task list files' for include_tasks/import_tasks usage
plugins/: all ansible plugins and modules go here, each in its own subdir
modules/: ansible modules
lookups/: lookup plugins
filters/: Jinja2 filter plugins
connection/: connection plugins required if not using default
roles/: directory for ansible roles
tests/: tests for the collection's content

這邊會用我最近寫的 line_notify Modules 當範例:

upload successful
備註:這個 namespace 完全是錯誤示範XD

主體是 line_notify.py 這支檔案,用 Python 開發 Ansible Modules 需要使用 ansible.module_utils 這個第三方函式庫做參數的傳入、使用等功能。如果習慣使用別的語言做開發,也可以參考 如何使用 Bash Script 開發 Ansible Modules如何使用 Ruby 開發 Ansible Modules

開發完之後就要準備把專案打包上傳到 Ansible Galaxy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 進到 Collection 的根目錄
~/Documents/developing_project ❯ cd hazel_shen/line_notify

# 打包壓縮檔
~/Doc/dev/hazel_shen/line_notify main ❯ ansible-galaxy collection build
Created collection for hazel_shen.line_notify at /Users/hazel/Documents/developing_project/hazel_shen/line_notify/hazel_shen-line_notify-1.0.1.tar.gz

# 確認版本編號(1.0.1)是否跟 galaxy.yml 寫的(1.0.1) 一樣,不然會上傳失敗
~/Documents/developing_project/hazel_shen/line_notify main ❯ ls -al
total 32
drwxr-xr-x 10 hazel staff 320 May 29 16:13 .
drwxr-xr-x 3 hazel staff 96 May 29 16:13 ..
drwxr-xr-x 12 hazel staff 384 May 29 16:12 .git
-rw-r--r-- 1 hazel staff 5 May 27 17:34 .gitignore
-rw-r--r-- 1 hazel staff 1290 May 27 20:10 README.md
drwxr-xr-x 2 hazel staff 64 May 27 15:43 docs
-rw-r--r-- 1 hazel staff 2346 May 27 19:45 galaxy.yml
-rw-r--r-- 1 hazel staff 2360 May 29 16:13 hazel_shen-line_notify-1.0.1.tar.gz
drwxr-xr-x 4 hazel staff 128 May 27 17:00 plugins
drwxr-xr-x 2 hazel staff 64 May 27 15:43 roles

最省力的方式就是把 galaxy.yml 裡面跟這個專案有關的資訊都寫一寫,其他都不多弄也沒關係,之後再補上。

  1. 在 Galaxy 網頁上選擇 My Content > + Add Content (上傳完之後想更新版本可以按底下的 Upload New Version)
    upload successful

  1. 上傳方式有兩種: Import Role from GitHub vs Upload New Collection
    upload successful
    upload successful

因為我寫的不是 Role , Role 更複雜而且要補的資訊更多,所以我選擇簡單上傳壓縮檔的方式(Upload New Collection)

  1. 上傳剛剛打包好的壓縮檔 (*.tar.gz)
    upload successful
    upload successful

  2. 檢視上傳結果,可以看到成功或失敗、失敗原因
    upload successful

  3. 大功告成啦!使用方法可以參照 我的 GitHub 說明文件



🥥 如何讓你的 Ansible playbook 組團打副本 - Ansible Tower Workflow 以及如何讓 Ansible Tower 使用剛剛寫好的 Module

Ansible 除了本身是個蠻不錯用的自動化腳本引擎之外,在撰寫 playbook 的時候也可以思索以下幾個問題:

1
2
3
4
1. 當一支 playbook 要做的功能太多的時候,是否可以拆成多支 Playbook 並且透過呼叫的方式完成工作(e.g. 使用別人寫好的 Roles)
2. 要透過什麼方式將這些 Playbooks 串聯在一起?
3. 假設在這一堆 playbooks 中,有某一支 Playbook 執行失敗,我該怎麼得知失敗發生以及詳細的錯誤資訊?
4. Playbook 執行失敗時,我要怎麼安插處理錯誤的 Playbooks?(Error Handling)

針對以上問題,每個人的應對作法可能都不太一樣,但是我想介紹一個省時又省力的工具 - 超棒der 🌟Ansible Tower🌟

Ansible Tower 是一個集中式 Playbooks 管理工具,有簡單的視覺化 Dashboard 可以看得到執行腳本成功失敗的統計結果、詳細的執行資訊。如果控制的節點數在 10 個以下的話 (以 IP 為計算單位),是可以免費使用的!

這篇文章會介紹的是 Ansible Tower 其中一項非常好用的功能 - ✨ Workflow✨

Workflow 運作示意圖如下,這支 Workflow 的應用情境是在 Azure 上面進行 Windows Server Provision & Deploy IIS Web Server。如果把這些流程都寫在一支 Playbook 裡面,這支 Playbook 會變得非常冗長且難以維護;假設再加上 error handling 的 tasks 的話,會變得更悲劇,因為還要去測試錯誤發生時執行的程式邏輯是不是對的。

所以在這個應用情境中我拆成三支 Playbooks 完成這個情境:

1
2
3
4
5
1. 於 Azure 上創建 Windows Server 2019 Data Center instance
2. 設定這台 Windows Server,開啟 WinRM listener,讓這台機器可以被遠端執行命令
3. 安裝 IIS Webserver

Playbook 執行失敗的話會發送 LINE Notification 到你的 LINE 聊天室。

Ansible Tower Use Cases

這邊解釋一下 Workflow 三種顏色代表的意義:

1
2
3
藍色的線:一定會執行的 Playbook <br>
綠色的線:上個腳本執行成功後會執行的下個 Playbook <br>
紅色的線:上個腳本執行失敗後會執行的下個 Playbook <br>

有興趣的讀者可以看影片了解實際的執行畫面和流程。

介紹完 Workflow 和情境之後,重點就是要怎麼讓 Ansible Tower 的 Ansible Engine 會自動下載你指定的模組呢?一樣這邊拿出範例解釋:

upload successful

requirements.yml 長得就像這樣,把 ${namespace}.${collection} 條列好:
upload successful

然後透過指定 collections 的方式,就可以使用剛剛寫好的 modules 了,相當方便。
upload successful

我自己是使用 GitHub 做 Ansible Playbooks 的專案管理,在 Ansible Tower 上可以透過 Project 的方式做到同步 Playbook:
upload successful

使用 Templates 就可以使用 line_notify_playbook,而因為我有在 requirements 以及 playbook 裡面指定我要下載和使用的 module,所以在第一次執行時,Ansible Tower 會直接從 Ansible Galaxy 下載需要的 Collections。
upload successful

Playbook 執行結果,理想上寫法是要抓 credentials,但我還在想怎麼寫 XD
upload successful

可以實際在 LINE 上面收到訊息
upload successful

打完收工,有興趣的人歡迎追蹤專案進度或直接送 PR 🙈


🥥 Referecne

🔥 Ansible Tower Notification
🔥 LINE Notify Document
🔥 How Ansible Works
🔥 Ansible Modules
🔥 Ansible Plugins
🔥 Practical Ansible Solutions: Modules and Plugins|packtpub.com
🔥 凍仁翔 - 現代 IT 人一定要知道的 Ansible 自動化組態技巧 - 20. Roles 是什麼?
🔥 凍仁翔 - 現代 IT 人一定要知道的 Ansible 自動化組態技巧 - 21. 怎麼使用 Roles?
🔥 Getting Started With Ansible Content Collections
🔥 Ansible Reference: Module Utilities
🔥 Writing Ansible Modules in Bash
🔥 ansible-for-rubyists
🔥 Ansible Tower