Ansible을 사용하면 GCP에서 Cloud IAP(Identity Aware Proxy) 뒤의 호스트에 연결할 수 있나요?

Ansible을 사용하면 GCP에서 Cloud IAP(Identity Aware Proxy) 뒤의 호스트에 연결할 수 있나요?

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 솔루션보다 두 배 빠릅니다. 우리 제품에 넣었어요.이는 호스트 이름 패턴에 의존하지 않는 구현입니다!

올바른 해결책은 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"

고쳐 쓰다gcloudGoogle 엔지니어가 호출해서는 안되는 응답을 했습니다.평행하게! 바라보다'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를 게시해 주셔서 감사합니다. 한 가지 제안은 영역을 하드코딩할 필요가 없도록 다음을 추가하는 것입니다.

단편:

ZONE=$(gcloud compute instances list --filter="name:${host}" --format='value(zone)')

gcloud_args="
--tunnel-through-iap \
--zone=${ZONE}

관련 정보