モチベ
インフラの学習のため何か良い題材がないかと探していたが、そういえばCloude Flareで管理しているDNSをTerraformに吸収させていないなではないかと思いやることにした。
今後はAWSなどインフラで遊んで作った成果物はTerraformに吸収させるようにしよう。
API Tokneの作成
Cloudflareの公式にあるTerraformを用いた管理のチュートリアルにAPI Tokneを使用する箇所があるので、作成する。
https://developers.cloudflare.com/terraform/tutorial/track-history/
Claudeflareの公式が出しているAPI Tokenの作成チュートリアルを読みながら作成していく。
https://developers.cloudflare.com/fundamentals/api/get-started/create-token/
- profile を選択する

- API Tokensを選択する

- Create Tokenを選択する

- 今回はDNSを取得したいのでEdit zone DNSを選択する

- Zoneリソースは特定のDNSのzone(今回は
shooonng.com)に絞る。

- 指定したZoneで問題がなければ
Create Tokenをクリックする

- Tokenが払い出される

- Curlが通るか確認
on ☸ admin on kubernetes-the-hard-way in default () dotfile on master
♥ ❯ curl "https://api.cloudflare.com/client/v4/user/tokens/verify" \
-H "Authorization: Bearer AmO_qsxxxxxxxxxxxxxxx" | jq .
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 184 0 184 0 0 892 0 --:--:-- --:--:-- --:--:-- 888
{
"result": {
"id": "f8a950762362ca1866ab89d675bca82e",
"status": "active"
},
"success": true,
"errors": [],
"messages": [
{
"code": 10000,
"message": "This API Token is valid and active",
"type": null
}
]
}
on ☸ admin on kubernetes-the-hard-way in default () dotfile on master
♥
importしてみる
以下の2つを実施する。
- state反映用のファイルを作成する
- stateに反映してimportする
先に以下3つをexportして変数として登録しておく。
- CLOUDFLARE_EMAIL - Cloudflareに登録しているメールアドレス
- CLOUDFLARE_API_KEY - 上記で取得したAPI Token
- CLOUDFLARE_ZONE_ID - CloudflareのZone ID
state反映用のファイルを作成する
ファイルを作成するにはcf-terraformingというツールを用いる
cf-terraformingのGitHub 公式のチュートリアル
公式のチュートリアルだとcf-tarraformingのver5.0のプロバイダーは cloudflare_record を定義していないためエラーが発生する。
on ☸ admin on kubernetes-the-hard-way in default () infra-terraform/cloudflare on master [!?] 🏎💨 v1.14.3default
♥ ❯ cf-terraforming generate --email $CLOUDFLARE_EMAIL --token $CLOUDFLARE_API_TOKEN -z d2ff8f58d8813dd4470dfa55f09540b3 --resource-type cloudflare_record > importing-example.tf
INFO[0000] terraform-binary-path flag not set
INFO[0000] Using explicit Terraform install path terraform-install-path=.
INFO[0004] detected provider registry=registry.terraform.io/cloudflare/cloudflare version=5.15.0
WARN[0004] Unsupported terraform v5 provider resource resource=cloudflare_record
on ☸ admin on kubernetes-the-hard-way in default () infra-terraform/cloudflare on master [!?] 🏎💨 v1.14.3default took 5s
♥
cloudflare_dns_record に変更すると動くようになる
最終的に以下のようなコマンドになる
cf-terraforming generate --email $CLOUDFLARE_EMAIL --token $CLOUDFLARE_API_TOKEN -z d2ff8f58d8813dd4470dfa55f09540b3 --resource-type cloudflare_dns_record > importing-example.tf
出来上がったファイルは以下のようになっている。
on ☸ admin on kubernetes-the-hard-way in default () infra-terraform/cloudflare on master [!?] 🏎💨 v1.14.3default took 3s
♥ ❯ cat importing-example.tf
resource "cloudflare_dns_record" "terraform_managed_resource_c4e7f3d4b45b022a456c762a04868488_0" {
content = "_1e50acc97e023be2f97dc14014edac0b.jkddzztszm.acm-validations.aws"
name = "_6e2510b7de5c2f6a659fa878d7fe59f2.shooonng.com"
proxied = false
tags = []
ttl = 1
type = "CNAME"
zone_id = "d2ff8f58d8813dd4470dfa55f09540b3"
settings = {
flatten_cname = false
}
}
resource "cloudflare_dns_record" "terraform_managed_resource_54b5da91eeb0ec9e09d924fc84c2cb5c_1" {
content = "d2474kqaq8cosu.cloudfront.net"
name = "myblog.shooonng.com"
proxied = false
tags = []
ttl = 1
type = "CNAME"
zone_id = "d2ff8f58d8813dd4470dfa55f09540b3"
settings = {
flatten_cname = false
}
}
on ☸ admin on kubernetes-the-hard-way in default () infra-terraform/cloudflare on master [!?] 🏎💨 v1.14.3default
♥
stateに反映してimportする
まだtfstateに反映できていないので、 terraform plan して反映する。
ローカルの設定をimportするため再び cf-terraformingを使用する。コマンドは以下を使用する。
cf-terraforming import --resource-type "cloudflare_dns_record" --email $CLOUDFLARE_EMAIL --key $CLOUDFLARE_API_KEY --zone $CLOUDFLARE_ZONE_ID
terraform import 用のコマンドが作成されるので実行してimportする。
on ☸ admin on kubernetes-the-hard-way in default () infra-terraform/cloudflare on master [!?] 🏎💨 default
♥ ❯ tf import cloudflare_dns_record.terraform_managed_resource_c4e7f3d4b45b022a456c762a04868488_0 d2ff8f58d8813dd4470dfa55f09540b3/c4e7f3d4b45b022a456c762a04868488
cloudflare_dns_record.terraform_managed_resource_c4e7f3d4b45b022a456c762a04868488_0: Importing from ID "d2ff8f58d8813dd4470dfa55f09540b3/c4e7f3d4b45b022a456c762a04868488"...
cloudflare_dns_record.terraform_managed_resource_c4e7f3d4b45b022a456c762a04868488_0: Import prepared!
Prepared cloudflare_dns_record for import
cloudflare_dns_record.terraform_managed_resource_c4e7f3d4b45b022a456c762a04868488_0: Refreshing state... [id=c4e7f3d4b45b022a456c762a04868488]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
on ☸ admin on kubernetes-the-hard-way in default () infra-terraform/cloudflare on master [!?] 🏎💨 v1.14.3default took 2s
♥ ❯ tf import cloudflare_dns_record.terraform_managed_resource_54b5da91eeb0ec9e09d924fc84c2cb5c_1 d2ff8f58d8813dd4470dfa55f09540b3/54b5da91eeb0ec9e09d924fc84c2cb5c
cloudflare_dns_record.terraform_managed_resource_54b5da91eeb0ec9e09d924fc84c2cb5c_1: Importing from ID "d2ff8f58d8813dd4470dfa55f09540b3/54b5da91eeb0ec9e09d924fc84c2cb5c"...
cloudflare_dns_record.terraform_managed_resource_54b5da91eeb0ec9e09d924fc84c2cb5c_1: Import prepared!
Prepared cloudflare_dns_record for import
cloudflare_dns_record.terraform_managed_resource_54b5da91eeb0ec9e09d924fc84c2cb5c_1: Refreshing state... [id=54b5da91eeb0ec9e09d924fc84c2cb5c]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
on ☸ admin on kubernetes-the-hard-way in default () infra-terraform/cloudflare on master [!?] 🏎💨 v1.14.3default took 2s
♥
terraform plan をして差分がないことを確認する。
on ☸ admin on kubernetes-the-hard-way in default () infra-terraform/cloudflare on master [!?] 🏎💨 v1.14.3default
♥ ❯ tf plan
cloudflare_dns_record.terraform_managed_resource_54b5da91eeb0ec9e09d924fc84c2cb5c_1: Refreshing state... [id=54b5da91eeb0ec9e09d924fc84c2cb5c]
cloudflare_dns_record.terraform_managed_resource_c4e7f3d4b45b022a456c762a04868488_0: Refreshing state... [id=c4e7f3d4b45b022a456c762a04868488]
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
on ☸ admin on kubernetes-the-hard-way in default () infra-terraform/cloudflare on master [!?] 🏎💨 v1.14.3default took 2s
♥
最終的なファイル構成や中身
ファイル構成は以下のようになる。
on ☸ admin on kubernetes-the-hard-way in default () infra-terraform on master [!?]
♥ ❯ tree cloudflare
cloudflare
├── backend.tf
├── dns.tf
├── env.sh
├── provider.tf
├── terraform.tfvars
└── variables.tf
1 directory, 6 files
on ☸ admin on kubernetes-the-hard-way in default () infra-terraform on master [!?]
♥
backend.tfはs3を指定して、そこにtfstateを保管している。
terraform {
backend "s3" {
region = "ap-northeast-1"
bucket = "shooonng-iac-tfstate"
key = "cloudflare/terraform.tfstate"
use_lockfile = true
}
}
cloudflareのDNSは以下のようにしている。名前が変更できないのがちょっと残念だ。
resource "cloudflare_dns_record" "terraform_managed_resource_c4e7f3d4b45b022a456c762a04868488_0" {
content = "_1e50acc97e023be2f97dc14014edac0b.jkddzztszm.acm-validations.aws"
name = "_6e2510b7de5c2f6a659fa878d7fe59f2.shooonng.com"
proxied = false
tags = []
ttl = 1
type = "CNAME"
zone_id = var.zone_id
settings = {
flatten_cname = false
}
}
resource "cloudflare_dns_record" "terraform_managed_resource_54b5da91eeb0ec9e09d924fc84c2cb5c_1" {
content = "d2474kqaq8cosu.cloudfront.net"
name = "myblog.shooonng.com"
proxied = false
tags = []
ttl = 1
type = "CNAME"
zone_id = var.zone_id
settings = {
flatten_cname = false
}
}
variables.tfは以下のように記載した。詳しい値はtfvarsに書いている。 もう少し上手く使う方法を模索したいな。
variable "zone_id" {
description = "Cloudflare Zone ID"
type = string
sensitive = true
}
variable "account_id" {
description = "Cloudflare Account ID"
type = string
sensitive = true
}
variable "domain" {
description = "Domain name"
type = string
default = "example.com"
}
provider.tfは以下のように記載した。 ただ変数をexportすることが多かったのであまり上手い使い方ができてないかもなと思っている。
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 5"
}
}
}
provider "cloudflare" {
# Cloudflare email saved in $CLOUDFLARE_EMAIL
# Cloudflare API token saved in $CLOUDFLARE_API_TOKEN
}
まとめ
チュートリアルを読めばcloudflareをterraformに吸収するのはそこまで難しくなかった。 これからは何か変更がある時はterraformをいじれば良いので管理が楽になったと思う。
また何か外部でサービスを使っていてterraformで構成を吸収できるならやりたいな。