Andible委派任务时使用循环导致的register变量问题
1、问题现象
今天编写kubernetes安装脚本时遇到个奇怪的问题,话不多说,直接上示例play
- hosts: nodes
gather_facts: no
tasks:
- name: Get join command
shell: kubeadm token create --print-join-command
delegate_to: "{{item}}"
with_items: "{{groups['master']}}"
register: join_command
failed_when: join_command.rc != 0
ignore_errors: yes
- name: test
debug:
msg: "join cmd is {{ join_command['stdout'] }}"
when: (groups['nodes'] | length > 0) and (join_command is defined)如上,可以看到我使用 delegate_to 将 Get join command 任务委派到master节点上去执行,并将结果注册为join_command变量,并使用debug模块进行查看,但是执行时报错:
fatal: [192.168.2.26]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'stdout'. 'dict object' has no attribute 'stdout'\n\nThe error appears to be in '/data/data/git/kubernetes/server/ansible_install/test.yaml': line 17, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n# when: join_command is defined\n - name: test\n ^ here\n"}2、排查过程
使用debug模块的var模块仔细观察对应的变量,playbook如下:
- hosts: nodes
gather_facts: no
tasks:
- name: Get join command
shell: kubeadm token create --print-join-command
delegate_to: "{{item}}"
with_items: "{{groups['master']}}"
register: join_command
failed_when: join_command.rc != 0
ignore_errors: yes
- name: test
debug:
var: join_command
when: (groups['nodes'] | length > 0) and (join_command is defined)输出变量如下:
"join_command": {
"changed": true,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"changed": true,
"cmd": "kubeadm token create --print-join-command",
"delta": "0:00:00.082566",
"end": "2024-05-28 10:56:16.481004",
"failed": false,
"failed_when_result": false,
"invocation": {
"module_args": {
"_raw_params": "kubeadm token create --print-join-command",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": null,
"executable": null,
"expand_argument_vars": true,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true
}
},
"item": "192.168.2.25",
"msg": "",
"rc": 0,
"start": "2024-05-28 10:56:16.398438",
"stderr": "",
"stderr_lines": [],
"stdout": "kubeadm join 192.168.2.25:6443 --token qrk818.j9hmeeygxc7ynr2l --discovery-token-ca-cert-hash sha256:5ddcb5d0381f32f7b26e284d0489ef44e72337a36e3c8698f4d504f04ba906fa ",
"stdout_lines": [
"kubeadm join 192.168.2.25:6443 --token qrk818.j9hmeeygxc7ynr2l --discovery-token-ca-cert-hash sha256:5ddcb5d0381f32f7b26e284d0489ef44e72337a36e3c8698f4d504f04ba906fa "
]
}
],
"skipped": false
}发现进行委派后的变量不太一样,这里也放一下正常的register变量
"join_command": {
"changed": true,
"cmd": "kubeadm token create --print-join-command",
"delta": "0:00:00.080176",
"end": "2024-05-28 10:47:56.296514",
"failed": false,
"failed_when_result": false,
"msg": "",
"rc": 0,
"start": "2024-05-28 10:47:56.290831",
"stderr": "",
"stderr_lines": [],
"stdout": "kubeadm join 192.168.2.25:6443 --token 4dvn2t.e7l46luxc87ggio2 --discovery-token-ca-cert-hash sha256:5ddcb5d0381f32f7b26e284d0489ef44e72337a36e3c8698f4d504f04ba906fa ",
"stdout_lines": [
"kubeadm join 192.168.2.25:6443 --token 4dvn2t.e7l46luxc87ggio2 --discovery-token-ca-cert-hash sha256:5ddcb5d0381f32f7b26e284d0489ef44e72337a36e3c8698f4d504f04ba906fa "
]
}可以看出,进行任务委派后得到的join_command.result中才包含我要的信息,且中间包含item,推测并不是任务委派导致的,而是使用循环导致的register变化,于是修改playbook如下:
- hosts: nodes
gather_facts: no
tasks:
- name: Get join command
shell: kubeadm token create --print-join-command
delegate_to: 192.168.2.25
# with_items: "{{groups['master']}}"
register: join_command
failed_when: join_command.rc != 0
ignore_errors: yes
- name: test
debug:
msg: "{{ join_command }}"
when: (groups['nodes'] | length > 0) and (join_command is defined)执行后变量结果:
"join_command": {
"changed": true,
"cmd": "kubeadm token create --print-join-command",
"delta": "0:00:00.080176",
"end": "2024-05-28 11:27:59.875088",
"failed": false,
"failed_when_result": false,
"msg": "",
"rc": 0,
"start": "2024-05-28 11:27:59.794912",
"stderr": "",
"stderr_lines": [],
"stdout": "kubeadm join 192.168.2.25:6443 --token 4dvn2t.e7l46luxc87ggio2 --discovery-token-ca-cert-hash sha256:5ddcb5d0381f32f7b26e284d0489ef44e72337a36e3c8698f4d504f04ba906fa ",
"stdout_lines": [
"kubeadm join 192.168.2.25:6443 --token 4dvn2t.e7l46luxc87ggio2 --discovery-token-ca-cert-hash sha256:5ddcb5d0381f32f7b26e284d0489ef44e72337a36e3c8698f4d504f04ba906fa "
]
}综上,基本得出结论,由于使用了with_items导致registry变量问题。接下来就是解决方法。
3、解决方法
目前能想到的解决方法有两种:
取消使用循环
使用循环,修改变量使用方法
这里采用了第二种,修改变量使用方法,修改后playbook如下:
- hosts: nodes
gather_facts: no
tasks:
- name: Get join command
shell: kubeadm token create --print-join-command
delegate_to: 192.168.2.25
with_items: "{{groups['master']}}"
register: join_command
failed_when: join_command.rc != 0
ignore_errors: yes
- name: test
debug:
msg: "{{ join_command.results[0].stdout }}"
when: join_command is defined从上面变量结果看,可以看出join_command.results是一个list类型变量,而非dict,所以在调用时需要用这种形式:join_command.results[0].stdout。
test任务执行结果如下:
TASK [test] *********************************************************************************************************************************************************************************************
ok: [192.168.2.26] => {
"msg": "kubeadm join 192.168.2.25:6443 --token mv7n3p.k0nkbd29nwwbjsx4 --discovery-token-ca-cert-hash sha256:5ddcb5d0381f32f7b26e284d0489ef44e72337a36e3c8698f4d504f04ba906fa "
}如上,解决了register变量问题。
总结:使用循环时,register变量会发生变化,需要修改对应的变量调用方法。
评论区