本日も乙

ただの自己満足な備忘録。

Cloud DNSのプライベートDNSゾーンがリリースされたので試してみた

本記事は Google Cloud Platform その1 Advent Calendar 2018 - Qiita の4日目の記事です。

GCPといえば、BigQueryとかSpannerとかGKEとかの話が多いですが、ネットワーク関連のアップデートもしばしばあります。

少々前になりますが、GCPサービスの Cloud DNS がプライベートDNSゾーンに対応しましたので早速試してみました。

cloud.google.com

今回はgcloudコマンドで作成していきます。バージョンが 222.0.0 以上である必要があるためアップデートしておいてください。

$ gcloud components update

今回は以下のようなDNSレコードを設定してみます *1

DNS 名 タイプ TTL(秒) データ
test-instance.example.com. A 60 10.0.0.6
test-instance2.example.com. CNAME 60 test-instance.example.com.
test-outdomain.example.com. CNAME 60 foo.example.net.

プライベートゾーンの作成

$ gcloud beta dns managed-zones create "my-new-zone" \
  --dns-name="example.com" \
  --description="exaple" \
  --networks="default" \
  --visibility=private

レコードの追加

# トランザクションの開始
$ gcloud dns record-sets transaction start \
  --zone=my-new-zone

# Aレコードの追加
$ gcloud dns record-sets transaction add 10.0.0.6 \
  --type=A \
  --name=test-instance.example.com. \
  --ttl=60 \
  --zone=my-new-zone

# CNAMEレコードの追加
$ gcloud dns record-sets transaction add test-instance.example.com. \
  --type=CNAME \
  --name=test-instance2.example.com. \
  --ttl=60  \
  --zone=my-new-zone

$ gcloud dns record-sets transaction add test-outdomain.example.com. \
  --type=CNAME \
  --name=foo.example.net. \
  --ttl=60  \
  --zone=my-new-zone

# トランザクションの実行(適用)
$ gcloud dns record-sets transaction execute \
  --zone=my-new-zone

トランザクションを開始すると、ローカルに以下のような transaction.yaml というファイルが生成され、transaction addtransaction remove するとYAMLファイルが編集されます。このファイルを直接編集してDNSレコードの追加・削除・変更を行なうこともできます。
transaction execute を実行すると transaction.yaml の内容がCloud DNSに反映されます。

$ cat transaction.yaml
---
additions:
- kind: dns#resourceRecordSet
  name: example.com.
  rrdatas:
  - ns-gcp-private.googledomains.com. cloud-dns-hostmaster.google.com. 2 21600 3600
    259200 300
  ttl: 21600
  type: SOA
deletions:
- kind: dns#resourceRecordSet
  name: example.com.
  rrdatas:
  - ns-gcp-private.googledomains.com. cloud-dns-hostmaster.google.com. 1 21600 3600
    259200 300
  ttl: 21600
  type: SOA

追加したらGCEインスタンスに入って名前解決ができるか確認します。

$ dig test-instance.example.com

; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7_5.1 <<>> test-instance.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 145
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;test-instance.example.com. IN        A

;; ANSWER SECTION:
test-instance.example.com. 60 IN A    10.0.0.6

;; Query time: 3 msec
;; SERVER: 169.254.169.254#53(169.254.169.254)
;; WHEN: 月 10月 29 10:51:45 UTC 2018
;; MSG SIZE  rcvd: 80


$ dig test-instance2.example.com

; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7_5.1 <<>> test-instance2.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 17272
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;test-instance2.example.com. IN A

;; ANSWER SECTION:
test-instance2.example.com. 60 IN CNAME test-instance.example.com.
test-instance.example.com. 60 IN A    10.0.0.6

;; Query time: 3 msec
;; SERVER: 169.254.169.254#53(169.254.169.254)
;; WHEN: 木 11月 01 10:20:56 UTC 2018
;; MSG SIZE  rcvd: 109

もちろん、VPCネットワーク外では名前解決ができません。

$ dig test-instance.example.com

; <<>> DiG 9.10.6 <<>> test-instance.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 9921
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4000
;; QUESTION SECTION:
;test-instance.example.com.     IN      A

;; AUTHORITY SECTION:
example.com.            893     IN      SOA     sns.dns.icann.org. noc.dns.icann.org. 2018100708 7200 3600 1209600 3600

;; Query time: 62 msec
;; SERVER: 10.33.3.10#53(10.33.3.10)
;; WHEN: Thu Nov 01 19:13:01 JST 2018
;; MSG SIZE  rcvd: 111

外部ドメインのCNAMEレコードで名前解決ができない問題

先程設定したCNAMEレコードの test-outdomain.example.com ですが名前を引くと以下のようにIPアドレスが返ってきません。この foo.example.net はAレコードでIPアドレスが正引きできるものとします。

$ dig test-outdomain.example.com

; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7_5.1 <<>> test-outdomain.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16587
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;test-outdomain.example.com. IN A

;; ANSWER SECTION:
test-outdomain.example.com. 60 IN CNAME foo.example.net.  # IPアドレスが返ってこない

;; Query time: 64 msec
;; SERVER: 169.254.169.254#53(169.254.169.254)
;; WHEN: Tue Nov 13 07:41:58 UTC 2018
;; MSG SIZE  rcvd: 142

サポートに問い合わせたところ、現時点でバグであり今後改善される予定とのことです。
サーバ内でDNSフォワーダを設定して内部DNSに向けるようにすれば、回避が可能です。これについては別の記事で詳しく取り上げていきたいと思います。

まとめ

Cloud DNSのプライベートDNSゾーンを設定してみました。一部バグがありますが、名前解決がVPCネットワーク内に閉じることができるため、外部に情報公開したくないドメインを設定できたり、アプリケーション側でサービスの利用などに使うことができますね。
試していませんが、複数VPCネットワークに紐付けができるので、ピアリングや共有VPCにすることで、プライベートDNSゾーンも共有しあってますます便利になるのではないかと思っています。

参考

*1:NS、SOAはゾーン作成時に自動生成されるため、表記上は省略しています