我在 GCE 上有几个实例,我真的不需要静态地址,但我仍然需要通过 dns 名称访问它们。由于每次重新启动实例时临时外部 IP 地址都会更改,因此我认为我可以使用某种启动脚本来更新 Google Cloud DNS 中该实例的 dns 条目(有点像 dyndns)。
我是否错过了什么,并且有一种更简单的方法可以通过 gcloud 将临时外部 IP 地址映射到 dns 记录?
如果没有,任何有关如何编写此类脚本的指针将不胜感激!
我在 GCE 上有几个实例,我真的不需要静态地址,但我仍然需要通过 dns 名称访问它们。由于每次重新启动实例时临时外部 IP 地址都会更改,因此我认为我可以使用某种启动脚本来更新 Google Cloud DNS 中该实例的 dns 条目(有点像 dyndns)。
我是否错过了什么,并且有一种更简单的方法可以通过 gcloud 将临时外部 IP 地址映射到 dns 记录?
如果没有,任何有关如何编写此类脚本的指针将不胜感激!
以下假设您在与您的 VM 相同的项目中使用 Google Cloud DNS for foo.bar.com(即 dns 名称“foo.bar.com.”),区域名称为“foo-bar-com”,并且您的VM 具有配置选项“此实例具有对所有 Google Cloud 服务的完全 API 访问权限。” 选择。您的 VM 在 DNS 中将被称为“my-vm.foo.bar.com”。
我确信这可以适当地修改以在不同的项目中使用 DNS 和/或更有限的权限。
可能值得注意:这假设您使用的是“Google Cloud DNS”而不是(仅)“Google Domains”注册商,如果您使用后者(托管您的 DNS,而不仅仅是作为注册商),那么他们有直接支持对于具有一些动态的合成动态 IP 地址,例如更新机制(但它们在许多其他方面受到更多限制)。
另请注意,要使交易成功,必须有一条具有正确 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
}
我将对@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
自从您发布此问题以来已经有一段时间了,但我会在此处发布我的答案以供将来参考。
我有类似的需求,我不想使用gcloud
CLI。
我创建了一个简单的 python 脚本,它与上面的 bash 脚本几乎相同,但使用Apache Libcloud和Google Cloud API 凭据(服务帐户和密钥)。
您可以在GitHub中找到代码。