테라폼 제공자에 대한 이해 - AWS 규범적 지침

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

테라폼 제공자에 대한 이해

Terraform에서 공급자는 클라우드 제공업체, 타사 도구 및 기타 API와 상호 작용하는 플러그인입니다. Terraform을 함께 AWS사용하려면 리소스와 상호 작용하는 AWS 공급자를 사용해야 합니다. AWS

AWS CloudFormation 레지스트리를 사용하여 타사 확장을 배포 스택에 통합한 적이 없다면 Terraform 공급자가 익숙해지는 데 시간이 걸릴 수 있습니다. CloudFormation 가 기본으로 제공되기 때문에 기본적으로 AWS 리소스 공급자가 이미 있습니다. AWS반면 Terraform에는 단일 기본 공급자가 없으므로 주어진 리소스의 출처에 대해 아무 것도 가정할 수 없습니다. 즉, Terraform 구성 파일에서 가장 먼저 선언해야 할 것은 리소스가 정확히 어디로 가고 어떻게 전달되는지입니다.

이러한 구분은 Terraform에는 존재하지 않는 복잡성을 한층 더 가중시킵니다. CloudFormation 하지만 이러한 복잡성으로 인해 유연성이 향상됩니다. 단일 Terraform 모듈 내에서 여러 공급자를 선언할 수 있으며, 그러면 생성된 기본 리소스가 동일한 배포 계층의 일부로 서로 상호 작용할 수 있습니다.

이는 다양한 방식으로 유용할 수 있습니다. 제공업체가 반드시 별도의 클라우드 공급자를 위한 것은 아닙니다. 공급자는 클라우드 리소스의 모든 소스를 대표할 수 있습니다. 아마존 엘라스틱 쿠버네티스 서비스 (Amazon EKS) 를 예로 들어 보겠습니다. Amazon EKS 클러스터를 프로비저닝할 때 Helm 차트를 사용하여 타사 확장을 관리하고 Kubernetes 자체를 사용하여 포드 리소스를 관리하는 것이 좋습니다. Helm과 Kubernetes에는 모두 자체 Terraform 공급자가 있으므로 AWS이러한 리소스를 모두 동시에 프로비저닝 및 통합한 다음 이들 간에 값을 전달할 수 있습니다.

Terraform의 다음 코드 예제에서 AWS 제공자는 Amazon EKS 클러스터를 생성한 다음 결과 쿠버네티스 구성 정보가 헬름 및 쿠버네티스 제공자 모두에게 전달됩니다.

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 각 접근 방식에는 장단점이 있습니다. 어느 것이 적합한지는 이 가이드의 범위를 벗어나지만, 두 도구를 모두 평가할 때는 차이점을 기억하는 것이 중요합니다.

Terraform 별칭 사용

Terraform에서는 사용자 지정 구성을 각 공급자에게 전달할 수 있습니다. 그렇다면 동일한 모듈 내에서 여러 공급자 구성을 사용하려면 어떻게 해야 할까요? 이 경우 별칭을 사용해야 합니다.   별칭은 리소스별 또는 모듈별 수준에서 사용할 제공자를 선택하는 데 도움이 됩니다. 동일한 제공자의 인스턴스가 두 개 이상 있는 경우 별칭을 사용하여 기본이 아닌 인스턴스를 정의합니다. 예를 들어 기본 제공자 인스턴스는 특정 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" }

이전 예제에서 볼 수 있듯이 provider 메타 인수와 alias 함께 를 사용하면 특정 리소스에 대해 다른 제공자 구성을 지정할 수 있습니다. 단일 스택에 여러 리소스를 프로비저닝하는 것은 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" } }