首页 文章

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

提问于
浏览
6

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

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

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

3 回答

  • 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
    }
    
  • 3

    你发布这个问题已经有一段时间了,但我会在这里发布我的答案以供将来参考 .

    我've had a similar need and I didn' t想要使用 gcloud CLI .

    我创建了一个简单的python脚本,其功能与上面的bash脚本完全相同,但使用 Apache LibcloudGoogle Cloud API credentials (服务帐户和密钥) .

    你可以在GitHub找到代码 .

  • 1

    我将对@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
    

    将它作为filename.service保存在/ etc / systemd / system中,并使用以下命令启用它:

    sudo systemctl enable filename.service
    

相关问题