Ansible 模組是擴充套件 Ansible 核心功能的關鍵。本文以 WordPress 使用者管理為例,示範如何使用 Python 和 PHP 開發自訂 Ansible 模組,並與 WordPress 的 XML-RPC API 進行互動,實作使用者資訊的更新與管理。同時,文章也涵蓋瞭如何解析模組引數、處理冪等性問題、提供事實(Facts)給 Ansible 以及與 AWS 平台的協同運作,以建立虛擬私有雲並啟動伺服器,提供更全面的 Ansible 自動化解決方案。透過本文提供的程式碼範例和詳細說明,讀者可以深入瞭解 Ansible 模組開發的技巧和最佳實踐,並將其應用於實際的自動化場景中。
撰寫自訂 Ansible 模組:WordPress 使用者管理範例
在前面的章節中,我們已經瞭解如何使用 Ansible 來管理 WordPress 的使用者。本章節將探討如何撰寫自訂的 Ansible 模組,以實作更靈活的使用者管理功能。
建立初始模組定義
首先,我們需要定義模組的引數。以下是一個基本的 wp_user 模組定義:
#!/usr/bin/python
from ansible.module_utils.basic import *
def main():
module = AnsibleModule(
argument_spec=dict(
url=dict(required=True),
username=dict(aliases=['name'], required=True),
password=dict(required=False),
display_name=dict(required=False)
)
)
params = module.params
# 模組邏輯將在這裡實作
module.exit_json(changed=True, name=params['username'])
if __name__ == '__main__':
main()
內容解密:
AnsibleModule是 Ansible 提供的基礎類別,用於建立模組。argument_spec定義了模組接受的引數,包括url、username、password和display_name。aliases允許為引數指定別名,例如username可以使用name作為別名。required指定某些引數是否為必填。
測試模組
使用 Ansible 提供的 test-module 工具來測試我們的模組:
$ ansible/hacking/test-module -m wp_user -a 'name="michael" password="pass"'
這個命令會執行我們的 wp_user 模組,並傳遞 name 和 password 引數。
與 WordPress XML-RPC API 互動
為了與 WordPress 的 XML-RPC API 互動,我們需要使用 Python 的 xmlrpclib 模組。以下程式碼展示瞭如何連線到 WordPress 的 XML-RPC 端點並進行簡單的測試:
import xmlrpclib
server = xmlrpclib.ServerProxy('%s/xmlrpc.php' % params['url'], use_datetime=True)
res = server.demo.sayHello()
module.exit_json(changed=True, name=res)
內容解密:
xmlrpclib.ServerProxy建立了一個到 WordPress XML-RPC 端點的連線。server.demo.sayHello()發送了一個測試請求到 WordPress,以驗證連線是否成功。
更新模組以支援更多引數
根據 WordPress 的檔案,我們可以更新我們的模組以支援更多使用者屬性的更新,例如 first_name、last_name、user_url 等。
module = AnsibleModule(
argument_spec=dict(
url=dict(required=True),
username=dict(aliases=['name'], required=True),
password=dict(required=False),
first_name=dict(required=False),
last_name=dict(required=False),
user_url=dict(required=False),
display_name=dict(required=False),
nickname=dict(required=False),
nicename=dict(required=False),
bio=dict(required=False)
)
)
內容解密:
- 更新了
argument_spec以包含更多使用者屬性。 - 使用了與 WordPress 檔案一致的引數名稱,除了
url被重新命名為user_url以避免衝突。
實作使用者更新邏輯
接下來,我們需要實作更新使用者詳細資訊的邏輯。這包括迭代所有提供的引數,並呼叫 wp.editProfile 端點來更新使用者資料。
details = {}
skip_fields = ['username', 'name', 'password', 'url']
mappings = {"user_url": "url"}
for k, v in params.iteritems():
if k in skip_fields:
continue
if v:
if k in mappings:
k = mappings[k]
details[k] = v
res = server.wp.editProfile(1, params['username'], params['password'], details)
內容解密:
- 建立了一個字典
details來儲存需要更新的使用者屬性。 - 跳過了不必要的欄位,如
username和password。 - 將
user_url對映到 WordPress 期望的url欄位。 - 使用
wp.editProfile更新了使用者的詳細資訊。
確保模組的冪等性
目前我們的模組總是傳回 changed: true,因為它無條件地向 WordPress 傳送請求。為了使模組具有冪等性,我們需要取得使用者的當前詳細資訊,並比較傳入的引數是否與現有資料不同。如果不同,才進行更新。
使用其他程式語言撰寫Ansible模組
撰寫Ansible模組並不侷限於Python,您可以使用任何您喜歡的程式語言。然而,若沒有ansible.module_utils.basic的協助,您就需要自行處理引數解析的工作。即使是基本的引數解析也可能變得相當複雜。以下是一個PHP範例,展示如何解析key=value格式並將輸入值傳回給Ansible:
PHP範例:解析引數並傳回Ansible
#!/usr/bin/env php
<?php
$args = file_get_contents($argv[1]);
$params = [];
$currentParam = '';
#### 內容解密:
此段程式碼的作用是讀取來自Ansible的引數檔案。`$argv[1]`代表傳遞給PHP指令碼的第一個引數,通常是包含模組引數的檔案路徑。`file_get_contents($argv[1])`讀取該檔案的內容,並將其儲存於`$args`變數中。
foreach (explode("\n", $args) as $arg) {
if (strpos($arg, "=") !== false) {
list($key, $value) = explode("=", $arg, 2);
$params[$key] = $value;
$currentParam = $key;
} else {
if ($currentParam) {
$params[$currentParam] .= "\n" . trim($arg);
}
}
}
#### 內容解密:
這段程式碼遍歷每一個從檔案讀取的行。如果該行包含`=`字元,則將其視為一個新的鍵值對,並將其加入到`$params`陣列中。如果該行不包含`=`字元,則將其視為前一個鍵的值的延續,並將其附加到對應的值後面。
$result = [
"changed" => false,
"meta" => $params
];
#### 內容解密:
這裡建立了一個結果陣列,包含兩個鍵:`changed`和`meta`。`changed`用於指示模組執行是否導致了變化,而`meta`則包含了傳遞給模組的引數。
echo json_encode($result);
exit(0);
#### 內容解密:
最後,將結果陣列編碼為JSON格式並輸出。這是Ansible預期的輸出格式。`exit(0)`表示指令碼成功執行。
撰寫模組的最佳實踐
- 支援檢查模式:讓您的模組支援檢查模式(check mode),這允許使用者在不實際執行的情況下預覽模組的效果。
- 冪等性:盡可能使您的模組具有冪等性,即多次執行模組應該具有相同的效果,除非外部條件發生了變化。
- 提供詳細的錯誤訊息:當模組執行失敗時,提供儘可能詳細的錯誤訊息,以幫助使用者診斷問題。
編寫自訂模組的深度解析與實踐
在 Ansible 自動化工具的應用中,模組(Module)是實作特定功能的基本單元。透過編寫自訂模組,使用者可以擴充套件 Ansible 的功能,以滿足特定的需求。本章節將探討如何編寫自己的 Ansible 模組,並提供實際的範例與解析。
建立 PHP 模組的基礎
首先,我們將建立一個簡單的 PHP 模組,用於解析輸入引數並傳回結果。以下程式碼展示瞭如何實作這一點:
foreach (array_merge(explode(" ", $args),['=']) as $part) {
if (strpos($part, "=") !== false) {
if ($currentParam) {
list($k, $v) = explode("=", $currentParam, 2);
$v = preg_replace('/"([^""]+)"/', '$1', $v);
$params[$k] = $v;
}
$currentParam = $part;
} else {
$currentParam .= ' '.$part;
}
}
echo json_encode($params);
內容解密:
- 引數解析邏輯:程式碼首先將輸入引數
$args進行分割和合併處理,以便正確解析包含空格的引數值。 - 鍵值對提取:當遇到包含 “=” 的部分時,程式碼會將其視為鍵值對進行處理,並儲存到
$params陣列中。 - 結果輸出:最終,解析後的引數以 JSON 格式輸出,方便 Ansible 的處理。
測試與驗證 PHP 模組
建立完成後,可以使用 ansible/hacking/test-module 工具進行測試。執行以下命令:
$ ansible/hacking/test-module -m demo_php -a 'name="michael" url="http://book.example.com" password="password" first_name="Michael" last_name="Heap"'
預期輸出結果為解析後的 JSON 資料:
{
"first_name": "Michael",
"last_name": "Heap",
"name": "michael",
"password": "password",
"url": "http://book.example.com"
}
提供事實(Facts)給 Ansible
除了執行特定任務外,模組還可以提供事實(Facts)供後續任務使用。透過在傳回資料中加入 ansible_facts 鍵,可以實作這一功能。
更新模組以提供新事實
以下範例展示瞭如何更新模組以傳回 wp_existing_users 事實:
facts = {
"wp_existing_users": existing_users
}
module.exit_json(changed=is_changed, user=dict(current_user), ansible_facts=facts)
內容解密:
- 事實定義:定義了一個名為
wp_existing_users的事實,用於儲存現有的 WordPress 使用者列表。 - 傳回資料結構:透過
module.exit_json方法傳回包含ansible_facts的資料結構,使得事實可以在後續任務中使用。
在 Playbook 中使用自訂模組與事實
建立一個名為 play.yml 的 Playbook,以示範如何使用自訂模組和事實:
---
- hosts: all
gather_facts: false
tasks:
- name: Update User
wp_user: username=michael password=password url="http://book.example.com" first_name="Michael"
- debug: var=wp_existing_users
執行 Playbook 時,需指定自訂模組路徑:
ansible-playbook -i 'localhost,' -M . -c local play.yml
內容解密:
- Playbook 結構:定義了一個簡單的 Playbook,包含更新使用者和除錯輸出事實兩個任務。
- 自訂模組呼叫:透過
wp_user模組更新使用者資訊。 - 事實除錯輸出:使用
debug模組輸出wp_existing_users事實,驗證自訂模組的功能。
與AWS的協同運作
到目前為止,我們一直將Ansible用作資源組態工具,但它能做的遠不止於此。在本章中,我們將探討Ansible的協同運作能力。具體來說,我們將與亞馬遜的AWS(Amazon Web Services)平台互動,以建立虛擬私有雲並在其內啟動一些伺服器。
建立AWS帳戶
在使用AWS之前,您需要前往https://aws.amazon.com/ 並點選右上角的「註冊」來建立帳戶(參見圖7-1)。註冊過程相當漫長,需要您的地址和帳單詳細資訊。AWS提供了一個免費層,其中包括每月750小時的虛擬機器使用時間,但他們仍然需要提前提供帳單詳細資訊。提供亞馬遜所需的所有詳細資訊後,您將進入身份驗證步驟。亞馬遜會撥打電話並要求您使用按鍵輸入PIN碼,以證明您提供的聯絡電話號碼屬於您(參見圖7-2)。
選擇支援計劃
在提示時選擇基本(免費)支援計劃,然後點選「繼續」(參見圖7-3)。
設定AWS帳戶
此時,您已擁有完全啟用的AWS帳戶。點選「登入控制檯」,然後使用您剛剛設定的電子郵件和密碼登入。登入後,在右上角選擇「N. Virginia」,然後將您的區域更改為「US West (Oregon)」。這是本文測試所使用的相同區域。某些詳細資訊(如AMI ID)會根據區域而有所不同,因此在跟隨本文進行操作時,確保您處於相同的區域非常重要。
IAM使用者
亞馬遜提供了一組根憑據,可讓您完全存取您的帳戶,但您不應在任何地方使用這些憑據。相反,您應該建立一個IAM(身份和存取管理)使用者,該使用者僅具有執行所需操作的許可權。首先,點選螢幕頂部的「服務」,然後從「安全與身份」選單中選擇IAM。這是您將建立受限制使用者的地方。
建立IAM使用者群組
在建立使用者之前,您需要建立一組許可權以新增到使用者。在左側的側邊欄中點選「群組」,然後在螢幕頂部點選「建立新群組」。將您的群組命名為AnsibleGroup,然後點選「下一步」。下一個螢幕可能會看起來相當令人生畏,但實際上並不那麼複雜。在這裡,您可以設定不同級別的存取許可權,包括完全存取和唯讀存取。您將為使用者提供對特定服務的完全存取許可權,因此在搜尋框中搜尋「FullAccess」。
新增許可權
您需要為使用者提供AmazonEC2FullAccess和AmazonVPCFullAccess策略,因此在清單中找到每個策略,並點選旁邊的核取方塊(參見圖7-4)。點選「下一步」,然後點選「建立群組」。接下來,在左側的側邊欄中點選「使用者」,然後在頂部點選「建立新使用者」。在第一個出現的方塊中輸入AnsibleBook(參見圖7-5)。這是您的IAM使用者的名稱。確保在點選「建立」之前勾選了「為每個使用者生成存取金鑰」。
金鑰對
在使用亞馬遜AWS時,需要兩種金鑰。第一種是API金鑰,它允許您使用亞馬遜的公開API控制您的虛擬機器。這些可以在本章前面下載的credentials.csv檔案中找到。第二種是SSH金鑰,它將用於登入您在本章中建立的任何機器。
建立SSH金鑰對
要登入任何機器,您需要指定一個SSH金鑰對,以便亞馬遜能夠預先載入到機器上。您還沒有金鑰對,因此讓我們為您建立一個。要建立金鑰對,請點選螢幕頂部的「服務」,然後選擇EC2。然後,在左側的側邊欄中,在「網路和安全」標題下選擇「金鑰對」。透過點選「建立金鑰對」並提供名稱來建立金鑰對。我已將我的金鑰對命名為aws-ansible,但您可以根據需要命名(參見圖7-6)。
內容解密:
建立 AWS 賬戶和 IAM 使用者是與 AWS 平台互動的第一步。這裡需要注意的是,亞馬遜提供了根憑據,但不建議直接使用。相反,應該建立一個具有有限許可權的 IAM 使用者,以提高安全性。同時,建立 SSH 金鑰對也是必要的,這將用於登入到建立的虛擬機器中。這一系列操作都是為了更好地管理和安全地使用 AWS 資源。
---
- name: Create an AWS account and IAM user
hosts: localhost
gather_facts: no
vars:
aws_access_key: YOUR_AWS_ACCESS_KEY
aws_secret_key: YOUR_AWS_SECRET_KEY
tasks:
- name: Create an IAM user
iam:
iam_type: user
name: AnsibleBook
state: present
register: iam_user
- name: Create access keys for the IAM user
iam:
iam_type: user
name: AnsibleBook
state: present
access_key_state: create
register: access_keys
- name: Save access keys to a file
copy:
content: "{{ access_keys.iam_user_access_keys[0].access_key_id }},{{ access_keys.iam_user_access_keys[0].secret_access_key }}"
dest: ./credentials.csv
內容解密:
此 Ansible Playbook 用於在 AWS 上建立 IAM 使用者,並為該使用者生成存取金鑰。首先,它定義了一個名為 Create an AWS account and IAM user 的 Playbook,指定在本地主機上執行且不收集事實。然後,它定義了兩個變數 aws_access_key 和 aws_secret_key,用於儲存 AWS 的存取金鑰和秘密金鑰。任務部分首先建立了一個名為 AnsibleBook 的 IAM 使用者,然後為該使用者生成了存取金鑰,並將這些金鑰儲存到名為 credentials.csv 的檔案中。這樣就完成了 IAM 使用者的建立和相關金鑰的管理。
AWS 賬戶設定流程圖示
@startuml
skinparam backgroundColor #FEFEFE
skinparam sequenceArrowThickness 2
title Ansible自訂模組WordPress使用者管理
actor "客戶端" as client
participant "API Gateway" as gateway
participant "認證服務" as auth
participant "業務服務" as service
database "資料庫" as db
queue "訊息佇列" as mq
client -> gateway : HTTP 請求
gateway -> auth : 驗證 Token
auth --> gateway : 認證結果
alt 認證成功
gateway -> service : 轉發請求
service -> db : 查詢/更新資料
db --> service : 回傳結果
service -> mq : 發送事件
service --> gateway : 回應資料
gateway --> client : HTTP 200 OK
else 認證失敗
gateway --> client : HTTP 401 Unauthorized
end
@enduml
此圖示展示了設定 AWS 賬戶的主要步驟,從開始註冊到完成設定,每一步驟都清晰地標示出來,有助於理解整個設定過程。