前言

隨著用 Terraform 管理的資源越來越多,tfstate 也會跟著膨脹,terraform plan 就會越來越慢,等的時候很容易就開始滑起網路了。

根本解法是把 tfstate 切分成適當的粒度,不過如果想用更省事的權宜技巧,我之前曾寫過介紹 terraform plan --parallelism 的文章。

只是這個方法會因環境而異,有時有效、有時無效,並不是很可靠。

雖然很抱歉要奪走你滑網路的藉口,但從 Terraform v1.17 之後,多了一個 terraform plan -minimal-refresh 參數,可以把 refresh 的範圍最小化,進而加快 plan 的速度。
※ 截至本文撰寫時,Terraform v1.17 仍是 beta 版。

先簡單補充一下 terraform plan 的機制。大家常以為 terraform plan 是在比較前一次保存的 tfstate 和 tf 檔案的差異,但實際上,為了偵測前一次保存的 tfstate 與真實資源之間的 drift,會先經過一個叫做 refresh 的階段,接著再比較 refresh 後、記憶體中的 tfstate 與 tf 檔案的差異。若有在 Terraform 管理外修改資源而產生 drift,refresh 階段的差異會在 plan 中以「Objects have changed outside of Terraform」之類的形式區分出來,這樣就能察覺到退化。

不過,當 tfstate 膨脹之後,這個 refresh 階段就會很重,所以也有人會用 terraform plan -refresh=false 這種做法,在承擔一些風險的前提下把 refresh 關掉。

新加入的 terraform plan -minimal-refresh 則是不會無條件 refresh 所有資源,而是先根據前一次保存的 tfstate 找出與 tf 檔案有差異的資源,再針對那些點對點地進行 refresh,把 refresh 的對象限制在會更新的資源上,藉此在避免 drift 帶來的退化風險的同時,加快 plan。

前言有點長,但總之就直接來試試看。

環境

我的環境如下:

  • Terraform: v1.17.0-beta1
  • Terraform AWS Provider: v6.63.0

截至本文撰寫時,Terraform v1.17 仍是 beta 版,請多加留意。

試看看

由於會受呼叫的 API、網路拓樸等因素影響,時間測量結果只能當作參考值;
不過先拿一個大小剛好適合驗證、而且 refresh 似乎會很慢的 Route53 資源,大約有 200 個的 tfstate 來測試。

為了比較,先用 Terraform v1.16.2 正常執行 terraform plan 並計時。在我的環境中大約花了 50 秒。

$ terraform --version
Terraform v1.16.2
on darwin_arm64
+ provider registry.terraform.io/hashicorp/aws v6.63.0

$ time terraform plan

xxx: Refreshing state... [id=xxx]
xxx: Refreshing state... [id=xxx]
xxx: Refreshing state... [id=xxx]
xxx: Refreshing state... [id=xxx]

(snip.)

No changes. Your infrastructure matches the configuration.

terraform plan  5.40s user 1.43s system 13% cpu 49.698 total

由於結果會因狀態而有些波動,順便也量一下 Terraform v1.17.0-beta1 在一般狀態下的表現。大約是 45 秒。以我的環境來看,Route53 的 API 大概就有這樣的波動。

$ terraform --version
Terraform v1.17.0-beta1
on darwin_arm64
+ provider registry.terraform.io/hashicorp/aws v6.63.0

$ time terraform plan

xxx: Refreshing state... [id=xxx]
xxx: Refreshing state... [id=xxx]
xxx: Refreshing state... [id=xxx]
xxx: Refreshing state... [id=xxx]

(snip.)

No changes. Your infrastructure matches the configuration.

terraform plan  5.98s user 1.50s system 16% cpu 45.118 total

接著來試本題的 terraform plan -minimal-refresh
先從完全沒有改動程式碼的情況開始。

$ time terraform plan -minimal-refresh

No changes. Your infrastructure matches the configuration.

terraform plan -minimal-refresh  3.16s user 0.53s system 103% cpu 3.549 total

因為一些原因沒辦法貼完整 log,不過沒有出現「Refreshing state...」的 log,大約 3~4 秒就結束了。超快耶。

接著隨便在 tf 檔案裡改一下資源定義,讓它只出現 1 個資源的 diff。

$ time terraform plan -minimal-refresh

xxx: Refreshing state... [id=xxx]

(snip.)

Plan: 0 to add, 1 to change, 0 to destroy.

terraform plan -minimal-refresh  3.18s user 0.54s system 91% cpu 4.058 total

4 秒就結束了。超快耶。
只有對應的那 1 個資源出現了「Refreshing state...」。

我也稍微確認一下行為:如果某個資源有變更,refresh 是否會波及其依賴資源。

$ time terraform plan -minimal-refresh

xxx: Refreshing state... [id=xxx]
xxx: Refreshing state... [id=xxx]
xxx: Refreshing state... [id=xxx]

(snip.)

Plan: 21 to add, 0 to change, 21 to destroy.

terraform plan -minimal-refresh  3.55s user 0.61s system 79% cpu 5.206 total

雖然有 21 個資源的差異,但 5 秒就結束了。
因為 log 輸出會變很長,所以省略了,不過包含相依資源在內,總共會對受影響的 21 個資源顯示「Refreshing state...」。看起來有正常運作。

如果想預設啟用,可以把它設定到環境變數 TF_CLI_ARGS_plan

export TF_CLI_ARGS_plan="-minimal-refresh"

如果是 apply,則是設定環境變數 TF_CLI_ARGS_apply

結語

我試用了 Terraform v1.17 新增的 terraform plan -minimal-refresh

在避免 Terraform 管理外 drift 帶來的退化風險的同時,又能兼顧 plan 加速,這算是一個很務實的平衡選擇,感覺還不錯吧。

-minimal-refresh 和一般 refresh 的取捨還有討論空間;例如,可以把平常本機使用改成 -minimal-refresh,而 CI/CD 則照常跑一般的 plan。或者如果你想用 -minimal-refresh 來加速 CI/CD,也可以每天針對 main 分支的所有資源跑一次帶有一般 refresh 的 plan 來做 drift 檢查,總之就各自找個合適的折衷點吧。


原文出處:https://qiita.com/minamijoyo/items/92c094b554d090b54a17


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝30   💬1  
441
🥈
我愛JS
3
🥉
NewsData
2
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登