↓メインコンテンツへスキップ
  1. Blogs/

TerraformでPrivate Cloud DNS ZoneとA Recordを作成してみた

3 分
Terraform GoogleCloud
0222-nnn
著者
0222-nnn
猫が好き
目次
Terraform-GoogleCloud - この記事は連載の一部です
パート 9: この記事

概要
#

Private Zoneは「指定したVPCからだけ名前解決できる」という仕組みです。ただしZoneとRecordを作っただけでは、それが本当に機能しているかわかりません。紐づけていないVPCやインターネットから引けてしまえば、Private Zoneを使う意味がなくなります。

Terraformで最小構成のPrivate ZoneとA Recordを作成します。3つの経路から実際に名前解決を試して確認します。紐づけたVPC内のVM、紐づけていない別VPCのVM、手元の端末の3つです。

Terraformの基本操作と、gcloud compute sshでのVM接続は前提としています。

Public ZoneやDNS Peeringは扱いません。Forwarding Zone、Split Horizon DNS、カスタムドメインの取得も扱いません。

検証すること
#

  • Private Cloud DNS ZoneをVPCへ関連付けられること
  • Private ZoneへA Recordを登録できること
  • 紐づけたVPC内のVMからは名前解決できること
  • 紐づけていない別VPCのVMからは名前解決できないこと(Zone作成の確認とは別)
  • インターネット経由(手元の端末)でも名前解決できないこと

今回の構成
#

Private ZoneはGlobalなResourceですが、名前を引けるVPCを指定します。指定していないVPCやインターネットからは見えません。それを確かめるため、検証用VMを紐づけたVPCと紐づけていない別VPCに1台ずつ作成します。

flowchart TB
    User["手元の端末
(インターネット経由)"] subgraph GCP["Google Cloud"] subgraph Project["Project"] subgraph DNS["Cloud DNS(Global)"] Zone["Managed Zone: example.internal.
visibility: private"] Rec["A Record: app.example.internal. → 10.10.0.10"] Zone --- Rec end subgraph Region["asia-northeast1"] subgraph VPC["VPC: tf-example-dns-vpc"] VMIn["VM: vm-in-zone"] end subgraph ExtVPC["VPC: tf-example-dns-external-vpc"] VMOut["VM: vm-outside-zone"] end end end end Zone -.->|"公開先として指定"| VPC

点線が公開範囲の指定です。tf-example-dns-external-vpcは指定されていません。実際に3つの経路で問い合わせると、次のようになります。

sequenceDiagram
    participant VMIn as VM(紐づくVPC)
    participant VMOut as VM(別VPC)
    participant Local as 手元の端末
    participant DNS as Private Zone

    VMIn->>DNS: getent hosts app.example.internal.
    DNS-->>VMIn: 10.10.0.10
    VMOut->>DNS: getent hosts app.example.internal.
    DNS--xVMOut: 解決できない
    Local->>DNS: getent hosts app.example.internal.
    DNS--xLocal: 解決できない

前提環境
#

  • Google Cloud CLIとApplication Default Credentials(ADC)
  • Terraform 1.10以降
  • Cloud DNSとVPC、Compute Engineを操作できる検証用Google Cloud Project
  • 検証時のバージョン:Terraform 1.14.3、google 7.43.0

使用するTerraformコード
#

Private Managed Zone
#

resource "google_dns_managed_zone" "private" {
  name       = var.managed_zone_name
  dns_name   = var.dns_name
  visibility = "private"

  private_visibility_config {
    networks {
      network_url = google_compute_network.dns.id
    }
  }
}

visibility = "private"とし、private_visibility_configで参照を許可するVPC(tf-example-dns-vpc)を指定します。このZoneはPublic Internetから名前解決できません。

DNS suffixは末尾のDotを含む完全修飾形式で指定します。

variable "dns_name" {
  default = "example.internal."

  validation {
    condition     = endswith(var.dns_name, ".")
    error_message = "dns_name must end with a dot."
  }
}

A Record
#

locals {
  record_fqdn = "${var.record_name}.${var.dns_name}"
}

resource "google_dns_record_set" "example" {
  name         = local.record_fqdn
  managed_zone = google_dns_managed_zone.private.name
  type         = "A"
  ttl          = var.record_ttl
  rrdatas      = [var.record_ip]
}

デフォルトではapp.example.internal.を10.10.0.10へ対応付け、TTLを300秒にします。このIPに対応する実体は無く、名前解決の確認だけが目的です。

検証用VM
#

resource "google_compute_instance" "vm_in_zone" {
  name         = var.vm_in_zone_name
  machine_type = var.machine_type
  zone         = var.zone
  tags         = ["iap-ssh"]

  network_interface {
    subnetwork = google_compute_subnetwork.dns.id
  }

  scheduling {
    provisioning_model = "SPOT"
    preemptible        = true
    automatic_restart  = false
  }
}

Zoneに紐づけたVPCへ1台、紐づけていない別VPCへ1台、同じ設定でVMを作成します。どちらも外部IPを持たず、IAP経由でのみSSHします。設定はBasic-Examples/04-compute-engineと同じです。

設定と実行
#

cd Basic-Examples/08-cloud-dns
cp terraform.tfvars.example terraform.tfvars
project_id = "your-project-id"
dns_name   = "example.internal."
record_ip  = "10.10.0.10"
terraform init
terraform fmt -check
terraform validate
terraform plan
terraform apply

VPC・Subnet・Firewallに加え、Zone・Record・VM2台が作成されます。合わせて12リソースです。

Apply complete! Resources: 12 added, 0 changed, 0 destroyed.

Outputs:

dns_name = "example.internal."
managed_zone_name = "tf-example-private-zone"
record_fqdn = "app.example.internal."
record_ip = "10.10.0.10"
vm_in_zone_name = "tf-example-dns-vm-in-zone"
vm_outside_zone_name = "tf-example-dns-vm-outside-zone"
zone = "asia-northeast1-a"

GCP側で確認する
#

gcloud dns managed-zones describe \
  "$(terraform output -raw managed_zone_name)" \
  --project=YOUR_PROJECT_ID
dnsName: example.internal.
name: tf-example-private-zone
privateVisibilityConfig:
  networks:
  - networkUrl: .../networks/tf-example-dns-vpc
visibility: private
gcloud dns record-sets list \
  --zone="$(terraform output -raw managed_zone_name)" \
  --name="$(terraform output -raw record_fqdn)" \
  --project=YOUR_PROJECT_ID
NAME                   TYPE  TTL  DATA
app.example.internal.  A     300  10.10.0.10

ZoneとRecordが存在することまでは確認できました。ただし、これは実際に名前解決できることを意味しません。

名前解決を実際に確認する
#

3つの経路で試します。

1. 紐づけたVPC内のVMから

gcloud compute ssh "$(terraform output -raw vm_in_zone_name)" \
  --zone="$(terraform output -raw zone)" \
  --tunnel-through-iap \
  --project=YOUR_PROJECT_ID \
  --command="getent hosts $(terraform output -raw record_fqdn)"
10.10.0.10      app.example.internal

解決できました。

2. 紐づけていない別VPCのVMから

gcloud compute ssh "$(terraform output -raw vm_outside_zone_name)" \
  --zone="$(terraform output -raw zone)" \
  --tunnel-through-iap \
  --project=YOUR_PROJECT_ID \
  --command="getent hosts $(terraform output -raw record_fqdn)"

出力なしで終了コード2(見つからない)でした。同じProject内でも、Zoneに紐づけていないVPCからは解決できません。

3. 手元の端末から(インターネット経由)

getent hosts app.example.internal.

こちらも出力なしで終了コード2でした。この「引けない」ことの確認が重要です。 Private Zoneを使う理由がそこにあるためです。

後片付けと注意点
#

terraform destroy
Destroy complete! Resources: 12 destroyed.

VMが2台起動したままだと課金が続きます。必ずdestroyしてください。 Private Zoneで使うDomain名が既存の社内DNSと競合しないよう注意します。

まとめ
#

  • VPCに限定したPrivate DNS Zoneを作成できる
  • FQDN末尾のDotをValidationできる
  • A Record、TTL、Private IPをTerraformで管理できる
  • Zoneに紐づけたVPCからは名前解決でき、紐づけていないVPCやインターネットからは解決できないことを実際に確認できる

参考資料
#

次回
#

次はSecret ManagerへSecretとSecret Versionを作成します。

Terraform-GoogleCloud - この記事は連載の一部です
パート 9: この記事

関連記事

Terraform StateをCloud Storage Remote Backendへ移行してみた
2 分
Terraform GoogleCloud CloudStorage
TerraformからGoogle Cloudへ接続してProject情報を取得してみた
3 分
Terraform GoogleCloud
TerraformでArtifact RegistryのDocker Repositoryを作成してみた
2 分
Terraform GoogleCloud Docker
TerraformでArtifact RegistryのコンテナをCloud Runへデプロイしてみた
2 分
Terraform GoogleCloud CloudRun ArtifactRegistry
TerraformでBigQuery DatasetとTableを作成してみた
2 分
Terraform GoogleCloud
TerraformでCloud KMSのKeyRingとCryptoKeyを作成してみた
2 分
Terraform GoogleCloud