簡介 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 去看執行結果。

如何用 terraform 專案管理 GCP 權限

參考 README

resources 資料夾裡修改權限設定,參考 如何開發 terraform 專案:resources

佈署

在 GitLab CI Pipeline 裡 Run Pipeline,填上對應的變數

下面為一個完整的例子

變數說明

  • COMMAND

    • planapply

      • CI 會準備 backend(下載 .tfstate

      • 如果有額外變數(service account 的 auth 相關變數)會處理變數檔案

      • CI 會忽略 planapply 後面所帶的參數,例如下 apply -h-h 會被忽略

    • 其他指令

      • CI 會準備 backend(下載 .tfstate

      • 但不會處理變數檔案。所以無法對現實環境做任何改變

      • CI 不會忽略後面所帶的參數,所以指令可帶參數

變數說明

  • WORKPATH

    • 工作目錄

    • resources 資料夾裡的,一個 leaf node 的資料夾會有一個獨立的 .tfstate

    • 以圖為例,resources/golden-armor2/iams 有一個 .tfstateresources/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.tfprovider.tf 也是必要的檔案,需要包含 gcp auth 所需的變數

ci-variables.sh

  • TERRAFORM_GCP_KEY 是操作 API 的 service account 的 GCP JSON KEY file,請從 Vault ci/terraform 找到對應的 KEY

  • TERRAFORM_VARIABLES 是 terraform 所需 variables 的 file,請從 Vault ci/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_CONFIGbackend.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_KEYTERRAFORM_VARIABLES 都是填寫 Vault KEY,所以可以透過 vault-env 來管理誰可以存取特定的環境跟特定種類的 GCP json key file 。如果要細分的話,可以把「管理權限的」跟「管理機器的」 service account 分開來,並只指定壯兔可以使用管理權限的 service account。

  • 這樣「權限相關的」佈署就會只有壯兔可以佈署

Terraform

By 球魚

Terraform

  • 343