I modified @Software Prophets answer slightly, since his script started failing once I had added more DNS records for my domains. I'm using the root domain for the A record, and the line gcloud dns record-sets list --zone="{your domain}
suddenly started returning a whole bunch of fields instead of the IP from the A record.
Since we only want the IP, we can dispense with the CNAME, MX, TXT and whatever else was being returned in column 4.
Here is my modified script to auto-update the external IP when/if it changes. I also added an if block so that it does nothing if the IP hasn't changed.
Bash script to update IP:
#!/usr/bin/bash
#
# This script updates the IP for the domain A record if it has changed.
# This allows us to use an ephemeral (dynamic) IP without having to pay
# for a static IP address.
# Update these with your DNS, Zone and Instance (DO NOT INCLUDE THE
# TRAILING DOT for the URL, we add this later!)
ZONENAME="example-zone-name"
INSTANCE="example-instance-VM-name"
URL="example.com"
# get EXISTING ip from Google Cloud DNS example.com from ZONENAME zone
EXISTING=`gcloud dns record-sets list --name="$URL." --type="A" --zone="$ZONENAME" | grep $URL | awk '{print $4}'`
# get NEW external IP from our INSTANCE record
NEW=`gcloud compute instances describe "$INSTANCE" --zone="europe-west1-b" | grep natIP | awk -F': ' '{print $2}'`
if [ "$EXISTING" = "$NEW" ]; then
# Do nothing, IP unchanged
echo "IP unchanged, do nothing";
else
# Update the record for this domain
gcloud dns record-sets transaction start -z="$ZONENAME"
gcloud dns record-sets transaction remove -z="$ZONENAME" \
--name="$URL." \
--type="A" \
--ttl=300 "$EXISTING"
gcloud dns record-sets transaction add -z="$ZONENAME" \
--name="$URL." \
--type="A" \
--ttl=300 "$NEW"
gcloud dns record-sets transaction execute -z="$ZONENAME"
fi
And the Systemd service hasn't changed, but here it is for completeness:
[Unit]
Description=Set root A records pointing to this VM to the correct external IP address for this instance
After=network.target auditd.service
[Service]
ExecStart=/path/to/your/bin/ephemeral.ip.sh
Type=oneshot
[Install]
WantedBy=multi-user.target