Terraform

Terraform - 원격저장소 & 격리

본 포스트는, Terraform Up & Running 테라폼 - OREILLY를 참고했습니다.

혼자서 작업하기에는 local에서 terraform state를 저장하는 것이 좋지만,

팀 단위 작업을 위해서는 원격 저장소가 필요합니다.

이를 위해서 가장 적합한 것은 스토리지 서비스입니다.

대표적으로 AWS에는 S3가 있는데 이와 같이 DynamoDB를 이용하면 적절합니다.


S3 & DynamoDB

S3는 AWS에서 제공하는 스토리지 서비스이며, DynamoDB는 AWS에서 제공하는 NoSQL서비스입니다.

원격저장소를 위해서 이를 구축해야하는데, 이를 위해 다른 폴더에서 테라폼 코드를 작성합니다.

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

먼저 동일하게 provider를 정의합니다.

# s3
resource "aws_s3_bucket" "terraform_state" {
  bucket = "jeongbin-terraform-bucket"

  lifecycle {
    prevent_destroy = true
  }
}

resource "aws_s3_bucket_versioning" "versioning_example" {
  bucket = aws_s3_bucket.terraform_state.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "example" {
  bucket = aws_s3_bucket.terraform_state.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

다음으로는 s3를 정의합니다.

lifecycle의 경우 prevent_destroy를 설정했는데, 이는 안에 객체가 있을 때 삭제되는 것을 방지하기 위한 옵션입니다.

버전 관리를 위해서 versioning을 enable로 설정했으며, encrytion도 설정해서 보안을 높혔습니다.

# DynamoDB
resource "aws_dynamodb_table" "terraform_locks" {
  name = "terraform-up-and-running-locks"
  billing_mode = "PAY_PER_REQUEST"
  hash_key = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }
}

DynamoDB의 경우 위와 같이 정의했습니다. 여기서 hash_key를 “LockID”로 설정했음을 주의하세요.

이렇게 terraform apply 를 통해 S3와 DynamoDB를 생성하면 이제 다시 사용하던 테라폼으로 이동합니다.


backend 정의

이전의 코드에서, 원격 저장소를 연결하기 위해서는 백엔드 정의가 필요합니다.

terraform {
  backend "s3" {
    bucket = "jeongbin-terraform-bucket"
    key = "global/s3/terraform.tfstate"
    region = "ap-northeast-2"

    dynamodb_table = "terraform-up-and-running-locks"
    encrypt = true
  }
}

백엔드 정의 같은 경우 이전에 생성한 bucket name과 dynamodb table이름을 입력해주면 됩니다.

이렇게 설정하고 terraform initterraform apply 를 통해 생성합니다.

이전과 다르게, local 환경에 tfstate 파일이 없는데, 이는 s3에 저장되어 있음을 확인 할 수 있습니다.


hcl파일

백엔드 파일에서의 단점은, 변수를 사용할 수 없다입니다.

위에서 보면 직접 “string”을 통해 작성했습니다.

이러한 점으로 사용할 때마다 작성해야 하는 불편함이 있을 수 있는데 이를 위해 hcl 파일을 정의하는 것도 방법입니다.

# backend.hcl
bucket = "jeongbin-terraform-bucket"
region = "ap-northeast-2"
dynamodb_table = "terraform-up-and-running-locks"
encrypt = true


# backend.tf
terraform {
  backend "s3" {
    key = "global/s3/terraform.tfstate"
  }
}

위와 같이 hcl파일을 정의하면 tf파일은 훨씬 간결해집니다.

이후 hcl의 데이터를 이용한다는 의미로

terraform init -backend-config=backend.hcl

를 옵션으로 사용하면 됩니다.


격리

테라폼에는 작업공간을 격리하는 기능이 있습니다.

여기서는 worksapce라고 부릅니다.

쿠버네티스 등에서 namespace를 사용해 보셨다면 익숙할 것 같습니다.

terraform workspace show

위의 명령어를 통해서 현재 워크스페이스를 알 수 있습니다.

terraform workspace new example1

새로운 워크스페이스를 생성하려면 new 명령어를 사용합니다.

terraform apply

이후 terraform apply 입력하면 이전과 다르게 새로운 자원이 생성됩니다. (단 terraform name이 아닌 aws 리소스 name이 같은 경우 에러가 날 수도 있음)

S3를 확인해보면 env:/ 라는 폴더에 생성한 tfstate가 있음을 알 수 있습니다.

terraform workspace select default

다시 원래 상태로 돌아 오기 위해서는 select를 통해 변경해줍니다.

이러한 격리는, 완전히 동일한 인프라를 배포되어 있는 인프라에 영향을 주지 않고 테스트하기에 적합합니다.


3항 연산자

terraform 에서도 3항 연산자를 사용 할 수 있는데

resource "aws_instance" "ec2" {
  ami = "ami-0ea5eb4b05645aa8a"
  instance_type = terraform.workspace == "defaults" ? "t3.nano": "t3.medium"
}

위와 같이, 작업 격리 환경에 따라 인스턴스 사양을 변경하는 등 유용하게 사용할 수 있습니다.