原簡體中文教程連結: Introduction.《Terraform入門教程》
Terraform 模組是獨立的基礎架構即程式碼片段,抽象化了基礎架構部署的底層複雜性。Terraform 使用者透過使用預置的設定碼加速採用 IaC,並降低了使用門檻。所以,模組的作者應盡量遵循諸如清晰的程式碼結構以及 DRY("Dont't Repeat Yourself")原則的程式碼最佳實踐。
本篇指導討論了模組架構的原則,用以幫助讀者編寫易於組合、易於分享及重用的基礎設施模組。這些架構建議對使用任意版本 Terraform 的企業都有好處,某些諸如「私有模組註冊表(Registry)」的模式僅在Terraform Cloud 以及企業版中才能使用。(本文不對相關內容進行翻譯)
本文是 Terraform 模組文件的補充和擴充。
透過閱讀文本,讀者可以:
要創建一個新模組,第一步是尋找一個早期採納者團隊,收集他們的需求。
與這支早期採納團隊一起工作使我們可以透過使用輸入變數以及輸出值來確保模組足夠靈活,從而打磨模組的功能。此外,還可以用最小的程式碼變更代價吸收其他有類似需求的團隊加入進來。這消除了程式碼重複,並縮短了交付時間。
完成以上任務後,需要謹記兩點:
創建新 Terraform 模組時最具挑戰的方面之一是決定要包含哪些基礎設施資源。
模組設計應該是有主見的,並且被設計成能很好地完成一個目標。如果一個模組的功能或目的很難解釋,那麼這個模組可能太複雜了。在最初確定模組的範圍時,目標應足夠小且簡單,易於開始編寫。
當建構一個模組時,需要考慮以下三個方面:
如同所有類型的程式碼一樣,模組的開發永遠不會完成,永遠會有新的模組需求以及變更。擁抱變化,最初的模組版本應致力於滿足最小可行產品(MVP)的標準。以下是在設計最小可行產品時需要謹記的指導清單:
在最小可行產品中輸出盡可能多的信息,即使目前沒有使用者需要這些資訊。這使得那些通常使用多個模組的終端使用者在使用該模組時更加輕鬆,可以使用一個模組的輸出作為下一個模組的輸入。
請記得在模組的 README
文件中記錄輸出值的文件。
某團隊想要透過 Terraform 創建一套包含 Web 層應用程式、App 層應用程式的基礎架構。
他們想要使用一個專用的 VPC,並遵循傳統的三層架構設計。他們的 Web 層應用程式需要一個自動伸縮群組(AutoScaling Group)。他們的 App 層服務需要一個自動伸縮組,一個 S3 儲存桶以及一個資料庫。下面的架構圖描述了期望的結果:
在這個場景中,一個負責從零開始撰寫 Terraform 程式碼的團隊,負責編寫一組用於配置基礎架構及應用的模組。負責應用程式的團隊成員將使用這些模組來配置他們需要的基礎架構。
請注意,雖然此範例使用了AWS 命名,但所描述的模式適用於所有雲端平台。
經過對應用程式團隊的需求進行審核,模組團隊將此應用程式基礎架構分割成如下模組:網路、Web、App、資料庫、路由,以及安全性。
當 Terraform 模組團隊完成模組開發後,他們應該將模組匯入到私人模組註冊表中,並且向對應的團隊成員宣傳模組的使用方法。舉例來說,負責網路的團隊成員將會使用開發的網路模組來部署和配置相應的應用程式網路。
網路模組負責網路基礎設施。它包含了網路存取控制清單(ACL)以及 NAT 閘道。它還可以包含應用程式所需的 VPC、子網路、對等連接以及 Direct Connect 等。
此模組包含這些資源是因為它們需要特定權限並且變化頻率較低。
網路模組傳回一組其他工作區(Workspace)以及模組可以使用的輸出值。如果VPC 的創建過程是由多個方面組成的,我們可能最終會需要將該模組進一步切割成具有不同功能的不同模組。
本場景中有兩個應用程式模組- 一個是 Web 層模組,另一個是 App 層模組。
Terraform 模組團隊完成這兩個模組的開發後,它們應分發給對應的團隊成員來部署他們的應用程式。隨著應用程式團隊的成員變得越來越熟悉 Terraform 程式碼,它們可以提出基礎架構方面的增強建議,或透過 Pull Request 配合他們自己的應用程式碼發布提交對基礎架構的變更請求。
Web 模組可建立和管理執行 Web 應用程式所需的基礎架構。它包含了負載平衡器和自動伸縮群組,同時也可以包含應用程式中使用的 EC2 虛擬機器執行個體、S3 儲存桶、安全性群組,以及日誌系統。此模組接收一個透過 Packer 預先建置的包含最新 Web 層應用程式發布版本代碼的虛擬機器映像的 AMI ID 作為輸入。
此模組包含這些資源是因為它們是高度封裝的,並且它們變化頻率較高。
App 模組建立和管理運行 App 層應用程式所需的基礎架構。它包含了負載平衡器和自動伸縮群組,同時也包含了應用程式中使用的 EC2 虛擬機器實例、S3 儲存桶、安全性群組,以及日誌系統。此模組接收一個透過 Packer 預先建置的包含最新 App 層應用程式發布版本代碼的虛擬機器映像的 AMI ID 作為輸入。
此模組包含這些資源是因為它們是高度封裝的,並且它們變化頻率較高。
資料庫模組創建並管理了運行資料庫所需的基礎設施資源。它包含了應用程式所需的RDS 實例,也包含了所有關聯的儲存、備份以及日誌資源。
此模組包含這些資源是因為它們需要特定權限並且變化頻率較低。
路由模組建立並管理網路路由所需的基礎設施資源。它包含了公共託管區域(Hosted Zone)、Route 53 以及路由表,也可以包含私人託管區域。
此模組包含這些資源是因為它們需要特定權限並且變化頻率較低。
安全模組可建立並管理所有安全所需的基礎設施資源。它包含一組IAM 資源,也可以包含安全群組(Security Group)及多因子認證(MFA)。
此模組包含這些資源是因為它們需要特定權限並且變化頻率較低。
除了範圍界定之外,我們在創建模組時還應牢記以下幾點:
嵌套模組是指在目前模組中對另一個模組的引用。嵌套模組可以是外部的,也可以是目前工作空間內的。使用嵌套模組是一項強大的功能;然而我們必須謹慎實踐以避免引入錯誤。
對於所有類型的嵌套模組,請考慮以下事項:
當我們需要使用那些定義了被多個應用程式堆疊、應用程式和團隊重複使用的標準化資源的通用模組時,嵌套的外部模組會很有用。外部模組通被集中管理和版本化控制,以使得消費者在使用新版本之前可以對其進行驗證。當我們依賴或希望使用位於外部的子模組時,請注意以下幾點:
在目前工作空間中嵌入一個模組使得我們能夠清楚地分離模組的邏輯元件,或是建立可在呼叫模組執行期間多次呼叫的可重複使用程式碼區塊。在下面的例子中,ec2-instance
是一個嵌入模組,根模組的 main.tf
引用了這個模組:
root-module-directory
├── README.md
├── main.tf
└── ec2-instances
└── main.tf
如果我們需要或傾向於使用嵌入模組,需要考慮以下幾點:
ec2-instance
模組是用來創建一台被用在多個地方的標準化的計算實例,該模組無法以這種形式被分享。為我們的模組創建並遵循一個命名約定將使得模組易於理解與使用。這將促進模組的採用和貢獻。以下是一個用來提升模組元素一致性的建議清單:
terraform | cloud provider | function | full name |
---|---|---|---|
terraform | aws | consul cluster | terraform-aws-consul_cluser |
terraform | aws | security module | terraform-aws-security |
terraform | azure | database | terraform-azure-database |
var.vpc_id
永遠不應該有預設值,因為每次使用模組時值都會不同。var.elb_idle_timeout
會有一個合理的預設值,但呼叫者也可以根據需求修改它的值。雖然模組結構是一個品味問題,我們應該將模組的結構記錄在文件中,並且在我們的所有模組之間保持統一的結構。為了要維持模組結構的一致:
.tf
文件,定義它們應包含哪些內容.gitignore
(或類似作用的)文件terraform.tfvars.example
檔案)README
文件詳細記述目錄存在的目的以及如何使用其中的文件隨著團隊模組的開發工作,簡化我們的協作。
一個 Terraform 模組應遵守所有良好的程式碼實踐:
main
分支的發布版本建立版本標籤,記錄文件(最起碼在 CHANGELOG
及 README
中記錄)。main
分支的所有變更進行程式碼審查定義並宣傳一套消費者團隊使用模組時應遵循的可重複工作流程。這個工作流程,就像模組本身一樣,應該考慮到使用者的需求。
原簡體中文教程連結: Introduction.《Terraform入門教程》