iT邦幫忙

2021 iThome 鐵人賽

DAY 26
0
DevOps

Terraform Workshop - Infrastructure as Code for Public Cloud 疫情警戒陪你度過 30 天系列 第 28

Day 26-如何測試 terraform 之一:長 code 短 code,能過測試的 code 才是好 code

本篇翻譯與講解 terraform 官方 blog 對於 test terraform 的建議

課程內容與代碼會放在 Github 上: https://github.com/chechiachang/terraform-30-days

賽後文章會整理放到個人的部落格上 http://chechia.net/

追蹤粉專可以收到文章的主動推播

https://ithelp.ithome.com.tw/upload/images/20210901/20120327NvpHVr2QC0.jpg


test your code

測試是程式碼開發的一環,對於程式碼的品質影響巨大,這裡不提測試的概念。總之,測試非常重要。

以 terraform 而言,有許多時候都會需要測試

  • 測試一個 terraform module 功能
  • 測試一個 root module 產生的 infrastructure 是否符合預期
  • 測試一段 .tf 修改是否會破壞現有功能
  • ...

那應該如何測試 terraform?

testing for terraform

官方 blog 對於測試 terraform 的文件描述

將團隊選擇測試策略,依照成本(時間成本與費用)排序,會是個階層金字塔

  • unit test
  • contract test
  • integration test
  • end-to-end test
  • manual test

基於這個基礎想法,分別討論如何測試 terraform

unit test

terraform fmt -check
terraform validate

實作有幾個選項

contract test

檢查 module 的 input 與 input format

  • 最基本的是給予 input variable type,而不要使用 any / object
  • 接著是使用 variable block 中的 validation {},為參數設定 validation,排除意外的參數

terraform 在 variable 中提供 custom validation rule 的功能

  • 絕大多數的公有雲 API 對於 request argument 都有限制,可以在官方文件查找,如果 terraform 使用不合法的參數,在 apply phase (api request 出去後) 會收到 error
  • 依據 api 限制,與業務需求設置 validation 可以讓 validate / plan phase 就出錯
  • 軟體工程中的fail-fast 原則
variable "listener_rule_priority" {
 type        = number
 default     = 1
 description = "Priority of listener rule between 1 to 50000"
 validation {
   condition     = var.listener_rule_priority > 0 && var.listener_rule_priority < 50000
   error_message = "The priority of listener_rule must be between 1 to 50000."
 }
}

contract test 可以延伸,所有在 terraform apply 之前,針對 content / format / input / output 的檢查都可以

integration test

整合測試針對 terraform apply 的結果做測試,也就是 terraform module 是否正確的產出 infrastructure

  • 透過 test framework,實際對公有雲發出 api request
  • 實際 apply,但是放在獨立的測試空間
  • 使用測試用的 name 與 id,來與實際的環境隔離,(ex. 使用 dev / stag /prod 以外的環境產生 infrastructure)
  • 使用測試用的參數可能是 testing name / id 或是 function 產生的 (ex. random name / id)
  • 根據 apply 後的 result 做測試
  • apply 後,destroy 產生的 infrasturcture

使用 terraform test framework

  • Terratest
  • 這個下一堂會示範如何使用 terratest framework

End-to-End test

當 terraform apply 後,產生的 infrastructure,使用者是否能正常使用

這個層級的測試需要導入使用者的測試例,會需要 QA 團隊協助

  • 如果 infrastructure 上部署 app,也需要 app 團隊

如何對 terraform 做 end-to-end test

  • 可以鎖住穩定的 app 版本
  • 使用新版的 terraform 在獨立的環境 apply
  • 執行 QA team 的 end-to-end 測試,在 app 不變的狀況下,改變 infra 是否會改變測試結果

End-to-End 通常會花費需多時間,但對於整體環境是非常必要的

Manual test

要如何手動測試 terraform?

如果是 app,我們會手動測試其功能

  • ex. 一個網站,連線到新版網站,並手動操作功能,來進行手動測試

回到 infrastructure,如何手動測試 infrastructure 的功能?

  • 針對公有雲的 infrastructure,除非我們發現奇怪的錯誤訊息,不然一般都會選擇穩定的 infra 產品,並相信公有雲的文件,也相信產生出的 infra 品質
  • ex. 把 aws ec2 生出來後,通常不會需要進去手動測試,他就是一個功能正常的 vm
  • 更多時候 terraform 撐出來的 infrastructure 出錯,多半是 terraform resource argument 填錯,產生意料之外的 infra

因此對 terraform 而言,針對嵾數做 variable validation 是十分有效的

summary

筆者建議,做少少的努力就可以獲得明顯成效的方法

  • terraform format + validation
  • auto terraform plan + apply
  • variable custom validation

app 產品穩定的話,應該有 end-to-end test,善用 QA 團隊既有的 end-to-end test

  • 鎖住 app 在穩定版本
  • 最好在上 stag / prod 之前,都能完成完整的 end-to-end test
  • 如果產品規模太大, end-to-end 跑不完的話,可以針對修改部分進行測試
  • 例如更改 network infra,就要求 QA 在新環境執行 networking 相關的 end-to-end test

完成以上內容,已經滿足一個『能夠正常乘載 app 的 infra 的需求了』。當然,實務上只是滿足需求不是終點,還有非常多可以調整優化的地方

為 terraform 額外寫 integration test,可以進一步提升 module 品質,降低成本與提升效能

  • terratest integration test 可以達到 module 品管
  • 可以針對複雜的 module 做,特別是 dependency module 多,階層複雜,參數複雜的 module
  • 簡單的 module ex. 只有一個 resource,沒有複雜依賴關係的 module 就不需要寫 terratest,寫了變成測試比 code 多太多

上一篇
Day 25-reverse terraform: terraformer,從 infrastructure 產生 .tf 內容
下一篇
Day 27-如何測試 terraform 之二:自動化測試寫起來辛苦,但跑起來就是一個爽
系列文
Terraform Workshop - Infrastructure as Code for Public Cloud 疫情警戒陪你度過 30 天32

1 則留言

0
mark_mew
iT邦新手 5 級 ‧ 2021-09-27 01:40:55

感謝有這篇,我最近才在思考未來該怎麼幫 Terraform 寫測試。

terraform 測試有蠻多地方值得思考的,想要深入的話可以看 terratest 這個專案

我要留言

立即登入留言