mat*_*mat 5 ssh ansible google-cloud
Cloud IAP 是 Google Cloud Platform 的一种代理,可让您连接到没有公共 IP 地址的计算实例,而无需 VPN。你站起来的实例,然后就可以使用gcloud
工具按名称连接到它像这样:gcloud compute ssh my-server-01
。这将通过代理对您进行身份验证,并使用您自己的 Google 帐户(使用称为操作系统登录的功能)将您登录到目标服务器。
我想让 ansible 做gcloud
工具正在做的事情,我需要一个自定义连接插件。
我找到了一种无需连接插件即可完成这项工作的方法。基本上,您可以编写一个包装该gcloud
工具的脚本并将ansible_ssh_executable
参数指向该脚本,您可以在清单级别定义该参数。您确实需要确保gcp_compute
清单插件按名称识别主机,因为这是所gcloud compute ssh
期望的。
这是脚本:
#!/bin/sh
set -o errexit
# Wraps the gcloud utility to enable connecting to instances which are behind
# GCP Cloud IAP. Used by setting the `ansible_ssh_executable` setting for a play
# or inventory. Parses out the relevant information from Ansible's call to the
# script and injects into the right places of the gcloud utility.
arg_string="$@"
grep_hostname_regex='[a-z]*[0-9]\{2\}\(live\|test\)'
sed_hostname_regex='[a-z]*[0-9]{2}(live|test)'
target_host=$(
echo "$arg_string\c" | grep -o "$grep_hostname_regex"
)
ssh_args=$(
echo "$arg_string\c" | sed -E "s# ${sed_hostname_regex}.*##"
)
cmd=$(
echo "$arg_string\c" | sed -E "s#.*${sed_hostname_regex} ##"
)
gcloud compute ssh "$target_host" \
--command="$cmd" \
--tunnel-through-iap \
-- $ssh_args
Run Code Online (Sandbox Code Playgroud)
笔记:
sed
例如,Linux 上的选项可能会有所不同。在对https://www.reddit.com/r/ansible/comments/e9ve5q/ansible_slow_as_a_hell_with_gcp_iap_any_way_to/进行讨论后,我改变了解决方案以使用通过套接字共享的 SSH 连接。
它比@mat 解决方案快两倍。我把它放在我们的 PROD 上。这是一个不依赖于主机名模式的实现!
正确的解决方案是使用堡垒/跳转主机,因为gcloud
命令仍然会产生产生的 Python 解释器ssh
- 它仍然效率低下!
ansible.cfg
:
[ssh_connection]
pipelining = True
ssh_executable = misc/gssh.sh
ssh_args =
transfer_method = piped
[privilege_escalation]
become = True
become_method = sudo
[defaults]
interpreter_python = /usr/bin/python
gathering = False
# Somehow important to enable parallel execution...
strategy = free
Run Code Online (Sandbox Code Playgroud)
gssh.sh
:
#!/bin/bash
# ansible/ansible/lib/ansible/plugins/connection/ssh.py
# exec_command(self, cmd, in_data=None, sudoable=True) calls _build_command(self, binary, *other_args) as:
# args = (ssh_executable, self.host, cmd)
# cmd = self._build_command(*args)
# So "host" is next to the last, cmd is the last argument of ssh command.
host="${@: -2: 1}"
cmd="${@: -1: 1}"
# ControlMaster=auto & ControlPath=... speedup Ansible execution 2 times.
socket="/tmp/ansible-ssh-${host}-22-iap"
gcloud_args="
--tunnel-through-iap
--zone=europe-west1-b
--quiet
--no-user-output-enabled
--
-C
-o ControlMaster=auto
-o ControlPersist=20
-o PreferredAuthentications=publickey
-o KbdInteractiveAuthentication=no
-o PasswordAuthentication=no
-o ConnectTimeout=20"
exec gcloud compute ssh "$host" $gcloud_args -o ControlPath="$socket" "$cmd"
Run Code Online (Sandbox Code Playgroud)
更新谷歌工程师的回应gcloud
不应该被并行调用!请参阅“gcloud compute ssh”不能并行使用
实验表明,使用 Ansiblefork=5
我几乎总是会出错。随着fork=2
我从来没有经历过的。
更新 2时间过去了,到 2020 年底,我可以gcloud compute ssh
并行运行(在 WSL 中我做了fork = 10
)而不会出现锁定错误。