description: “本文探討 Ansible 的進階變數管理與雲端整合實踐。首先說明如何利用 group_varshost_vars 目錄結構化地組織變數,並透過 Ansible Vault 加密機制保護密碼等敏感資料,確保自動化流程的安全性。接著,文章轉向雲端場景,闡述在 Azure…” 在現代化 IT 維運中,自動化工具的變數管理與安全性是基礎設施即程式碼的核心。傳統靜態設定檔難以應對雲端環境的動態性與彈性。本文從 Ansible 的變數組織策略出發,探討如何利用 group_varshost_vars 將配置與邏輯分離,並透過 Ansible Vault 確保敏感資訊在版本控制中的安全。進一步地,我們將此概念延伸至 Microsoft Azure,展示如何配置與使用動態清單。透過 Azure 標籤與動態清單外掛程式,Ansible 能即時發現並分類雲端資源,無需手動維護主機清單,從而實現對大規模、動態基礎設施的無縫自動化管理,這對於提升 CI/CD 流程的效率與可靠性至關重要。

Ansible 變數管理與敏感資料保護實踐

本章節將延續 Ansible 變數的管理探討,聚焦於如何將變數值與特定群組或主機進行綁定,並進一步深化 Ansible Vault 的應用。我們將透過實際範例,展示如何利用 group_varshost_vars 目錄結構來組織變數,並說明如何使用 ansible-vault 命令來加密和解密敏感數據,確保在自動化流程中的資料安全。

組織變數:group_varshost_vars 的應用

為了更精細地管理變數,Ansible 提供了 group_varshost_vars 這兩個預設目錄。這些目錄讓您可以根據清單中定義的主機群組或個別主機來組織變數文件。

  • group_vars/: 此目錄用於存放針對特定主機群組定義的變數。目錄下的子目錄名稱必須與清單中定義的群組名稱相符。例如,如果您在清單中有一個名為 database 的群組,您可以在 group_vars/database/ 目錄下創建變數文件(如 main.ymlvars.yml),這些變數將僅對 database 群組中的主機生效。
  • host_vars/: 此目錄用於存放針對特定單一主機定義的變數。目錄下的子目錄名稱必須與清單中定義的主機名稱相符。例如,如果您在清單中定義了一個名為 webserver1 的主機,您可以創建 host_vars/webserver1/ 目錄,並在其中放置變數文件。

範例:為 database 群組定義變數

延續先前 MySQL 角色的範例,我們需要為 database 群組定義 mysql_usermysql_password。我們可以在 Ansible 專案的根目錄下創建以下結構:

.
├── inventory
├── playbook.yml
├── roles/
│   └── mysql/
│       ├── tasks/
│       │   └── main.yml
│       └── defaults/
│           └── main.yml
└── group_vars/
    └── database/
        └── main.yml

group_vars/database/main.yml 文件中,我們可以定義這些特定於 database 群組的變數:

# group_vars/database/main.yml
mysql_user: mydbuserdef
mysql_password: mydbpassworddef

當您執行劇本並指定了包含 database 群組的清單時,Ansible 會自動載入 group_vars/database/main.yml 中的變數,並將它們應用於 database 群組中的所有主機。這使得劇本更加乾淨,並且變數的配置與劇本邏輯分離。

劇本的更新:

在主劇本 playbook.yml 中,您需要確保 database 群組被正確地指向了 mysql 角色:

# playbook.yml
---
- hosts: database
  become: true # 確保以 root 權限執行任務,例如安裝軟體
  roles:
    - mysql
---

執行此劇本時,Ansible 會自動讀取 group_vars/database/main.yml 中的變數,並將 mydbuserdefmydbpassworddef 作為 mysql_usermysql_password 的值傳遞給 mysql 角色中的任務。

使用 Ansible Vault 保護敏感資料

儘管 group_varshost_vars 提供了良好的變數組織方式,但將敏感資訊(如密碼)以明文形式儲存在這些文件中仍然存在安全風險。Ansible Vault 提供了解決方案。

加密變數文件:

您可以使用 ansible-vault encrypt 命令來加密包含敏感變數的文件。

ansible-vault encrypt group_vars/database/main.yml

執行此命令後,系統會提示您輸入一個 Vault 密碼。輸入後,group_vars/database/main.yml 文件的內容將被加密,您將無法直接讀取。

解密與修改:

若要修改加密的文件,可以使用 ansible-vault decrypt 命令:

ansible-vault decrypt group_vars/database/main.yml

同樣,這會提示您輸入 Vault 密碼。解密後,您可以像編輯普通文件一樣修改內容,然後再次使用 ansible-vault encrypt 加密。

使用密碼文件進行自動化:

在自動化流程(如 CI/CD 管道)中,手動輸入密碼是不切實際的。您可以將 Vault 密碼儲存在一個安全的文件中(例如 ~/.vault_pass.txt),並在執行 Ansible 命令時通過 --vault-password-file 選項指定該文件。

# 創建密碼文件 (確保此文件權限嚴格控制)
echo "your_super_secret_vault_password" > ~/.vault_pass.txt
chmod 600 ~/.vault_pass.txt

# 執行劇本時指定密碼文件
ansible-playbook -i inventory playbook.yml --vault-password-file ~/.vault_pass.txt

在劇本執行時提供密碼:

  • 互動模式: 使用 --ask-vault-pass 選項,Ansible 會在執行時提示您輸入密碼。
    ansible-playbook -i inventory playbook.yml --ask-vault-pass
    
  • 自動模式 (CI/CD): 使用 --vault-password-file 選項指向包含密碼的文件。

透過這種方式,敏感的資料(如資料庫密碼)被安全地加密,只有在執行 Ansible 命令時提供正確的 Vault 密碼,才能被解密並用於配置目標主機。這大大提升了基礎設施即程式碼的安全性。

動態清單 (Dynamic Inventory) 在 Azure 環境的應用

本章節將探討如何運用動態清單 (Dynamic Inventory) 來管理 Azure 基礎設施。相較於靜態清單,動態清單能更有效地處理不斷變動的雲端資源,特別是當環境是按需建立的臨時性資源時。我們將詳細介紹如何配置 Ansible 以存取 Azure 資源,包括建立 Azure Service Principal 並設定必要的環境變數。此外,我們也會說明如何利用 Azure 標籤 (Tags) 來實現對虛擬機的精確分組與過濾,為動態清單的生成奠定基礎。

靜態清單的挑戰與動態清單的優勢

在傳統的基礎設施管理中,我們通常使用靜態清單文件來記錄所有需要管理的伺服器。然而,當我們轉向雲端環境,特別是像 Azure 這樣彈性的平台時,虛擬機的生命週期可能變得非常短暫。例如,自動擴展的應用程式伺服器、臨時的測試環境,這些資源的創建和銷毀是頻繁發生的。

在這種情況下,手動維護一個靜態的清單文件將變得極其困難且耗時。每次有新虛擬機創建或銷毀,都需要手動更新清單,這不僅容易出錯,也大大降低了自動化管理的效率。

動態清單的出現正是為了解決這個問題。它允許 Ansible 直接從雲端平台(如 Azure)的 API 獲取最新的資源資訊,並將這些資訊轉換為 Ansible 可以識別的清單格式。這意味著:

  • 即時性: Ansible 始終能獲取最新的資源列表,無需手動更新。
  • 自動化: 資源的創建和銷毀會自動反映在清單中,實現無縫管理。
  • 彈性: 能夠輕鬆應對大規模、動態變化的雲端環境。

配置 Ansible 以存取 Azure 資源

要在 Azure 環境中使用 Ansible 並實現動態清單,首先需要讓 Ansible 能夠安全地存取您的 Azure 帳戶。這通常透過 Azure Service Principal 來實現。

建立 Azure Service Principal:

Azure Service Principal 是一個應用程式身份,它允許應用程式(在這裡是 Ansible)以程式化的方式存取 Azure 資源。建立 Service Principal 的步驟類似於 Terraform 的配置:

  1. 登入 Azure CLI: 使用 az login 命令登入您的 Azure 帳戶。

  2. 創建 Service Principal: 使用 az ad sp create-for-rbac 命令創建一個 Service Principal。在創建時,您需要指定所需的角色(例如 Contributor)和訂閱 ID。

    az ad sp create-for-rbac --role Contributor --scopes /subscriptions/<subscription_id>
    

    此命令會輸出 Service Principal 的相關資訊,包括 appId (Client ID)、password (Client Secret) 和 tenant ID。

  3. 設定環境變數: 為了讓 Ansible 能夠使用這些資訊,您需要將它們導出為環境變數。

    export AZURE_SUBSCRIPTION_ID=<your_subscription_id>
    export AZURE_CLIENT_ID=<your_service_principal_appId>
    export AZURE_SECRET=<your_service_principal_password>
    export AZURE_TENANT=<your_tenant_id>
    

    這些環境變數將被 Ansible 的 Azure 模組和動態清單外掛程式讀取,以進行身份驗證和授權。

利用 Azure 標籤 (Tags) 進行資源分組

在動態清單中,我們需要一種方式來過濾和分組 Azure 虛擬機,以便 Ansible 可以將任務應用到特定的資源集合上。Azure 標籤 (Tags) 是實現這一目標的理想機制。

標籤的作用:

標籤是鍵值對,您可以附加到 Azure 資源(包括虛擬機)上,用於組織、分類和管理資源。例如,您可以為虛擬機添加以下標籤:

  • environment: production
  • application: webserver
  • role: frontend
  • project: myapp

添加標籤:

您可以使用多種方式為 Azure 虛擬機添加標籤:

  • Azure CLI:
    az vm update --resource-group <resource_group_name> --name <vm_name> --set tags.environment=production tags.application=webserver
    
  • Azure PowerShell:
  • Terraform: 在創建虛擬機資源時,直接在配置中定義 tags 區塊。

一旦為虛擬機添加了標籤,Ansible 的動態清單外掛程式就可以利用這些標籤來創建相應的群組。例如,所有標有 environment: production 的虛擬機可能會被自動分組到一個名為 production 的 Ansible 群組中。

透過這種方式,我們可以根據標籤的定義,動態地生成 Ansible 清單,從而精確地定位和管理 Azure 環境中的虛擬機資源。

建立 Azure 動態清單外掛程式配置

安裝 Ansible Azure 集合 (Collection)

為了讓 Ansible 能夠與 Azure 資源進行互動,我們需要安裝 azure.azcollection。這個集合包含了與 Azure 相關的模組和動態清單外掛程式。

安裝方式:

您可以使用 pip 來安裝所需的 Python 依賴,或透過 ansible-galaxy 來安裝 Azure 集合。

  1. 使用 pip 安裝依賴: 創建一個名為 requirements-azure.txt 的文件,並在其中列出所需的依賴套件。

    # requirements-azure.txt
    azure-identity
    azure-mgmt-compute
    azure-mgmt-resource
    azure-mgmt-network
    

    然後,執行以下命令來安裝這些套件:

    pip3 install -r requirements-azure.txt
    
  2. 使用 ansible-galaxy 安裝 Azure 集合: 這是更推薦的方式,因為它將所有 Azure 相關的 Ansible 組件統一管理。

    ansible-galaxy collection install azure.azcollection
    

配置 Azure 動態清單外掛程式

安裝完 Azure 集合後,我們需要創建一個動態清單配置文件,告訴 Ansible 如何連接到 Azure 並獲取資源資訊。

創建動態清單文件:

創建一個新的文件,其名稱必須以 _azure_rm.yml 結尾。例如,我們可以命名為 inv.azure_rm.yml

# inv.azure_rm.yml
plugin: azure_rm

# 指定要包含的資源群組。Ansible 將只從這些群組中收集 VM。
include_vm_resource_groups:
  - demoAnsible

# (可選) 根據標籤 (tags) 對 VM 進行分組。
# 如果您的 VM 具有 'role' 標籤,Ansible 會自動創建 'role_webserver' 和 'role_database' 等群組。
keyed_groups:
  - key: tags.role
    prefix: role

配置說明:

  • plugin: azure_rm: 指定使用 Azure Resource Manager (ARM) 動態清單外掛程式。
  • include_vm_resource_groups: 這是核心配置。它指定了 Ansible 應該從哪些 Azure 資源群組中收集虛擬機資訊。在我們的範例中,我們只關注 demoAnsible 這個資源群組。
  • keyed_groups: 這個參數允許您根據 VM 的標籤 (tags) 來自動創建 Ansible 群組。
    • key: tags.role: 表示我們將根據名為 role 的標籤來進行分組。
    • prefix: role: 表示創建的群組名稱將以 role_ 作為前綴。例如,如果一個 VM 的 role 標籤是 webserver,它將被自動分組到 Ansible 的 role_webserver 群組中。

執行 Ansible 與動態清單

配置完成後,您就可以像使用靜態清單一樣,在 ansible-playbook 命令中指定這個動態清單文件。

ansible-playbook -i inv.azure_rm.yml your_playbook.yml

當 Ansible 執行時,它會:

  1. 讀取 inv.azure_rm.yml 文件。
  2. 使用您之前設定的環境變數(AZURE_SUBSCRIPTION_ID, AZURE_CLIENT_ID, AZURE_SECRET, AZURE_TENANT)連接到 Azure。
  3. 查詢 demoAnsible 資源群組中的所有虛擬機。
  4. 根據 role 標籤(或其他您配置的 keyed_groups)將這些虛擬機分組。
  5. 然後,您可以編寫劇本,針對這些動態生成的群組執行任務。

例如,如果您想配置所有標記為 role: webserver 的虛擬機,您的劇本可以這樣寫:

# your_playbook.yml
---
- hosts: role_webserver # Ansible 會根據標籤自動創建這個群組
  gather_facts: yes
  roles:
    - webserver_role # 假設您有一個 webserver_role
---

透過動態清單,您可以輕鬆管理 Azure 環境中不斷變化的虛擬機資源,確保您的自動化配置始終與實際基礎設施保持同步。

縱觀現代 IT 自動化管理的複雜挑戰,從變數的結構化組織、敏感資料的加密保護,到對應雲端環境的動態清單,這一系列實踐不僅是技術操作的演進,更體現了管理思維的深刻變革。將 group_varshost_vars 應用於變數管理,相當於為自動化流程建立了清晰的權責框架與溝通協議,避免了單一指令式管理的混亂與僵化。在此基礎上,Ansible Vault 的整合則扮演了關鍵的信任機制,它將安全內建於流程之中,而非事後補救,從根本上解決了自動化過程中信任與風險的平衡難題。

然而,真正的突破在於動態清單的引入。它將整個管理系統從靜態的、被動的配置模式,提升至動態的、具備環境覺察能力的主動適應模式。這種從「管理已知」到「探索未知」的轉變,徹底釋放了雲端基礎設施的彈性潛力。我們預見,未來 3-5 年,這種「結構化、安全化、動態化」三位一體的管理模型將成為基礎設施即程式碼(IaC)的標準典範,並進一步與 AIOps 融合,形成具備初步自我修復與優化能力的智慧運維生態。

玄貓認為,這套整合實踐已不僅是 Ansible 的最佳路徑,它更代表了一種雲端原生時代的基礎設施治理哲學。對於追求高效、安全與韌性的技術領導者而言,掌握這套方法論,等同於為團隊植入了持續適應與演化的核心競爭力。