今日はTerraformでCloudflareのDNS設定をしっかり管理してみたので、その手順を記しておきます。
大前提
- backendがすでに用意・設定されている
- 以下のドキュメントを参考に設定しておきましょう!
構成
今回は複数のドメインを管理することも視野に入れて、このようなディレクトリ構成にしました。
-
example-com/
-
required_providers.tf
-
required_providers
をここで定義 - 若干腑に落ちないですが、各モジュールに定義しないと、
you must specify that source address in each module which requires that provider
と怒られてしまうのでモジュールごとに設定します
-
-
records.tf
- 各Aレコード、AAAAレコードなどの
cloudflare_record
をここに定義
- 各Aレコード、AAAAレコードなどの
-
vars.tf
- CloudflareのAPIキーなどの
variable
をここに定義(外側から渡せるようにする)
- CloudflareのAPIキーなどの
-
-
example-net/
-
example-com/
と同様の構成
-
-
main.tf
-
example-com/
とexample-net/
のmodule
をここから呼び出す
-
-
secrets.auto.tfvars
- CloudflareのAPIキーなどの秘匿情報をここに記載
-
.gitignore
に忘れずに入れておきましょう!
-
vars.tf
- secrets.tfvarsから指定する
variable
をここに指定
- secrets.tfvarsから指定する
-
provider.tf
- 親モジュールにCloudflareのmoduleを定義しておきます
を参考に、子モジュール内にprovider
を置かないようにしています。
各ドメインのモジュールの定義
こちらは定義しておかないと、you must specify that source address in each module which requires that provider
のエラーになってしまうので各モジュールに置いておきます。
(設定しておかないと、親モジュールの設定と反してhashicorp/cloudflare
を見に行くようになってしまいエラーになってしまうようです。ちなみにcloudflare/cloudflare
を見に行く設定が正しいです。)
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
}
}
}
variableを定義して外から設定値を渡せるようにしておきます。
zone_idは各ドメイン固有のものなので、locals
を使っても良いかと思いますが今回はvarsで外から渡すようにしました。
variable "cloudflare_zone_id" {
type = string
}
肝心のドメインの設定ですが、例としていくつかAレコードを設定する際の設定を記しておきます。
もちろん、toset
などの便利なものも使えるので必要に応じてlocalsなども活用してシンプルに設定していきましょう。
設定可能な項目についてはこちらの公式ドキュメントが参考になります。
# test.example.com
resource "cloudflare_record" "a-test" {
name = "test"
type = "A"
value = "1.1.1.1"
zone_id = var.cloudflare_zone_id
proxied = true
}
# test2.example.com
resource "cloudflare_record" "a-test2" {
# もちろんtosetも使えます!
for_each = toset([
"1.1.1.1",
"1.0.0.1",
])
name = "test2"
type = "A"
value = each.key
zone_id = var.cloudflare_zone_id
proxied = true
}
親モジュールの定義
各モジュールを削除したい時を配慮してproviderは子モジュール内ではなく親モジュールに定義しておきます。(削除時の厄介な挙動にぶち当たらないために)
また、バージョンの罠にハマらないようにしっかりバージョンは固定しておきます。
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "3.11.0"
}
}
}
provider "cloudflare" {
email = var.cloudflare_email
api_key = var.cloudflare_api_key
}
こちらはシンプルにzone_idだけ外から渡すようにしました。ここから各ドメインのモジュールを呼び出します。
module "example-com" {
source = "./example-com"
cloudflare_zone_id = "xxxxxxxxxxxxxxxxxxxxxxxx"
}
module "example-net" {
source = "./example-net"
cloudflare_zone_id = "xxxxxxxxxxxxxxxxxxxxxxxx"
}
シークレットはsecrets.auto.tfvars
に定義しておきます。(忘れずに.gitignoreに入れておきましょう)
ちなみに、通常tfvarsファイルは-var-file
オプションで明示的に渡してあげる必要がありますが、auto.tfvars
にすることで指定しなくても自動的に読み込むようにできます。
cloudflare_email = "<YOUR_CF_EMAIL_HERE>"
cloudflare_api_key = "<YOUR_CF_API_KEY_HERE>"
tfvarsから読み出したい設定はvars.tfに置いておきます。
variable "cloudflare_email" {
type = string
}
variable "cloudflare_api_key" {
type = string
}
さいごに
Terraformからapplyした後に、Cloudflareのダッシュボードを見に行くと設定が反映されているのが確認出来ると思いますが、Terraformから作成したリソースの編集保護などの機能はないためそのまま普通に編集出来てしまいます。
編集してしまうとそのリソースはTerraform側と差分が生じてエラーになってしまうのでうっかり触らないように注意しましょう。