Как обновить Google Cloud DNS с помощью эфемерного IP-адреса для экземпляра

У меня есть несколько экземпляров на GCE, для которых мне действительно не нужны статические адреса, но мне все равно нужно сделать их доступными через DNS-имя. Поскольку эфемерные внешние IP-адреса меняются каждый раз при перезапуске экземпляра, я подумал, что могу использовать какой-то сценарий запуска для обновления записи DNS для этого экземпляра в Google Cloud DNS (что-то вроде dyndns).

Я что-то пропустил, и есть более простой способ сопоставить эфемерные внешние IP-адреса с записью DNS через gcloud?

Если нет, мы будем очень признательны за любые советы о том, как написать такой скрипт!


person s3ncha    schedule 11.01.2016    source источник


Ответы (3)


Ниже предполагается, что вы используете Google Cloud DNS для foo.bar.com (т.е. DNS-имя «foo.bar.com.») С именем зоны «foo-bar-com» в том же проекте, что и ваша виртуальная машина, и что ваша ВМ есть опция конфигурации «У этого экземпляра есть полный доступ API ко всем сервисам Google Cloud». выбрано. Ваша виртуальная машина будет называться "my-vm.foo.bar.com" в DNS.

Я уверен, что это можно соответствующим образом изменить для работы с DNS в другом проекте и / или с более ограниченными разрешениями.

Вероятно, стоит отметить: это предполагает, что вы используете `` Google Cloud DNS '', а не (только) регистратор `` Google Domains '', если вы используете последний (для размещения своего DNS, а не только в качестве регистратора), тогда у них есть прямая поддержка для синтетического динамического IP-адреса с некоторыми динамиками, такими как механизм обновления (но они более ограничены множеством других способов).

Также обратите внимание, что для успешной транзакции уже должна быть запись с правильным IP и правильным TTL (то есть при первом запуске вы можете удалить любую запись вручную через пользовательский интерфейс и запустить этот код с dns_del закомментировал).

#!/bin/bash

ttlify() {
  local i
  for i in "$@"; do
    [[ "${i}" =~ ^([0-9]+)([a-z]*)$ ]] || continue
    local num="${BASH_REMATCH[1]}"
    local unit="${BASH_REMATCH[2]}"
    case "${unit}" in
                     weeks|week|wee|we|w) unit=''; num=$[num*60*60*24*7];;
                           days|day|da|d) unit=''; num=$[num*60*60*24];;
                     hours|hour|hou|ho|h) unit=''; num=$[num*60*60];;
      minutes|minute|minut|minu|min|mi|m) unit=''; num=$[num*60];;
      seconds|second|secon|seco|sec|se|s) unit=''; num=$[num];;
    esac
    echo "${num}${unit}"
  done
}

dns_start() {
  gcloud dns record-sets transaction start    -z "${ZONENAME}"
}

dns_info() {
  gcloud dns record-sets transaction describe -z "${ZONENAME}"
}

dns_abort() {
  gcloud dns record-sets transaction abort    -z "${ZONENAME}"
}

dns_commit() {
  gcloud dns record-sets transaction execute  -z "${ZONENAME}"
}

dns_add() {
  if [[ -n "$1" && "$1" != '@' ]]; then
    local -r name="$1.${ZONE}."
  else
    local -r name="${ZONE}."
  fi
  local -r ttl="$(ttlify "$2")"
  local -r type="$3"
  shift 3
  gcloud dns record-sets transaction add      -z "${ZONENAME}" --name "${name}" --ttl "${ttl}" --type "${type}" "$@"
}

dns_del() {
  if [[ -n "$1" && "$1" != '@' ]]; then
    local -r name="$1.${ZONE}."
  else
    local -r name="${ZONE}."
  fi
  local -r ttl="$(ttlify "$2")"
  local -r type="$3"
  shift 3
  gcloud dns record-sets transaction remove   -z "${ZONENAME}" --name "${name}" --ttl "${ttl}" --type "${type}" "$@"
}

lookup_dns_ip() {
  host "$1" | sed -rn 's@^.* has address @@p'
}

my_ip() {
  ip -4 addr show dev eth0 | sed -rn 's@^    inet ([0-9.]+).*@\1@p'
}

doit() {
  ZONE=foo.bar.com
  ZONENAME=foo-bar-com
  dns_start
  dns_del my-vm 5min A `lookup_dns_ip "my-vm.${ZONE}."`
  dns_add my-vm 5min A `my_ip`
  dns_commit
}
person MaZe    schedule 14.01.2016

Я собираюсь немного рассказать об ответе @MaZe. Кроме того, я покажу использование systemd, поэтому этот сценарий запускается автоматически при запуске, если вы используете Ubuntu или другой дистрибутив, использующий systemd.

#!/bin/bash

EXISTING=`gcloud dns record-sets list --zone="{your domain}" | grep xxx.yyyy.com | awk '{print $4}'`
NEW=`gcloud compute instances describe {your instance} --zone={your zone} | grep natIP | awk -F': ' '{print $2}'`
gcloud dns record-sets transaction start -z={your domain}
gcloud dns record-sets transaction remove -z={your domain} \
    --name="xxx.yyyy.com." \
    --type=A \
    --ttl=300 "$EXISTING"
gcloud dns record-sets transaction add -z={your domain} \
   --name="xxx.yyyy.com." \
   --type=A \
   --ttl=300 "$NEW"
gcloud dns record-sets transaction execute -z={your domain}

Сохраните его в /path/to/script.sh и запустите в systemd:

[Unit]
Description=Set xxx.yyyy.com to the correct external ip address of this instance
After=network.target auditd.service

[Service]
ExecStart=/path/to/script.sh
Type=oneshot

[Install]
WantedBy=multi-user.target

Сохраните его в / etc / systemd / system как filename.service и включите с помощью:

sudo systemctl enable filename.service
person Software Prophets    schedule 17.07.2018
comment
В чем преимущество этого по сравнению с работой cron? - person paradroid; 10.02.2019
comment
Полагаю, нет, если вы можете запустить задание один раз при запуске. Обычно, если есть что-то, что вы хотите запустить при запуске, вы используете сценарий systemd, подобный этому, а если есть что-то, что вы хотите запланировать, например повторяющееся задание, вы используете cron. Я обнаружил, что мне нужно это только для запуска один раз, и я настроен до следующего запуска. Этот сценарий systemd мне хорошо послужил. - person Software Prophets; 11.02.2019
comment
Ну ладно, имеет смысл. На самом деле я намеревался использовать это на аппаратном сервере, отличном от Google, где динамический IP-адрес меняется относительно часто, но для обновления записей DNS в Google Cloud DNS. - person paradroid; 11.02.2019
comment
@paradroid Я считаю, что эфемерный IP-адрес изменяется только при запуске, поэтому вам не нужно повторно запускать его с помощью cron. - person user5532169; 18.08.2019
comment
Если обновляемый экземпляр всегда является текущим экземпляром, {your instance} и {your zone} можно заменить на `curl http://metadata.google.internal/computeMetadata/v1/instance/name -H Metadata-Flavor:Google` и `curl http://metadata.google.internal/computeMetadata/v1/instance/zone -H Metadata-Flavor:Google` соответственно. - person user5532169; 18.08.2019
comment
Я обнаружил, что эфемерный IP-адрес также может измениться при выходе из приостановленного состояния. Есть ли какое-либо событие для возобновления внутри виртуальной машины для запуска сценария обновления IP? cc @ user5532169 - person noseratio; 27.09.2020
comment
@noseratio Я еще не пробовал, но поиск в Интернете показывает, что вы можете поместить сценарий в / lib / systemd / system-sleep / и сделать его исполняемым, а затем любой сценарий, находящийся в этом каталоге, будет выполняться во время приостановки и возобновить. Для резюме вам может понадобиться такая проверка: if [$ {1} = post]; тогда. Найдите systemd / system-sleep для получения дополнительной информации. - person Software Prophets; 28.09.2020
comment
@SoftwareProphets звучит отлично, я попробую, спасибо! - person noseratio; 28.09.2020

Прошло некоторое время с тех пор, как вы разместили этот вопрос, но я опубликую здесь свой ответ для справок в будущем.

У меня была аналогичная потребность, и я не хотел использовать gcloud CLI.

Я создал простой скрипт python, который делает почти то же самое, что и приведенный выше скрипт bash, но использует Apache Libcloud и учетные данные Google Cloud API (учетная запись и ключ службы). .

Вы можете найти код в GitHub.

person Or Polaczek    schedule 15.04.2017