iT邦幫忙

2025 iThome 鐵人賽

DAY 13
1
DevOps

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

Day13 - 善用 Ansible Facts 讓 Playbook 更聰明

  • 分享至 

  • xImage
  •  

今日目標

  • 了解 Ansible Facts
  • 如何控制 Ansible Facts 搜集的內容 (gather_factsgather_subsetfilter)
  • 使用 Facts 做條件判斷和模板渲染
  • 建立自定義的 Local Facts,並認識 Fact Caching

什麼是 Ansible Facts?

Ansible Facts 是 Ansible 連線到主機時會自動幫我們搜集遠端主機系統資訊 (ex: OS、CPU、IP 等等...),這個功能讓我們能夠在 Playbook 做一些更細緻化的判斷。

但是相對的如果開啟 Ansible Facts 會造成 Playbook 執行速度會變比較慢,所以這個功能就要取決各位的需求去做決定,因為預設這功能是啟動的,所以需要自己透過 gather_facts: false 將其關閉。

蒐集和控制的方式

在 Playbook 中控制

---
- hosts: all
  gather_facts: true
  vars:
    # 僅收集必要資訊,以利加速執行速度
    gather_subset: "!all,network,virtual"
  tasks:
    - name: Refresh facts with subset
      setup:
        gather_subset: "{{ gather_subset }}"

透過 Ad-hoc 的方式

ansible -i inventory.ini all -m setup -a 'filter=ansible_distribution*'
ansible -i inventory.ini all -m setup -a 'gather_subset=!all,network,virtual'

常見的 subset:allminnetworkhardwarevirtualfacterohai,可以用 !all 排除全部後再挑選。

舉個例子

---
# facts-demo.yml
- name: Day13 facts demo
  hosts: all
  gather_facts: true
  tasks:
    - name: Show key facts
      debug:
        msg:
          - "OS: {{ ansible_facts['distribution'] }} {{ ansible_facts['distribution_version'] }}"
          - "Kernel: {{ ansible_facts['kernel'] }}"
          - "CPU: {{ ansible_facts['processor_vcpus'] | default(ansible_facts['processor_count']) }}"
          - "IPv4: {{ ansible_facts['default_ipv4']['address'] | default('N/A') }}"

    - name: Derive values via set_fact
      set_fact:
        app_port: "{{ 443 if ansible_facts['os_family'] == 'RedHat' else 80 }}"
        cache_enabled: "{{ (ansible_facts['memtotal_mb'] | int) > 4096 }}"

    - name: Render config from facts (to /tmp)
      template:
        src: templates/facts.ini.j2
        dest: /tmp/facts-demo.ini
        mode: '0644'
# templates/facts.ini.j2
# Managed by Ansible – DO NOT EDIT
os={{ ansible_facts['distribution'] }}
os_ver={{ ansible_facts['distribution_version'] }}
hostname={{ ansible_facts['hostname'] }}
ip={{ ansible_facts['default_ipv4']['address'] | default('') }}
cpu={{ ansible_facts['processor_vcpus'] | default(ansible_facts['processor_count']) }}
app_port={{ app_port }}
cache_enabled={{ cache_enabled | ternary('true','false') }}
# 各位會看到裡面會有機器的資訊
cat /tmp/facts-demo.ini

安裝自定義的 Local Facts

在遠端主機上建立 /etc/ansible/facts.d/*.fact (JSON/INI 皆可),setup 會讀入到 ansible_facts['ansible_local']

- name: Install custom local facts
  become: yes
  copy:
    dest: /etc/ansible/facts.d/app.fact
    mode: '0644'
    content: |
      {"app": {"role": "web", "tier": "frontend", "owner": "platform"}}

- name: Refresh facts (only local facts)
  setup:
    filter: ansible_local

- name: Use local fact
  debug:
    msg: "Role={{ ansible_facts['ansible_local']['app']['role'] }}"
  when: ansible_facts['ansible_local'] is defined and 'app' in ansible_facts['ansible_local']

Fact Caching

開頭筆者有說過使用 Facts 會導致執行速度變得比較慢,所以這時候我們會需要透過一些 cache 的方式來加速。

# ansible.cfg
[defaults]
# 讓 Ansible 自己判斷要不要重新取得主機資訊
gathering = smart
fact_caching = jsonfile
# 指定 cache 的目錄
fact_caching_connection = ./.ansible/facts_cache
# fact cache 存活時間
fact_caching_timeout = 86400

開啟 cache 機制雖然說會減少執行速度,換句話說就是減少 Ansible 重複搜集主機資訊的次數,但記得如果有更新硬體或網路的話記得清除或等待 cache 過期。

作業練習

  • 練習 1:撰寫 Playbook 只蒐集 networkvirtual,輸出主要介面與是否為 VM。
  • 練習 2:建立 app.fact,在 Playbook 依 ansible_local.app.role 決定要安裝的套件。
  • 練習 3:啟用 Fact Caching,量測連續兩次執行時間差異。

結論

相信各位在閱讀完今天的文章後,會發現可以讀取遠端機器的資訊是一件非常棒的事情,因為我們就可以透過不同的資訊去做到不一樣的操作。

像是 Day08 有提到的條件判斷,大家也可以想想怎麼利用這些有趣的功能來讓我們的流程更具彈性。

明日預告

明天來試試看能不能綜合這幾天的學習成果完成一個小型的部署任務。


上一篇
Day12 - 善用 Jinja2 template 製作動態設定檔
下一篇
Day14 - ansible.cfg 介紹與 FastAPI 自動化部署實戰
系列文
不爆肝學習 Ansible 的短暫30天14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言