上面講解 Terraform 的基本操作流程,提供範本原始碼,以及一步一步導入的詳細步驟。各位應該都可以依照上面幾篇的說明,開始快樂的使用 Terraform 了。
而當使用 Terraform 的規模越來越大,管理的資料越來越多時,開始會出現一些問題,例如重複的 terraform code 越來越多,協同工作 review 不太容易,state 的內容管理與鎖管理,等等。這些問題可以透過一些工作流程的改>進,或是導入新的小工具,來改善工作效率。
接下來筆者推薦幾個心得與工具,希望能提升使用 Terraform 的效率與產值
以下幾篇文章,適合已經使用過 terraform 一點時間,有經驗的團隊,並打算更大規模導入 terraform,正在尋求改善的方向。
當團隊已經開始大規模使用 terraform,tf 檔案越來越多。我們為了增加程式碼的重複利用性,會使用 terraform module 將常用的 tf 檔案封裝。
使用一段時間 terraform ,很快就會發現的第一個問題是:不論怎麼從 tf 檔案中提取重複部分,做成 module,還是有很多部分的 tf code 是完全重複的,例如:
Terraform 的語法要求上面這些參數都明確的定義,這讓整個 module 或資料夾的描述非常清楚。但會處就是,這些描述的參數道出都是,而且不斷的重複,每個 module 或資料夾都要提供,不然在 terraform validate 時會因為應
提供參數未提供,導致錯誤。雖然立意良好,但卻嚴重違反 DRY (Don't Repeat Yourself) 的原則
有沒有可能用其他工具,避免這些重複的參數,backend,provider 等等?
推薦有大量使用的團隊,直接使用 Terragrunt 這款工具。
他是一層 terraform 的 wrapper
Terragrunt 有許多功能,例如
導入 Terragrunt 可以避免重複代碼,降低維護成本,提升生產效率
上述說明可能不太清楚,我們實際看範例,以前幾篇我們使用的範例 repository 為例子,把 gcp 的資料夾目錄應該長這樣:
可以很清楚見到底下幾個東西不斷重複
由於 my-new-project, gke-playground, national-team-5g 三個專案是獨立的專案,各自可以獨立運行。但其實同屬於同公司的專案,可能許多內容都是重複的。
tree gcp
gcp
├── README.md
├── Makefile
├── my-new-project/
│ ├── terraform.tf
│ ├── terraform.tfvars
│ ├── variable.tf
│ └── provider.tf
├── gke-playground/
│ ├── terraform.tf
│ ├── terraform.tfvars
│ ├── variable.tf
│ └── provider.tf
├── national-team-5g/
│ ├── dev
│ │ ├── terraform.tf
│ │ ├── terraform.tfvars
│ │ ├── variable.tf
│ │ └── provider.tf
│ ├── stag
│ │ ├── terraform.tf
│ │ ├── terraform.tfvars
│ │ ├── variable.tf
│ │ └── provider.tf
│ └── prod
│ ├── terraform.tf
│ ├── terraform.tfvars
│ ├── variable.tf
│ └── provider.tf
├── templates/
└── modules/
可以很清楚見到底下幾個東西不斷重複
這邊的目的,是有系統化的處理這些重複的代碼
gcp
├── terraform.tfvars # gcp 共用的參數
├── terragrunt.hcl # gcp 共用的程式碼
├── national-team-5g/
│ ├── terraform.tfvars # national-team-5g 共用的參數
│ ├── terragrunt.hcl # national-team-5g 共用的程式碼
│ ├── dev
│ │ ├── terraform.tfvars # dev 的參數
│ │ └── terragrunt.hcl # dev 環境自己的程式碼
│ ├── staging
│ │ ├── terraform.tfvars # staging 的參數
│ │ └── terragrunt.hcl # staging 環境自己的程式碼
│ └── prod
│ ├── terraform.tfvars # prod 的參數
│ └── terragrunt.hcl # prod 環境自己的程式碼
差異非常多是吧,但這邊只是從資料目錄結構看,其實如果從 tf 檔案內部的程式碼看,裡面的代碼更是精簡到不行,用起來非常的爽XD
chmod u+x terragrunt
mv terragrunt /usr/local/bin/terragrunt
Terragrunt 的 DRY feature,其實內容都大同小異
├── national-team-5g/
│ ├── dev
│ │ ├── terraform.tfvars # staging 的參數
│ │ └── provider.tf
│ ├── stag
│ │ ├── terraform.tfvars # staging 的參數
│ │ └── provider.tf
│ └── prod
│ ├── terraform.tfvars # prod 的參數
│ └── provider.tf
例如
national-team-5g/dev/provider.tf
provider "google" {
version = "~>v3.25.0"
credentials = file(var.credential_json)
project = var.project
region = var.region
}
改成
national-team-5g/dev/terragrunt.hcl
generate "provider" {
path = "provider.tf"
if_exists = "overwrite"
contents = <<EOF
provider "google" {
version = "~>v3.25.0"
credentials = file(var.credential_json)
project = var.project
region = var.region
}
EOF
}
執行
cd national-team-5g/dev
terragrunt plan
關於參數
tf 檔案,在許多 block 中禁止使用 variable,這層限制有其考量,但是缺點是造成許多 hard coded 的程式碼。
Terragrunt 產生的程式碼,由於是在 terragrunt 執行後,terraform 執行前,因次沒有這層限制,可以做許多事情,例如 code generate 以及 function 運算,terragrunt 提供許多內建 function,這邊只介紹常用幾個。
範例兩個檔案
project/dev/terraform.hcl
include {
path = find_in_parent_folders()
}
project/terraform.hcl
env = path_relative_to_include()
最後 parse 後的結果
project/dev/terraform.hcl
env = "dev"
做了兩件事
Terragrunt 可以精簡程式碼,大福提升生產效率,然而在還不熟悉 terraform 核心功能之前,不建議過早導入,會導致多餘的學習成本。