1. 變量
Ansible利用變量存儲可重復使用的值,可以簡化項目的創建和維護,減少錯誤數量。
1.1 變量名稱
由字符串組成,必須以字母開頭,并且只能含有字母、數字和下劃線,和其它編程語言很類似。
1.2 常見變量
- 要創建的用戶
- 要安裝的軟件包
- 要重新啟動的服務
- 要刪除的?件
- 要從互聯網檢索的存檔
1.3 定義變量
在不同位置定義變量具有不同的優先級,優先級規則是:越具體越優先,就近優先(離 task 越近,優先級越高)。
以下是一些常見定義位置的示例(優先級從低到高):
- 在清單中定義的組變量
[webservers] # 主機組
web1.example.com # 主機1
web2.example.com # 主機2[webservers:vars] # 組變量
nginx_port=8080
package_name=nginx
- 在清單或 playbook 所在目錄的 group_vars 子目錄中定義的組變量
- 在清單中定義的主機變量
# 清單定義的主機變量 http_port
[webservers]
web1.example.com http_port=80
web2.example.com http_port=8080
- 在清單或 playbook 所在目錄的 host_vars 子目錄中定義的主機變量
- 在運行時中發現的主機事實(由 setup 模塊自動收集)
- playbook 中的 play 變量 (vars 關鍵字和 vars_files 指令)
# var 關鍵字(內聯定義)
---
- hosts: localhostvars:app_name: "my_application"app_port: 8080tasks:- debug:msg: "Deploying {{ app_name }} on port {{ app_port }}"# vars_files 指令 (從外部文件加載)
---
- hosts: localhostvars_files:- vars/settings.yml # 加載外部變量文件tasks:- debug:msg: "Deploying {{ app_name }} on port {{ app_port }}"# vars/settings.yml
---
app_name: "my_application"
app_port: 8080
- 任務變量
- 在命令行中定義的額外變量,使用 --extra-vars 或 -e 選項定義(優先級最高)
# 此處僅為示例 xxx.yaml 和 varname=var 需替換為真實的
ansible-navigator run xxx.yaml -e "varname=var"# 示例
# 單個變量
ansible-playbook deploy.yml -e "package_to_install=apache2"
# 列表
ansible-playbook deploy.yml -e '{"packages_to_remove": ["old_app1", "old_app2"]}'
# 變量文件(需創建一個臨時變量文件 vars_file.yml)
ansible-playbook deploy.yml -e "@vars_file.yml"
建議選擇全局唯一的變量名稱。如果不同級別有相同名稱的變量,優先級高的變量會覆蓋優先級低的。
1.4 清單變量
分類:主機變量(用于特定主機),組變量,前者優先級高。
定義方法:
1)在清單文件中定義。
2)在與 playbook 相同的工作目錄中創建 group_vars (存放組變量文件)和 host_vars (存放主機變量文件)兩個目錄。
推薦使用?group_vars?和?host_vars?目錄來管理變量,而不是寫在清單文件中。
示例的項目架構:
my_ansible_project/
├── inventory.ini
├── host_vars/
│ └── web1.example.com.yml
├── group_vars/
│ └── webservers.yml
└── site.yml
對應的項目文件:
文件?group_vars/webservers.yml?內容
---
# 適用于所有 webservers 組主機的變量
firewall_package: ufw
common_packages:- vim- git- htop
文件 host_vars/web1.example.com.yml 內容
---
# 僅適用于 web1.example.com 的特定變量
host_specific_setting: "This is only for web1"
nginx_sites_enabled:- host1.example.com- admin.example.com
1.5 使用字典定義變量
Ansible的模塊也是采用的字典,有層級關系,更直觀。以定義用戶信息為例:
# 扁平化變量(難以管理)
# 注意變量名不要重復
user_alice_name: alice
user_alice_uid: 1234
user_alice_groups: developers
user_alice_home: /home/alice
user_bob_name: bob
user_bob_uid: 1235
user_bob_groups: bob
user_bob_home: /home/bob# 使用字典變量(推薦)
users:alice:name: aliceuid: 1234groups: developershome: /home/alicebob:name: bobuid: 1235groups: bobhome: /home/bob
使用方法
對于上一示例,想要訪問 alice 的 uid可采用以下兩種方式:
# 等價的
users.alice.uid
users['alice']['uid'] # Python語法
盡管兩種都有效,但是建議Ansible項目的所有文件采用一致的一種語法。
1.6 變量使用
將變量名稱放在雙花括號 {{ 變量名稱 }} 中,任務執行時,Ansible 會將其替換為對應的值。
注意:變量名稱和雙花括號之間有空格。
強烈建議:使用引號,如"{{ 變量名稱 }}",防止 Ansible 當作YAML字典處理。
1.7 捕獲命令輸出
使用?register?關鍵字將一個任務的輸出捕獲到一個變量中。這個變量是一個復雜的字典,包含了命令執行的結果、標準輸出、標準錯誤和返回碼等。
- name: register_testhosts: localhosttasks:- name: check fileansible.builtin.command: ls /etc/hostnameregister: file_check
2. Vault
對于配置遠程服務器需要訪問的密碼或 API 密鑰等敏感數據,如果以純文本形式存儲在變量清單或其它 Ansible 文件中,安全風險極高。推薦使用隨 Ansible 提供的 Ansible Vault?,它可以加密和解密任何由Ansible使用的結構化數據文件,通過 ansible-vault 命令行工具創建、編輯、加密、解密和查看文件。
可類比 K8s 的 ConfigMap(存放非機密信息)和 Secret(存放機密信息)。
Vault 使用 AES256 對稱加密算法來保護文件,加密和解密都使用同一個密碼(Vault密碼)作為密鑰。
2.1 使用方法
2.1.1 創建加密文件
默認使用編輯器 vi 打開文件
ansible-vault create filename.yml
2.1.2 查看加密文件
ansible-vault view filename.yml
2.1.3 編輯加密文件
ansible-vault edit filename.yml
2.1.4 加密現有文件
使用 --output=OUTPUT_FILE 選項,可將加密文件保存為新的名稱。
ansible-vault encrypt filename.yml
2.1.5 解密現有文件
解密單個文件時,可使用 --output 選項以其他名稱保存解密的文件。
ansible-vault decrypt filename.yml
2.1.6 更改加密文件密碼
使用 ansible-vault rekey filename 命令更改加密文件的密碼。執行后,它會先要求輸入當前密碼,然后提示輸入新密碼,也可以使用 --new-vault-password-file 選項直接指定包含新密碼的文件。
ansible-vault rekey filename.ymlansible-vault rekey --new-vault-password-file=new_password.txt filename.yml
2.2 運行?Vault 加密的文件的 playbook
需要向 ansible-playbook 命令提供其加密密碼,有以下三種方式:
1)交互方式,根據提示輸入密碼(需要禁用 artifact 工件,具體原因后期介紹工件時解釋)
ansible-navigator run -m stdout \
--playbook-artifact-enable false filename.yml \
--vault-id @prompt
2)指定 Vault 密碼文件(最安全)
密碼必須在該文件中存儲為一行字符串。
ansible-navigator run -m stdout filename.yml \
--vault-password-file=vault-pw-file
建議:設置密碼文件的權限為 600,確保只有所有者可讀;
???????????將密碼文件存儲在安全的位置,不要納入版本控制系統。
3)使用 $ANSIBLE_VAULT_PASSWORD_FILE 環境變量
# 設置環境變量
export ANSIBLE_VAULT_PASSWORD_FILE=~/path/to/vault-password-file# 運行 playbook(無需額外指定密碼文件參數)
ansible-navigator run -m stdout filename.yml
補充:可以通過 ansible-navigator 使用多個 Ansible Vault 密碼,將多個 --vault id 或 --vault-password-file 選項傳遞給 ansible-navigator 命令。
3. Facts(事實)
Ansible 事實是 Ansible 從受管節點自動探查到的變量,由 ansible.builtin.setup 模塊調取,其中包含的信息存儲到可重復使用的變量中。
以下僅列舉部分(使用 Python 語法表述字典),根據變量名稱也可大致知道表述的內容。
事實描述 | 變量 |
---|---|
短主機名稱 | ansible_facts['hostname'] |
完全限定的域名 | ansible_facts['fqdn'] |
主要 IPv4 地址(基于路由) | ansible_facts['default_ipv4']['address'] |
所有網絡接口的名稱列表 | ansible_facts['interfaces'] |
特定網絡接口的詳細信息(eth0) | ansible_facts['interfaces']['eth0'] |
網絡接口的 IP 地址配置 | ansible_facts['interfaces']['eth0']['ipv4']['address'] |
磁盤分區的大小(/dev/vda1) | ansible_facts['devices']['vda']['partitions']['vda1']['size'] |
DNS 服務器列表 | ansible_facts['dns']['nameservers'] |
當前運行的內核版本 | ansible_facts['kernel'] |
操作系統版本 | ansible_facts['distribution_version'] |
總內存大小(MB) | ansible_facts['memtotal_mb'] |
可用內存大小(MB) | ansible_facts['memfree_mb'] |
【提問】Linux 中使用什么命令查看磁盤的使用情況?
答:df命令
對于大型的集群系統,在執行play,task之前,需要先知道受管節點的配置情況(收集事實),軟硬件環境和配置情況會通過變量引用成為代碼的一部分。
3.1 查看事實
運行一個收集事實并使用ansible.builtin.debug 模塊顯示,以下示例會顯示事實的全部內容。只需要特定信息時,只選擇特定變量即可。
# fact_test.yml
---
- name: Fact dumphosts: all# gather_facts: true # 默認為truetasks:- name: Print all factsansible.builtin.debug:var: ansible_facts
# 運行該playbook
ansible-navigator run -m stdout fact_test.yml
# 內容會很多
3.2 關閉事實
為 play 禁用事實收集,將gather_facts 關鍵字設置為 no。可以加快 playbook 的運行速度,或者在受控節點不支持 setup 模塊時使用。
即使在 play 設置 gather_facts 為 no 的情況下,任務仍可以通過設置 ansible.builtin.setup 模塊手動收集事實。
---
- name: Play with manual fact gatheringhosts: allgather_facts: no # 關閉自動收集tasks:- name: Manually collect only disk factsansible.builtin.setup: # 設置 ansible.builtin.setup 模塊gather_subset:- network
3.3 事實子集
模塊默認收集全部事實,但可以通過配置僅收集事實的子集。子集的具體內容可以參考 Ansible 官方文檔或使用 ansible-doc setup 命令查看。
---
- name: Various fact gathering exampleshosts: alltasks:- name: Collect all facts (default behavior)ansible.builtin.setup:gather_subset:- all- name: Collect network-related factsansible.builtin.setup:gather_subset:- network- name: Collect hardware and network factsansible.builtin.setup:gather_subset:- hardware- network- name: Collect all facts except networkansible.builtin.setup:gather_subset:- "!network"- name: Collect minimal fact setansible.builtin.setup:gather_subset:- min
3.3 自定義事實
管理員可以使用自定義事實定義受管主機的特定值。自定義事實存儲在受管節點的本地文件中。
自定義事實可以在 INI 或 JSON 格式(效率高,語法麻煩)的文件中靜態定義,也可以通過可執行腳本在運行時動態生成。
ansible.builtin.setup 模塊會自動從受管節點的 /etc/ansible/facts.d 目錄中收集自定義事實,文件的擴展名必須為 .fact。
注意: 自定義事實不支持 YAML 格式。
4. 魔法變量
有些變量不由 ansible.builtin.setup 模塊收集,但有用,此時就需要魔法變量,它是一種特殊的變量,可以獲取與特定受管主機相關的信息。
使用場景:在一個任務中需要訪問其他受管主機的信息。
常用魔法變量
變量名稱 | 描述 |
---|---|
hostvars | 包含所有受管主機的非事實變量 |
hostvars[inventory_hostname] | 當前主機的所有變量(包括事實和自定義變量) |
group_names | 列出當前受管主機所屬的所有組 |
groups | 列出 inventory 中所有組和對應的主機 |
inventory_hostname | 在 inventory 中定義的主機名(可能與事實主機名不同) |
如有問題或建議,歡迎在評論區中留言~