なぜGoogle Cloud DNSを「ただのDNS」と侮ってはいけないのか?―パブリックとプライベートの深淵
SREの現場で「名前解決ができない」というアラートが鳴るとき、その原因の9割は設定ミスか、ネットワークの境界(ペリメータ)に対する無理解です。
Google Cloud DNSは、単なるBINDの置き換えではありません。Googleのグローバルネットワークバックボーンに直結した、超高可用性・低レイテンシの「分散型権威DNS」です。今回は、Web API設計やインフラ運用に携わるエンジニアが絶対に押さえておくべき、パブリックゾーンとプライベートゾーンの「境界線」と「挙動のリアル」を解説します。
—
1. パブリックゾーンとプライベートゾーン:脳内スイッチの切り替え
まず大前提として、Google Cloud DNSにおける「パブリック」と「プライベート」は、「誰がそのDNSレコードを引けるか」という権限の分離を意味します。
- パブリックゾーン: インターネット全体に公開されます。外部ユーザーがあなたのWeb APIにアクセスするための入り口です。
- プライベートゾーン: 指定したVPCネットワーク内でのみ有効です。外部からは一切見えず、社内システムやマイクロサービス間の通信に利用します。
現場の落とし穴:オーバーラップの優先順位
ここでよくあるトラブルが、「パブリックと同じドメイン名をプライベートで設定した場合、どちらが勝つか?」という疑問です。答えはシンプル、「プライベートゾーンが常に優先される」です。
VPC内で名前解決が走ると、Googleの内部ネットワークはまず「プライベートゾーン」を検索し、ヒットしなければ「パブリックゾーン」を見に行きます。この優先順位を理解していないと、本番環境のWeb APIを叩いているつもりが、検証用のプライベートなエンドポイントに迷い込むという、冷や汗ものの事故を引き起こします。
—
2. 実践:プライベートゾーンによる内部ルーティング
例えば、api.internal.example.com という内部エンドポイントを、VPC内のGKEポッドから叩く設定を考えてみましょう。
Cloud DNSプライベートゾーンの設定 (Terraform例)
# VPC内で名前解決を完結させるためのゾーン設定
resource "google_dns_managed_zone" "private_zone" {
name = "internal-zone"
dns_name = "internal.example.com."
visibility = "private" # これが重要:公開範囲をVPCに限定
private_visibility_config {
networks {
network_url = google_compute_network.main_vpc.self_link
}
}
}
# 具体的なAレコードの定義
resource "google_dns_record_set" "api_endpoint" {
name = "api.${google_dns_managed_zone.private_zone.dns_name}"
managed_zone = google_dns_managed_zone.private_zone.name
type = "A"
ttl = 300
rrdatas = ["10.0.0.5"] # 内部ロードバランサーのIPを指定
}
—
3. 疎通確認とデバッグの作法
「名前解決が通らない」という時、dig コマンドで安易に外部のDNS(8.8.8.8など)を叩いても無意味です。プライベートゾーンはVPCの外からは見えないからです。
現場で使うべきデバッグコマンド
VPC内のコンテナ(あるいはVM)から、名前解決の経路を確認します。
# 1. そもそもそのホストから解決できるか?
dig api.internal.example.com @169.254.169.254
# 2. curlで応答をテスト(HTTPステータスを確認)
curl -I -v http://api.internal.example.com/healthz
169.254.169.254 はGoogle Cloudのメタデータサーバー兼DNSリゾルバーです。プライベートゾーンの設定が正しければ、ここで正しく内部IPが返ってくるはずです。
—
4. Web API開発者が知るべきレイテンシの真実
Web APIの設計において、DNSの解決時間は「無視できるもの」と考えがちですが、高トラフィックなシステムではDNSクエリの回数自体がボトルネックになります。
Tips: DNSキャッシングの最適化
Python等で長時間稼働するバックエンドを書く場合、デフォルトのDNSキャッシュ設定が意図通りか確認してください。
import socket
import time
# DNS解決のレイテンシを計測するスニペット
def check_dns_latency(hostname):
start = time.perf_counter()
ip = socket.gethostbyname(hostname)
end = time.perf_counter()
print(f"IP: {ip}, Time: {(end - start) * 1000:.2f}ms")
# 本番環境では、アプリケーション層でもキャッシュを持つことを検討すべき
check_dns_latency("api.internal.example.com")
もし頻繁に外部APIを叩く必要があるなら、Cloud DNSの TTL を調整するだけでなく、アプリケーション側で名前解決の結果をキャッシュ(あるいはホストファイル的なメモリ保持)を行うことで、数ミリ秒の短縮が可能になります。この数ミリ秒の積み重ねが、マイクロサービスアーキテクチャ全体でのレスポンス改善に直結します。
—
最後に:ネットワークは「見えないからこそ」泥臭く検証する
クラウドのマネージドDNSは非常に優秀ですが、「魔法」ではありません。パケットは必ずしも期待通りには飛ばないものです。
1. VPCフローログを確認する: 接続先IPが本当に意図したものか、パケットがドロップされていないか。
2. DNSクエリログを有効にする: Cloud DNSのログをCloud Loggingに流し込み、実際に誰が・どのドメインを・どこから引こうとしているのかを可視化する。
この「泥臭い」調査の習慣こそが、いざ障害が起きた時に「DNSの問題なのか、それともアプリケーションのタイムアウトなのか」を即座に切り分ける、SREとしての真の武器になります。
次にネットワークの設定をするときは、ぜひ「このパケットは今、どのゾーンのどのネームサーバーを叩いているのか?」を脳内でトレースしてみてください。それが、インフラエンジニアとしての腕の見せ所です。
コメント