С помощью Ansible можно ли подключиться к хостам, которые находятся за Cloud IAP (Identity-Aware Proxy) в GCP?

В bashбез опции dotglobскрытые файлы игнорируются, если только глобус не запрашивает их явно (, то есть с литералом в начале .). И .и ..не игнорируются (в отличие от того, что делают более разумные оболочки, такие как pdksh, zshили fish).

При использовании dotglobигнорируются только .и .., если только шаблон не начинается с ..

В extglobbashдобавлена ​​поддержка некоторых из kshрасширенных операторов глобуса. Однако здесь с ошибкой/ошибкой, когда дело доходит до !(...).

В обоих ksh(, хотя и не вpdkshbash, @(.*)— это один из случаев, когда вы явно запрашиваете точечные файлы (, хотя в документации это не проясняется ).

Но в !(.git)вы не запрашиваете файлы точек. kshи zshв эмуляции kshобрабатывают это правильно, но bashпредполагает, что вы запрашиваете файлы точек. И это включает .и ..даже с dotglob. Таким образом, .gitбудет скопирован как часть копирования ..

Чтобы обойти это, вы можете использовать!([.]git)(здесь [.]делает .неявным )в сочетании с dotglobили явно исключает .и ..с!(.git|.|..):

$ bash -O extglob -c 'echo !(.git)'
... foo.foo
$ bash -O extglob -O dotglob -c 'echo !(.git)'
... foo.foo
$ bash -O extglob -O dotglob -c 'echo !([.]git)'
foo.foo
$ bash -O extglob -c 'echo !(.git|.|..)'
foo.foo

В последнем случае я бы все равно добавил параметр dotglob, потому что bashв будущей версии может быть исправлено, чтобы не включать точечные файлы здесь, как в других оболочках.

Поскольку я использую zsh, который имеет свои собственные расширенные операторы (с опцией extendedglob, не включенной по умолчанию, чтобы сохранить совместимость с Борном; он также поддерживает ksh globs с опцией kshglob, но они более неудобны ), я бы сделал:

set -o extendedglob # (in my ~/.zshrc)
cp -a -- ^.git(D) target/

(обратите внимание, что -aподразумевает -rи вам нужен --, так как мы не можем гарантировать, что имена файлов не будут начинаться с-).

^.gitявляется zshэквивалентом ksh !(.git). (D)для включения точечных файлов (, но никогда .и..)только для этого шара.

1
04.10.2019, 07:57
3 ответа

Я нашел способ заставить это работать без подключаемого модуля. По сути, вы можете написать скрипт, обертывающий инструмент 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.
  • Регулярные выражения «host» должны соответствовать вашему соглашению об именах. Если у вас нет согласованного соглашения об именах, которое работало бы так же, как у меня, вам нужно найти какой-то другой способ анализа информации.
4
27.01.2020, 23:22

После обсужденияhttps://www.reddit.com/r/ansible/comments/e9ve5q/ansible_slow_as_a_hell_with_gcp_iap_any_way_to/я изменил решение, чтобы использовать совместное использование соединения SSH через сокет.

Это в два раза быстрее решения @mat. Поставил на наш PROD. Вот реализация, которая не зависит от шаблонов имен хостов!

Правильным решением является использование хоста 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"

ОБНОВЛЕНИЕ Инженер Google ответил, что gcloudне должны вызываться параллельно ! См. «Gcloud Compute ssh» не может использоваться параллельно

.

Эксперименты показали, что с Ansible fork=5я почти всегда сталкивался с ошибкой. С fork=2я никогда не сталкивался с ним.

ОБНОВЛЕНИЕ 2 Прошло время, и по состоянию на конец 2020 года я могу запустить gcloud compute sshпараллельно (в WSL. Я сделалfork = 10)без ошибок блокировки.

6
17.02.2020, 15:24

Спасибо за публикацию этих @gavenkoa и @matt. Одно из предложений состоит в том, чтобы добавить следующее, чтобы вам не нужно было жестко кодировать зону.

Фрагмент:

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

gcloud_args="
--tunnel-through-iap \
--zone=${ZONE}
1
18.12.2020, 00:31

Теги

Похожие вопросы