Terraform 상태 관리하기

변재한·2023년 5월 11일
0
post-thumbnail

Terraform 상태 관리하기

Terraform 상태란 ?

테라폼을 실행할 때마다 테라폼은 생성한 인프라에 대한 정보를 테라폼 상태 파일에 기록함.

기본적으로 /jaehan/hi 폴더에서 테라폼을 실행하면 테라폼은 /jaehan/hi/terraform.tfstate 파일을 생성함.

해당 파일에는 tf 확장자를 가진 파일의 테라폼 리소스가 실제 리소스의 표현으로 매핑되는 내용을 기록하는 JSON 형식이 포함됨.

**ALB 실습 시 생성된 terraform.tfstate**

{
  "version": 4,
  "terraform_version": "1.3.9",
  "serial": 83,
  "lineage": "437cff4a-6990-cf45-4876-0dcc4fb63f30",
  "outputs": {
    "latest_ami_id": {
      "value": "ami-034000b759564de42",
      "type": "string"
    }
  },
  "resources": [
    {
      "mode": "data",
      "type": "aws_ami",
      "name": "ubuntu",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "architecture": "x86_64",
            "arn": "arn:aws:ec2:ap-northeast-2::image/ami-034000b759564de42",
            "block_device_mappings": [
              .
							.
							.
							.

테라폼은 위 상태파일을 기준으로 리소스의 ID를 이용해 최신상태를 가져와서 테라폼의 구성과 비교하여 어느 변경 사항을 적용해야 하는지 결정.

때문에, 여러 명이 테라폼을 사용하게 되면 동기화 문제와 동시쓰기 문제가 발생함.

상태파일 동기화

협업하는 과정에서 상태파일이 동기화되어 있지 않으면 다른 사람이 작업한 내용이 사라질 수 있거나 예상치 못한 결과를 초래할 수 있음.

해결방법

상태파일 동기화 문제는 테라폼 backend를 이용하여 해결할 수 있음.

backend는 상태파일을 저장하는 위치를 설정.

원격 저장소의 예

AWS S3, Azure Blob Storage, Google Cloud Storage, Consul, Postgres database 등

실습

먼저 S3를 생성해야 함.

resource "aws_s3_bucket" "terraform-state" {
  bucket = "terraform-jaehan-state"

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

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

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

앞선 실습 ASG 폴더에 backend.tf 생성

terraform {
  backend "s3" {
    bucket = "terraform-jaehan-state"
    key    = "terraform.tfstate"
    region = "ap-northeast-2"
  }
}

tf init 명령어 실행!

이후에 terraform apply 명령어를 수행할 시 아래 사진처럼 상태파일이 더이상 로컬에 생성되지 않고,

backend로 지정한 S3에 생성되는 것을 확인할 수 있다.

동시쓰기 문제


상태파일 동기화 문제에 이어 **동시에 여러 사용자가 상태파일을 업데이트** 할 시

충돌을 일으켜 예상치 않은, 원하지 않는 문제가 발생할 수 있다.

⇒ 잠금 기능(Locking) 필요

대부분의 backend는 기본적으로 잠금 기능을 지원.

But, AWS의 S3는 앞선 문제를 해결해주지 않고, 다이나모 DB를 곁들여서 사용

먼저, S3(backend)와 DynamoDB(locks) 사전생성

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

# S3 Bucket 생성
resource "aws_s3_bucket" "terraform-state" {
  bucket = "terraform-jaehan-state"

  lifecycle {
    prevent_destroy = true
  }

  versioning {
    enabled = true
  }

  server_side_encryption_configuration {
    rule {
        apply_server_side_encryption_by_default {
          sse_algorithm = "AES256"
        }
    }
  }
}

# DynamoDB 생성
resource "aws_dynamodb_table" "terraform_locks" {
  name = "terraform_jaehan_locks"
  billing_mode = "PAY_PER_REQUEST"
  hash_key = "LockID"

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

output "dynamodb_table_name" {
  value       = aws_dynamodb_table.terraform_locks.name
  description = "The name of DynamoDB table"
}

DynamoDB 생성 화면


실습


Terraform으로 배포할 인프라 구성 - 단일 웹서버


단일 웹서버 포스트

단일 웹서버 Terraform 코드 apply 중 DynamoDB 테이블 화면

apply 후

더 나아가서..


**테라폼의 backend 블록에서는 변수나 참조를 사용할 수 없다!**

# 실행되지 않는 코드
terraform {
  backend "s3" {
    profile = "example"
    bucket = var.bucket
    key = "terraform.tfstate"
    region = var.region

    dynamodb_table = var.dynamodb_table
    encrypt = true
  }
}

즉, 관련된 모든 이름 등을 테라폼 백엔드를 구성할 때마다 수동으로 복사해서 붙여넣어야 한다.

⇒ 복사해서 수동 변경 작업을 자주 하면 에러 발생 확률 Up!

해결방법


backend.hcl 파일 활용

  • 반복되는 인수를 별도의 파일로 추출하여 활용
# backend.hcl
bucket = "terraform-jaehan-state"
region = "ap-northeast-2"
dynamodb_table = "terraform_jaehan_locks"
encrypt = true

모듈(이후 나올 예정)마다 서로 다른 key 값을 설정해야 하기 때문에 일단은 key만 남겨둔다고 한다.

그 외에 인수는 다 제거~

terraform {
  backend "s3" {
    profile = "example"
    key = "workspace/terraform.tfstate"
  }
}

이후 구성한 것들을 결합하여 init 명령어 실행

$ tf init -backend-config=backend.hcl
profile
Infra and Devops 엔지니어가 되고 싶어용

0개의 댓글