Domain-Name-System
如何在沒有靜態外部 IP 的情況下將外部 DNS 記錄指向 GCP VM 實例?
我在 Google Cloud 中有很多很少需要調試的虛擬機。一直執行它們會花費很多,因此它們大部分時間都處於關閉狀態。問題是如果機器重新啟動,臨時 IP 地址會發生變化,並且 DNS 記錄將不匹配。我知道可以使用靜態 IP 地址,但是**IP 靜態 IP 地址(已分配但未使用)**非常昂貴,來源https://cloud.google.com/vpc/network-pricing
在不使用靜態外部 IP 地址的情況下,將外部 DNS 記錄指向很少重新啟動的 VM 的好方法是什麼?
我在 Google Cloud DNS 中有一個域,在其他提供商中也有外部 DNS 域。
一切順利。為了在@Sergiusz 的先前答案中添加一點內容,這就是我所做的。
- 在 Cloud DNS 中配置了一個區域(不在問題範圍內)
- 創建了一個分配了 DNS 管理員角色/權限的服務帳戶(可以收緊一點),然後將服務帳戶的 json 密鑰下載到 VM 上的 /root/sa-file.json
- 使用自定義值更新了 VM 的元數據:
dns_zone_name(用於儲存區域的名稱,fe gcp-jd-zone)
dns_domain(用於儲存 fqdn,fe gcp.jabbsondude.com)
dns_record_ttl(用於儲存創建的 A 記錄的 ttl,fe 600)
key_path(使用服務帳戶密鑰儲存文件的路徑,fe /root/sa-file.json)
- 使用啟動腳本更新了 VM 的元數據:
#!/bin/bash host=$HOSTNAME url_project_id="http://metadata.google.internal/computeMetadata/v1/project/project-id" url_ip_address="http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip" url_attributes="http://metadata.google.internal/computeMetadata/v1/instance/attributes" get_metadata() { local data=`curl -s -f $url_attributes/$1 -H "Metadata-Flavor: Google"` if [ -z "$data" ]; then echo "$1 does not exist in metadata. Exiting." exit 1 fi echo "$data" } auth_gcloud() { project=`curl -s $url_project_id -H "Metadata-Flavor: Google"` echo "Authenticating gcloud with service account ($key_path), project ($project)." gcloud auth activate-service-account --project=$project --key-file=$key_path >/dev/null 2>&1 if [ $? -eq 0 ]; then echo "Authentication succeeded." else echo "Authentication failed. Exiting." exit 2 fi } dns_check_record_exists() { echo "Checking if record ($host.$dns_domain) already exists in Cloud DNS" dns_data=`gcloud beta dns record-sets list --zone=$dns_zone_name --name=$host.$dns_domain --format=text` if [ $? -eq 0 ]; then echo "Received answer from Cloud DNS." else echo "Didn't receive any data from Cloud DNS. Exiting." exit 3 fi if [[ -n "$dns_data" ]]; then echo "Found existing record." return 1 # data exists else echo "Didn't find existing record." return 0 # no data fi } dns_record_create() { echo "Creating new record in Cloud DNS ($host.$dns_domain) in zone ($dns_zone_name) with ip ($ip) and ttl ($dns_record_ttl)" gcloud beta dns record-sets create $host.$dns_domain --rrdatas=$ip --type=A --zone=$dns_zone_name --ttl=$dns_record_ttl >/dev/null 2>&1 } dns_record_update() { echo "Updating existing record in Cloud DNS ($host.$dns_domain) in zone ($dns_zone_name) with ip ($ip) and ttl ($dns_record_ttl)" gcloud beta dns record-sets update $host.$dns_domain --rrdatas=$ip --type=A --zone=$dns_zone_name --ttl=$dns_record_ttl >/dev/null 2>&1 } # getting metadata dns_zone_name="$(get_metadata dns_zone_name)" dns_domain="$(get_metadata dns_domain)" dns_record_ttl="$(get_metadata dns_record_ttl)" key_path="$(get_metadata key_path)" # getting exterinal ip ip=`curl -s $url_ip_address -H "Metadata-Flavor: Google"` # validating external ip if [[ -n "$ip" && $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then echo "External ip detected: $ip" auth_gcloud dns_check_record_exists if [ $? -eq 0 ]; then dns_record_create else dns_record_update fi else echo "No external ip detected. Exiting." exit 5 fi
以下是它在 VM 實例詳細資訊中的外觀: img
- 重新啟動虛擬機
日誌的輸出(如果是 Debian,則為 /var/log/daemon.log):
Found startup-script in metadata. startup-script: External ip detected: 123.213.132.2 startup-script: Authenticating gcloud with service account (/root/sa-file.json), project (jabbsondude-proj). startup-script: Authentication succeeded. startup-script: Checking if record (instance-1.gcp.jabbsondude.com) already exists in Cloud DNS startup-script: Received answer from Cloud DNS. startup-script: Didn't find existing record. startup-script: Creating new record in Cloud DNS (instance-1.gcp.jabbsondude.com) in zone (gcp-jd-zone) with ip (123.213.132.2) and ttl (600) startup-script exit status 0
該腳本用於為使用上述腳本啟動的每個 VM 創建和更新 A 記錄。它可能可以通過更多檢查來改進,這只是我在過去一個小時裡出於好奇而想出的。
讓我知道您是否需要任何幫助,或者是否有問題。