Cloud IAPは、VPNなしでパブリックIPアドレスなしでコンピューティングインスタンスに接続できるようにするGoogle Cloud Platform用のプロキシです。インスタンスを設定したら、gcloud
このユーティリティを使用して名前でインスタンスに接続できますgcloud compute ssh my-server-01
。これはプロキシを介してあなたを認証し、Googleアカウントを使用してターゲットサーバーにログインします(オペレーティングシステムログインと呼ばれる機能を使用)。
gcloud
ツールが何をするには、カスタム接続プラグインが必要だと思います。
答え1
議論後https://www.reddit.com/r/ansible/comments/e9ve5q/ansible_slow_as_a_hell_with_gcp_iap_any_way_to/ソケットを介したSSH接続共有を使用するようにソリューションを変更しました。
@matソリューションより2倍高速です。私たちの製品に入れました。これはホスト名パターンに依存しない実装です!
正しい解決策は Bastion/Jump ホストを使用することです。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
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"
修正するgcloud
Googleエンジニアが呼び出すべきではない応答をしました。平行に!バラより'gcloudcomputessh' は並列に使用できません。
実験によると、Ansibleを使用すると、fork=5
ほとんど常にエラーが発生します。私はfork=2
そのようなことを経験したことがありません。
アップデート2時間の経過とともに、2020年末までにロックエラーなしで並列に実行できましたgcloud compute ssh
(WSLでは実行しました)。fork = 10
答え2
プラグインを接続せずにこれを行う方法を見つけました。デフォルトでは、ツールをラップ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
メモ:
- これはmacOSでテストされました。
sed
たとえば、Linuxではオプションが異なる場合があります。 - 「ホスト」正規表現は命名規則と一致する必要があります。私のように一貫した命名規則がない場合は、情報を解析する別の方法を見つける必要があります。
答え3
@gavenkoaと@mattを投稿していただきありがとうございます。 1つの提案は、領域をハードコードする必要がないように、次のものを追加することです。
フラグメント:
ZONE=$(gcloud compute instances list --filter="name:${host}" --format='value(zone)')
gcloud_args="
--tunnel-through-iap \
--zone=${ZONE}