ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Terraform | Terraform State
    Iac 2022. 1. 23. 21:38

    테라폼은 인프라가 변경될 때마다 형상을 tfstate파일에 기록함으로써 현재 생성되어 있는 인프라 형상을 관리합니다.

    따라서 테라폼으로 인프라를 생성하면 현재 디렉터리에 terraform.tfstate라는 파일이 생성되는 것을 확인할 수 있습니다.

     

    terraform backend

    로컬에서 state파일을 사용할 경우 다른 개발자와 tfstate파일을 공유하기에는 번거로움이 있습니다.

    이러한 문제를 해결하고자 테라폼에서는 backend라는 기능을 제공합니다.

     

    terraform backend라는 것은 생성되는 tfstate파일을 AWS의 S3, kubernetes 등 따로 저장되도록 하여

    여러 사용자들에게 공유할 수 있도록 하는 것입니다.

     

    AWS를 사용하고 있기 때문에 terraform backend로 S3를 사용하는 예제를 작성해보도록 하겠습니다.

     

    먼저 terraform backend 될 S3버킷을 생성합니다.

    # s3.tf
    resource "aws_s3_bucket" "terraform_state" {
        bucket = "bob-terraform-state-bucket"
        acl    = "private"
    
        # 코드의 이력을 관리하기 위해 활성화 합니다.
        versioning {
            enabled = true
        }
    
        # 서버 측 암호화를 활성화 합니다.(S3에 저장된 파일이 암호화 됩니다.)
        server_side_encryption_configuration {
            rule {
                apply_server_side_encryption_by_default {
                    sse_algorithm = "AES256"
                }
            }
        }
        
        # s3에 파일이 존재 하더라도 강제로 지우도록 합니다.
        force_destroy = true
    
        tags = {
            Name        = "state bucket"
        }
    }

     

    terraform init
    terraform apply

     

    버킷을 생성하게 되면 현재 경로에 terraform.tfstate파일이 존재하는 것을 확인할 수 있습니다.

     

    이제 terraform backend로 S3를 지정하여 terraform.tfstate을 만들어둔 S3버킷으로 관리될 수 있도록 합니다. 

    # main.tf
    provider "aws" {
      region = "ap-northeast-2"
    
      default_tags {
        tags = {
          Terraform = "true"
        }
      }
    }
    
    terraform {
        backend "s3" {
          bucket = "bob-terraform-state-bucket"
          key    = "terraform.tfstate"
          region = "ap-northeast-2"
        }
    }

     

    terraform init을 하게되면 local에 있던 terraform.tfstate파일의 내용이 사라지고 만들어둔 S3에 해당 tfstate파일이 들어가 있는 것을 확인할 수 있습니다.

     

    하지만 이렇 게 공유된 tfstate을 여러 사용자가 동시에 사용한다고 했을 때 문제가 발생할 수 있습니다.

    예를 들어 두 명의 개발자가 서로 다르게 인프라를 변경을 한다면 변경된 내용을 tfstate에 지정하게 되는데 분명 충돌이 일어날 것입니다.

     

    따라서 terraform에는 잠금(lock) 기능을 제공합니다.

    잠금 기능이란 한 명이 apply를 통해서 tfstate를 변경하는 작업을 진행 중이라면 다른 개발자는 apply를 진행할 수 없는 상태를 말합니다.

     

    잠금 기능을 이용하기 위해서는 AWS의 DynamoDB가 필요합니다.

    # dynamodb.tf
    resource "aws_dynamodb_table" "terraform_locks" {
        name           = "bob-terraform-locks"
        billing_mode   = "PAY_PER_REQUEST"
        hash_key       = "LockID"
    
        attribute {
            name = "LockID"
            type = "S"
        }
    }

    위와 같이 DynamoDB를 작성 후 apply를 통해 생성합니다.

     

    추가적으로 해당 S3에서 tfstate를 사용하기 위해서는 IAM계정에 다음 2가지의 권한이 필요합니다.

    이후 main.tf에 설정된 terraform backend설정을 변경합니다

    # main.tf
    ...
    terraform {
        backend "s3" {
          bucket = "bob-terraform-state-bucket"
          key    = "terraform.state"
          region = "ap-northeast-2"
    	  
          # dynamodb추가
          dynamodb_table = "bob-terraform-locks"
          encrypt = true
        }
    }

    설정을 변경한 후 terraform init -migrate-state을 이용하여 init을 하게 되면 앞으로 변경되는 state에 대해서 적용이 되는 걸 확인할 수 있습니다.

     

    terraform workspace

    마지막으로 하나의 프로젝트에서 하나의 tfstate가 아닌 각각의 tfstate를 사용하고 싶을 경우 테라폼에서 제공하는 workspace기능을 사용할 수 있습니다.

     

    명령어

    현재 사용중인 workspace를 조회합니다.

    terraform workspace show

    생성되어있는 모든 workspace를 조회합니다.

    terraform workspace list

    새로운 workspace를 생성합니다.

    # prod라는 workspace를 생성합니다.
    terraform workspace new prod

    만들어진 workspace를 선택합니다.

    terraform workspace select prod

     

    workspace를 생성할 경우 위에서 생성된 내용이 아닌 완전히 새로운 tfstate인 것을 확인할 수 있습니다.

     

    간단한 예시로 다음과 같이 사용할 수 있습니다.

    # Prod환경에서와 test환경에서 인스턴스 타입을 다르게 사용하는 예시
    resource "aws_instance" "web" {
      ami           = data.aws_ami.ubuntu.id
      instance_type = terraform.workspace == "prod" ? "m5.large" : "t2.micro"
    ...
    }

     

    마무리

    테라폼을 사용하면서 state파일을 관리하는 방법들에 대해서 정리해보았습니다.

     

    실행한 예제를 삭제하기 위해서는 다음과같이 terraform backend를 지정한 것을 local로 돌린 후 삭제를 해야 에러 없이 삭제를 진행할 수 있습니다.

    # main.tf
    provider "aws" {
      region = var.region
    
      default_tags {
        tags = {
          Terraform = "true"
        }
      }
    }
    
    # terraform {
    #     backend "s3" {
    #       bucket = "bob-terraform-state-bucket"
    #       key    = "terraform.state"
    #       region = "ap-northeast-2"
    
    #       dynamodb_table = "bob-terraform-locks"
    #       encrypt = true
    #     }
    # }

    terraform backend를 지정한 부분을 주석, 삭제 후 init를 진행하여 tfstate를 local에서 관리되도록 변경합니다.

    terraform init -migrate-state

    모든 리소스를 삭제합니다.

    terraform destroy

    감사합니다.

    'Iac' 카테고리의 다른 글

    Terraform | EKS 만들어 보기  (0) 2022.01.28
    Terraform | Terraform 버전관리  (0) 2022.01.21
    Terraform | Terraform 이란  (0) 2022.01.20
Designed by Tistory.