

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

# 了解地形提供者
<a name="providers"></a>

在 Terraform 中，*提供程序*是與雲提供商，第三方工具和其他 API 進行交互的插件。若要搭配使用 Terraform AWS，您可以使用與資源互動的[AWS 提供者](https://registry.terraform.io/providers/hashicorp/aws/latest/docs)。 AWS 

如果您從未使用[AWS CloudFormation 登錄](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry.html)將第三方擴充功能併入部署堆疊中，則 Terraform [提供者](https://developer.hashicorp.com/terraform/language/providers)可能需要一些習慣。因為 CloudFormation 是原生的 AWS，所以預設情況下， AWS 資源提供者已經存在。另一方面，Terraform 沒有單一的默認提供程序，因此不能假設給定資源的來源。這意味著需要在 Terraform 配置文件中聲明的第一件事就是資源的去向以及它們將如何到達那裡。

這種區別為不存在的 Terraform 增加了一層額外的複雜性。 CloudFormation但是，這種複雜性提供了更高的靈活性 您可以在單一 Terraform 模組中宣告多個提供者，然後建立的基礎資源可以作為相同部署層的一部分互動。

這可以在許多方面有用。供應商不一定要針對單獨的雲提供商。提供者可以代表雲端資源的任何來源。例如，以 Amazon Elastic Kubernetes Service（Amazon EKS）。佈建 Amazon EKS 叢集時，您可能想要使用 Helm 圖表來管理第三方擴充功能，並使用 Kubernetes 本身來管理網繭資源。由 AWS於 [Helm](https://registry.terraform.io/providers/hashicorp/helm/latest/docs) 和 [Kubernetes](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs) 都有自己的 Terraform 提供者，因此您可以同時佈建和整合這些資源，然後在這些資源之間傳遞值。

在 Terraform 的下列程式碼範例中， AWS 提供者會建立 Amazon EKS 叢集，然後產生的 Kubernetes 組態資訊會傳遞給 Helm 和 Kubernetes 提供者。

```
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 4.33.0"
    }

    helm = {
      source  = "hashicorp/helm"
      version = "2.12.1"
    }

    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "2.26.0"
    }
  }
  required_version = ">= 1.2.0"
}

provider "aws" {
  region = "us-west-2"
}

resource "aws_eks_cluster" "example_0" {
  name     = "example_0"
  role_arn = aws_iam_role.cluster_role.arn
  vpc_config {
    endpoint_private_access = true
    endpoint_public_access  = true
    subnet_ids              = var.subnet_ids
  }
}

locals {
  host        = aws_eks_cluster.example_0.endpoint
  certificate = base64decode(aws_eks_cluster.example_0.certificate_authority.data)
}

provider "helm" {
  kubernetes {
    host                   = local.host
    cluster_ca_certificate = local.certificate
    # exec allows for an authentication command to be run to obtain user
    # credentials rather than having them stored directly in the file
    exec {
      api_version = "client.authentication.k8s.io/v1beta1"
      args        = ["eks", "get-token", "--cluster-name", aws_eks_cluster.example_0.name]
      command     = "aws"
    }
  }
}

provider "kubernetes" {
  host                   = local.host
  cluster_ca_certificate = local.certificate
  exec {
    api_version = "client.authentication.k8s.io/v1beta1"
    args        = ["eks", "get-token", "--cluster-name", aws_eks_cluster.example_0.name]
    command     = "aws"
  }
}
```

當涉及到兩個 IaC 工具時，有一個關於提供者的權衡。Terraform 完全依賴外部位於提供程序包，這些提供程序包是驅動其部署的引擎。 CloudFormation 內部支持所有主要 AWS 流程。使用 CloudFormation，僅當您想合併第三方擴展時，才需要擔心第三方提供商。每種方法都有優點和缺點。哪一種適合您超出了本指南的範圍，但是在評估兩種工具時記住差異很重要。

## 使用地形別名
<a name="using-terraform-aliases"></a>

在 Terraform 中，您可以將自定義配置傳遞給每個提供程序。那麼，如果您想在同一個模塊中使用多個提供程序配置怎麼辦？ 在這種情況下，您必須使用[別名](https://developer.hashicorp.com/terraform/language/providers/configuration#alias-multiple-provider-configurations)。  別名可協助您選取要在每個資源或每個模組層級使用的提供者。當您有多個相同提供者的執行個體時，您可以使用別名來定義非預設執行個體。例如，您的預設提供者執行個體可能是特定的 AWS 區域，但您可以使用別名來定義替代區域。

下列 Terraform 範例會示範如何使用別名來佈建不同的值區。 AWS 區域提供者的預設區域為`us-west-2`，但您可以使用 east 別名在中佈建資源`us-east-2`。

```
provider "aws" {
  region = "us-west-2"
}

provider "aws" {
  alias  = "east"
  region = "us-east-2"
}

resource "aws_s3_bucket" "myWestS3Bucket" {
  bucket = "my-west-s3-bucket"
}

resource "aws_s3_bucket" "myEastS3Bucket" {
  provider = aws.east
  bucket   = "my-east-s3-bucket"
}
```

如前面的範例所示，當您`alias`搭配中`provider`繼引數使用時，您可以為特定資源指定不同的提供者組態。在單一堆疊 AWS 區域 中佈建多個資源只是個開始。別名提供者在許多方面都非常方便。

例如，一次佈建多個 Kubernetes 叢集是很常見的。別名可協助您設定其他 Helm 和 Kubernetes 提供者，以便您可以針對不同的 Amazon EKS 資源以不同的方式使用這些第三方工具。下列 Terraform 程式碼範例說明如何使用別名來執行此工作。

```
resource "aws_eks_cluster" "example_0" {
  name     = "example_0"
  role_arn = aws_iam_role.cluster_role.arn
  vpc_config {
    endpoint_private_access = true
    endpoint_public_access  = true
    subnet_ids              = var.subnet_ids[0]
  }
}

resource "aws_eks_cluster" "example_1" {
  name     = "example_1"
  role_arn = aws_iam_role.cluster_role.arn
  vpc_config {
    endpoint_private_access = true
    endpoint_public_access  = true
    subnet_ids              = var.subnet_ids[1]
  }
}

locals {
  host         = aws_eks_cluster.example_0.endpoint
  certificate  = base64decode(aws_eks_cluster.example_0.certificate_authority.data)
  host1        = aws_eks_cluster.example_1.endpoint
  certificate1 = base64decode(aws_eks_cluster.example_1.certificate_authority.data)
}

provider "helm" {
  kubernetes {
    host                   = local.host
    cluster_ca_certificate = local.certificate
    exec {
      api_version = "client.authentication.k8s.io/v1beta1"
      args        = ["eks", "get-token", "--cluster-name", aws_eks_cluster.example_0.name]
      command     = "aws"
    }
  }
}

provider "helm" {
  alias = "helm1"
  kubernetes {
    host                   = local.host1
    cluster_ca_certificate = local.certificate1
    exec {
      api_version = "client.authentication.k8s.io/v1beta1"
      args        = ["eks", "get-token", "--cluster-name", aws_eks_cluster.example_1.name]
      command     = "aws"
    }
  }
}

provider "kubernetes" {
  host                   = local.host
  cluster_ca_certificate = local.certificate
  exec {
    api_version = "client.authentication.k8s.io/v1beta1"
    args        = ["eks", "get-token", "--cluster-name", aws_eks_cluster.example_0.name]
    command     = "aws"
  }
}

provider "kubernetes" {
  alias                  = "kubernetes1"
  host                   = local.host1
  cluster_ca_certificate = local.certificate1
  exec {
    api_version = "client.authentication.k8s.io/v1beta1"
    args        = ["eks", "get-token", "--cluster-name", aws_eks_cluster.example_1.name]
    command     = "aws"
  }
}
```