Terraform | Terraform State
테라폼은 인프라가 변경될 때마다 형상을 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가지의 권한이 필요합니다.
- https://www.terraform.io/language/settings/backends/s3#s3-bucket-permissions
- https://www.terraform.io/language/settings/backends/s3#dynamodb-table-permissions
이후 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
감사합니다.