Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Terraform에 다중 Provider 사용하기

AWS, GCP 등 클라우드를 사용할 때 보통 주로 사용하는 리전이 정해져 있다. 일부 Route53이나 CloudFront처럼 리전이 정해져 있지 않은 서비스도 있지만, 대다수 서비스는 리전을 선택해서 사용해야 하고 국내에서는 보통 서울(ap-northeast-2)이나 도쿄(ap-northeast-1) 리전을 사용한다.

Terraform에서도 다음처럼 provider에서 리전을 지정해서 해당 폴더에 작성한 리소스가 사용할 기본 리전을 지정할 수 있다.

provider "aws" {
  version = "~> 1.33"
  region  = "ap-northeast-1"
}

여러 리전을 사용하는 경우 폴더별로 리전을 나누어 사용할 수도 있겠지만 폴더 관리를 그렇게 하지 않거나 특정 상황에서는 같은 폴더에서 여러 리전에 리소스를 생성해야 하는 경우가 생긴다. 매년 수없이 나오는 AWS의 신규 서비스는 특정 리전에 먼저 공개되므로 이를 사용하기 위해서 다른 리전을 사용할 수도 있고 ACM에서 발급한 인증서를 CloudFront에 연결하는 경우에는 Terraform으로 ACM 인증서 생성하기에서 설명했듯이 인증서를 버지니아 북부(us-east-1)에 만들어야 하므로 어쩔 수 없지 다른 리전을 지정해야 한다. 이전 글에서도 사용해 봤지만 좀 더 살펴보자.

이런 경우 provider를 여러 개 선언할 수 있다.

provider "aws" {
  version = "~> 1.33"
  region  = "ap-northeast-1"
}

provider "aws" {
  alias   = "virginia"
  region  = "us-east-1"
}

이때 추가로 지정하는 provider에는 반드시 alias를 지정해야 한다. 그렇지 않으면 다음과 같이 오류가 난다.

$ terraform plan

Error: provider.aws: multiple configurations present; only one configuration is allowed per provider

그리고 기본 provider에는 alias가 없어야 한다. 모든 프로바이더에 alias가 없으면 따로 지정하지 않는 한 어떤 프로바이더가 기본인지 알 수 없으므로 다음과 같이 리전을 물어보게 된다.

$ terraform  plan
provider.aws.region
  The region where AWS operations will take place. Examples
  are us-east-1, us-west-2, etc.

  Default: us-east-1
  Enter a value:

ACM 인증서를 us-east-1 리전에 생성하려면 리소스 선언에 provider = "aws.virginia"를 추가하면 된다. 이러면 해당 리소스는 지정한 리전에 생성된다.

resource "aws_acm_certificate" "demo_sideeffect_kr" {
  provider          = "aws.virginia"

  domain_name       = "demo.sideeffect.kr"
  validation_method = "EMAIL"
}

provider는 모든 선언에서 사용할 수 있는데 클라우드에서 리소스 정보를 가져오는 data에서도 다음과 같이 지정해서 사용할 수 있다.

data "aws_availability_zones" "virginia" {
  provider = "aws.virginia"
}

provider의 사용법은 모듈을 사용할 때만 약간 다르다. 기본적으로 모듈에서 프로바이더는 루트 모듈에서만 지정할 수 있고 모듈 내부의 리소스는 이를 상속받는다.

module "demo" {
  source   = "./demo"

  provider = "aws.virginia"
}

이 경우 실행을 하면 다음과 같이 오류가 발생한다.

$ terraform  plan

Error: module "demo": "provider" is not a valid argument

모듈에서는 providers를 이용해서 맵으로 지정해야 한다.

module "demo" {
  source   = "./demo"

  providers = {
    aws = "aws.virginia" 
  }
}

처음에 이 구조를 봤을 때는 프로바이더를 여러 번 지정해서 한 번에 여러 리전에 만들 수 있는 건가 싶었지만 그렇지는 않다. 내부 구조는 모르지만, 동작은 모듈 내의 provider.aws를 지정한 값으로 지정하는 역할을 한다. 그래서 Terraform 문서에 나온 대로 모듈에서 여러 프로바이더를 사용하는 경우 모듈 내에 프로바이더를 다음과 같이 지정하고 있다고 해보자.

provider "aws" {
  alias = "src"
}

provider "aws" {
  alias = "dst"
}

이때는 모듈의 alias를 이용해서 아래와 같이 지정하면 각 프로바이더에 원하는 리전을 지정할 수 있다.

module "demo" {
  providers = {
    aws.src = "aws.tokyo"
    aws.dst = "aws.virginia"
  }
}
2018/08/30 23:40 2018/08/30 23:40