我想解決的問題?
需要在運行時添加一個主機,並將帶有一些(未知列表)變量添加為host_vars。最好不要將任何文件保存在磁盤上,也不要任何“ set_facts”。
什麼是動態Inventory和組變量?
通過利用動態Inventory,你現在可以根據Inventory提供的組來映射主機。如果沒有動態Inventory,則用戶將被迫手動維護主機映射,這在你有許多不斷刪除和增加主機的情況下會很繁瑣的。每次執行Ansible時,它都會根據動態Inventory腳本的輸出生成一個新的Inventory文件。這是很有用的,因為我們的基礎架構是動態的。
解決方案?
有一個Ansible模塊:add_host,它允許我們在運行時將主機添加到組中。但問題在於該模塊在與主機名相同的級別上如何獲取主機的變量列表?看下以下寫法:
- hosts: localhost gather_facts: no tasks: - add_host: name: foo foo_var: play - hosts: foo gather_facts: no tasks: - debug: var=foo_var delegate_to: localhost
這樣寫是可以的。但是,假設你不知道什麼是宿主變量。假設你是從外部API獲取的,那你就必須使用變量:new_host和new_host_vars,並且你不確定知道new_host_vars的內容?
我發現Ansible模塊有一個技巧,有一個很少使用的'args'參數。這不是模塊參數,而是tasks參數,列出了模塊的自由格式參數。
因此,我們可以這樣做:
--- - hosts: localhost gather_facts: no tasks: - add_host: name: '{{ new_host }}' args: '{{ new_host_vars }}' vars: new_host: foo new_host_vars: foo_var: play - hosts: foo gather_facts: no tasks: - debug: var=foo_var delegate_to: localhost
對現有主機會有什麼影響?
一個有趣的功能是我們可以對現有主機執行此操作:
----- hosts: localhost gather_facts: no tasks: - add_host: name: '{{ new_host }}' args: '{{ new_host_vars }}' vars: new_host: foo new_host_vars: foo_var: play - hosts: foo gather_facts: no tasks: - debug: var=foo_var delegate_to: localhost - hosts: localhost gather_facts: no tasks: - add_host: name: '{{ new_host }}' args: '{{ new_host_vars }}' vars: new_host: foo new_host_vars: foo_var: play2 - hosts: foo gather_facts: no tasks: - debug: var=foo_var delegate_to: localhost
(Ansible 2.7)按預期執行,會有play和play2輸出。
而且,它在普通Inventory和動態主機之間具有合理的交互作用:add_host中的變量使靜態Inventory中的host_vars變得模糊,但new_host_vars保留了值。
如何使用groups呢?
只需使用'groups'變量。
- hosts: localhost gather_facts: no tasks: - add_host: name: '{{ new_host }}' groups: [petz, baz] args: '{{ new_host_vars }}' vars: new_host: foo new_host_vars: foo_var: play
當然,你也可以使用它僅將現有主機添加到組中。
一次添加幾臺主機
你可能會注意到,我總是將其分配給localhost。如果要添加一個以上的主機,則需要使用是帶with_items循環而不是hosts:來進行。
與--limit一起使用
不要忘記在limit中包含“ localhost”以允許add_host在localhost上運行。
最後一個例子
我們將通過查詢外部API以獲取組主機組,並將其添加。
--- - hosts: localhost tasks: - name: Query external API for hosts uri: url: http://example.com/?group=petz return_content: true register: petz_list - name: Adding hosts from server response add_host: name: '{{ item.name }}' groups: [petz] args: '{{ item.vars }}' with_items: '{{ petz_list.json }}'
外部API響應的數據結構如下:
[ { "name": "foo", "vars": { "some_var": "something" } }, { "name": "bar", "vars": { "some_var": "something2" } } ]
參考資料:
https://ansible-tran.readthedocs.io/en/latest/docs/intro_dynamic_inventory.html
https://segmentfault.com/a/1190000015953283#articleHeader6
看起來,我好像是寫了關於add_host模塊的使用方法。歡迎留言交流使用經驗。