본문 바로가기

Infrastructure/Terraform

[Terraform] 공급자(Provider) 버전 관리

공급자 버전 잠금 및 업그레이드

이전 장에서 원격 리포지토리에 상태를 저장하는 방법에 대해서 알아보았다.
이번 장에서는 "Terraform 공급자"의 버전을 관리하는 방법에 대해서 알아본다.
모든 소스 코드는 리포지토리에 올려두었다.


Intro

  • "Terraform 공급자(Provider)"는 "Terraform"과 대상 API 간에 통신하여 리소스를 관리한다.

  • 대상 API가 기능을 변경하거나 추가할 때마다 "공급자 유지 관리자"는 버전을 지정하여 업데이트할 수 있다.

  • 여러 사용자 또는 자동화 도구가 동일한 "Terraform" 구성을 실행하는 경우 모두 동일한 버전의 필수 공급자를 사용해야 한다.

  • 구성에서 공급자 버전을 관리하는 방법에는 두 가지가 있다.

  • 공급자 버전의 범위를 적절하게 지정하지 않으면 "Terraform"은 버전 제약 조건을 충족하는 최신 공급자 버전을 다운로드하며, 이로 인해 예상치 못한 인프라 변경이 발생할 수 있다.

  • 범위가 지정된 제공자 버전을 지정하고, 종속성 잠금 파일을 사용하면 "Terraform"이 올바른 공급자 버전을 사용하여 구성이 일관되게 적용되도록 할 수 있다.

  • 이번 예시에서는 초기화된 "Terraform" 구성에서 S3 버킷을 생성한 후, 최신 버전의 AWS 공급자를 사용하도록 "Terraform" 종속성 잠금 파일을 업데이트하고 새 공급자 버전의 요구 사항을 준수하도록 "Terraform" 구성을 편집한다.


전제 조건(Prerequisites)

  • "Terraform OSS"와 "Terraform Cloud"에서 동일한 워크플로를 사용하여 프로젝트를 구축할 수 있으며, 예제에서는 "Terraform Cloud"를 사용한다.
  • "Terraform Cloud"를 사용해보지 않은 사용자는 참고 자료의 "What is Terraform Cloud - Intro and Sign Up" 문서를 확인하여 계정을 생성하도록 한다.

파일 확인

  • 예시에서 사용될 파일은 총 세개로 main.tf, terraform.tf, .terraform.lock.hcl 파일이 있다.

main.tf

  • AWS 공급자를 사용하여 임의로 지정된 S3 버킷을 ap-northeast-2 리전에 배포한다.
provider "aws" {
  region = "ap-northeast-2"
}

resource "random_pet" "petname" {
  length    = 5
  separator = "-"
}

resource "aws_s3_bucket" "sample" {
  bucket = random_pet.petname.id

  acl    = "public-read"
  region = "ap-northeast-2"

  tags = {
    public_bucket = true
  }
}

terraform.tf

  • 구성에 필요한 공급자 버전과 "Terraform" 버전을 지정한다.
terraform {
  required_providers {
    random = {
      source  = "hashicorp/random"
      version = "3.1.0"
    }

    aws = {
      source  = "hashicorp/aws"
      version = ">= 2.0.0"
    }
  }

  required_version = ">= 1.1"
}
  • terraform 블록에는 required_providers 공급자 로컬 이름, 소스 주소 및 버전을 지정하는 블록이 포함되어 있다.
  • 이러한 구성파일을 초기화하면 "Terraform"은 아래의 항목을 다운로드한다.
    • 3.1.0 버전의 random 공급자
    • 2.0.0보다 큰 AWS 공급자의 최신 버전. >= 연산자는 구성과 호환되는 최소 공급자 버전을 지정한다.
  • "Terraform" 블록은 1.1 보다 큰 "Terraform 바이너리"만 >=연산자를 사용하여 이 구성을 실행할 수 있도록 지정한다.

terraform.lock.hcl

  • "Terraform" 1.1 이상의 버전을 사용하여 처음으로 "Terraform" 구성을 초기화하면 .terraform.lock.hcl이 작업 디렉터리에 새 파일을 생성한다.
  • "Terraform"이 팀과 원격 실행 환경에서 동일한 공급자 버전을 사용하도록 버전 제어 저장소에 잠금 파일을 포함해야 한다.
    .gitignore 파일에 .terraform.lock.hcl을 추가하지 말고 버전에 따라 관리되도록 해야 한다는 의미다.
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.

provider "registry.terraform.io/hashicorp/aws" {
  version     = "4.51.0"
  constraints = ">= 2.0.0"
  hashes = [
    "h1:gcJ7Wl7NSFTacEekzzkggUTCn9KMsGr8TH2mXrj9EJ4=",
    "zh:10aebfd8f22f7a69a2fcfcf35cb17ebbc0966ac8e822a9a0e1c843e429389de7",
    # ...
  ]
}

provider "registry.terraform.io/hashicorp/random" {
  version     = "3.1.0"
  constraints = "3.1.0"
  hashes = [
    "h1:9cCiLO/Cqr6IUvMDSApCkQItooiYNatZpEXmcu0nnng=",
    "zh:2bbb3339f0643b5daa07480ef4397bd23a79963cc364cdfbb4e86354cb7725bc",
    # ...
  ]
}
  • AWS 공급자의 버전을 확인해보면 2.50.0으로 설치된 것을 확인할 수 있다.
    이것은 작성일 기준 2.0.0 이후의 버전 중 최신 버전이 4.51.0이기 때문에 >= 연산자에 의해 설치된 것을 알 수 있다.

구성 초기화 및 적용

  • "Terraform Cloud"를 연동하여 상태값이 원격 스토리지에 저장되도록 한다.
terraform {
  cloud {
    organization = "roy-company-name"
    workspaces {
      name = "roy-company-workspace-1"
    }
  }

  required_providers {
    random = {
      source = "hashicorp/random"
      version = "3.1.0"
    }

    aws = {
      source = "hashicorp/aws"
      version = ">= 2.0.0"
    }
  }

  required_version = ">= 1.1"
}
  • terraform init 명령어를 사용하여 "Terraform"을 초기화하면 "Terraform Cloud" 조직에 새로운 작업 공간(workspace)를 생성한다.
  • 정상적으로 구성을 apply하기 위해서는 "Terraform Cloud"에 로그인되어 있어야 하며, AWS 자격 증명이 설정되어 있어야 한다.
    만약 설정되지 않았다면, 참고 자료의 "Create a Credentials Variable Set" 문서를 확인하도록 한다.
$ terraform init

Initializing Terraform Cloud...

Initializing provider plugins...
- Finding hashicorp/aws versions matching ">= 2.0.0"...
- Finding hashicorp/random versions matching "3.1.0"...
- Installing hashicorp/aws v4.51.0...
- Installed hashicorp/aws v4.51.0 (signed by HashiCorp)
- Installing hashicorp/random v3.1.0...
- Installed hashicorp/random v3.1.0 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

AWS 공급자 버전 업그레이드

  • -upgrade 플래그는 구성에 지정된 버전 제약 조건 내에서 일관된 최신 버전으로 모든 공급자를 업그레이드 한다.
  • 주의할 점은 버전 업그레이드를 위해서 잠금파일을 직접 수정해서는 안된다는 것이다.
$ terraform init -upgrade

Initializing Terraform Cloud...

Initializing provider plugins...
- Finding hashicorp/random versions matching "3.1.0"...
- Finding hashicorp/aws versions matching ">= 2.0.0"...
- Using previously-installed hashicorp/random v3.1.0
- Using previously-installed hashicorp/aws v4.51.0

Terraform Cloud has been successfully initialized!
  • "Terraform"은 최신 버전의 AWS 공급자를 설치하게 되고, .terraform.lock.hcl 파일의 AWS 버전도 수정된다.

  • -upgrade 플래그를 통해서 더 낮은 버전으로 다운그레이드 또한 가능하다.

  • 공급자의 버전이 잠기지 않았을 때 발생하는 문제를 확인해본다.
    참고로, aws_s3_bucket 리소스의 acl 속성은 AWS 공급자 v3.0.0+ 버전에서는 유효했지만, v4.0.0+ 버전에서는 더 이상 사용되지 않는다.

$ terraform apply
Running apply in Terraform Cloud. Output will stream here. Pressing Ctrl-C
will cancel the remote apply if it's still pending. If the apply started it
will stop streaming the logs, but will not stop the apply running remotely.

Preparing the remote apply...

To view this run in a browser, visit:
https://app.terraform.io/app/roy-company-name/roy-company-workspace-1/runs/run-1pvmwMX18SZyPBHu

Waiting for the plan to start...

Terraform v1.3.5
on linux_amd64
Initializing plugins and modules...
╷
│ Warning: Argument is deprecated
│ 
│   with aws_s3_bucket.sample,
│   on main.tf line 13, in resource "aws_s3_bucket" "sample":
│   13:   acl    = "public-read"
│ 
│ Use the aws_s3_bucket_acl resource instead
╵
╷
│ Error: Value for unconfigurable attribute
│ 
│   with aws_s3_bucket.sample,
│   on main.tf line 14, in resource "aws_s3_bucket" "sample":
│   14:   region = "ap-northeast-2"
│ 
│ Can't configure a value for "region": its value will be decided
│ automatically based on the result of applying this configuration.
╵
Operation failed: failed running terraform plan (exit 1)
  • AWS 공급자 v4.0.0+ 버전과 호환되도록 main.tf 파일을 수정해본다.
provider "aws" {
  region = "ap-northeast-2"
}

resource "random_pet" "petname" {
  length    = 5
  separator = "-"
}

resource "aws_s3_bucket" "sample" {
  bucket = random_pet.petname.id

  tags = {
    public_bucket = true
  }
}

resource "aws_s3_bucket_acl" "example" {
  bucket = aws_s3_bucket.sample.id
  acl    = "public-read"
}
  • 다시 구성을 apply하면 정상적으로 적용되는 것을 확인할 수 있다.
  • 인프라를 담당하는 여러 사용자가 동일한 공급자 버전을 사용하게 되면 위에서 살펴본 것과 같은 문제가 발생할 수 있으므로 주의해야 한다.
  • "적용(apply)" 단계가 성공적으로 완료되면 "업데이트된 잠금 파일"을 사용하여 구성 버전 제어에 커밋하는 것이 안전하며, "계획(plan)" 또는 "적용(apply)" 단계가 실패하면 잠금 파일을 버전 제어에 커밋해서는 안된다.

참고 자료

'Infrastructure > Terraform' 카테고리의 다른 글

[Terraform] String Functions  (0) 2023.03.15
[Terraform] Numeric Functions  (0) 2023.03.15
[Terraform] 표준 모듈 구조  (0) 2023.01.25
[Terraform] 원격 상태 저장  (0) 2023.01.25
[Terraform] 기본 개념  (0) 2023.01.25