如何使用临时IP为实例更新Google Cloud DNS

s3n*_*cha 9 dns google-compute-engine gcloud google-cloud-dns

我在GCE上有几个实例,我不需要静态地址,但我仍然需要通过dns名称访问它们.由于短暂的外部IP地址每次重新启动时都会发生变化,我认为我可以使用某种启动脚本来更新Google Cloud DNS中的该实例的dns条目(有点像dyndns).

我错过了什么,有一种更简单的方法可以通过gcloud将短暂的外部IP地址映射到dns记录吗?

如果没有,任何关于如何编写此类脚本的指针都将受到高度赞赏!

MaZ*_*aZe 5

以下假设您在foo.bar.com(即dns名称为"foo.bar.com.")中使用Google Cloud DNS,区域名称为"foo-bar-com",与您的VM位于同一项目中,并且VM具有配置选项"此实例具有对所有Google Cloud服务的完全API访问权限." 选择.您的VM将在DNS中名为"my-vm.foo.bar.com".

我确信这可以被适当修改以在不同的项目中使用DNS和/或更有限的权限.

可能值得注意的是:这假设您使用的是"Google Cloud DNS",而不是(仅仅)"Google Domains"注册商,如果您使用的是后者(托管您的DNS,而不仅仅是注册商),那么他们会直接支持对于合成动态ip地址和一些类似更新机制的dyndns(但它们在其他方面更受限制).

还要注意,为了使事务成功,必须有一个具有正确IP和正确TTL的记录(即,第一次运行它时,您可能希望通过UI手动删除任何条目,并使用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
}
Run Code Online (Sandbox Code Playgroud)


Out*_*rce 5

我将对@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}
Run Code Online (Sandbox Code Playgroud)

将其保存到 /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
Run Code Online (Sandbox Code Playgroud)

将其保存在 /etc/systemd/system 中作为 filename.service 并启用它:

sudo systemctl enable filename.service
Run Code Online (Sandbox Code Playgroud)

  • 没有,我想,如果您可以在启动时运行一次作业。通常,如果您想在启动时运行某些内容,则使用像这样的 systemd 脚本;如果您想安排某些内容,例如重复性工作,则使用 cron。我发现我只需要运行一次就可以了,直到下次启动。这个 systemd 脚本一直很好地为我服务。 (2认同)