DDetB.Log
article thumbnail
Published 2023. 7. 29. 22:22
Terraform - State DevOps/Terraform
이 포스팅은 CloudNet@ 팀이 진행하는 테라폼 기초 입문 스터디에 참여하며 ‘테라폼으로 시작하는 IaC’ 책을 기준하여 정리한 글입니다.

테라폼은 Stateful 애플리케이션이다. 프로비저닝 결과에 따른 State를 저장하고 프로비저닝한 모든 내용을 JSON 형태로 저장하여 상태를 추적한다. State에는 작업자가 정의한 코드와 실제 반영된 프로비저닝 결과를 저장하고, 이 정보를 토대로 이후의 리소스 생성, 수정, 삭제에 대한 동작 판단 작업을 수행한다.

State의 목적과 의미

State의 역할은 다음과 같다.

  • 테라폼 구성과 실제를 동기화하고, 각 리소스에 고유한 아이디를 맵핑
  • 리소스 종속성과 같은 메타데이터를 저장하고 추적
  • 테라폼 구성으로 프로비저닝된 결과를 캐싱하는 역할을 수행

vpc.tf

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

resource "aws_vpc" "myvpc" {
  cidr_block       = "10.10.0.0/16"

  tags = {
    Name = "t101-study"
  }
}

실행 및 확인

$ terraform init && terraform plan && terraform apply -auto-approve
...

$ cat terraform.tfstate | jq
...
"serial": 2,
...

vpc.tf 수정 - 태그 수정

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

resource "aws_vpc" "myvpc" {
  cidr_block       = "10.10.0.0/16"

  tags = {
    Name = "tf-state"
  }
}

실행 및 확인

$ terraform plan && terraform apply -auto-approve

$ ls terraform.tfstate*
terraform.tfstate        terraform.tfstate.backup

$ diff terraform.tfstate terraform.tfstate.backup
<   "serial": 4,
---
>   "serial": 2,
...

=> 백업 파일 생성됨을 확인

State 동기화

테라폼 구성 파일은 기존 State와 구성을 비교해 실행 계획에서 생성, 수정, 삭제 여부를 결정한다.

유형 구성 리소스 정의 State 구성 데이터 실제 리소스 기본 예상 동작
1 있음     리소스 생성
2 있음 있음   리소스 생성
3 있음 있음 있음 동작 없음
4   있음 있음 리소스 삭제
5     있음 동작 없음

구성 리소스와 State, 그리고 실제 리소스 여부에 따라 위와 같은 시나리오가 예상된다. 다음은 위 표의 각 유형과 예외상황에 대한 동작을 확인한다.

유형1 : 신규 리소스 정의

main.tf

locals {
  name = "mytest"
}

resource "aws_iam_user" "myiamuser1" {
  name = "${local.name}1"
}

resource "aws_iam_user" "myiamuser2" {
  name = "${local.name}2"
}

실행 및 확인

$ terraform init && terraform apply -auto-approve
$ terraform state list
$ terraform state show aws_iam_user.myiamuser1

$ ls *.tfstate
$ cat terraform.tfstate | jq

$ terraform apply -auto-approve
$ ls *.tfstate

# iam 사용자 리스트 확인
$ aws iam list-users | jq

 

유형2 : 실제 리소스 수동 제거

실행 및 확인

$ aws iam delete-user --user-name mytest1
$ aws iam delete-user --user-name mytest2
$ aws iam list-users | jq

$ terraform plan
$ terraform plan -refresh=false
$ cat terraform.tfstate | jq .serial

$ terraform apply -auto-approve
$ terraform state list
$ cat terraform.tfstate | jq .serial

# iam 사용자 리스트 확인
$ aws iam list-users | jq

 

유형3 : 코드, State, 형상 모두 일치한 경우

실행 및 확인

$ terraform apply -auto-approve
$ cat terraform.tfstate | jq .serial
$ terraform apply -auto-approve
$ cat terraform.tfstate | jq .serial
$ terraform apply -auto-approve
$ cat terraform.tfstate | jq .serial

 

유형4 : 코드에서 일부 리소스 삭제

main.tf 수정

locals {
  name = "mytest"
}

resource "aws_iam_user" "myiamuser1" {
  name = "${local.name}1"
}

실행 및 확인

$ terraform apply -auto-approve
$ terraform state list
$ terraform state show aws_iam_user.myiamuser1

$ ls *.tfstate
$ cat terraform.tfstate | jq

# iam 사용자 리스트 확인
$ aws iam list-users | jq

 

유형6 : 실수로 tfstate 파일 삭제

실행 및 확인

# 실수로 tfstate 파일 삭제
$ rm -rf terraform.tfstate*

$ terraform plan
$ terraform plan -refresh=false

$ terraform apply -auto-approve
$ terraform state list
$ cat terraform.tfstate | jq

# iam 사용자 리스트 확인
$ aws iam list-users | jq

# iam user 삭제
$ aws iam delete-user --user-name mytest1

 

워크스페이스

State를 관리하는 논리적인 가상 공간을 워크스페이스라고 한다. 테라폼 구성파일은 동일하지만 작업자는 서로 다른 State를 갖는 실제 대상을 프로비저닝할 수 있다. 워크스페이스의 기본값은 default로 정의된다.

main.tf

resource "aws_instance" "mysrv1" {
  ami           = "ami-0ea4d4b8dc1e46212"
  instance_type = "t2.micro"
  tags = {
    Name = "t101-week4"
  }
}

실행 및 확인

# [분할/터미널1] 모니터링
$ export AWS_PAGER=""
$ while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text ; echo "------------------------------" ; sleep 1; done

$ terraform init && terraform apply -auto-approve
$ terraform state list

$ cat terraform.tfstate | jq -r '.resources[0].instances[0].attributes.public_ip'
$ cat terraform.tfstate | jq -r '.resources[0].instances[0].attributes.private_ip'

# terraform.tfstate에 private 담긴 내용은?
$ cat terraform.tfstate | jq -r '.resources[0].instances[0].private' | base64 -d | jq

# 워크스페이스 확인
$ terraform workspace list

신규 워크스페이스 생성 및 확인

# 새 작업 공간 workspace 생성 : mywork1
$ terraform workspace new mywork1
$ terraform workspace show

# 서브 디렉터리 확인
$ tree terraform.tfstate.d
terraform.tfstate.d
└── mywork1

# plan 시 어떤 결과 내용이 출력되나요?
$ terraform plan

# apply 해보자!
$ terraform apply -auto-approve


# 워크스페이스 확인
$ terraform workspace list

$ cat terraform.tfstate | jq -r '.resources[0].instances[0].attributes.public_ip'
$ cat terraform.tfstate.d/mywork1/terraform.tfstate | jq -r '.resources[0].instances[0].attributes.public_ip'


# 새 작업 공간 workspace 생성 : mywork2
$ terraform workspace new mywork2

# 서브 디렉터리 확인
$ tree terraform.tfstate.d
...

# plan & apply
$ terraform plan && terraform apply -auto-approve
$ cat terraform.tfstate | jq -r '.resources[0].instances[0].attributes.public_ip'
$ cat terraform.tfstate.d/mywork1/terraform.tfstate | jq -r '.resources[0].instances[0].attributes.public_ip'
$ cat terraform.tfstate.d/mywork2/terraform.tfstate | jq -r '.resources[0].instances[0].attributes.public_ip'

# workspace 정보 확인
$ terraform workspace show
$ terraform workspace list

# 실습 리소스 삭제
$ terraform workspace select default
$ terraform destroy -auto-approve
$ terraform workspace select mywork1
$ terraform destroy -auto-approve
$ terraform workspace select mywork2
$ terraform destroy -auto-approve
profile

DDetB.Log

@DDetMok

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!