簡介 Terraform
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10219969/截圖_2023-02-13_上午10.47.35.png)
可以用來控制 GCP、AWS、Azure、Linode 等 infra 的框架。
Provider
-
安裝
provider
透過provider
來控制,而provider
底層其實是去串各家的 API,所以要自己寫provider
也是可以 -
provider
會定義平臺商提供的可控制服務,一般稱作resource
,例如:VM、權限角色、服務賬戶、Network Policy 之類的。id
是 resource instance 的唯一識別標準。
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10219970/截圖_2023-02-13_下午12.11.10.png)
有狀態性
-
你可以把 Terraform 當做一次性的腳本使用,但如果照正常的方式使用,它是有狀態的
-
它會將狀態保存在
.tfstate
檔案裡,而這份檔案可以照個人所需搬移到想要的地方保存 -
目前 backend 是 GCS,也就是把
.tfstate
存在 (golden-dev) GCS 裡
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10219971/截圖_2023-02-13_下午12.05.58.png)
有狀態性
-
.tfstate
會以resource
為單位,描述記錄真實世界的樣態。如果在執行的時候,真實世界的樣態與 .tfstate 不同(以id
作為兩者有沒有關聯的判準),而沒有被.tfstate
記錄,會在執行時報錯,但需要人為修正。 -
Terraform 有一系列跟狀態操作有關的 CLI,會在 進階:在 local debug 的方式 提及
執行 apply
時發生什麼事
假設我們現在有一個 my.tf
的檔案,是第一次執行,所以 .tfstate
是空的,然後真實世界已經有一些基本機器存在
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10219974/截圖_2023-02-13_下午12.29.07.png)
執行 apply
時發生什麼事
執行完 apply
後會變成 .tfstate
有記錄第一次執行後的狀態,跟真實世界會有執行後的樣子
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10219977/截圖_2023-02-13_下午12.30.27.png)
執行 apply
時發生什麼事
現在對 my.tf
做一些修改
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10219978/截圖_2023-02-13_下午12.32.24.png)
執行 apply
時發生什麼事
執行完 apply
時,Terraform 會去比對 my.tf
跟 .tfstate
的差異,然後新增修改刪除
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10226831/截圖_2023-02-16_下午3.13.12.png)
執行 apply
時發生什麼事
所以在做 apply
的時候,要很小心。
建議都使用 plan
去看執行結果。
佈署
在 GitLab CI Pipeline 裡 Run Pipeline,填上對應的變數
下面為一個完整的例子
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10226834/截圖_2023-02-16_下午3.15.30.png)
變數說明
-
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
性質越接近越好管理,所以這樣設計。
-
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10219993/截圖_2023-02-13_下午5.47.12.png)
變數說明
-
DESTROY
-
如果你的執行中牽扯「destroy」,想要通過 CI,必須要加上這個參數
-
DESTROY
= true
-
佈署
執行完就直接在 GitLab 上看結果就好。
-
注意事項:
-
Terraform 在建立 service account resource 的時候,會報錯。目前看起來是 TF 的問題。因為如果用 google cli 就不會。
-
已經有人開 bug issue ,看未來會不會解決。目前只能手動建立 service account,再做其他操作
-
進階:terraform 專案的 gitlab ci 怎麼運作?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10219994/截圖_2023-02-14_上午9.52.26.png)
如何開發 terraform 專案:modules
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10219996/截圖_2023-02-13_下午5.59.36.png)
modules
底下,一個資料夾就一個 module
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10219997/截圖_2023-02-13_下午5.59.55.png)
-
module
的觀念可以參考官網。簡而言之是可以復用設定檔,也可以將多個resource
的建立打包在一起。 -
我建議「每個
resources
資料夾的專案都基於modules
資料夾裡的module
」會比較好,因為復用性比較高。
一個簡單的 module 專案資料夾結構
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10219998/截圖_2023-02-13_下午6.03.57.png)
-
README
- 建議可以寫一下,最好可以把遇到的 Error 都記錄起來,因為跟第三方的平臺打架,會用到很多莫名奇妙的規定 -
main.tf
- 主程式 -
variables.tf
- 定義這個 module 的 input -
version.tf
- 定義這個 module 的 provider 版本等等資訊 -
(
output.tf
) - 定義這個 module 會輸出什麼
除了整合 resource
,也可以嵌套其他 module
。圖例是嵌套 google 提供的 module
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10220002/截圖_2023-02-13_下午6.07.53.png)
如何開發 terraform 專案:resources
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10220004/截圖_2023-02-14_上午9.31.55.png)
resources
底下第一層資料夾是 gcp 的專案,第二層資料夾是資源的種類。
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10220006/截圖_2023-02-14_上午9.32.37.png)
.terraform.lock.hcl
resources
裡的專案要有 .terraform.lock.hcl
跟一般的 lock 檔一樣,記錄安裝的 provider
的版本。要在引用 module
後,下 terraform init
才會有 lock 檔產出
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10226916/截圖_2023-02-16_下午3.20.09.png)
variables.tf & provider.tf
variables.tf
與 provider.tf
也是必要的檔案,需要包含 gcp auth 所需的變數
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10220012/截圖_2023-02-14_上午9.36.59.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10226918/截圖_2023-02-16_下午3.21.41.png)
ci-variables.sh
-
TERRAFORM_GCP_KEY
是操作 API 的 service account 的 GCP JSON KEY file,請從 Vaultci/terraform
找到對應的 KEY -
TERRAFORM_VARIABLES
是 terraform 所需 variables 的 file,請從 Vaultci/terraform
找到對應的 KEY
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10226939/截圖_2023-02-16_下午3.31.02.png)
剩下的都是主程式,以 iams
的例子而言,裡面一個檔案對應一個 service account 或是 role。如果要改權限就改主程式。
![](https://s3.amazonaws.com/media-p.slid.es/uploads/356411/images/10226921/截圖_2023-02-16_下午3.20.09.png)
開發的疑難雜症
在 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
- 275