iT邦幫忙

2025 iThome 鐵人賽

DAY 16
0
DevOps

不爆肝學習 Ansible 的短暫30天系列 第 16

Day16 - 今天來點比較進階的 Inventory

  • 分享至 

  • xImage
  •  

今日目標

  • 熟悉 INI 與 YAML 兩種 Inventory 格式
  • 學會合併多個 Inventory 來源與套用群組/子群組
  • 掌握主機匹配語法、群組/主機變數位置
  • 認識動態 Inventory (Inventory Plugins)、Constructed 分群

INI 與 YAML?

Day03 認識 Inventory 時,筆者就介紹過 INI 與 YAML 兩種 Inventory 格式了。

所以本篇會預設各位已經擁有這兩份檔案

# inventory.ini
[all]
192.0.2.10 ansible_user=ubuntu
192.0.2.11 ansible_user=ubuntu
192.0.2.12 ansible_user=ubuntu

---
# host.yaml
web_servers:
  hosts:
    vultr:
      ansible_host: 192.0.2.10
      ansible_port: 22
      ansible_user: deploy
      ansible_python_interpreter: /usr/bin/python3

那我們也可以將這兩份 Inventory 檔案做個合併

  • 直接以逗號串接:
ansible-inventory -i 'inventory.ini,host.yaml' --graph
  • 或使用『目錄』作為 inventory 來源 (建議將多檔放同資料夾):
ansible-inventory -i inventories/ --graph

群組、子群組與變數

為什麼筆者比較喜歡使用 YAML 的格式呢,舉個例子:

---
# 相信大家會覺得這樣的格式在對於團隊開發上可讀性會比較高
all:
  children:
    web:
      hosts:
        web01: { ansible_host: 192.0.2.21 }
        web02: { ansible_host: 192.0.2.22 }
    db:
      hosts:
        db01: { ansible_host: 192.0.2.31 }
  vars:
    ansible_user: ubuntu

💡 Tips:所以筆者建議 group_vars/<group>.yaml 放群組變數; host_vars/<host>.yaml 放主機變數。

靈活選擇主機 (Patterns)

# 指定群組或主機
ansible web -i host.yaml -m ping
ansible web[0] -i host.yaml -m ping       # 第一台 (若有支援 Index 的話)

# 運算子
ansible 'web:&prod' -i host.yaml -m ping  # 交集
ansible 'web:db'    -i host.yaml -m ping  # 聯集
ansible 'all:!db'   -i host.yaml -m ping  # 差集 (排除 db)

前面提到的都是靜態,那有動態的嗎?

有!!!我們可以透過 Constructed 來定義好每個主機的 template,白話來說就是先挖個洞,然後根據主機的 hostvars 來自動把這些洞填滿。

---
# inventory-constructed.yaml
plugin: constructed
strict: false
compose:
  app_env: "{{ hostvars[inventory_hostname].app_env | default('dev') }}"
groups:
  web: "'web' in (hostvars[inventory_hostname].roles | default([]))"
  prod: "hostvars[inventory_hostname].app_env | default('dev') == 'prod'"
keyed_groups:
  - key: app_env
    prefix: env

使用方式:

ansible-inventory -i 'inventory.ini,host.yaml,inventory-constructed.yaml' --graph

雲端 Plugins 的一些概念

  • 常見:aws_ec2azure_rmgcp_computek8s
  • 以外部 API 查詢主機列表,並可用 filterskeyed_groups 動態分組
  • 需安裝相應 collections,並提供憑證與連線設定

與 Facts 的互動

  • ansible-inventory 不會連線主機蒐集 facts; Constructed 依賴 inventory 現有變數
  • 在 Playbook 中可先收集 facts 再用 group_by 進一步分群:
---
- hosts: all
  gather_facts: true
  tasks:
    - name: Group by OS family
      group_by:
        key: "os_{{ ansible_facts['os_family'] | lower }}"

列印 Inventory 與群組資訊

---
# inventory-inspect.yml
- name: Inspect inventory
  hosts: all
  gather_facts: false
  tasks:
    - name: Show host summary
      debug:
        msg:
          - "host={{ inventory_hostname }}"
          - "ip={{ ansible_host | default('N/A') }}"
          - "groups={{ group_names | join(',') }}"

驗證與檢查:

ansible-inventory -i 'inventory.ini,host.yaml' --graph
ansible-playbook -i 'inventory.ini,host.yaml' inventory-inspect.yml --syntax-check

常見問題與排錯

  • 找不到主機:確認 inventory 路徑與檔案格式、或逗號分隔是否加引號
  • 變數覆蓋不如預期:檢查優先序與變數存放位置 (host_vars vs group_vars)
  • Constructed 沒生效:檔名是否被讀取、條件運算式是否正確、字串需加引號
  • Plugin 認證錯誤:雲端插件需對應的 credentials 與組態,可先用 -list 測試

作業練習時間

  • 練習 1:將 inventory.ini 的主機加上 roles=['web'],再用 Constructed 分出 web 群組
  • 練習 2:新增 group_vars/web.yaml 設定 app_port=8000,在簡單 Playbook 中印出該值
  • 練習 3:撰寫 inventory-inspect.yml 顯示每台主機所屬的 env* 群組 (搭配 keyed_groups)

明日預告

明天來講講 Ansible 怎麼做敏感性資料的加密


上一篇
# Day15 - 善用 Roles 積木化 Playbook
下一篇
Day17 - 幫敏感資訊加個密吧:Ansible Vault
系列文
不爆肝學習 Ansible 的短暫30天21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言