使用 Ansible,是否可以连接到 GCP 中 Cloud IAP(身份感知代理)后面的主机?

mat*_*mat 5 ssh ansible google-cloud

Cloud IAP 是 Google Cloud Platform 的一种代理,可让您连接到没有公共 IP 地址的计算实例,而无需 VPN。你站起来的实例,然后就可以使用gcloud工具按名称连接到它像这样:gcloud compute ssh my-server-01。这将通过代理对您进行身份验证,并使用您自己的 Google 帐户(使用称为操作系统登录的功能)将您登录到目标服务器。

我想让 ansible 做gcloud工具正在做的事情,我需要一个自定义连接插件。

mat*_*mat 6

我找到了一种无需连接插件即可完成这项工作的方法。基本上,您可以编写一个包装该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)

笔记:

  • 这是在 macOS 上测试的。sed例如,Linux 上的选项可能会有所不同。
  • “主机”正则表达式需要符合您的命名约定。如果您没有像我一样的一致命名约定,您将需要找到其他方法来解析信息。


gav*_*koa 5

在对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)而不会出现锁定错误。