Ansible,如何使用角色设置全局事实?
Ansible, how to set a global fact using roles?
我正在尝试使用 Ansible 部署一个只有两个服务器节点的小型 k3s 集群。部署第一个服务器节点,我称之为“master”,使用 Ansible 很容易设置。但是,设置第二个服务器节点(我称之为“节点”)给我带来了挑战,因为我需要从主服务器中提取节点令牌的值,并使用它在“节点”上调用 k3s 安装命令" vm.
我正在使用 Ansible 角色,这就是我的剧本:
- hosts: all
roles:
- { role: k3sInstall , when: 'server_type is defined'}
- { role: k3sUnInstall , when: 'server_type is defined'}
这是我来自 k3sInstall 角色目录的 main.yml 文件:
- name: Install k3s Server
import_tasks: k3s_install_server.yml
tags:
- k3s_install
这是我的 k3s_install_server.yml:
---
- name: Install k3s Cluster
block:
- name: Install k3s Master Server
become: yes
shell: "{{ k3s_master_install_cmd }}"
when: server_role == "master"
- name: Get Node-Token file from master server.
become: yes
shell: cat {{ node_token_filepath }}
when: server_role == "master"
register: nodetoken
- name: Print Node-Token
when: server_role == "master"
debug:
msg: "{{ nodetoken.stdout }}"
# msg: "{{ k3s_node_install_cmd }}"
- name: Set Node-Token fact
when: server_role == "master"
set_fact:
nodeToken: "{{ nodetoken.stdout }}"
- name: Print Node-Token fact
when: server_role == "node" or server_role == "master"
debug:
msg: "{{ nodeToken }}"
# - name: Install k3s Node Server
# become: yes
# shell: "{{ k3s_node_install_cmd }}{{ nodeToken }}"
# when: server_role == "node"
我注释掉了 Install k3s Node Server
任务,因为我无法正确引用我在 server_role == master
时设置的 nodeToken 变量。
这是调试的输出:
TASK [k3sInstall : Print Node-Token fact] ***************************************************************************************************************************************************************************************************************************************************************************
ok: [server1] => {
"msg": "K10cf129cfedafcb083655a1780e4be994621086f780a66d9720e77163d36147051::server:aa2837148e402f675604a56602a5bbf8"
}
ok: [server2] => {
"msg": ""
}
我的主机文件:
[p6dualstackservers]
server1 ansible_ssh_host=10.63.60.220
server2 ansible_ssh_host=10.63.60.221
我分配了以下 host_vars 个文件:
server1.yml:
server_role: master
server2.yml:
server_role: node
我已经尝试在 k3sInstall/vars/main.yml 中分配 nodeToken 变量,并在 [= 中从 k3sInstall 角色向上一级分配52=].yml 但这并没有帮助。
我尝试寻找一种使用块级变量的方法,但找不到任何东西。
如果您为 master 设置变量,则它不适用于其他主机,例如
- hosts: master,node
tasks:
- set_fact:
nodeToken: K10cf129cfedaf
when: inventory_hostname == 'master'
- debug:
var: nodeToken
给予
ok: [master] =>
nodeToken: K10cf129cfedaf
ok: [node] =>
nodeToken: VARIABLE IS NOT DEFINED!
如果您想“将所有结果和事实应用于同一批次的所有主机” 使用run_once: true,例如
- hosts: master,node
tasks:
- set_fact:
nodeToken: K10cf129cfedaf
when: inventory_hostname == 'master'
run_once: true
- debug:
var: nodeToken
给予
ok: [master] =>
nodeToken: K10cf129cfedaf
ok: [node] =>
nodeToken: K10cf129cfedaf
在您的情况下,将“run_once: true”添加到任务中
- name: Set Node-Token fact
set_fact:
nodeToken: "{{ nodetoken.stdout }}"
when: server_role == "master"
run_once: true
以上代码有效,因为在 run_once: true
之前应用了条件 when: server_role == "master"
。引用自 run_once
"Boolean that will bypass the host loop, forcing the task to attempt to execute on the first host available and afterward apply any results and facts to all active hosts in the same batch."
更安全的代码是添加独立的 set_fact 而不是依赖条件 when: 和 run_once,例如
- set_fact:
nodeToken: "{{ nodetoken.stdout }}"
when: inventory_hostname == 'master'
- set_fact:
nodeToken: "{{ hostvars['master'].nodeToken }}"
run_once: true
在此用例中使用 when
可能不是最合适的,您可能 delegating some tasks 比所谓的 master 服务器更好。
例如,根据您的清单变量,您可以将一个事实委托给 localhost
来定义主服务器。
然后,要从 master 服务器中的文件中获取令牌,您可以将此任务和事实仅委派给此服务器。
鉴于剧本:
- hosts: all
gather_facts: no
tasks:
- set_fact:
master_node: "{{ inventory_hostname }}"
when: server_role == 'master'
delegate_to: localhost
delegate_facts: true
- set_fact:
token: 12345678
run_once: true
delegate_to: "{{ hostvars.localhost.master_node }}"
delegate_facts: true
- debug:
var: hostvars[hostvars.localhost.master_node].token
when: server_role != 'master'
这会产生预期的结果:
PLAY [all] ********************************************************************************************************
TASK [set_fact] ***************************************************************************************************
skipping: [node1]
ok: [node2 -> localhost]
skipping: [node3]
TASK [set_fact] ***************************************************************************************************
ok: [node1 -> node2]
TASK [debug] ******************************************************************************************************
skipping: [node2]
ok: [node1] =>
hostvars[hostvars.localhost.master_node].token: '12345678'
ok: [node3] =>
hostvars[hostvars.localhost.master_node].token: '12345678'
PLAY RECAP ********************************************************************************************************
node1 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
node2 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
node3 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
我正在尝试使用 Ansible 部署一个只有两个服务器节点的小型 k3s 集群。部署第一个服务器节点,我称之为“master”,使用 Ansible 很容易设置。但是,设置第二个服务器节点(我称之为“节点”)给我带来了挑战,因为我需要从主服务器中提取节点令牌的值,并使用它在“节点”上调用 k3s 安装命令" vm.
我正在使用 Ansible 角色,这就是我的剧本:
- hosts: all
roles:
- { role: k3sInstall , when: 'server_type is defined'}
- { role: k3sUnInstall , when: 'server_type is defined'}
这是我来自 k3sInstall 角色目录的 main.yml 文件:
- name: Install k3s Server
import_tasks: k3s_install_server.yml
tags:
- k3s_install
这是我的 k3s_install_server.yml:
---
- name: Install k3s Cluster
block:
- name: Install k3s Master Server
become: yes
shell: "{{ k3s_master_install_cmd }}"
when: server_role == "master"
- name: Get Node-Token file from master server.
become: yes
shell: cat {{ node_token_filepath }}
when: server_role == "master"
register: nodetoken
- name: Print Node-Token
when: server_role == "master"
debug:
msg: "{{ nodetoken.stdout }}"
# msg: "{{ k3s_node_install_cmd }}"
- name: Set Node-Token fact
when: server_role == "master"
set_fact:
nodeToken: "{{ nodetoken.stdout }}"
- name: Print Node-Token fact
when: server_role == "node" or server_role == "master"
debug:
msg: "{{ nodeToken }}"
# - name: Install k3s Node Server
# become: yes
# shell: "{{ k3s_node_install_cmd }}{{ nodeToken }}"
# when: server_role == "node"
我注释掉了 Install k3s Node Server
任务,因为我无法正确引用我在 server_role == master
时设置的 nodeToken 变量。
这是调试的输出:
TASK [k3sInstall : Print Node-Token fact] ***************************************************************************************************************************************************************************************************************************************************************************
ok: [server1] => {
"msg": "K10cf129cfedafcb083655a1780e4be994621086f780a66d9720e77163d36147051::server:aa2837148e402f675604a56602a5bbf8"
}
ok: [server2] => {
"msg": ""
}
我的主机文件:
[p6dualstackservers]
server1 ansible_ssh_host=10.63.60.220
server2 ansible_ssh_host=10.63.60.221
我分配了以下 host_vars 个文件:
server1.yml:
server_role: master
server2.yml:
server_role: node
我已经尝试在 k3sInstall/vars/main.yml 中分配 nodeToken 变量,并在 [= 中从 k3sInstall 角色向上一级分配52=].yml 但这并没有帮助。
我尝试寻找一种使用块级变量的方法,但找不到任何东西。
如果您为 master 设置变量,则它不适用于其他主机,例如
- hosts: master,node
tasks:
- set_fact:
nodeToken: K10cf129cfedaf
when: inventory_hostname == 'master'
- debug:
var: nodeToken
给予
ok: [master] =>
nodeToken: K10cf129cfedaf
ok: [node] =>
nodeToken: VARIABLE IS NOT DEFINED!
如果您想“将所有结果和事实应用于同一批次的所有主机” 使用run_once: true,例如
- hosts: master,node
tasks:
- set_fact:
nodeToken: K10cf129cfedaf
when: inventory_hostname == 'master'
run_once: true
- debug:
var: nodeToken
给予
ok: [master] =>
nodeToken: K10cf129cfedaf
ok: [node] =>
nodeToken: K10cf129cfedaf
在您的情况下,将“run_once: true”添加到任务中
- name: Set Node-Token fact
set_fact:
nodeToken: "{{ nodetoken.stdout }}"
when: server_role == "master"
run_once: true
以上代码有效,因为在 run_once: true
之前应用了条件 when: server_role == "master"
。引用自 run_once
"Boolean that will bypass the host loop, forcing the task to attempt to execute on the first host available and afterward apply any results and facts to all active hosts in the same batch."
更安全的代码是添加独立的 set_fact 而不是依赖条件 when: 和 run_once,例如
- set_fact:
nodeToken: "{{ nodetoken.stdout }}"
when: inventory_hostname == 'master'
- set_fact:
nodeToken: "{{ hostvars['master'].nodeToken }}"
run_once: true
在此用例中使用 when
可能不是最合适的,您可能 delegating some tasks 比所谓的 master 服务器更好。
例如,根据您的清单变量,您可以将一个事实委托给 localhost
来定义主服务器。
然后,要从 master 服务器中的文件中获取令牌,您可以将此任务和事实仅委派给此服务器。
鉴于剧本:
- hosts: all
gather_facts: no
tasks:
- set_fact:
master_node: "{{ inventory_hostname }}"
when: server_role == 'master'
delegate_to: localhost
delegate_facts: true
- set_fact:
token: 12345678
run_once: true
delegate_to: "{{ hostvars.localhost.master_node }}"
delegate_facts: true
- debug:
var: hostvars[hostvars.localhost.master_node].token
when: server_role != 'master'
这会产生预期的结果:
PLAY [all] ********************************************************************************************************
TASK [set_fact] ***************************************************************************************************
skipping: [node1]
ok: [node2 -> localhost]
skipping: [node3]
TASK [set_fact] ***************************************************************************************************
ok: [node1 -> node2]
TASK [debug] ******************************************************************************************************
skipping: [node2]
ok: [node1] =>
hostvars[hostvars.localhost.master_node].token: '12345678'
ok: [node3] =>
hostvars[hostvars.localhost.master_node].token: '12345678'
PLAY RECAP ********************************************************************************************************
node1 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
node2 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
node3 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0