之前透過 Terraform 在 GCP 上建立外部和內部的全球 IP,延續上一篇的文,我們要把 Global IP 在 CloudFlare 上做 DNS 解析綁定,使我們一般在瀏覽網頁時能夠輸入網址進行訪問。
查看 terraform cloudflare_record 官方文件 可以看到與 dns 的相關設定會使用這個 resource。 而要操作 CloudFlare 必須取得要調整的 Website zone id 與操作者的 api token
接下來開始撰寫 terraform 代碼
resource "cloudflare_record" "example" {
zone_id = "your_zone_id"
name = "terraform"
type = "A"
comment = "Managed by Terraform"
value = "192.0.2.1"
proxied = false
ttl = 3600
}
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "4.28.0"
}
}
}
provider "cloudflare" {
api_token = "your_api_token"
}
接著執行 terraform 指令部署上去就可以到 CloudFlare 頁面上查看是否建立成功。
這部分需要提前設定好狀態檔
狀態檔如下
接著修改 terraform 代碼,在代碼的部分使用 data 去取得 GCS 上的 Global IP 狀態檔
resource "cloudflare_record" "example" {
zone_id = "your_zone_id"
name = "terraform"
type = "A"
comment = "Managed by Terraform"
# 添加這行取得IP
value = data.terraform_remote_state.global_ip.outputs.global_ip_info.address
proxied = false
ttl = 3600
}
# 來源設定
data "terraform_remote_state" "global_ip" {
backend = "gcs"
config = {
bucket = "alan-test-terraform"
prefix = "gcp/global-ip"
}
}
先建立一個資料夾叫做 modules,並依序建立以下檔案放在這個資料夾
variables.tf
variable "cloudflare_api_token" {
type = string
}
variable "zone_id" {
type = string
}
variable "name" {
type = string
}
variable "type" {
type = string
}
variable "comment" {
type = string
}
variable "allow_overwrite" {
type = bool
}
variable "records" {
type = list(object({
value = optional(string)
proxied = optional(bool, false)
ttl = optional(number, 1)
}))
}
這裡補充說明一下 optional
函數,這個函數的主要功能是指定這些屬性是可選的,並且當未使用時,第二個欄位則是這個屬性的預設值。
main.tf
resource "cloudflare_record" "dns_records" {
for_each = { for idx, rec in var.records : idx => rec }
zone_id = var.zone_id
name = var.name
type = var.type
comment = var.comment
allow_overwrite = var.allow_overwrite
value = each.value.value
ttl = each.value.ttl
proxied = each.value.proxied
}
outputs.tf
這裡的用意主要是看想輸出 resource 的哪些值,並將這個 output 的資料結構取名為 dns_records_details
output "dns_records_details" {
value = [for r in cloudflare_record.dns_records : {
address = r.value
name = r.name
type = r.type
ttl = r.ttl
proxied = r.proxied
}]
}
provider.tf
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "4.28.0"
}
}
}
provider "cloudflare" {
api_token = var.cloudflare_api_token
}
接著在主目錄建立自己的設定檔
main.tf
module "cloudflare_dns_records" {
source = "./modules"
zone_id = "your-zone-id"
cloudflare_api_token = "your-api-token"
name = "terraform"
type = "A"
comment = "Managed by Terraform"
allow_overwrite = false
records = [{
value = data.terraform_remote_state.global_ip.outputs.global_ip_info.address
proxied = false
ttl = null
}
]
}
如果有需要新增多筆 records,可以在根目錄
data.tf
data "terraform_remote_state" "global_ip" {
backend = "gcs"
config = {
bucket = "alan-test-terraform"
prefix = "gcp/global-ip"
}
}
這裡因為有使用到 gcp 的 global ip,因此需要定義 data.tf
outputs.tf
output "dns_records_list" {
value = module.cloudflare_dns_records.dns_records_details
}
這裡的 output 用意是將 modules 裡的 output 拿來用,因為我們執行的環境是在根目錄下執行,而 modules 裡的 output 只能在內部被定義與訪問,如果要將 modules 的 output 拿來外部使用,必須在要引用的地方定義好 output 值,這樣就能讓你在根目錄下執行 Terraform 時能夠使用 modules 的 output 值。
provider.tf
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "4.28.0"
}
}
}
這樣就已經完成簡單的模組化了。 完整代碼在這裡