

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 了解地形模塊
<a name="modules"></a>

在基礎結構即程式碼 (IaC) 的領域中，*模組*是隔離並封裝在一起以供重複使用的獨立程式碼區塊。模塊的概念是 Terraform 開發的一個不可避免的方面。如需詳細資訊，請參閱 Terraform 文件中的[模組](https://developer.hashicorp.com/terraform/language/modules)。 AWS CloudFormation 還支持模塊。如需詳細資訊，請參閱 AWS 雲端作業和移轉部落格中的[簡介 AWS CloudFormation 模組](https://aws.amazon.com/blogs/mt/introducing-aws-cloudformation-modules/)。

Terraform 中模塊之間的主要區別在於 CloudFormation 模塊 CloudFormation 是通過使用特殊的資源類型（）`AWS::CloudFormation::ModuleVersion`導入的。在 Terraform 中，每個配置都至少有一個模塊，稱為[根](https://developer.hashicorp.com/terraform/language/modules#the-root-module)模塊。位於 **main.tf** 檔案或 Terraform 組態檔案中的檔案中的 Terraform 資源會被視為位於根模組中。然後根模塊可以調用其他模塊以包含在堆棧中。[下列範例顯示使用開放原始碼 eks 模組佈建 Amazon Elastic Kubernetes Service (Amazon EKS) 叢集的根模組。](https://registry.terraform.io/modules/terraform-aws-modules/eks/aws/latest)

```
terraform {
  required_providers {
    helm = {
      source  = "hashicorp/helm"
      version = "2.12.1"
    }
  }
  required_version = ">= 1.2.0"
}

module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "20.2.1"
  vpc_id  = var.vpc_id
}

provider "helm" {
  kubernetes {
    host                   = module.eks.cluster_endpoint
    cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
  }
}
```

您可能已經注意到上述配置文件不包括 Pro AWS vider。這是因為模塊是獨立的，可以包含自己的提供程序。由於 Terraform 提供者是全域的，因此子模組的提供者可以在根模組中使用。儘管如此，所有模塊值都不是如此。默認情況下，模塊中的其他內部值僅限於該模塊，並且需要聲明為輸出才能在根模塊中訪問。您可以利用開放原始碼模組來簡化堆疊中的資源建立作業。例如，eks 模組的功能不僅僅是佈建 EKS 叢集，還可以佈建一個功能完整的 Kubernetes 環境。使用它可以節省您編寫數十行額外的代碼，前提是 eks 模塊配置適合您的需求。

## 呼叫模組
<a name="calling-modules"></a>

[https://developer.hashicorp.com/terraform/cli/commands/init](https://developer.hashicorp.com/terraform/cli/commands/init)該`terraform init`命令執行的默認步驟之一是找到所有子模塊，並將它們作為依賴項導入到目`.terraform/modules`錄中。在開發過程中，無論何時添加新的外部來源模塊，都必須在使用`apply`命令之前重新初始化。當您聽到對 Terraform *模塊*的引用時，它指的是此目錄中的軟件包。嚴格來說，您在代碼中聲明的模塊是*調用模塊*，因此在實踐中，module 關鍵字調用實際模塊，該模塊被存儲為依賴關係。

通過這種方式，調用模塊作為在部署發生時要替換的完整模塊的更簡潔的代表。您可以通過在堆棧中創建自己的模塊來利用這個想法，通過使用任何您想要的標準來強制執行資源的邏輯分離。請記住，這樣做的最終目標應該是降低堆棧複雜性。由於在模塊之間共享數據需要您從模塊內部輸出數據，因此有時過於依賴模塊可能會使事情過於複雜化。

## 根模塊
<a name="the-root-module"></a>

由於每個 Terraform 配置至少都有一個模塊，因此它可以幫助您檢查您將要處理的模塊的模塊屬性：根模塊。每當您在 Terraform 項目上工作時，根模塊都包含頂級目錄中的所有`.tf`（或`.tf.json`）文件。當您`terraform apply`在該頂級目錄中運行時，Terraform 會嘗試運行它在那裡找到的每個`.tf`文件。除非在其中一個頂層組態檔案中呼叫子目錄中的任何檔案，否則會略過這些檔案。

這在構建代碼方面提供了一些靈活性。這也是為什麼將 Terraform 部署引用為模塊而不是文件更準確的原因，因為單個過程可能涉及多個文件。Terraform 建議使用[標準模組結構](https://developer.hashicorp.com/terraform/language/modules/develop/structure)以取得最佳實務。但是，如果您要將任何文`.tf`件放在頂級目錄中，它將與其餘文件一起運行。事實上，模組中的所有頂層`.tf`檔案都會在您執行時部署`terraform apply`。那麼地形首先運行哪個文件？ 這個問題的答案非常重要。

Terraform 在初始化之後和堆棧部署之前執行了一系列步驟。首先，分析現有的組態，然後建立[相依性圖形](https://developer.hashicorp.com/terraform/internals/graph)。依賴關係圖確定要求什麼樣的資源以及它們應該被解決的順序。例如，包含在其他資源中參照之屬性的資源，會在其相依資源之前處理。同樣地，使用`depends_on`參數明確宣告相依性的資源，也會在資源指定的資源之後進行處理。如果可能的話，Terraform 可以實現並行性並同時處理非依賴資源。您可以使用地形圖形命令在部署之前查看依賴關係[圖](https://developer.hashicorp.com/terraform/cli/commands/graph)。

建立相依性圖表之後，Terraform 會決定部署期間需要執行的動作。它的依賴關係圖與最新的狀態文件進行比較。此流\\ 'b5\\ '7b 的結果稱為「*計劃*」，非常類似於 CloudFormation[變更集](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-changesets-create.html)。您可以使用[地形平面圖指令來查看目前的計畫](https://developer.hashicorp.com/terraform/cli/commands/plan)。

作為最佳實踐，建議盡可能接近標準模塊結構。如果您的組態檔案變得太長而無法有效管理，而邏輯分離可能會簡化管理，您可以將程式碼分散到多個檔案中。請記住相依性圖表和計劃流程的運作方式，讓您的堆疊盡可能有效率地執行。