2019年02月02日

ansible跳板机

[2019-05-31 Fri 17:45]

场景

公司内网的机器是不允许直连的,所以需要一个跳板机才能连。

在我自己机器上的虚机,用ansible使用跳板机,通过ssh forward方式,调到内网的机器上进行管理。

在内网跳板机上虽然可以不用ssh forward就可以很方便的访问内网其他的机器,但是跳板机无法联网安装ansible,手工下载安装ansible,需要太多的其他组件,太麻烦了。

在自己的虚机上pip install ansible,很方便就可以完成安装。

ansible机器
我自己机器上用virtualbox跑的centos虚机,virtualbox使用nat网络访问内网ip。
jumpbox(跳板机)
jumpbox_user@jumpbox(10.200.200.2)
内网机器
10.100.100.0/24

ssh配置

建立虚机到跳板机的ssh信任关系

虚机和跳板机之间直接使用秘钥登录,这样就不需要输入跳板机的密码。

# 建一个dsa的密钥对
ssh-keygen -t dsa

# 把秘钥copy到jumpbox机器上的jumpbox_user用户下
ssh-copy-id -i id_dsa -p 2222 jumpbox_user@10.200.200.2

好像用RSA算法(可用于加密和数字签名)秘钥登录时总是提示要输入密码,换成DSA加密算法(用于数字签名算法)。

测试

在虚机中执行

# 测试免密登录jumpbox是否正常
ssh -vvv -p 2222 jumpbox_user@jumpbox

# 测试通过跳板机进行ssh forward是登录内网机器是否正常提示密码
ssh -vvv -p 22 internal_user@internal_ip

配置

ProxyCommand 指定一个命令(或程序, 称为 Proxy), SSH 客户端将通过标准输入输出和这个命令启动后的进程进行正常的 SSH 通信, 而 Proxy 连接着 SSH 服务器(一般是一个 Server Proxy, 再由该 Server Proxy 连接服务器). Proxy 和 Server Proxy 之间组成了一条隧道. 如果两者之间用 HTTP 协议进行通信, 则整个系统便称为”tunneling SSH over HTTP”, 当然也可以使用 UDP, TCP, IP 以及其它任意的可行的协议.

SSH ProxyCommand 相对于 SOCKS, HTTP 或者其它的 Proxy 技术, 更简单. 因为它工作在进程间的文件 IO 通信, 用任何支持 socket 的编程语言, 都能轻易地编写出一个可用的 Proxy. 复杂度只落在隧道本身. 想一想, 如果没有 ProxyCommand, 你需要改变或侵入操作系统的 TCP 子系统才能实现 SSH 隧道. ProxyCommand 提供了方便应用隧道的接口, 网络程序都应该提供这样的接口, 而不是完全依赖于 socket.

因为一个会话就会启动一个 ProxyCommand 进程, 所以, 只有在会话依赖于连接的协议上才能使用这种技术.

虚机中ssh的默认配置文件是 ~/.ssh/config

如果不用默认配置文件可以自己写一个,如 ~/ssh_config ,内容与下面的 ~/.ssh/config 相同, 然后ssh命令行 -f ssh_config_file 指定配置文件。

ssh test@jumpbox -p 2222 -F ~/ssh_config

Host可以使用通配符,否则一堆机器需要每个都配一个Host会疯掉的,如果有 Host * ,那么需要放到配置文件的最后面。

[albert@master ~]$ cat ~/.ssh/config
# internal server
Host 10.100.100.*
     User internal_user
     Port 22
     #ForwardAgent yes
     ProxyCommand ssh -qaY -i /home/albert/.ssh/id_rsa jumpbox_user@10.200.200.2 -p 2222 'nc -w 14400ms %h %p'
     #IdentityFile /home/albert/.ssh/id_rsa
     Compression yes
     ControlPersist 5m
     ServerAliveInterval 60
     ServerAliveCountMax 5
     ControlMaster auto
     #ControlPath ~/.ssh/sockets/%r@%h-%p

ansible

ssh到内部ip,想让ansible使用密码登录,不想在每个内部机器上都配置我的虚机用户的秘钥。

虚机ssh(秘钥方式) -> jumpbox ssh(用户名/密码) -> internal server

ansible安装

pip安装的版本是ansible 2.8。

sudo pip install ansible

使用密码登录内部机器需要安装sshpass

[albert@master ~]$ ansible -i internal_hosts 10.100.100.2 -m shell -a "hostname;/usr/sbin/ip a"
10.100.100.2 | FAILED | rc=-1 >>
to use the 'ssh' connection type with passwords, you must install the sshpass program

使用yum安装sshpass。

yum install -y sshpass

ansible的配置文件 - ~/.ansible.cfg

默认使用虚机用户home目录下的 ~/.ansible.cfg ansible的配置文件,虚机中使用普通用户登录的,不想用/etc/ansible.cfg。

[albert@master ~]$ cat ~/.ansible.cfg
[ssh_connection]
# ssh arguments to use
# Leaving off ControlPersist will result in poor performance, so use
# paramiko on older platforms rather than removing it, -C controls compression use
#ssh_args=-C -o ForwardAgent=yes -o StrictHostKeyChecking=no -o ControlMaster=auto -o ControlPersist=5m
ssh_args=-C -o StrictHostKeyChecking=no -o ControlMaster=auto -o ControlPersist=5m

# uncomment this to disable SSH key host checking
host_key_checking = False

# Enabling pipelining reduces the number of SSH operations required to
# execute a module on the remote server. This can result in a significant
# performance improvement when enabled, however when using "sudo:" you must
# first disable 'requiretty' in /etc/sudoers
#
# By default, this option is disabled to preserve compatibility with
# sudoers configurations that have requiretty (the default on many distros).
#
pipelining = True

ansible -i : Inventory,指定主机,默认是 /etc/ansible/hosts

配置 ansible_ssh_user 和 ansible_ssh_pass ,使用用户名/密码登录内网机器。

[albert@master ~]$ cat internal_hosts
[internal]
10.100.100.1
10.100.100.2
...
10.100.100.254

[internal:vars]
ansible_ssh_user='internal_user'
ansible_ssh_pass='internal_user_password'
ansible -h
  -i INVENTORY, --inventory=INVENTORY, --inventory-file=INVENTORY
                        specify inventory host path or comma separated host
                        list.

ssh第一次连接的时候一般会提示输入yes进行确认为将key字符串加入到 ~/.ssh/known_hosts文件中的问题

在 =~/.ansible.cfg中ssh_args加入

[ssh_connnection]
ssh_args = -o StrictHostKeyChecking=no

ansible执行 ip a 报错的问题

ansible在执行命令时会包一层 sh -c , 所以要用全路径 /usr/sbin/ip

ansible命令参数速度优化

-C 好像打开ssh压缩的速度也不是很快

vim ~/.ansible.cfg

ssh_args=-C

pipeline

在 ~/.ansible.cfg 中配置 pipelining = True。貌似ansible在单个机器上执行命令的时间从16s降到了8s。

-t /tmp/a

ansible的 -t--tree 选项是将ansible的执行结果按主机名保存在指定目录下的文件中。

有些时候,ansible执行起来的速度会非常慢,这种慢体现在即使执行的是一个立即返回的简单命令(如ping模块),也会耗时很久, 且不是因为ssh连接慢导致的。如果使用-t选项,将第一次执行得到的结果按inventory中定义的主机名保存在文件中, 下次执行到同一台主机时速度将会变快很多,即使之后不再加上-t选项,也可以在一定时间内保持迅速执行。 即使执行速度正常(如执行一个Ping命令0.7秒左右),使用-t选项也可以在此基础上变得更快。

ansible -i internal_hosts internal -m shell -a "hostname;hostname -i;/usr/sbin/ip a" -t /tmp/a -f 15

-f 并发数

默认是同步5个并发,5个同步任务执行完后再执行下一批任务。

10个并发
不报错
15个并发
不报错
20个并发
会有报错