或许也不算 bug,只不过我们的编排环境比较复杂,以至于 ansible 的开发人员没预料到。

我在这里提出了 https://github.com/ansible/ansible/issues/23754#issuecomment-300515201

大概就是这样的。

我的 hosts 编排如下:

[hd3]
hd3-master ansible_host=20.20.20.3
hd3-node1 ansible_host=20.20.20.4
hd3-node3 ansible_host=20.20.20.6

[hd4]
hd4-master ansible_host=20.20.20.4
hd4-node1 ansible_host=20.20.20.5
hd4-node2 ansible_host=20.20.20.6
hd4-node3 ansible_host=20.20.20.7

你可以看到,hd3-node3 和 hd4-node2 的内网 IP 是一样的。我是通过同一个公网 IP,不同的端口,登入到不同的跳板机,最后到达目标机器。路径如下:

                                   |---> port1 ---> hd3-jumper ---> hd3-node3
controler ---> ROUTER_PUBLIC_IP ---|
                                   |---> port2 ---> hd4-jumper ---> hd4-node2

group_vars/hd3 里的 ProxyCommand 是:

ansible_ssh_common_args: '-o ProxyCommand="ssh -p 22222 -W %h:%p -q ROUTER_PUBLIC_IP"'

group_vars/hd4 里的 ProxyCommand 是:

ansible_ssh_common_args: '-o ProxyCommand="ssh -p 33333 -W %h:%p -q ROUTER_PUBLIC_IP"'

因为在部署过程中遇到某些机器操作失败,我就通过以下命令来检测目标机器是否就是我要操作的:

ansible nodes -m command -a 'hostname'

结果发现:

hd3-node3 | SUCCESS | rc=0 >>
hd3-node3

hd4-node2 | SUCCESS | rc=0 >>
hd3-node3

啊啊啊~~~求解!

---------- 2017-05-11 更新 ------------

经过查看 ansible.cfg,发现:

# plays will gather facts by default, which contain information about
# the remote system.
#
# smart - gather by default, but don't regather if already gathered
# implicit - gather by default, turn off with gather_facts: False
# explicit - do not gather by default, must say gather_facts: True
#gathering = smart

启用并改成 gathering = implicit 可以一定程度上消除。