簡介 Terraform
可以用來控制 GCP、AWS、Azure、Linode 等 infra 的框架。
Provider
-
安裝
provider
透過provider
來控制,而provider
底層其實是去串各家的 API,所以要自己寫provider
也是可以 -
provider
會定義平臺商提供的可控制服務,一般稱作resource
,例如:VM、權限角色、服務賬戶、Network Policy 之類的。id
是 resource instance 的唯一識別標準。
有狀態性
-
你可以把 Terraform 當做一次性的腳本使用,但如果照正常的方式使用,它是有狀態的
-
它會將狀態保存在
.tfstate
檔案裡,而這份檔案可以照個人所需搬移到想要的地方保存 -
目前 backend 是 GCS,也就是把
.tfstate
存在 (golden-dev) GCS 裡
有狀態性
-
.tfstate
會以resource
為單位,描述記錄真實世界的樣態。如果在執行的時候,真實世界的樣態與 .tfstate 不同(以id
作為兩者有沒有關聯的判準),而沒有被.tfstate
記錄,會在執行時報錯,但需要人為修正。 -
Terraform 有一系列跟狀態操作有關的 CLI,會在 進階:在 local debug 的方式 提及
執行 apply
時發生什麼事
假設我們現在有一個 my.tf
的檔案,是第一次執行,所以 .tfstate
是空的,然後真實世界已經有一些基本機器存在
執行 apply
時發生什麼事
執行完 apply
後會變成 .tfstate
有記錄第一次執行後的狀態,跟真實世界會有執行後的樣子
執行 apply
時發生什麼事
現在對 my.tf
做一些修改
執行 apply
時發生什麼事
執行完 apply
時,Terraform 會去比對 my.tf
跟 .tfstate
的差異,然後新增修改刪除
執行 apply
時發生什麼事
所以在做 apply
的時候,要很小心。
建議都使用 plan
去看執行結果。
佈署
在 GitLab CI Pipeline 裡 Run Pipeline,填上對應的變數
下面為一個完整的例子
變數說明
-
COMMAND
-
plan
與apply
-
CI 會準備 backend(下載
.tfstate
) -
如果有額外變數(service account 的 auth 相關變數)會處理變數檔案
-
CI 會忽略
plan
跟apply
後面所帶的參數,例如下apply -h
,-h
會被忽略
-
-
其他指令
-
CI 會準備 backend(下載
.tfstate
) -
但不會處理變數檔案。所以無法對現實環境做任何改變
-
CI 不會忽略後面所帶的參數,所以指令可帶參數
-
-
變數說明
-
WORKPATH
-
工作目錄
-
resources
資料夾裡的,一個 leaf node 的資料夾會有一個獨立的.tfstate
-
以圖為例,
resources/golden-armor2/iams
有一個.tfstate
,resources/local/tests
有一個.tfstate
-
我覺得
.tfstate
裡的resource
性質越接近越好管理,所以這樣設計。
-
變數說明
-
DESTROY
-
如果你的執行中牽扯「destroy」,想要通過 CI,必須要加上這個參數
-
DESTROY
= true
-
佈署
執行完就直接在 GitLab 上看結果就好。
-
注意事項:
-
Terraform 在建立 service account resource 的時候,會報錯。目前看起來是 TF 的問題。因為如果用 google cli 就不會。
-
已經有人開 bug issue ,看未來會不會解決。目前只能手動建立 service account,再做其他操作
-
進階:terraform 專案的 gitlab ci 怎麼運作?
如何開發 terraform 專案:modules
modules
底下,一個資料夾就一個 module
-
module
的觀念可以參考官網。簡而言之是可以復用設定檔,也可以將多個resource
的建立打包在一起。 -
我建議「每個
resources
資料夾的專案都基於modules
資料夾裡的module
」會比較好,因為復用性比較高。
一個簡單的 module 專案資料夾結構
-
README
- 建議可以寫一下,最好可以把遇到的 Error 都記錄起來,因為跟第三方的平臺打架,會用到很多莫名奇妙的規定 -
main.tf
- 主程式 -
variables.tf
- 定義這個 module 的 input -
version.tf
- 定義這個 module 的 provider 版本等等資訊 -
(
output.tf
) - 定義這個 module 會輸出什麼
除了整合 resource
,也可以嵌套其他 module
。圖例是嵌套 google 提供的 module
如何開發 terraform 專案:resources
resources
底下第一層資料夾是 gcp 的專案,第二層資料夾是資源的種類。
.terraform.lock.hcl
resources
裡的專案要有 .terraform.lock.hcl
跟一般的 lock 檔一樣,記錄安裝的 provider
的版本。要在引用 module
後,下 terraform init
才會有 lock 檔產出
variables.tf & provider.tf
variables.tf
與 provider.tf
也是必要的檔案,需要包含 gcp auth 所需的變數
ci-variables.sh
-
TERRAFORM_GCP_KEY
是操作 API 的 service account 的 GCP JSON KEY file,請從 Vaultci/terraform
找到對應的 KEY -
TERRAFORM_VARIABLES
是 terraform 所需 variables 的 file,請從 Vaultci/terraform
找到對應的 KEY
剩下的都是主程式,以 iams
的例子而言,裡面一個檔案對應一個 service account 或是 role。如果要改權限就改主程式。
開發的疑難雜症
在 README 有把一些開發時遇到的問題,記錄下來。如果遇到類似的問題可以參考
進階:在 local debug 的方式
我建議大家還是盡量在 GitLab CI 上 debug ,因為這樣比較不會不小心在 local 端動到 GCP 的環境。也不會在 git 的時候,把重要檔案 git 進去
不過有的時候,當 debug 到火大的時候,在 local debug 會比較快
在 local debug
-
到 Vault
ci/terraform
把相關 key files 都載下來 -
下載
BACKEND_CONFIG
到backend.conf
-
cd $WORKPATH
-
terraform init -backend-config=backend.conf
-
terraform plan -var-file=terraform.tfvars
處理 .tfstate
-
terraform 有一系列指令是關於
.tfstate
的操作 -
terraform state list
:列出現有記錄的資源 -
terraform state show
:列出資源的細節 -
terraform import
:用來導入沒有在.tfstate
裡的,真實世界的資源。雖然它很好用,但我覺得沒有規劃下導入所有東西會造成混亂,所以使用時要謹慎一點 -
terraform state rm
:刪除記錄中的資源。通常用在.tfstate
有誤的時候
進階:用 Vault 管理專案權限
-
因為
TERRAFORM_GCP_KEY
跟TERRAFORM_VARIABLES
都是填寫 Vault KEY,所以可以透過vault-env
來管理誰可以存取特定的環境跟特定種類的 GCP json key file 。如果要細分的話,可以把「管理權限的」跟「管理機器的」 service account 分開來,並只指定壯兔可以使用管理權限的 service account。 -
這樣「權限相關的」佈署就會只有壯兔可以佈署
Terraform
By 球魚
Terraform
- 328