Cloudflare PagesのTerraform Moduleを作った
Cloudflare Pagesを簡単にセットアップしたい
Cloudflare Pagesは、簡単に静的ファイルをホスティングできるので便利で、いろいろなテスト的な使い方をしているのですが、毎回コンソールでセットアップするのが手間に感じたので、Terraformの勉強も兼ねて、TerraformでCloudflare Pagesプロジェクトとその関連リソースを管理するようにしました。
最終的な構成
$ tree .
.
├── README.md
└── cloudflare
├── main.tf
├── modules
│ └── pages
│ ├── README.md
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
├── terraform.tfstate
├── terraform.tfstate.backup
├── terraform.tfvars
└── variables.tf
3 directories, 10 files
上記が最終的なディレクトリ構造です。
将来的にはcloudflare以外のリソースも管理することを考えて、プロジェクトルートにcloudflare
ディレクトリを作成し、その中にCloudflare関連のmoduleを配置するようにしました。
Pages Moduleについて
普段Cloudflare Pagesを使うときに、GitHub連携をさせないパターンが多いので、今回はとてもシンプルに空のプロジェクトと、カスタムドメインの設定とそれに伴うDNSの設定ができるようなModuleにしました。
完成形としては以下のとおりです。
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 4.0"
}
}
}
resource "cloudflare_pages_project" "cloudflare_pages" {
account_id = var.cloudflare_account_id
name = var.project_name
production_branch = var.production_branch
}
resource "cloudflare_pages_domain" "cloudflare_pages" {
account_id = var.cloudflare_account_id
project_name = cloudflare_pages_project.cloudflare_pages.name
domain = var.custom_domain
}
resource "cloudflare_record" "cloudflare_pages" {
zone_id = var.cloudflare_zone_id
name = var.custom_domain
value = cloudflare_pages_project.cloudflare_pages.subdomain
type = "CNAME"
proxied = true
}
variable "cloudflare_account_id" {
description = "Cloudflare account ID"
type = string
nullable = false
}
variable "project_name" {
description = "Cloudflare pages project"
type = string
nullable = false
}
variable "production_branch" {
description = "Production branch for Cloudflare pages project"
type = string
default = "main"
nullable = true
}
variable "custom_domain" {
description = "Custom subdomain for Cloudflare pages project"
type = string
nullable = false
}
variable "cloudflare_zone_id" {
description = "Cloudflare zone ID"
type = string
nullable = false
}
output "name" {
description = "Cloudflare pages project name"
value = cloudflare_pages_project.cloudflare_pages.name
}
output "default_url" {
description = "Cloudflare pages project default URL"
value = cloudflare_pages_project.cloudflare_pages.subdomain
}
output "custom_url" {
description = "Cloudflare pages project custom URL"
value = cloudflare_record.cloudflare_pages.name
}
躓いたところ
terraform applyに失敗する
最初は、terraform apply
を実行すると、Cloudflare Pagesにカスタムドメインを設定するためには、Cloudflare Pagesのプロジェクトが必要だというエラーが出てきてしまいました。
これは、はじめは以下のように各リソースに対して値を与えてそれぞれのリソースを作成するようにしていたため、Cloudflare Pagesのプロジェクトが作成される前に、カスタムドメインの設定が行われてしまっていたためです。
resource "cloudflare_pages_project" "cloudflare_pages" {
account_id = var.cloudflare_account_id
name = var.project_name
production_branch = var.production_branch
}
resource "cloudflare_pages_domain" "cloudflare_pages" {
account_id = var.cloudflare_account_id
project_name = var.project_name
domain = var.custom_domain
}
resource "cloudflare_record" "cloudflare_pages" {
zone_id = var.cloudflare_zone_id
name = var.custom_domain
value = cloudflare_pages_project.cloudflare_pages.subdomain
type = "CNAME"
proxied = true
}
これを修正して、Cloudflare Pagesのプロジェクトリソースのoutputを参照するようにしたところ依存関係が解決し、正常に適用できるようになりました。
ちなみにこれ以外にもdepends_on
を使う方法もあるようですが、今回はoutputを使う方法で解決しました。
Inconsistent dependency lock fileエラー
最初は、terraform plan
を実行すると、以下のエラーが出てしまいました。
Error: Inconsistent dependency lock file
│
│ The following dependency selections recorded in the lock file are inconsistent with the current configuration:
│ - provider registry.terraform.io/hashicorp/cloudflare: required by this configuration but no version is selected
│
│ To update the locked dependency selections to match a changed configuration, run:
│ terraform init -upgrade
hashcorp/cloudflare
のバージョンが指定されていないというエラーですが、terraform init -upgrade
を実行しても解決しませんでした。
実際に使用しているのはcloudflare/cloudflare
なので、その旨をmoduleのmain.tf
に記載して解決しました。
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 4.0"
}
}
}
まとめ
とりあえずTerraformでリソース管理デビューを果たすことができました。今後は、他のリソースも管理できるようにしていきたいと思います。
多分、Terraformのベストプラクティスとかもあると思うので、それも勉強していきたいですね。
ありがとうございました。
Discussion