Ansible Playbook 的變數機制允許使用者根據不同環境和需求調整佈署設定,提升自動化效率。設定變數的位置多元,包含角色預設值、庫存變數、Playbook 變數等,Ansible 會根據優先順序套用變數值。在角色中,可以透過 defaults/main.yml 設定預設變數值,並在 tasks/main.yml 和範本檔案中使用這些變數。例如,可以將資料函式庫連線資訊、網域名稱等設定為變數,方便管理和修改。此外,Ansible 也支援透過 set_fact 模組動態設定變數,例如根據主機事實或其他變數的值設定新的變數。除了在 Playbook 中直接定義變數外,還可以利用 vars_prompt 互動式提示使用者輸入變數值,或是使用 vars_files 載入外部 YAML 檔案中的變數,增加 Playbook 的彈性。
將變數套用到 Playbook
在 Ansible Playbook 中,除了指定要包含的角色(role)之外,還可以指定要在該角色中使用的變數。這樣可以使 Playbook 更加靈活和安全。
更新 Playbook 以使用變數
首先,讓我們更新 Playbook 以指定一些新的變數。這些變數將用於使 Playbook 更加安全。我們將使用不同的語法來指定角色,並告訴 Ansible 哪個條目是要執行的角色。
- hosts: all
become: true
roles:
- role: mheap.wordpress
database_name: michaelwp
database_user: michaelwp
database_password: bananas18374
內容解密:
hosts: all:指定 Playbook 要執行的主機群組。become: true:啟用許可權提升,以便以更高許可權執行任務。roles:指定要包含的角色列表。role: mheap.wordpress:指定要執行的角色名稱。database_name、database_user、database_password:為角色指定變數。
在任務檔案中使用變數
接下來,我們需要在任務檔案中使用這些變數。開啟 roles/mheap.wordpress/tasks/main.yml 檔案,並將任何硬編碼的資料函式庫名稱、使用者或密碼替換為新的變數。
- name: Create WordPress MySQL database
mysql_db: name="{{database_name}}" state=present
- name: Create WordPress MySQL user
mysql_user: name="{{database_user}}" host=localhost password="{{database_password}}" priv="{{database_name}}.*:ALL"
- name: Does the database exist?
command: mysql -u root {{database_name}} -e "SELECT ID FROM {{database_name}}.wp_users LIMIT 1;"
register: db_exist
ignore_errors: true
changed_when: false
- name: Copy WordPress DB
template: src=wp-database.sql dest=/tmp/wp-database.sql
when: db_exist.rc > 0
- name: Import WordPress DB
mysql_db: target=/tmp/wp-database.sql state=import name="{{database_name}}"
when: db_exist.rc > 0
內容解密:
mysql_db和mysql_user模組使用變數來建立資料函式庫和使用者。command模組使用變數來檢查資料函式庫是否存在。template模組用於將wp-database.sql檔案複製到遠端主機,並替換其中的變數。
在範本檔案中使用變數
我們還需要在 wp-config.php 範本檔案中使用這些變數。開啟 roles/mheap.wordpress/templates/wp-config.php 檔案,並將硬編碼的資料函式庫憑證替換為變數。
/** The name of the database for WordPress */
define('DB_NAME', '{{database_name}}');
/** MySQL database username */
define('DB_USER', '{{database_user}}');
/** MySQL database password */
define('DB_PASSWORD', '{{database_password}}');
內容解密:
- 使用 Jinja2 語法
{{variable_name}}將變數插入到範本檔案中。
自定義 WordPress 網域名稱
目前,WordPress 的 URL 被硬編碼為 book.example.com。讓我們更新角色,以便接受網域名稱作為變數。
- role: mheap.wordpress
database_name: michaelwp
database_user: michaelwp
database_password: bananas18374
wp_domain: book.example.com
內容解密:
- 新增
wp_domain變數來指定 WordPress 網域名稱。
更新相關檔案以使用 wp_domain 變數
我們需要更新相關檔案以使用 wp_domain 變數。
- 編輯
roles/mheap.nginx/templates/default檔案,將server_name和root目錄更新為使用wp_domain變數。
server_name {{wp_domain}};
root /var/www/{{wp_domain}};
編輯
roles/mheap.wordpress/files/wp-database.sql檔案,將所有出現的book.example.com替換為{{wp_domain}}。編輯
roles/mheap.wordpress/tasks/main.yml檔案,將所有出現的book.example.com替換為{{wp_domain}}。
自定義預設文章標題和內容
我們還可以自定義預設文章的標題和內容。
- role: mheap.wordpress
database_name: michaelwp
database_user: michaelwp
database_password: bananas18374
wp_domain: book.example.com
initial_post_title: Hey There
initial_post_content: >
This is an example post. Change me to say something interesting.
內容解密:
- 新增
initial_post_title和initial_post_content變數來自定義預設文章的標題和內容。
透過使用變數,我們可以使 Playbook 更加靈活和可重複使用。我們可以根據需要自定義不同的變數,以佈署不同的 WordPress 安裝。
第5章:引數化Playbook
變數位置
Ansible對變數有很好的支援,不僅可以在Playbook或檔案中使用,還可以在16個不同的位置定義變數。雖然Ansible檔案解釋了這16個位置之間的變數優先順序,但並沒有提供如何使用每個位置的範例,或者更重要的是,何時使用每個位置。我們將逐一檢視每個位置,並解釋何時使用它來設定變數。在Playbook中常用的位置已經被標記,以給你一個常見擴充套件點的想法。
這些位置按照從最不重要到最重要的順序排列;也就是說,角色預設值具有最低的優先順序,並且被其他所有設定所覆寫。庫存群組變數會覆寫角色預設值,但本身會被set_fact模組所覆寫。
角色預設值(常用)
這是角色目錄下的defaults/main.yml檔案。在此檔案中設定的變數具有最低的優先順序,這使得它非常適合設定預設值。例如,在your_role/defaults/main.yml中:
your_name: World
庫存變數
當你為Ansible建立一個庫存檔案以連線到你的Vagrant機器時,你使用了庫存變數。大多數情況下,你只會在庫存檔案中使用特定於庫存的變數(例如ansible_user或ansible_ssh_private_key_file,我們在第2章中介紹過),但你可以設定任何你喜歡的變數。這個變數將只在這個主機上可用。例如:
192.168.33.20 your_name=World
你也可以為一組主機或一組群組指定變數,例如:
[app]
192.168.33.20
192.168.33.21
[admin]
192.168.33.33
[database]
192.168.33.55
[websites:children]
app
admin
[app:vars]
your_name=World
[admin:vars]
your_name=World
[database:vars]
your_name=Michael
[websites:vars]
php_version: 7
庫存群組變數
要為庫存設定群組變數,你的庫存需要放在自己的資料夾中。建立一個名為inventory的資料夾,並將你的庫存檔案(在第2章中介紹過)移到裡面;也就是說,你的實際庫存檔案位於inventory/inventory。
要使用庫存群組變數,你必須建立一個名為inventory/group_vars的資料夾,它可以包含你建立的任何群組的變數檔案,例如下面的inventory/inventory檔案:
[app]
192.168.33.20
192.168.33.21
[admin]
192.168.33.33
[database]
192.168.33.55
為了指定這個庫存檔案中的主機的群組變數,你必須有一個像圖5-1一樣的資料夾結構。
在inventory/group_vars/admin.yml中定義的任何變數都將在admin群組中的任何主機上可用。
庫存主機變數
與庫存群組變數類別似,你可以為每個主機指定變數。使用相同的庫存檔案:
[app]
192.168.33.20
192.168.33.21
[admin]
192.168.33.33
[database]
192.168.33.55
你可以建立一個像圖5-2一樣的資料夾結構。
在192.168.33.20.yml中定義的任何變數都將在主機192.168.33.20上可用。
在inventory/host_vars/192.168.33.20.yml中建立以下內容:
your_name: World
這與在庫存檔案中具有以下內容在功能上是等價的:
192.168.33.20 your_name=World
Playbook群組變數(常用)
群組變數也可以在Playbook層級的group_vars資料夾中定義。它們的外觀和行為與庫存group_vars資料夾完全相同,除了它們位於與playbook.yml相同的層級,並且具有稍微更高的優先順序。
Playbook主機變數(常用)
就像群組變數一樣,主機變數也可以在Playbook層級定義。它們在功能上等同於庫存host_vars,但具有稍微更高的優先順序。
主機事實
Ansible有“事實”的概念,它是關於當前主機的可用資訊。有許多不同的事實可用,包括機器執行的作業系統、它的IP地址,甚至是機器上使用的記憶體量。這些事實在Ansible執行期間以變數的形式存在,供你在Playbook和範本中使用。
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title Ansible Playbook 變數設定與應用
package "Ansible 架構" {
component [Control Node] as control
package "Ansible 組件" {
component [Inventory] as inventory
component [Playbooks] as playbooks
component [Roles] as roles
component [Modules] as modules
}
package "Managed Nodes" {
component [Web Server] as web
component [DB Server] as db
component [App Server] as app
}
}
control --> inventory : 主機清單
control --> playbooks : 任務定義
playbooks --> roles : 引用角色
roles --> modules : 使用模組
control --> web : SSH 連線
control --> db : SSH 連線
control --> app : SSH 連線
note right of control
無需在目標主機安裝 Agent
透過 SSH 執行任務
end note
@enduml此圖示展示了Ansible中不同變數位置的優先順序,從最低到最高。
內容解密:
此圖表呈現了 Ansible 變數設定的優先順序,從最低到最高。最低優先順序是角色預設值,然後依序是庫存變數、庫存群組變數、Playbook 群組變數、Playbook 主機變數、主機事實,最後是由 set_fact 模組設定的值具有最高優先順序。這種層級結構確保了 Ansible 在執行任務時能夠正確地解析和使用變數。
修改 wp-database.sql 的存放位置
由於現在使用的是 template 模組而不是 copy 模組,因此也需要更改 wp-database.sql 的存放位置。將其從 files 目錄移至 templates 目錄,使用以下命令:
mv provisioning/roles/mheap.wordpress/files/wp-database.sql provisioning/roles/mheap.wordpress/templates
此步驟確保 wp-database.sql 檔案位於正確的位置,以便 template 模組能夠正確處理它。
內容解密:
這段程式碼的作用是移動 wp-database.sql 檔案到正確的目錄下。因為從 copy 模組切換到了 template 模組,所以需要將檔案移到 templates 目錄下。這樣做可以確保 Ansible 在執行任務時能夠找到並正確處理這個檔案。
重建 Vagrant 虛擬機器
此時,是時候再次執行 Ansible 了。由於資料函式庫已經存在,新的 wp-database.sql 檔案不會被匯入。這已經有一段時間沒有銷毀虛擬機器並從頭開始重建了,所以這似乎是一個很好的機會來確保一切都按預期工作。
在終端機中與 Vagrantfile 相同的目錄下執行 vagrant destroy,然後執行 vagrant up。Vagrant 將銷毀虛擬機器並建立一個空的虛擬機器供 Ansible 執行。這將需要幾分鐘的時間,所以讓它在背景執行,並繼續閱讀本章。
內容解密:
這段文字指示讀者銷毀並重新建立 Vagrant 虛擬機器,以確保 Ansible 的設定是正確且完整的。首先執行 vagrant destroy 銷毀現有的虛擬機器,然後執行 vagrant up 重新建立。這樣可以驗證整個佈署流程是否正確無誤。
設定 Playbook 的變數
在 Ansible 中,變數的使用使得 Playbook 更加靈活和可重複使用。本章節將介紹如何在 Playbook 中引數化變數,包括如何設定事實(facts)、註冊變數(registered variables)、使用 set_fact 模組、直接在 Playbook 中定義變數、使用 vars_prompt 提示使用者輸入,以及使用 vars_files 讀取外部變數檔案。
主機事實(Host Facts)
當 Ansible 執行時,它會執行 setup 模組來收集主機的事實。如果定義的事實名稱與角色預設值或群組/主機變數相同,則會被主機事實覆寫。主機事實具有較高的優先順序。
檢視可用事實
要檢視某個主機可用的事實,可以使用 setup 模組,如下所示:
ansible all –i /path/to/inventory –m setup
註冊變數(Registered Variables)
在 Playbook 中,您可能需要儲存模組的輸出以便稍後存取。例如,以下 Playbook 將 /etc/hosts 的檔案系統資訊儲存在名為 hosts_info 的變數中:
---
- hosts: all
tasks:
- stat: path=/etc/hosts
register: hosts_info
- debug: var=hosts_info
註冊變數具有較高的優先順序,如果已經定義了同名的變數,則會被覆寫。
設定事實(Set Facts)
您可以使用 set_fact 模組明確設定事實,以便稍後使用。例如:
---
- hosts: all
tasks:
- set_fact: example_var="Hello world"
- debug: var=example_var
這是 set_fact 的簡單範例。當您需要操作另一個模組呼叫的結果時,它才真正開始變得有用。
操作模組輸出
以下範例展示瞭如何操作 stat 模組的輸出,將其轉換為大寫:
- hosts: all
tasks:
- stat: path=/etc/hosts
register: host_info
- set_fact: example_var="{{host_info.stat.path|upper}}"
- debug: var=example_var
Playbook 變數
您可以在 Playbook 中直接設定變數,以覆寫角色中的某些變數,或是在小型 Playbook 中將所有內容保留在同一個檔案中。
定義變數
要在 Playbook 中定義變數,只需在與 tasks 同一層級建立一個 vars 區段:
---
- hosts: all
gather_facts: false
vars:
your_name: World
tasks:
- debug: msg="Hello {{your_name}}"
vars_prompt
執行 Playbook 時,可能需要收集執行階段的資訊,例如密碼或只有使用者才能提供的資訊。您可以在 Playbook 中指定 vars_prompt 區段來收集這些資訊。
使用 vars_prompt
以下範例展示瞭如何使用 vars_prompt:
---
- hosts: all
vars_prompt:
- name: your_name
prompt: "What is your name?"
tasks:
- debug: msg="Hello {{your_name}}"
當 Ansible 提示您輸入值時,它不會顯示您輸入的值,以防您輸入敏感資訊。
vars_files
Playbook 可以讀取 group_vars 和 host_vars,但您也可以指示它們透過 vars_files 引數讀取額外的變數檔案。
使用 vars_files
以下範例展示瞭如何使用 vars_files:
---
- hosts: all
vars_files:
- michael.yml
tasks:
- debug: msg="Hello {{your_name}} from {{location}}"
此 Playbook 將載入與 Playbook 同一資料夾中的 michael.yml。
動態包含變數檔案
您可以根據其他變數動態包含變數檔案,例如:
---
- hosts: all
vars_files:
- "{{ ansible_os_family }}.yml"
這將根據作業系統家族包含相應的變數檔案,例如 Redhat.yml 或 Debian.yml。
使用者輸入與 vars_files
您也可以讀取使用者輸入並使用它來包含變數檔案:
---
- hosts: all
vars_prompt:
- name: include_file
prompt: "Which file should we include?"
vars_files:
- "{{include_file}}.yml"
tasks:
- debug: msg="Hello {{your_name}} from {{location}}"
如果檔案不存在,將會出現錯誤。
提供預設值
您可以為 vars_files 提供預設值,Ansible 將包含它找到的第一個檔案:
---
- hosts: all
vars_prompt:
- name: include_file
prompt: "Which file should we include?"
vars_files:
- ["{{include_file}}.yml", "default_user.yml"]
tasks:
- debug: msg="Hello {{your_name}} from {{location}}"