5.1 State의 목적과 의미
- 상태 파일은 배포할 때마다 변경되는 프라이빗 API private API로, 오직 테라폼 내부에서 사용하기 위한 것입니다.
- 테라폼 상태 파일을 직접 편집하거나 직접 읽는 코드로 작성해서는 안됩니다.
팀 단위에서 테라폼 운영 시 문제점
- 상태 파일을 저장하는 공유 스토리지 Shared storage for state files
- 각 팀원이 동일한 테라폼 상태 파일 사용을 위해서, 공유 위치에 저장이 필요
- 상태 파일 잠금 Locking state files
- 잠금 기능 없이 두 팀원이 동시에 테라폼 실행 시 여러 테라폼 프로세스가 상태 파일을 동시에 업데이트하여 충돌 가능(경쟁 상태 race condition)
- 상태 파일 격리 Isolating state files
- 예를 들면 테스트 dev 와 검증 stage 과 상용 prodction 각 환경에 대한 격리가 필요
상태 파일 공유로 버전 관리 시스템 비추천
- 수동 오류 Manual error
- 테라폼을 실행하기 전에 최신 변경 사항을 가져오거나 실행하고 나서 push 하는 것을 잊기 쉽습니다(?).
- 팀의 누군가가 이전 버전의 상태 파일로 테라폼을 실행하고, 그 결과 실수로 이전 버전으로 롤백하거나 이전에 배포된 인프라를 복제하는 문제가 발생 할 수 있음.
- 잠금 Locking
- 대부분의 버전 관리 시스템은 여러 명의 팀 구성원이 동시에 하나의 상태 파일에 terraform apply 명령을 실행하지 못하게 하는 잠금 기능이 제공되지 않음.
- 시크릿 Secrets
- 테라폼 상태 파일의 모든 데이터는 평문으로 저장됨. 민감 정보가 노출될 위험.
지원되는 원격 백엔드 : AWS S3, Azure Blob Storage, Google Cloud Storage, Consul, Postgres database, k8s secret 등 - 링크
- 수동 오류 해결 : plan/apply 실행 시 마다 해당 백엔드에서 파일을 자동을 로드, apply 후 상태 파일을 백엔드에 자동 저장
- 잠금 : apply 실행 시 테라폼은 자동으로 잠금을 활성화, -lock-timout=<TIME> 로 대기 시간 설정 지정 가능
- 시크릿 : 대부분 원격 백엔드는 기본적으로 데이터를 보내거나 상태 파일을 저장할 때 암호화하는 기능을 지원
상태 확인 실습
# 파일 내용을 바꾸며 재배포
terraform plan && terraform apply -auto-approve
# 상태 파일 비교(바로 직전 상태 백업)
ls terraform.tfstate*
terraform.tfstate terraform.tfstate.backup
diff terraform.tfstate terraform.tfstate.backup
< "serial": 6,
---
> "serial": 4,
...
5.2 State 동기화
테라폼 구성 파일은 기존 State와 구성을 비교해 실행 계획에서 생성, 수정, 삭제 여부를 결정한다
- 테라폼 구성과 State 흐름 : Plan 과 Apply 중 각 리소스에 발생할 수 있는 네 가지 사항, 아래 실행 계획 출력 기호와 의미기호 의미
+ Create - Destroy -/+ Replace ~ Updated in-place - Replace 동작은 기본값을 삭제 후 생성하지만 lifecycle의 create_before_destroy 옵션을 통해 생성 후 삭제 설정 가능
유형별 실습
유형 별 실습 + 문제상황 → 복구 import* : 테라폼 구성에 추가된 리소스와 State에 따라 어떤 동작이 발생하는지 다음 표로 살펴본다유형 구성 리소스 정의(*.tf) State 구성 데이터 실제 리소스 기본 예상 동작
1 | 있음 | 리소스 생성 | ||
2 | 있음 | 있음 | 리소스 생성 | |
3 | 있음 | 있음 | 있음 | 동작 없음 |
4 | 있음 | 있음 | 리소스 삭제 | |
5 | 있음 | 동작 없음 |
유형1 : 신규 리소스 정의 → Apply ⇒ 리소스 생성
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 : 실제 리소스 수동 제거 → Apply ⇒ 리소스 생성
# 실제 리소스 수동 제거
aws iam delete-user --user-name mytest1
aws iam delete-user --user-name mytest2
aws iam list-users | jq
terraform state list
# 아래 명령어 실행 결과 차이는?
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 : Apply → Apply ← 코드, 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 : 코드에서 일부 리소스 삭제 → Apply
# 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 파일 삭제 → plan/apply ← 책에는 없는 내용
# 실수로 tfstate 파일 삭제
terraform state list
aws_iam_user.myiamuser1
rm -rf terraform.tfstate*
#
terraform plan
aws iam list-users | jq
terraform plan -refresh=false
#
terraform apply -auto-approve
terraform state list
cat terraform.tfstate | jq
# iam 사용자 리스트 확인
aws iam list-users | jq
⇒ 위 상황에서 복구? 하는 방법은? import 등 방법이 있습니다!
유형7 : 실수로 tfstate 파일 삭제 시 → import 로 tfstate 파일 복구 - Docs Tutorialshttps://malwareanalysis.tistory.com/633
# 실행
# iam 사용자 리스트 확인
$ aws iam list-users | jq
# import 도움말 : 빨간색 설명 출력...
$ terraform import
# ADDR은 리소스주소 , ID는
# terraform [global options] import [options] ADDR ID
$ terraform import aws_iam_user.myiamuser1 mytest1
aws_iam_user.myiamuser1: Importing from ID "mytest1"...
aws_iam_user.myiamuser1: Import prepared!
Prepared aws_iam_user for import
aws_iam_user.myiamuser1: Refreshing state... [id=mytest1]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
#
$ terraform state list
$ cat terraform.tfstate | jq
$ terraform apply -auto-approve
- 다음 실습을 위해 삭제: terraform destroy -auto-approve
5.3 Terraform Backend
backend "s3" {
#bucket = "<닉네임>-hello-t1014-remote-backend"
bucket = "gasida-hello-t1014-remote-backend"
key = "terraform/state-test/terraform.tfstate"
region = "ap-northeast-2"
#dynamodb_table = "terraform-lock" 주석처리
}
- 테라폼의 backend 블록에는 변수나 참조를 사용 할 수 없음 → 아래 코드 사용할 수 없음
- 그 결과 S3 버킷 이름, 리전, DynamoDB 테이블 이름을 모두 테라폼 모듈에 수동으로 복사붙여녛어야 함, 심지어 key 값은 중복되면 안되며 고유하게 넣어야함
- partial configuration 을 통해 일부 매개 변수를 전달해서 사용 할 수 있음 - 링크
- 다만, 이 경우에도 모듈마다 서로 다른 key 값을 설정해야 하기 때문에 key 매개 변수는 테라폼 코드에 있어야함
- 부분적으로 구성한 것들을 모두 결합하려면 -backend-config 인수와 함께 terraform init 명령을 실행
- terraform init -backend-config=backend.hcl
⇒ 위 단점을 보완해주는 오픈 소스 테라그런트(Terragrunt)가 있음
5.4 워크스페이스
상태 파일 격리 소개 State File Isolation
- 테라폼 상태를 격리하지 않았을 때 발생하는 일 - 링크
- 환경을 격리하는 방법
- 작업 공간을 통한 격리 Isolation via workspaces
- 동일한 구성에서 빠르고 격리된 테스트 환경에 유용
- 파일 레이아웃을 이용한 격리 Isolation via file layout
- 보다 강력하게 분리해야 하는 운영 환경에 적합
- 테라폼 프로젝트의 파일 레이아웃 설명
- 각 테라폼 구성 파일을 분리된 폴더에 넣기. (예. stage , prod)
- 각 환경에 서로 다른 백엔드 구성. (예. S3 버킷 백엔드의 AWS 계정을 분리)
[예시]
최상위 폴더
- stage : 테스트 환경과 같은 사전 프로덕션 워크로드 workload 환경
- prod : 사용자용 맵 같은 프로덕션 워크로드 환경
- mgmt : 베스천 호스트 Bastion Host, 젠킨스 Jenkins 와 같은 데브옵스 도구 환경
- global : S3, IAM과 같이 모든 환경에서 사용되는 리소스를 배치
각 환경별 구성 요소
- vpc : 해당 환경을 위한 네트워크 토폴로지
- services : 해당 환경에서 서비스되는 애플리케이션, 각 앱은 자체 폴더에 위치하여 다른 앱과 분리
- data-storage : 해당 환경 별 데이터 저장소. 각 데이터 저장소 역시 자체 폴더에 위치하여 다른 데이터 저장소와 분리
명명 규칙 naming conventions (예시)
- variables.tf : 입력 변수
- outputs.tf : 출력 변수
- main-xxx.tf : 리소스 → 개별 테라폼 파일 규모가 커지면 특정 기능을 기준으로 별도 파일로 분리 (ex. main-iam.tf, main-s3.tf 등) 혹은 모듈 단위로 나눔
- dependencies.tf : 데이터 소스
- providers.tf : 공급자
소개 : State를 관리하는 논리적인 가상 공간을 워크스페이스라고 한다 - 링크
- 테라폼 구성 파일은 동일하지만 작업자는 서로 다른 State를 갖는 실제 대상을 프로비저닝할 수 있다.
- 워크스페이스는 기본 default로 정의된다. 로컬 작업 환경의 워크스페이스 관리를 위한 CLI 명령어로 workspace가 있다.
# 새 작업 공간 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'
# graph 확인
terraform graph > graph.dot
# 새 작업 공간 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
- 장점
- 하나의 루트 모듈에서 다른 환경을 위한 리소스를 동일한 테라폼 구성으로 프로비저닝하고 관리
- 기존 프로비저닝된 환경에 영향을 주지 않고 변경 사항 실험 가능
- 깃의 브랜치 전략처럼 동일한 구성에서 서로 다른 리소스 결과 관리
- 단점
- State가 동일한 저장소(로컬 또는 백엔드)에 저장되어 State 접근 권한 관리가 불가능
- 모든 환경이 동일한 리소스를 요구하지 않을 수 있으므로 테라폼 구성에 분기 처리가 다수 발생 가능
- 프로비저닝 대상에 대한 인증 요소를 완벽히 분리하기 어려움⇒ 해결하기 위해 루트 모듈을 별도로 구성하는 디렉터리 기반의 레이아웃을 사용할 수 있다 or Terraform Cloud 환경의 워크스페이스를 활용
- → 가장 큰 단점은 완벽한 격리가 불가능
'🍀 Cloud Architect > IaC' 카테고리의 다른 글
[Terraform] 테라폼으로 EKS 배포하기 (0) | 2024.07.27 |
---|---|
[Terraform] Module & Runner (0) | 2024.07.14 |
[Terraform] 테라폼 Provider (0) | 2024.07.06 |
[Terraform] 프로비저너, terraform_data, moved, CLI 환경변수 (0) | 2024.06.30 |
[Terraform] 테라폼 반복문, 조건문, 함수 (0) | 2024.06.29 |