Terraform 실행 흐름과 상태 관리 : .tfstate와 S3 + DynamoDB 백엔드 적용하기

이숭늉·2025년 6월 25일
0

DevOps

목록 보기
15/19
post-thumbnail

🖱️Terraform 실행 흐름과 상태 관리 : .tfstate와 S3 + DynamoDB 백엔드 적용하기

Terraform을 공부하면서 리소스 상태의 흐름을 이해하고 관리하는 방법의 중요성을 느꼈다. 이번 글에서는 Terraform이 리소스를 어떻게 적용하는지, .tfstate는 어떤 역할을 하는지, 그리고 협업을 위한 위한 백엔드 구성까지 실습과 함께 정리해볼 것이다.


AWS 연동 후 적용

우선 Terraform 사용 환경을 aws와 연동하기 위해서는

  • AdministratorAccess 권한이 있는 IAM 사용자에게서 액세스 키를 생성 후,
  • 터미널에서 다음 명령어를 입력하면 된다.
aws configure

AWS Access Key ID [None or 기존 설정 정보]: <액세스 키> 
AWS Secret Access Key [None or 기존 설정 정보]: <시크릿 키> 
Default region name [region]: 리전 영문명 # (예 : us-east-1)
Default output format [format]: json 

# 설정이 제대로 되었는지 확인
cat ~/.aws/credentials

tf 파일에 AWS에 프로비저닝하고 싶은 리소스 코드을 끝냈다면 이제 아래 명령어를 차례로 입력하면 된다.

  1. terraform init
  • 워크페이스에서 프로비저닝 가능한 환경을 만든다. 이때 백엔드 설정이 적용된다.
  1. terraform plan
  • 적용될 변경 사항을 미리 확인한다.
  1. terraform apply
  • 실제로 벤더사 API를 호출해서 인프라를 생성/변경한다.
  • 변경이 완료되면, 변경된 리소스 상태를 반영하여 .tfstate 파일을 업데이트한다.
  1. terraform destroy
  • 정의된 인프라를 제거한다.
  • 리소스 간 의존성을 자동 계산하여 삭제 순서를 정한다.

이는 현재 워크스페이스 내 모든 .tf 파일을 기반으로 실행된다.

terraform apply 시 동작 방식

여기서 terraform apply가 어떤 방식으로 동작하는지를 자세히 살펴보겠다.
이는 다음 세 가지를 비교한다.

  • 선언 상태 (.tf 파일) -> 원하는 최종 결과
  • 저장 상태 (.tfstate) -> 내가 이전에 만든 것의 정보
  • 실제 상태 (API 조회) -> 지금 실제 클라우드에 있는 것

그 후 다음과 같이 판단한다.

  • .tfstate에 있는데 실제 API엔 없다 -> 누가 삭제했네? -> 재생성
  • .tfstate엔 없는데 실제 API에 있다 -> 내가 만든 게 아니네? -> 무시
  • .tf.tfstate가 다르다 -> 설정 변경 요청이네 -> 업데이트

상태 파일 .tfstate과 백엔드 구성

테라폼은 현재 인프라 상태를 .tfstate에 저장해두고 그걸 기준으로 변경 사항을 계획(plan)하고 실행(apply)한다. 기본적으로 이 파일은 워크스페이스의 ./state/terraform.tfstate 위치에 저장되지만, 기본 위치와 다르게 지정하고 싶은 경우 테라폼의 backend 블록에서 지정할 수 있다.
이는 협업 시 중요한데 동시에 동일한 state에 접근이 발생하면 잠금 파일의 내용이 표기되면서 에러가 발생할 수 있다.
그래서 보통 이를 해결하기 위해 AWS의 경우는 S3를 사용한다. 상태 파일을 S3에 저장하고, 동시에 작업할 수 없도록 DynamoDB로 락을 걸면 상태 파일은 암호화되어 안전하게 보관된다.

락 과정

  1. 테라폼이 plan/apply 실행
  2. DynamoDB 테이블에서 LockID라는 항목을 PutItem으로 삽입해 잠금을 건다.
  3. 잠금이 걸려 있으면 다른 사용자는 잠금이 해제될 때까지 대기하거나 에러를 받는다.
  4. 실행이 끝나면 해당 항목을 삭제하여 잠금을 해제한다.

실습 : 백엔드를 S3 + DynamoDB로 설정

  1. S3와 DynamoDB를 콘솔에서 미리 프로비저닝한다.


    테이블을 보면 메타데이터 항목이 하나 존재한다.
  1. main.tfbackend 블록을 아래와 같이 작성한다.
    # main.tf
    terraform {
      required_providers {
        aws = {
            source = "hashicorp/aws"
            version = "~> 5.0"
        }
      }
      backend "s3" {
        bucket = "tf-backend-bucket-0w0"
        key = "study/terraform.tfstate"
        region = "ap-northeast-2"
        dynamodb_table = "tf-lock-table"
        encrypt = true
      }
    }
  2. terraform init을 실행하면 백엔드가 S3로 설정된다.
  1. 간단하게 백엔드 블록 아래에 다음과 같이 프로비저닝할 EC2 리소스 코드를 작성 후, apply한다.

    # EC2
    resource "aws_instance" "tf-instance" {
      ami = "ami-0077297a838d6761d"
      instance_type = "t2.micro"
      key_name = "my-keypair"
      associate_public_ip_address = true
      subnet_id = "subnet-xxxxxx"
      private_ip = "172.31.40.10"
      tags = {
        "Name" = "tf-instance"
      }
    }
    

    EC2도 잘 프로비저닝되었고, S3에 terraform.tfstate 파일이 잘 생성된 것을 확인할 수 있다.


그럼 이제 락이 잘 걸리는지 실험을 해보자.

태그를 살짝 바꿔주고 terraform apply 입력 후, enter a value 상태에서 스탑한다.

다른 터미널에서 변경 사항을 만든 후 apply를 실행하자 에러가 발생한다.

이 상태에서 DynamoDB 콘솔 항목을 보면, 이렇게 Info 값이 있는 잠금 레코드가 생성된 것을 확인할 수 있다.

이 레코드는 락이 해제되면 다시 사라진다.

‼️ 주의할점 : 이때 백엔드 리소스 (S3, DynamoDB)는 반드시 테라폼으로 생성한 모든 리소스를 다 destroy한 뒤, 가장 마지막에 삭제해야 한다.

이상으로 글을 마치겠다!

profile
부지런히 살자

0개의 댓글