TL;DR
前情提要 - Ansible 入門筆記(ㄧ) - 核心概念及架構
使用 Ansible
同時部署多台機器時,使用Variable
機制可以根據需求,賦予不同群組、不同節點特定的參數,增加部署的彈性及效率。
Jinja2 渲染
在開始探討 Ansible
的 Variable 前,我們先花點篇幅介紹 Jinja2
的渲染機制。
Jinja2是Python一套相當強大的模板引擎,許多Python相關的套件都有支援,例如: Flask
, FastAPI
。
場內連結: 對於Flask
, FastAPI
有興趣的朋友,歡迎看看我的其他筆記:
你可以將 Jinja2
的功能理解為:
根據需求將資訊動態寫入到檔案中
舉例來說,身為一個網頁設計師,你接到了一個案子,需要替公辰麵館設計一個網頁如下:
<html>
<head>
<title> 歡迎蒞臨-公辰麵館 </title>
</head>
<body>
<h1>公辰麵館讚啦!</h1>
</body>
</html>
因為網頁寫的太棒了,隔壁的華貞生魚片也希望你替他們設計一個相同的網頁,於是你又動手開工:
<html>
<head>
<title> 歡迎蒞臨-華貞生魚片 </title>
</head>
<body>
<h1>華貞生魚片讚啦!</h1>
</body>
</html>
仔細一看,這兩個網頁的架構幾乎一模一樣 (真是沒有職業道德的網頁設計師),只有店名的地方不一樣,如果能夠更省點時間有多好?
這時候 Jinja2
就派上用場了,你可以設計一個 模板(Template),裡面包含了重複的資訊,並且把要替換的資訊挖空:
<html>
<head>
<title> 歡迎蒞臨-{{ customer }} </title>
</head>
<body>
<h1>{{ customer }}讚啦!</h1>
</body>
</html>
這時候只要提供 customer
這個變數, Jinja2
就會按照上面的模板,自動將customer
變數填進去,也就是說你只需要提供不同的 customer
,就可以快速的產生數百間店面的網頁!
真是薛翻了!
Variable
在 Ansible
的專案資料夾中有兩種類型的 Variable: Host Variable
以及 Group Variable
。
專案架構
Ansible
透過這兩種變數的交互使用,「快速」且「彈性」管理多台機器,先來個案例:
假設你準備要部署服務,而你的環境如下圖:
從上圖中,由外而內:
有兩個獨立的環境(Environment):
SIT
和PROD
每個環境中按照功能導向可分為兩種群組(Group):
Web-Server
DB-Server
每個群組中依照需求又可有多台主機(Node)
設定 Inventory File - 區別環境
上圖的架構在 Ansible
的架構中該如何表達呢?
首先需要掌握幾個重點:
- 一個環境會有一個
Inventory File
Inventory File
中定義了節點的連線資訊 和 節點隸屬的群組
理解上述重點後,我們可以產生下列的Inventory File
:
第一個 Inventory File
- SIT
# SIT
[Web_Server] # 定義群組
Node_A ansible_host=127.0.0.1 ansible_port=44
Node_B ansible_host=192.168.16.49 ansible_port=44
[DB_Server] # 定義群組
Node_C ansible_host=127.0.0.1 ansible_port=3306
Node_D ansible_host=192.168.16.49 ansible_port=3306
第二個 Inventory File
- Production
# Production
[Web_Server] # 定義群組
Node_E ansible_host=192.168.16.6 ansible_port=44
Node_F ansible_host=192.168.16.22 ansible_port=44
[DB_Server] # 定義群組
Node_H ansible_host=192.168.17.12 ansible_port=3306
Node_G ansible_host=192.168.17.84 ansible_port=3306
一個環境會有一個Inventory File,其定義了節點的連線資訊及各節點隸屬的群組
此時專案資料夾將會長這樣:
ansible_project
| - README.md
| - SIT # Inventory File
| - Production # Inventory File
| - main.yml # Playbook
定義好 Inventory File
後,透過指定 Inventory File
就可以對不同的環境進行操作:
ansible-playbook -i SIT main.yml # 操作SIT環境
ansible-playbook -i Production main.yml # 操作Production環境
Group Variable - 群組變數
在開頭我們提到使用 Variable
可以有彈性的操作多台機器,又介紹了 Jinja2
這種語法,現在我們來揭曉原因!
在 Playbook
中可以使用 Jinja2
語法,舉個例子,我們設計一個簡單的 Playbook
,在執行時會透過 Debug 模組印出特定的值.
# main.yml
- name: task-for-db
hosts: DB_Server
tasks:
- name: db-show-group
debug:
msg: I'm a database node! My group is {{ group_value }}
- name: task-for-web
hosts: Web_Server
tasks:
- name: web-show-group
debug:
msg: I'm a web node! My group is {{ group_value }}
接下來可以在 group_vars
資料夾下,根據群組名稱建立同名的 yaml 檔案:
# group_vars/Web_Server.yml
group_value: GROUP_WEB
# group_vars/DB_Server.yml
group_value: GROUP_DB
當 Playbook
被執行時, Ansible
會造訪 group_vars
資料夾讀取這些變數:
Playbook
中hosts
設定為Web_Server
的區塊,有個{{ group_value }}
,Ansible
將自動從group_vars/Web_Server.yml
中將設定的變數填入.Playbook
中hosts
設定為DB_Server
的區塊,有個{{ group_value }}
,Ansible
將自動從group_vars/DB_Server.yml
中將設定的變數填入.
當群組有自己專用的變數時,可以設定在
group_vars
中,例如DB_Server會需要資料庫的名稱、連線資訊,而 Web_Server 則不需要。
此時我們將前面的專案結構稍微擴充 :
ansible_project
| - README.md
| - SIT # Inventory File
| - Production # Inventory File
| main.yml # Playbook
|
| - group_vars/
| - DB_Server.yml # Group Variable
| - Web_Server.yml # Group Variable
Host Variable - 節點變數
Host Variable 放置的是節點專屬的變數
有別於 Group Value
放置的是群組專用的變數,有時候我們會需要設定「節點」專屬的變數 (例如節點的ip、Linux的版本等等)。
舉例來說,我們稍微擴充一下 Playbook
:
# main.yml
- name: task-for-db
hosts: DB_Server
tasks:
- name: db-show-group
debug:
msg: I'm a database node! My group is {{ group_value }}
- name: db-show-node
debug:
msg: My node information(DB) is {{ node_value }}
- name: task-for-web
hosts: Web_Server
tasks:
- name: web-show-group
debug:
msg: I'm a web node! My group is {{ group_value }}
- name: web-show-node
debug:
msg: My node information(Web) is {{ node_value }}
這些節點專屬的變數統一放在 host_vars/
資料夾下,且名稱會與節點同名
# /host_vars/Node_A.yml
node_value: I'm Node A
# /host_vars/Node_B.yml
node_value: I'm Node B
當 Playbook
被執行時, Ansible
會造訪 host_vars
資料夾讀取這些變數:
Ansible
在Node_A
機器上執行Playbook
安排的任務時,將自動從host_vars/Node_A.yml
中將設定的變數填入{{ node_value }}
.Ansible
在Node_B
機器上執行Playbook
安排的任務時,將自動從host_vars/Node_B.yml
中將設定的變數填入{{ node_value }}
.
當節點有自己專用的變數時,可以設定在
host_vars/
中,例如節點A與節點B分別有不同的IP位置。
此時我們繼續擴充專案結構 :
ansible_project
| - README.md
| - SIT # Inventory File
| - Production # Inventory File
| main.yml # Playbook
|
| - group_vars/
| - DB_Server.yml # Group Variable
| - Web_Server.yml # Group Variable
| - host_vars/
| - Node_A.yml # Host Variable
| - Node_B.yml # Host Variable
.
.
.
| - Node_H.yml # Host Variable
結論
本篇筆記記錄了 Ansible
容易搞混的 Variable
機制,根據部署時的需求可以選擇使用 Group Variable
或是 Host Variable
.
這些Variable
都會在Playbook
執行時透過Jinja2
的渲染將變數填入。
在多台機器上部署服務時,通常做的事情都是相同的,只是使用的參數會有所不同,透過 Group Variable
和 Host Variable
的交叉使用,可以靈活設定每一個節點。
一旦某些參數需要進行調整(例如Production
環境的某個IP要更換),可以直接更換Variable
設定的值就好,不需要勞師動眾的調整Playbook
。
在下篇筆記中,我們將會繼續介紹 Ansible
的應用,包含:
- 如何使用
role
來提高Ansible
專案的程式碼重用率 - 使用
Ansible-Galaxy
來取得眾多開源Playbook
感謝您的閱讀!如果有任何問題歡迎透過電子郵件聯繫我!
我們下次見!