Outsider's Dev Story

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

Terraform 0.10.x에서 분리된 Provider의 사용

지난 8월 Terraform이 0.10 버전으로 올라왔다. 0.10에서는 몇 가지 큰 변경사항이 생겼는데 가장 대표적인 부분이 Provider의 분리이다.

별도로 관리되는 Provider

이전 버전까지는 Terraform안에 모든 Provider가 모두 담겨 있었다. 여기서 Provider는 AWS, Google Cloud Platform, GitHub, InfluxDB 등 Terraform으로 관리하고자 하는 서비스를 의미한다. 이 중에는 AWS나 GCP처럼 대형 클라우드도 있고 아주 간단한 서비스도 있지만, 현재는 60개 이상의 Provider가 존재한다.

HashiCorp에서 밝힌 내용에 따르면 Provider가 70개가 넘어가면서 각 서비스에 새로운 기능이 나와도 사용자들은 Terraform의 새로운 버전을 항상 기다려야 하고 또 이 복잡도로 인해서 Terraform에 버그가 생길 가능성도 커지고 있다. 예를 들어 Amazon이 re:invent에서 새로운 AWS 서비스를 발표하면 사용자들은 이 기능을 Terraform에 추가해 달라고 요청하고 이 기능을 사용하려면 Terraform의 새 버전이 나와야 한다는 것이다.

그래서 0.10부터는 Provider를 모두 별도의 플러그인으로 분리하고 Terraform은 그 자체의 핵심 기능만 제공하기로 했다. 그래서 Terraform을 본연의 기능에 충실하고 각 Provider에 새로운 기능이나 버그에 대해서는 각 플러그인이 해결하고 릴리스함으로써 더 유연하게 대처할 수 있게 된 것이다. 이 Provider를 제공하는 GitHub 조직을 terraform-providers라고 새로 만들고 여기서 각 Provider의 개발과 릴리스를 진행하고 있다. Provider 버전과 관련한 최근 글을 보면 SemVer 따르기로 했고 현재는 초기 개발 단계인 0.x.x 버전에 있지만 각 Provider 팀에서 어느 정도 준비가 되면 1.0.0을 릴리스 할 것이라고 한다.

Terraform 0.10의 사용

현재 Terraform 최신 버전은 0.10.5이다. 아무것도 없는 상황에서 다음과 같이 S3 버킷을 AWS에 만드는 Terraform 구성 파일을 만든다고 해보자.

provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_s3_bucket" "kr_ne_outsider_test" {
  bucket = "kr.ne.outsider.test"
  acl    = "private"
}

0.9.x 까지는 여기서 terraform plan을 하면 결과가 나오지만, 이제는 오류가 발생한다.

$ terraform plan
Plugin reinitialization required. Please run "terraform init".
Reason: Could not satisfy plugin requirements.

Plugins are external binaries that Terraform uses to access and manipulate
resources. The configuration provided requires plugins which can't be located,
don't satisfy the version constraints, or are otherwise incompatible.

1 error(s) occurred:

* provider.aws: no suitable version installed
  version requirements: "(any version)"
  versions installed: none

Terraform automatically discovers provider requirements from your
configuration, including providers used in child modules. To see the
requirements and constraints from each module, run "terraform providers".

error satisfying plugin requirements

플러그인 요구사항을 만족하게 하지 못했으므로 terraform init을 실행하라는 문구이다. 앞에서 설명한 대로 Terraform Provider가 분리되었으므로 terraform init으로 이를 받아와야 한다. 이는 Terraform이 자동으로 추적하는데 provider "aws"이 아니더라도 설정에서 AWS 리소스를 사용하고 있으므로 aws Provider가 필요하다. 해당 설정에서 필요한 Provider 정보를 보고 싶으면 terraform providers를 실행하면 된다. 뒤에서 설명하겠지만 provider의 버전을 명시하면 여기에 지정한 버전 조건이 같이 나온다.

$ terraform providers
.
└── provider.aws

이제 terraform init으로 플러그인을 설치해보자.

$ terraform init

Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "aws" (0.1.4)...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.aws: version = "~> 0.1"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

AWS Provider 0.1.4가 설치된 것을 볼 수 있다. 따로 Provider의 버전을 지정하지는 않았으므로 최신 버전을 가져와서 설치한다.

설치하면 .terraform 폴더 아래 구조로 설치가 된다.(이 폴더는 git에서 관리할 필요가 없다.)

.terraform/
└── plugins
  └── darwin_amd64
    ├── lock.json
    └── terraform-provider-aws_v0.1.4_x4


Provider 버전 지정

경험상 Provider의 버전마다 지원 내용이 다르고 Terraform이 인프라를 다루고 있으므로 약간 조심스럽게 다루는 편이 좋다고 생각한다. 같이 Terraform을 사용하는 사람 간에 Provider의 버전을 맞추려면 다음과 같이 버전을 지정할 수 있다.

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

이렇게 하면 0.1.4 버전 이상의 버전을 사용하게 되고 버전을 특정 버전으로 고정하려면 version = "= 0.1.4"처럼 사용하면 된다.

Provider 업데이트

이렇게 사용해보자 Provider를 사용하다가 새로운 버전이 나왔을 때 어떻게 되는가가 궁금해졌다. 현재 AWS Provider의 최신 버전은 0.1.4이지만 강제로 0.1.2를 설치했다.

.terraform/
└── plugins
  └── darwin_amd64
    ├── lock.json
    └── terraform-provider-aws_v0.1.2_x4

설치된 버전을 확인하는 명령어는 몰라서 폴더를 보면 설치된 버전을 알 수 있다. 이 상태에서 terraform init을 해도 새 버전을 설치하거나 하진 않는다.

$ terraform init

Initializing provider plugins...

Terraform has been successfully initialized!

문서를 보면 이미 Provider가 설치된 경우 설치된 것을 그대로 사용하고 이를 업그레이드하려면 terraform init -upgrade를 사용하라고 되어 있다.

$ terraform init -upgrade

Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "aws" (0.1.4)...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

로그를 보면 새 버전을 다운로드 받는 것을 볼 수 있다. 폴더를 열어보면 새 버전으로 업그레이드가 되어 있다.

.terraform/
└── plugins
  └── darwin_amd64
    ├── lock.json
    └── terraform-provider-aws_v0.1.4_x4


기존에 0.9.x 이하에서 관리하던 Terraform

기존 0.9.x 이하 버전의 Terraform으로 관리하던 부분이 있어도 마이그레이션의 크게 어려움은 없다. 개인적으로 관리하는 Terraform에서도 같게 init을 하고 프로바이더를 설치한 뒤에 plan을 하자 바로 사용할 수 있었다.

$ terraform providers
.
├── provider.aws
└── provider.terraform

provider.terraform.tfstate를 원격으로 관리하기 위함이다.

2017/09/19 18:15 2017/09/19 18:15