본문 바로가기

♻ Terraform(테라폼)/Terraform 활용

테라폼을 활용한 S3 버킷 저장소 생성 (lock)

테라폼 리소스를 AWS S3에 저장하여, 코드 관리를 할 수 있으며, 리소스 잠금을 활성화 하여 

main.tf 파일을 생성한다.

별도의 폴더를 만들고 main.tf 파일을 생성하는것을 추천한다.

예를들어 S3라는 폴더를 생성하고 폴더 하위에 main.tf 라는 테라폼 구현 파일을 생성한다.

AWS S3를 원격 상태 스토리지로 사용

S3를 생성하는 테라폼 코드

# 리전 선택 및 설정
provider "aws" {
  region = "ap-northeast-2"
}

# S3버킷을 생성
resource "aws_s3_bucket" "terraform-state" {
  bucket = "terraform-up-and-running-state-seung"

  ## 실수로 S3 버킷을 삭제하는 것을 방지
  lifecycle {
    prevent_destroy = true
  }

  ## 코드 이력을 관리하기 위해 상태 파일의 버전 관리를 활성화
  versioning {
    enabled = true
  }

  ## 서버 측 암호화를 활성화
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }
}

위의 코드에서 설정한 4가지 인수에 대해 설명

1. bucket: S3 버킷의 이름은 고유해야 하므로, 고유한 이름으로 설정하는것이 중요

2. prevent_destroy: 해당 설정을 true로 할 경우 terraform destroy와 같은 명령어를 통해 자원을 삭제 시 오류와 함께 자동으로 종료된다. 삭제를 원할경우 해당 값을 주석처리 하면 된다.

3. versioning: S3 버킷에 파일이 업로드 될때마다 새 버전을 만들도록 설정, 이를 통해 언제든지 이전버전으로 되돌릴수 있다.

4. server_side_encription_configuration: S3 버킷에 기록된 모든 데이터를 서버측에서 암호화 한다. S3에 파일이 저장될 때마다 암호회 된다.

다이나모 DB를 활용한 테라폼 리소스 잠금 활성화

위에 작성한 코드에 dynamodb_table을 생성하는 코드를 추가한다.

# 다이나모 DB에 테이블을 생성한다.
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"
  }
}

terraform plan을 통해 리소스 생성 계획을 본다.

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_dynamodb_table.terraform_locks will be created
  + resource "aws_dynamodb_table" "terraform_locks" {
      + arn              = (known after apply)
      + billing_mode     = "PAY_PER_REQUEST"
      + hash_key         = "LockID"
      + id               = (known after apply)
      + name             = "terraform-up-and-running-locks"
      + read_capacity    = (known after apply)
      + stream_arn       = (known after apply)
      + stream_label     = (known after apply)
      + stream_view_type = (known after apply)
      + tags_all         = (known after apply)
      + write_capacity   = (known after apply)

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

      + point_in_time_recovery {
          + enabled = (known after apply)
        }

      + server_side_encryption {
          + enabled     = (known after apply)
          + kms_key_arn = (known after apply)
        }

      + ttl {
          + attribute_name = (known after apply)
          + enabled        = (known after apply)
        }
    }
.
.
중간 생략
.
.
Plan: 2 to add, 0 to change, 0 to destroy.

위의 내용을 보면 2개의 리소스가 추가되는것을 확인 할 수 있다. 2개의 리소스는 S3 버킷과 다이나모 DB 리소스일 것이다.

아래의 명령어를 통해 리소스를 생성한다.

terraform plan

terraform apply

생성이 완료되면 아래와 같이 생성이 완료되었다는 메세지가 나온다.

aws_dynamodb_table.terraform_locks: Creating...
aws_s3_bucket.terraform-state: Creating...
aws_s3_bucket.terraform-state: Creation complete after 3s [id=terraform-up-and-running-state-seung]
aws_dynamodb_table.terraform_locks: Creation complete after 7s [id=terraform-up-and-running-locks]
╷
│ Warning: Argument is deprecated
│
│   with aws_s3_bucket.terraform-state,
│   on main.tf line 7, in resource "aws_s3_bucket" "terraform-state":
│    7: resource "aws_s3_bucket" "terraform-state" {
│
│ Use the aws_s3_bucket_server_side_encryption_configuration resource instead
│
│ (and one more similar warning elsewhere)
╵

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

테라폼 코드를 S3에 저장하기 위한 방법

# terraform 리소스를 S3에 저장하기 위한 설정
terraform {
  backend "s3" {
    ## 이전에 생성한 버킷 이름으로 변경 
    bucket = "terraform-up-and-running-state-seung"
    key    = "global/s3/terraform.tfstate"
    region = "ap-northeast-2"

    ## 이전에 생성한 다이나모DB 테이블 이름으로 변경
    dynamodb_table = "terraform-up-and-running-locks"
    encrypt        = true
  }
}

위 코드에서 설정 내용을 하나씩 살펴보면 아래와 같다.

bucket: 사용할 S3 버킷 명 이다. 이전에 생성한 버킷 명으로 변경 해줘야 한다.

key: 테라폼 상태 파일을 저장할 S3 버킷 내의 파일의 경로이다. 해당 경로를 global/s3/terraform.tfstate로 설정한 것을 추후에 알아본다.

dynamodb_table: 잠금에 사용할 다이나모DB 테이블 이다. 이 테이블 이름을 위에서 생성한 다이나모DB 테이블의 이름으로 변경 해주어야 한다.

여기서 주의할 점은 테라폼이 S3버킷에 상태 파일을 저장하도록 지시 하려면 terraform init 명령을 재 실행해 줘야 한다. init 명령을 통해 공급자 코드를 다운로드 할 수 있을 뿐만 아니라 테라폼의 백엔드도 구성이 가능하다.

init 명령은 멱등성이 있으므로 여러번 사용해도 리소스에는 변경이 없다.

명령어를 통해 terraform의 리소스를 S3에 저장하도록 구현 한다.

terraform init

terraform init을 수행하면 아래와 같은 안내 메세지가 출력된다.

내용은 테라폼은 로컬 디스크에 이미 상태파일이 있음을 자동으로 감지하고, 새로운 S3 백엔드에 복사한다는 메세지이다. yes를 입력하면 테라폼 상태가 S3 버킷에 저장 된다. 그리고 실제로 S3가 생성되었는지 확인을 해본다.

C:\Users\hist\terraform\S3>terraform init

Initializing the backend...
Do you want to copy existing state to the new backend?
  Pre-existing state was found while migrating the previous "local" backend to the
  newly configured "s3" backend. No existing state was found in the newly
  configured "s3" backend. Do you want to copy this state to the new "s3"
  backend? Enter "yes" to copy and "no" to start with an empty state.

  Enter a value: yes


Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v4.9.0

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.

S3 저장소 확인

- S3로 이동하여 파일이 정상적으로 생성되었는지 확인하면 아래와 같다.

DynamoDB 확인

DynamoDB에서 테이블을 확인하면 아래와 같이 정상적으로 생성된것을 확인 할 수 있다.

정상수행 확인

백엔드 옵션이 활성화 되면 테라폼은 명령을 실행하기 전에 이 S3버킷에서 최신 상태를 자동으로 가져온다. 그리고 명령을 수행 후에는 최신 상태를 자동으로 S3버킷으로 푸시하여 저장한다. 이 동작이 정상적으로 구동이 되는지 확인한다.

아래 명령어를 추가하여 terraform 리소스를 정상 적으로 저장 하는지 테스트 한다. terraform apply를 통해 적용을 하고 결과를 확인한다.

# S3 버켓에 테라폼 리소스가 정상적으로 저장 되고 있는지 테스트
output "s3_bucket_arn" {
  value       = aws_s3_bucket.terraform-state.arn
  description = "The ARN of the S3 bucket"
}

# DynamoDB에 정상적으로 응답이 오는지 테스트
output "dynamodb_table_name" {
  value       = aws_dynamodb_table.terraform_locks.name
  description = "The name of the Dynamo table"
}

결과 확인

Outputs를 확인하면 정상적으로 결과를 출력한 것을 볼 수 있다.

Changes to Outputs:
  + dynamodb_table_name = "terraform-up-and-running-locks"
  + s3_bucket_arn       = "arn:aws:s3:::terraform-up-and-running-state-seung"

You can apply this plan to save these new output values to the Terraform state, without changing any real infrastructure.
.
.
.
Outputs:

dynamodb_table_name = "terraform-up-and-running-locks"
s3_bucket_arn = "arn:aws:s3:::terraform-up-and-running-state-seung"

콘솔로 접속하여 S3 버전 및 DynamoDB를 확인한다.

terraform 리소스를 이와 같이 S3에 저장을 하면 코드가 변경되면 새로운 파일로 저장이 되기 때문에 이전 데이터로의 롤백이 쉽고 이력이 남는다는 장점이 있다.

하지만 단점도 존재 하는데 첫번째 단점은 AWS자원에 종속된다는 단점과 자원을 삭제 할때의 문제점 등이 존재 한다.

자원 삭제 순서

1. 테라폼 코드로 이동하여 backend 구성을 제거 후 terraform init 명령을 재실행하여 테라폼 상태를 로컬 디스크에 다시 복사

2. terraform destroy 명령을 실행하여 S3 버킷 및 다이나모DB 테이블을 삭제

두번째 단점은 backend 블록에서는 변수나 참조를 사용할 수 없다는 점이다. 변수를 사용할 수 없으므로 모든 값을 직접 하드 코딩 하던가 아니면 .hcl 확장자를 가진 파일을 별도로 생성하여 변수를 담고 해당 파일을 함께 실행해야 한다.

또 다른 옵션은 테라폼의 몇 가지 단점을 보완해주는 오픈 소스 도구인 테라그런트를 사용하는 것이다.

테라그런트를 사용하면 버킷 이름, 리전, 다이나모DB 테이블 이름 같은 모든 기본 backend 설정을 하나의 파일에 정의하고 key 매개 변수를 모듈의 상대 경로를 설정하여 구성을 반복하지 않도록 도와준다.