方法一:直接写入inventory的方式
核心参数: ansible_ssh_common_args options
more ansible_*_args
Ansible 利用了 OpenSSH 的ProxyCommand来实现跳过Bastion(proxy/ jump)的功能。
优点是全都写入一个文件,逻辑清晰。下面对应的inventory文件:
# file: tmp2_hosts
[gatewayd]
foo ansible_host=10.47.1.249 ansible_ssh_common_args=' -o ProxyCommand="ssh -W %h:%p 54.183.22.215"'
如果有多个vm,每一个都要照着上面 ansible_ssh_common_args 的配置写一遍,这就不够简洁了。
改造一下,用分组的方式
# file: tmp_hosts
[jump]
54.183.22.215
[gatewayd]
foo ansible_host=10.47.1.249
[gatewayd:vars]
ansible_ssh_common_args=' -o ProxyCommand="ssh -W %h:%p 54.183.22.215"'
[all:vars]
ansible_ssh_private_key_file='aws-staging-private.pem'
上面的例子定义了一个组gatewayd,再定义了这个组的变量 [gatewayd:vars],告诉它要通过proxy去连接。
对应的yml文件,实现简单的ping 功能。
# file: tmp.yml
---
- hosts: gatewayd
remote_user: ubuntu
gather_facts: yes
tasks:
- name: test ping
ping:
执行效果:
$ ansible-playbook -i tmp_hosts tmp.yml
PLAY [gatewayd] ******************************************************************************************
TASK [Gathering Facts] ***********************************************************************************
ok: [foo]
TASK [test ping] *****************************************************************************************
ok: [foo]
PLAY RECAP ***********************************************************************************************
foo : ok=2 changed=0 unreachable=0 failed=0
方法二:灵活性更强的配置方式
这是官方FAQ的例子。
定义一个组都要通过proxy 连接(相当于把上面例子中的 [gatewayd:vars] 部分单独拿出来)
# file: group_vars/gatewayed.yml
ansible_ssh_common_args: ' -o ProxyCommand="ssh -i group_vars/eea_rsa -W %h:%p -q redhat@40.83.74.108"'
定义这个组里有哪些机器
# file: hosts
[gatewayed]
foo ansible_host=192.168.3.5
small-test-01
测试效果
$ ansible -i hosts gatewayed -m ping
small-test-01 | SUCCESS => {
"changed": false,
"ping": "pong"
}
foo | SUCCESS => {
"changed": false,
"ping": "pong"
}
方法三:解耦的方式
方法二的缺点是:当我们有很多组的时候,我们要确保每个组都要归属于gatewayed,例如:
# inventory file: host1
[gatewayed:children]
ambari-nodes
ambari-server
....
[ambari-nodes]
roy-vm-hdp-01
roy-vm-hdp-02
..
# inventory file: host2
[gatewayed:children]
kafka-broker
postgresl-server
[kafka-broker]
kafka-01
kafka-02
...
上述文件 [gatewayed:children] 出现多次,每个组都要配置它。当inventory文件很多,并且由不同的人来维护时,成本就高了。
下面的解耦方法涉及到两个文件:ansible.cfg 和 ssh.cfg (第二个文件名字可以换,它由前一个文件定义)
ansible.cfg
:
[ssh_connection]
ssh_args = -C -F ./ssh.cfg
I prefer to place ansible.cfg
in the current directory with my playbooks, inventory, roles, and host/group variables.
ssh.cfg
:
# All hosts
Host *
# Security
ForwardAgent no
# Connect through bastion hosts
ProxyCommand ssh -W %h:%p royjump.eastasia.cloudapp.azure.com
# Bastion hosts
Host royjump
HostName royjump.eastasia.cloudapp.azure.com
ProxyCommand none
# Connection multiplexing
ControlMaster auto
ControlPersist 2m
ControlPath ~/.ssh/ansible-%r@%h:%p
[注意] 跳板机 要配置为可以DNS解析的全域名, 如 royjump.eastasia.cloudapp.azure.com,如果不能解析,改自己的/etc/hosts文件来解决。这个问题卡了我很长时间。
# inventory file: myhosts
[bastion]
royjump
[backend]
roy-internal
Inventory 文件中没有出现关于跳板机怎么配置的问题,把这个问题隐藏了,用户只需要关注最原始的inventory应该怎么写。
验证
test.yml
- hosts: bastion
tasks:
- ping:
- hosts: backend
tasks:
- ping:
run playbook to connect these 2 machines.
$ ansible-playbook -i myhosts test.yml
PLAY [bastion] *****************************************************************
TASK [Gathering Facts] *********************************************************
ok: [royjump]
TASK [ping] ********************************************************************
ok: [royjump]
PLAY [backend] *****************************************************************
TASK [Gathering Facts] *********************************************************
ok: [roy-internal]
TASK [ping] ********************************************************************
ok: [roy-internal]
PLAY RECAP *********************************************************************
roy-internal : ok=2 changed=0 unreachable=0 failed=0
royjump : ok=2 changed=0 unreachable=0 failed=0
2018.11.22 更新: “方法三”不是官方推荐的方法,在CentOS测试通过,但效率很慢,对于简单测试,耗时是“方法二”的4倍。在Mac OS测试时,发现“方法三”有bug,不一定能测通。
方法四:在命令行中写入参数
参数:--ssh-common-args
e.g.
ansible-playbook --ssh-common-args='-o ProxyCommand="ssh -W %h:%p -q ec2-user@1.2.3.4"' site.yml
优点:不用关心配置文件关于bastion部分。
缺点:这么长的参数记不住,适合生成脚本再运行。