使用Ansible的playbook将set_fact任务委托给所有主机应用
ansible.builtin.set_fact – 设置主机变量和事实。 — Ansible文档
在ansible-playbook中,有一个名为set_fact的模块,可以设置新的变量。
模块的概述如下。
・在这个模块中,你可以设置新的变量。
・变量会根据每个主机的设置模块检测到的事实来设置。
・这些变量可以在ansible-playbook执行期间的随后的play中使用。
・要使用事实缓存在执行之间保存变量,请将cacheable设置为yes。
・通过set_fact创建的变量的优先级取决于是否被缓存。
・根据标准Ansible变量的优先级规则,由于其他许多类型的变量的优先级更高,所以这个值有可能被覆盖。
・该模块也支持Windows目标。
我认为在ansible运行时获取的输出并后续将其保存为变量的情况是相当常见的。
正如摘要中所述,这些变量是针对每个主机进行设置的。
如果想要在另一台主机上使用设置在特定主机上的set_fact,需要使用delegate_to指定并将其传递给其他主机。
delegate_to 的含义
任务运行控制:委派和本地操作的控制 – Ansible文档
使用delegated_to可以在不同的主机上执行指定的任务。通常情况下,Playbook会在与hosts匹配的主机上执行任务,但使用delegated_to可以在hosts之外或特定的主机上执行任务。
游戏规则的例子 de
我将尝试对属于Ubuntu组的Ubuntu01和Ubuntu02使用set_fact。
-
- ホストがubuntu01 → ubuntu01: definedのみ
- ホストがubuntu02 → ubuntu02: definedのみ
设定。
库存
all:
children:
ubuntu:
hosts:
ubuntu01:
ubuntu02:
如果不使用delegate_to(委托给)Playbook的话
我們將創建一個Playbook,其中使用set_fact為變量進行定義,已定義的變量將被標記為defined,未定義的變量將被標記為undefined。
---
- hosts: ubuntu
tasks:
- name: set_fact to ubuntu01
set_fact:
ubuntu01: defined
when: inventory_hostname == "ubuntu01"
- name: set_fact to ubuntu02
set_fact:
ubuntu02: defined
when: inventory_hostname == "ubuntu02"
- name: debug set_fact
debug:
msg: |
"ubuntu01 is {{ ubuntu01 | default('undefined') }}"
"ubuntu02 is {{ ubuntu02 | default('undefined') }}"
执行结果
$ ansible-playbook set_fact.yml -i inventory.yml -v
PLAY [ubuntu] *******************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************
ok: [ubuntu02]
ok: [ubuntu01]
TASK [set_fact to ubuntu01] *****************************************************************************************************************
ok: [ubuntu01] => {"ansible_facts": {"ubuntu01": "defined"}, "changed": false}
skipping: [ubuntu02] => {"changed": false, "skip_reason": "Conditional result was False"}
TASK [set_fact to ubuntu02] *****************************************************************************************************************
skipping: [ubuntu01] => {"changed": false, "skip_reason": "Conditional result was False"}
ok: [ubuntu02] => {"ansible_facts": {"ubuntu02": "defined"}, "changed": false}
TASK [debug set_fact] **************************************************************************************************************
ok: [ubuntu01] => {
"msg": "\"ubuntu01 is defined\"\n\"ubuntu02 is undefined\"\n"
}
ok: [ubuntu02] => {
"msg": "\"ubuntu01 is undefined\"\n\"ubuntu02 is defined\"\n"
}
PLAY RECAP **********************************************************************************************************************************
ubuntu01 : ok=3 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
ubuntu02 : ok=3 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
在ubuntu01中,我们发现以下是正确的(ubuntu02则相反)。
-
- ubuntu01: defined
- ubuntu02: undefined
使用委派给(delegate_to)的场景
让我们尝试使用 delegate_to 在所有主机之间传递变量。
---
- hosts: ubuntu
tasks:
- name: set_fact to ubuntu01
set_fact:
ubuntu01: defined
delegate_to: "{{ item }}" # 変数を渡すホスト
delegate_facts: true # fact変数の更新する場合trueにする必要がある
with_items: "{{ groups['all'] }}" # 全ホストに受け渡す
when: inventory_hostname == "ubuntu01"
- name: set_fact to ubuntu02
set_fact:
ubuntu02: defined
delegate_to: "{{ item }}" #
delegate_facts: true
with_items: "{{ groups['all'] }}"
when: inventory_hostname == "ubuntu02"
- name: debug set_fact
debug:
msg: |
"ubuntu01 is {{ ubuntu01 | default('undefined') }}"
"ubuntu02 is {{ ubuntu02 | default('undefined') }}"
执行结果
ansible-playbook set_fact.yml -i inventory.yml -v
Using /Users/yukihisa/.ghq/github.com/ymmmtym/terraform-cloud-oci/ansible.cfg as config file
PLAY [ubuntu] *******************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************
ok: [ubuntu02]
ok: [ubuntu01]
TASK [set_fact to ubuntu01] *****************************************************************************************************************
ok: [ubuntu01 -> ubuntu01] => (item=ubuntu01) => {"ansible_facts": {"ubuntu01": "defined"}, "ansible_loop_var": "item", "changed": false, "item": "ubuntu01"}
ok: [ubuntu01 -> ubuntu02] => (item=ubuntu02) => {"ansible_facts": {"ubuntu01": "defined"}, "ansible_loop_var": "item", "changed": false, "item": "ubuntu02"}
skipping: [ubuntu02] => (item=ubuntu01) => {"ansible_loop_var": "item", "changed": false, "item": "ubuntu01", "skip_reason": "Conditional result was False"}
skipping: [ubuntu02] => (item=ubuntu02) => {"ansible_loop_var": "item", "changed": false, "item": "ubuntu02", "skip_reason": "Conditional result was False"}
TASK [set_fact to ubuntu02] *****************************************************************************************************************
skipping: [ubuntu01] => (item=ubuntu01) => {"ansible_loop_var": "item", "changed": false, "item": "ubuntu01", "skip_reason": "Conditional result was False"}
skipping: [ubuntu01] => (item=ubuntu02) => {"ansible_loop_var": "item", "changed": false, "item": "ubuntu02", "skip_reason": "Conditional result was False"}
ok: [ubuntu02 -> ubuntu01] => (item=ubuntu01) => {"ansible_facts": {"ubuntu02": "defined"}, "ansible_loop_var": "item", "changed": false, "item": "ubuntu01"}
ok: [ubuntu02 -> ubuntu02] => (item=ubuntu02) => {"ansible_facts": {"ubuntu02": "defined"}, "ansible_loop_var": "item", "changed": false, "item": "ubuntu02"}
TASK [debug set_fact] ***********************************************************************************************************************
ok: [ubuntu01] => {
"msg": "\"ubuntu01 is defined\"\n\"ubuntu02 is defined\"\n"
}
ok: [ubuntu02] => {
"msg": "\"ubuntu01 is defined\"\n\"ubuntu02 is defined\"\n"
}
PLAY RECAP **********************************************************************************************************************************
ubuntu01 : ok=3 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
ubuntu02 : ok=3 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
根据set_fact任务的内容,可以看出ubuntu01和ubuntu02都已经定义了这两个变量。
这次通过 group[‘all’] 将数据传递给了所有主机,但也可以通过 IP (主机名) 来指定单个主机。此外,不仅可以在 set_fact 中使用,当然也可以在其他模块中使用。
参考来源
-
- <Ansible>「delegate_to」ディレクティブの使い方 – Qiita
- [Ansible] playをまたいだ変数保持をdelegate_toとfact変数で行う (Ansibleでkubeadmのworkerノード追加) – zaki work log