Ansible 自動化佈署中,處理錯誤與有效委派任務至關重要,特別是管理大型叢集時。max_fail_percentage 引數允許設定任務執行可容忍的錯誤比例上限,超過門檻則中止執行,確保佈署流程穩定性。任務委派功能則讓特定任務可在不同主機執行,例如在叢集升級時,利用 delegate_to 或 local_action 將主機從負載平衡器移除或新增,提升操作靈活性。run_once 選項則確保特定任務在多個目標主機中僅執行一次,適用於資料函式庫升級等場景,避免重複操作。此外,Ansible 也支援透過 SSH Proxy 連線目標主機,以及在 Playbook 執行期間提示使用者輸入變數值,提升自動化流程的彈性與互動性。最後,Tags 功能讓使用者能選擇性執行特定任務,方便管理和除錯大型 Playbook。
進階 Ansible 主題:任務委派與錯誤處理
在前面的章節中,我們探討瞭如何使用 Ansible 進行自動化佈署和管理。在本章中,我們將探討兩個進階主題:任務委派(Task Delegation)和錯誤處理(Error Handling)。這兩個主題對於管理和維護大型叢集至關重要。
使用 max_fail_percentage 進行錯誤處理
在進行自動化佈署時,錯誤處理是一個重要的議題。Ansible 提供了 max_fail_percentage 引數,讓我們可以在任務執行過程中設定允許的最大錯誤比例。當錯誤比例超過設定的門檻時,Ansible 將會中止任務的執行。
以下是一個範例 playbook,展示瞭如何使用 max_fail_percentage:
---
- name: 示範 max_fail_percentage
hosts: frontends
max_fail_percentage: 30
serial: 5
tasks:
- name: 模擬任務失敗
command: /bin/false
ignore_errors: true
- name: 第二個任務
debug:
msg: "如果第一個任務失敗,這個任務不會被執行"
在這個範例中,我們設定 max_fail_percentage 為 30%,並使用 serial 引數將主機分成批次執行。如果第一批次中的錯誤比例超過 30%,Ansible 將會中止任務的執行。
任務委派
在某些情況下,我們需要在不同的主機上執行特定的任務。例如,在進行叢集升級時,我們可能需要先將主機從負載平衡器中移除,進行升級後再將其增加回來。Ansible 的任務委派功能可以幫助我們實作這一點。
以下是一個範例 playbook,展示瞭如何使用任務委派:
---
- name: 示範任務委派
hosts: frontends
tasks:
- name: 將主機從負載平衡器中移除
command: ./remove_from_loadbalancer.sh {{ inventory_hostname }}
args:
chdir: "{{ playbook_dir }}"
delegate_to: localhost
- name: 佈署程式碼到主機
debug:
msg: "佈署程式碼的邏輯將在這裡執行"
- name: 將主機增加回負載平衡器
command: ./add_to_loadbalancer.sh {{ inventory_hostname }}
args:
chdir: "{{ playbook_dir }}"
delegate_to: localhost
程式碼解析:
delegate_to: localhost:這個指令告訴 Ansible 在本地主機(localhost)上執行指定的任務,而不是在清單中的遠端主機上執行。command模組:用於執行 shell 指令碼,例如remove_from_loadbalancer.sh和add_to_loadbalancer.sh。args:用於指定命令執行的引數和工作目錄。
在這個範例中,我們使用 delegate_to 引數將任務委派給本地主機執行。第一個和第三個任務分別將主機從負載平衡器中移除和增加回來,而第二個任務則在遠端主機上執行佈署程式碼的邏輯。
使用 local_action 簡化任務委派
Ansible 還提供了一個簡化的語法 local_action,可以用來替代 delegate_to: localhost。以下是一個範例:
---
- name: 第二個任務委派範例
hosts: frontends
tasks:
- name: 從本地主機到清單主機的 rsync
local_action: command rsync -a /tmp/ {{ inventory_hostname }}:/tmp/target/
程式碼解析:
local_action:簡化了在本地主機上執行命令的語法,等同於使用delegate_to: localhost。rsync命令:用於將本地檔案同步到遠端主機。
這個範例展示瞭如何使用 local_action 將本地檔案同步到遠端主機。
進階 Ansible 主題:任務委派與流程控制
在管理複雜的 IT 環境時,Ansible 提供了一系列進階功能來最佳化自動化流程。其中,任務委派(Task Delegation)和 run_once 選項是兩個非常實用的功能,能夠幫助我們更精確地控制 Playbook 的執行。
任務委派
任務委派允許我們在特定的主機上執行任務,而不是在 Playbook 預設的目標主機上。這在需要從特定主機執行某些操作時非常有用,例如從本地主機將檔案同步到遠端伺服器。
使用 local_action 進行任務委派
在 Ansible 中,我們可以使用 local_action 來指定在本地主機上執行的任務。以下是一個範例 Playbook,展示瞭如何使用 local_action 將本地目錄同步到遠端主機:
---
- name: 第二個任務委派範例
hosts: frontends
tasks:
- name: 從本地主機到遠端主機執行 rsync
local_action:
module: rsync
src: /path/to/local/directory/
dest: /path/to/remote/directory/
recursive: yes
執行此 Playbook 後,我們可以看到 rsync 命令確實是在本地主機上執行的,從而實作了將整個目錄樹複製到遠端伺服器的目的。
內容解密:
local_action:用於指定在本地主機上執行的任務。module: rsync:指定要使用的模組為rsync,用於檔案同步。src和dest:分別指定本地來源路徑和遠端目標路徑。recursive: yes:確保rsync命令遞迴複製整個目錄樹。
使用 run_once 選項
在叢集環境中,有時我們需要確保某些任務只執行一次。run_once 選項正是為此設計的。它允許我們在 Playbook 中指定某些任務只執行一次,無論有多少主機在目標清單中。
範例 Playbook
以下是一個簡單的 Playbook,展示瞭如何使用 run_once 選項:
---
- name: 示範 run_once 指令的 Playbook
hosts: frontends
tasks:
- name: 升級資料函式庫結構
debug:
msg: 正在升級資料函式庫結構...
run_once: true
執行此 Playbook 後,我們可以看到儘管 Playbook 是針對所有 10 個主機執行的,但升級任務只在其中一個主機上執行了一次。
內容解密:
run_once: true:確保該任務只執行一次。debug模組:用於輸出除錯資訊,在實際應用中可以替換為執行特定命令或指令碼的任務。
注意事項
使用 run_once 時需要注意,它是針對每個批次(batch)執行的。如果 Playbook 設定了 serial 引數(例如 serial: 5),那麼該任務將在每個批次中執行一次。因此,在設計 Playbook 時,需要考慮到這種行為可能帶來的影響。
進階Ansible主題:第八章
控制Playbook流程與本地執行
在管理複雜的IT基礎設施時,Ansible的run_once選項對於確保某些任務只在特定的主機上執行一次非常有用。這個功能特別適用於需要對多個主機執行一次性任務的場景,例如資料函式庫schema升級。
使用run_once控制任務執行
考慮以下Playbook範例:
---
- name: Upgrade database schema
hosts: db_servers
tasks:
- name: Execute schema upgrade
command: /path/to/upgrade/script.sh
run_once: true
在這個例子中,即使db_servers組中包含多個主機,schema升級任務也只會在其中一台主機上執行一次。
執行結果如下:
frt10.example.com : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
值得注意的是,這種行為可能會導致意外的結果,例如上述輸出顯示schema升級執行了兩次。因此,在使用run_once時,需要仔細規劃Playbook的流程,以確保達到預期的結果。
本地執行Playbook與在localhost執行的區別
在使用Ansible時,瞭解在本地執行Playbook與在localhost執行Playbook之間的區別至關重要。當你在localhost上執行Playbook時,Ansible預設會透過SSH連線到localhost。
示範本地執行與SSH連線的差異
首先,建立一個包含以下內容的本地inventory檔案:
[local]
localhost
然後,嘗試使用ad hoc命令對這個inventory執行ping模組:
$ ansible -i localhosts -m ping all --ask-pass
這個命令會提示你接受localhost的SSH主機金鑰並輸入SSH密碼。成功連線後,你會看到類別似以下的輸出:
localhost | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
使用ansible_connection=local進行本地連線
為了避免使用SSH連線到localhost,你可以在inventory檔案中為localhost設定ansible_connection=local變數:
[local]
localhost ansible_connection=local
這樣,Ansible就會直接在本地執行命令,而不需要建立SSH連線。
驗證本地執行結果
你可以透過以下步驟驗證本地執行的結果:
- 檢查本地
/tmp目錄下是否存在測試檔案:$ ls -l /tmp/foo ls: cannot access /tmp/foo: No such file or directory - 使用Ansible ad hoc命令建立測試檔案:
$ ansible -i localhosts2 -m file -a "path=/tmp/foo state=touch" all frt01.example.com | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "dest": "/tmp/foo", "gid": 0, "group": "root", "mode": "0644", "owner": "root", "size": 0, "state": "file", "uid": 0 } - 再次檢查測試檔案是否存在:
$ ls -l /tmp/foo -rw-r--r-- 1 root root 0 Apr 24 16:28 /tmp/foo
使用代理和跳板主機
在許多網路環境中,核心網路裝置可能只能透過代理或跳板主機存取。Ansible支援透過組態inventory檔案來實作透過跳板主機連線到目標主機。
考慮以下inventory組態:
[switches]
cmls01.example.com
cmls02.example.com
[switches:vars]
ansible_ssh_common_args='-o ProxyCommand="ssh -W %h:%p -q bastion.example.com"'
這裡,我們定義了一個名為switches的組,包含兩個Cumulus Networks交換機。然後,透過ansible_ssh_common_args變陣列態SSH連線,使其透過bastion.example.com跳板主機進行代理。
使用以下命令測試連線:
$ ansible -i switches -m ping all
cmls02.example.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
cmls01.example.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
進階Ansible主題:第八章
使用SSH Proxy進行連線
在某些情況下,我們可能需要透過一台跳板機(bastion host)來連線到目標主機。Ansible支援使用SSH Proxy來實作這一功能。首先,我們需要在ansible.cfg檔案中啟用ssh_args組態,並指定ProxyCommand。
[ssh_connection]
ssh_args = -o ProxyCommand="ssh -W %h:%p -q [email protected]"
在這個範例中,我們將跳板機設定為bastion.example.com,並透過它來連線到目標主機。
內容解密:
ssh_args組態:此組態允許我們指定額外的SSH引數。在這裡,我們使用-o ProxyCommand來指定ProxyCommand。ProxyCommand引數:此引數指定了用於連線目標主機的命令。在這個例子中,我們使用ssh -W %h:%p -q [email protected]來連線到跳板機,並透過它來連線目標主機。%h:代表目標主機的hostname。%p:代表目標主機的port。-q:代表quiet模式,減少輸出資訊。
這樣,當我們執行Ansible playbook時,它會自動透過跳板機連線到目標主機,而不需要我們手動進行任何額外的組態。
在Playbook執行期間提示使用者輸入
有時候,我們希望在執行playbook的過程中能夠根據使用者的輸入來決定某些變數的值。Ansible提供了vars_prompt模組來實作這一功能。
範例Playbook
---
- name: 簡單的playbook範例,示範如何在playbook中提示使用者輸入
hosts: frontends
vars_prompt:
- name: loginid
prompt: "請輸入您的使用者名稱"
private: no
- name: password
prompt: "請輸入您的密碼"
private: yes
tasks:
- name: 登入操作
debug:
msg: "正在以 {{ loginid }} 身份登入..."
內容解密:
vars_prompt部分:定義了兩個變數loginid和password,並在執行playbook時提示使用者輸入。private: no:表示使用者輸入的內容會被顯示在終端上。private: yes:表示使用者輸入的內容不會被顯示在終端上,通常用於輸入密碼等敏感資訊。
debug任務:使用debug模組輸出一個訊息,訊息中包含了使用者輸入的loginid變數的值。
執行這個playbook時,Ansible會提示使用者輸入使用者名稱和密碼,並將輸入的值儲存在對應的變數中,然後在後續的任務中使用這些變數。
使用Tags選擇性地執行任務
隨著playbook規模的增長,我們可能希望能夠選擇性地執行某些任務,而不是每次都執行整個playbook。Ansible的tags功能可以幫助我們實作這一需求。
範例Playbook
---
- name: 簡單的playbook範例,示範如何使用tags
hosts: frontends
tasks:
- name: 安裝nginx
yum:
name: nginx
state: present
tags:
- install
- name: 從範本佈署nginx組態檔案
template:
src: templates/nginx.conf.j2
dest: /etc/nginx.conf
tags:
- customize
內容解密:
tags關鍵字:用於為任務指定標籤。在這個例子中,第一個任務被標記為install,第二個任務被標記為customize。--tags和--skip-tags選項:執行playbook時,可以使用這些選項來指定要執行或跳過哪些標籤對應的任務。--tags install:只執行標記為install的任務。--skip-tags customize:執行除了標記為customize之外的所有任務。
透過使用tags,我們可以靈活地控制playbook中任務的執行,從而提高自動化管理的效率和靈活性。