Ansible9:變量之Fact


fact簡介

ansible有一個模塊叫setup,用於獲取遠程主機的相關信息,並可以將這些信息作為變量在playbook里進行調用。而setup模塊獲取這些信息的方法就是依賴於fact。

# ansible test -m setup
192.168.0.187 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.0.187"
        ],
        "ansible_all_ipv6_addresses": [
            "fe80::f816:3eff:fe4f:6611"
        ],
        "ansible_apparmor": {
            "status": "disabled"
        },
        "ansible_architecture": "x86_64",
        "ansible_bios_date": "04/01/2014",
        "ansible_bios_version": "Ubuntu-1.8.2-1ubuntu1~cloud0",
        
        ...output omitted...
}

setup獲取的這些信息,都是可用於該主機的變量。

自定義fact

1. 手動設置fact

ansible除了能獲取到預定義的fact的內容,還支持手動為某個主機定制fact。稱之為本地fact。本地fact默認存放於被控端的/etc/ansible/facts.d目錄下,如果文件為ini格式或者json格式,ansible會自動識別。以這種形式加載的fact是key為ansible_local的特殊變量。

下面是一個簡單的示例,在ansibler主控端定義一個ini格式的custom.fact文件內容如下:

[general]
package = httpd
service = httpd
state = started

然后我們編寫一個playbook文件名為setup_facts.yml內容如下:

---
- name: Install remote facts
  hosts: test
  vars: 
    remote_dir: /etc/ansible/facts.d
    facts_file: custom.fact
  tasks:
    - name: Create the remote directory
      file:
        state: directory
        recurse: yes
        path: "{{ remote_dir }}"
    - name: Install the new facts
      copy:
        src: "{{ facts_file }}"
        dest: "{{ remote_dir }}"

執行該playbook,完成facts的推送:

ansible-playbook setup_facts.yml

此時,我們可以在被控端看到新的facts已經生成:

# ansible test -m setup        
192.168.0.187 | SUCCESS => {
    "ansible_facts": {
    
        ...output omitted...
        
        "ansible_local": {
            "custom": {
                "general": {
                    "package": "httpd",
                    "service": "httpd",
                    "state": "started"
                }
            }
        },

        ...output omitted...
  
}

我們可以寫一個簡單的playbook來使用這些facts:

- name: Install Apache and starts the service
  hosts: test
  tasks:
    - name: Install the required package
      yum: 
        name: "{{ ansible_facts.ansible_local.custom.general.package }}"
        state: latest
    - name: Start the service
      service: 
        name: "{{ ansible_facts.ansible_local.custom.general.service }}"
        state: "{{ ansible_facts.ansible_local.custom.general.state }}"

2. 使用set_fact模塊定義新的變量

set_fact模塊可以自定義facts,這些自定義的facts可以通過template或者變量的方式在playbook中使用。如果你想要獲取一個進程使用的內存的百分比,則必須通過set_fact來進行計算之后得出其值,並將其值在playbook中引用。

下面是一個set_fact模塊的應用示例:

- name: set_fact example
  hosts: test
  tasks:
    - name: Calculate InnoDB buffer pool size
      set_fact: innodb_buffer_pool_size_mb="{{ ansible_memtotal_mb / 2 |int }}"
      
    - debug: var=innodb_buffer_pool_size_mb

執行playbook如下:

# ansible-playbook set_fact_ex.yaml 

PLAY [set_fact example] *****************************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************************************
ok: [192.168.0.187]

TASK [Calculate InnoDB buffer pool size] ************************************************************************************************************************************
ok: [192.168.0.187]

TASK [debug] ****************************************************************************************************************************************************************
ok: [192.168.0.187] => {
    "innodb_buffer_pool_size_mb": "3911.0"
}

PLAY RECAP ******************************************************************************************************************************************************************
192.168.0.187                : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

這種設置方式只在當前playbook當中有效

手動采集fact

通常情況下,我們在運行play的時候,ansible會先嘗試ssh到被控端采集fact,如果此時,被控制端的ssh還沒有完全啟動,就會導致整個play執行失敗。這個時候,我們可以先顯示的關閉fact采集,然后在task中通過wait_for等待被控端ssh端口被正常監聽,再在task中使用setup模塊來手動采集fact:

- name: Deploy apps
  hosts: webservers
  gather_facts: False
  tasks:
    - name: wait for ssh to be running
      local_action: wait_for port=22 host="{{ inventory_hostname }}" search_regex=OpenSSH
    - name: gather facts
      setup:
    ......

啟用fact緩存

如果在play中需要引入fact,則可以開啟fact緩存。fact緩存目前支持三種存儲方式,分別為JSON、memcached、redis。

1. Json文件fact緩存后端

使用JSON文件作為fact緩存后端的時候,ansible將會把采集的fact寫入到控制主機的文件中。

ansible.cfg配置如下:

[defaults]
gathering = smart
#緩存時間,單位為秒
fact_caching_timeout = 86400    
fact_caching = jsonfile
#指定ansible包含fact的json文件位置,如果目錄不存在,會自動創建
fact_caching_connection = /tmp/ansible_fact_cache    

2. Redis fact緩存后端

使用redis作為fact緩存后端,需要在控制主機上安裝redis服務並保持運行。需要安裝python操作redis的軟件包。

ansible.cfg配置如下:

[defaults]
gathering = smart
fact_caching_timeout = 86400 
fact_caching = redis

3. Memcached fact緩存后端

使用memcached作為fact緩存后端,需要在控制主機上安裝Memcached服務並保持運行,需要安裝python操作memcached的軟件包。

ansible.cfg配置如下:

[defaults]
gathering = smart
fact_caching_timeout = 86400 
fact_caching = memcached

關閉fact

如果不想從fact中獲取變量,或者說整個playbook當中都沒有使用到fact變量,可以通過如下方法關閉fact以提升執行效率:

- hosts: test
  gather_facts: no

也可以在ansible.cfg中添加如下配置:

[defaults]
gathering = explicit


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM