State
테라폼 State 소개 및 실습 - 블로그 Github
State의 목적과 의미
상태 파일 확인 실습
mkdir 5.0 && cd 5.0
touch 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
# 상태 파일 확인(VSCODE) : JSON 형식
ls
cat terraform.tfstate | jq
...
"serial": 2,
...
# 아래 정보는 terraform.tfstate 정보를 통해 출력
terraform state list
terraform state show aws_vpc.myvpc
확인
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_vpc" "myvpc" {
cidr_block = "10.10.0.0/16"
tags = {
Name = "tf-state"
}
}
태그 수정 후 확인
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_vpc" "myvpc" {
cidr_block = "10.10.0.0/16"
tags = {
Name = "tf-state"
}
}
# 배포 : plan 시 tfstate 상태와 코드 내용을 비교해서 검토
terraform plan && terraform apply -auto-approve
# 상태 파일 비교 : 백업 파일 생성됨
ls terraform.tfstate*
terraform.tfstate terraform.tfstate.backup
diff terraform.tfstate terraform.tfstate.backup
< "serial": 4,
---
> "serial": 2,
...
한 번 더 수정
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_vpc" "myvpc" {
cidr_block = "10.10.0.0/16"
tags = {
Name = "tf-state-tag-change"
}
}
# 배포
terraform plan && terraform apply -auto-approve
# 상태 파일 비교(바로 직전 상태 백업)
ls terraform.tfstate*
terraform.tfstate terraform.tfstate.backup
diff terraform.tfstate terraform.tfstate.backup
< "serial": 6,
---
> "serial": 4,
...
확인
삭제
terraform destroy -auto-approve
이론
State 동기화
소개 : 테라폼 구성 파일은 기존 State와 구성을 비교해 실행 계획에서 생성, 수정, 삭제 여부를 결정한다
- 상태 파일은 배포할 때마다 변경되는 프라이빗 API private API로, 오직 테라폼 내부에서 사용하기 위한 것입니다.
- 테라폼 상태 파일을 직접 편집하거나 직접 읽는 코드로 작성해서는 안됩니다.
팀 단위에서 테라폼 운영 시 문제점
- 상태 파일을 저장하는 공유 스토리지 Shared storage for state files
- 각 팀원이 동일한 테라폼 상태 파일 사용을 위해서, 공유 위치에 저장이 필요
- 상태 파일 잠금 Locking state files
- 잠금 기능 없이 두 팀원이 동시에 테라폼 실행 시 여러 테라폼 프로세스가 상태 파일을 동시에 업데이트하여 충돌 가능(경쟁 상태 race condition)
- 상태 파일 격리 Isolating state files
- 예를 들면 테스트 dev 와 검증 stage 과 상용 prodction 각 환경에 대한 격리가 필요
지원되는 원격 백엔드 : AWS S3, Azure Blob Storage, Google Cloud Storage, Consul, Postgres database, k8s secret 등 - 링크
- 수동 오류 해결 : plan/apply 실행 시 마다 해당 백엔드에서 파일을 자동을 로드, apply 후 상태 파일을 백엔드에 자동 저장
- 잠금 : apply 실행 시 테라폼은 자동으로 잠금을 활성화, -lock-timout=<TIME> 로 대기 시간 설정 지정 가능
- 시크릿 : 대부분 원격 백엔드는 기본적으로 데이터를 보내거나 상태 파일을 저장할 때 암호화하는 기능을 지원
실습을 위해서 5.1 디렉터리를 신규 생성 후 열기 → main.tf 파일 생성 - random_provider password
mkdir 5.1 && cd 5.1
touch main.tf
resource "random_password" "mypw" {
length = 16
special = true
override_special = "!#$%"
}
확인
#
terraform init && terraform plan
ls *.tfstate
#
terraform apply -auto-approve
terraform state list
terraform state show random_password.mypw
# (참고) sensitive value 내용은 테라폼 콘솔에서 보일까요?
echo "random_password.mypw" | terraform console
echo "random_password.mypw.result" | terraform console
# VSCODE에서 확인
ls *.tfstate
cat terraform.tfstate | jq
cat terraform.tfstate | jq | grep result
YLGmKyb3jOuI8sEf
- 테라폼에서는 JSON 형태로 작성된 State를 통해 속성과 인수를 읽고 확인할 수 있다. 테라폼에서는 type과 name으로 고유한 리소스를 분류하며, 해당 리소스의 속성과 인수를 구성과 비교해 대상 리소스를 생성, 수정, 삭제한다.
- State는 테라폼만을 위한 API로 정의할 수도 있다. Plan을 실행하면 암묵적으로 refresh 동작을 수행하면서 리소스 생성의 대상(클라우드 등)과 State를 기준으로 비교하는 과정을 거친다. 이 작업은 프로비저닝 대상의 응답 속도와 기존 작성된 State의 리소스 양에 따라 속도 차이가 발생한다. 대량의 리소스를 관리해야 하는 경우 Plan 명령에서 -refresh=false 플래그를 사용해 State를 기준으로 실행 계획을 생성하고, 이를 실행에 활용해 대상 환경과의 동기화 과정을 생략할 수 있다.
# 실행 계획 생성 시 저장되어 있는 State와 실제 형상을 비교하는 기본 실행
time terraform plan
# 실행 계획 생성 시 실제 형상과 비교하지 않고 실행 계획을 생성하는 -refresh=false 옵션
time terraform plan -refresh=false
유형 별 실습 + 문제상황 → 복구 import : 테라폼 구성에 추가된 리소스와 State에 따라 어떤 동작이 발생하는지 다음 표로 살펴본다
유형1 : 신규 리소스 정의 → Apply ⇒ 리소스 생성
- 실습을 위해서 5.2 디렉터리를 신규 생성 후 열기 → main.tf 파일 생성
mkdir 5.2 && cd 5.2
touch 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 : 실제 리소스 수동 제거 → Apply ⇒ 리소스 생성
- 실행
# 실제 리소스 수동 제거
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 : 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
terraform plan -refresh=false
#
terraform apply -auto-approve
terraform state list
cat terraform.tfstate | jq
# iam 사용자 리스트 확인
aws iam list-users | jq
유형7 : 실수로 tfstate 파일 삭제 시 → import 로 tfstate 파일 복구 - Docs Tutorials
실행
# 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
import 실행
Terraform Backend : AWS S3 + DynamoDB
https://developer.hashicorp.com/terraform/language/settings/backends/s3
- [악분님] 실습 따라하기 - Blog
- [사전 준비] 리모트 공용 저장소 AWS S3 생성
#
git clone https://github.com/sungwook-practice/t101-study.git example
cd example/state/step3_remote_backend/s3_backend
tree
# VSCODE에서 코드 파일들 확인 : main.tf, variables.tf , terraform.tfvars
## S3 버킷에 버저닝 활성화 <- 권장 옵션 설정
# terraform.tfvars 파일 내용 수정 : 각자 자신의 '닉네임' 추가하여 S3 버킷 이름 작성
bucket_name = "<닉네임>-hello-t1014-remote-backend"
bucket_name = "gasida-hello-t1014-remote-backend"
# 생성
terraform init && terraform apply -auto-approve
# 확인
terraform state list
aws s3 ls
테라폼 자원 배포 시 ‘리모트 백엔드 저장소’ 설정 사용
# VSCODE에서 provider.tf 코드 확인
cd ../vpc
ls
cat provider.tf
# VSCODE에서 provider.tf 수정
...
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" 주석처리
}
...
# 테라폼 초기화
terraform init
Initializing the backend...
Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
...
# tfstate 파일 로컬 확인
terraform apply -auto-approve
terraform state list
ls
# AWS S3 버킷 내에 tfstate 파일 확인
MYBUCKET=gasida-hello-t1014-remote-backend
aws s3 ls s3://$MYBUCKET --recursive --human-readable --summarize
Locking 을 위한 DynamoDB 활용을 위해 DynamoDB 생성
- 테라폼에서 DynamoDB 잠금을 사용하기 위해서는 LockID 라는 기본 키가 있는 테이블을 생성해야됨
# VSCODE에서 provider.tf 코드 확인
cd ../dynamodb
ls
cat main.tf
# 생성
terraform init && terraform apply -auto-approve
# 확인
terraform state list
terraform state show aws_dynamodb_table.terraform_state_lock
# DynamoDB 테이블 생성 확인
aws dynamodb list-tables --output text
TABLENAMES terraform-lock
aws dynamodb describe-table --table-name terraform-lock | jq
aws dynamodb describe-table --table-name terraform-lock --output table
2번 테라폼 자원 배포에 백엔드 설정 수정 및 적용
# VSCODE에서 provider.tf 코드 확인
cd ../vpc
cat provider.tf
# VSCODE에서 provider.tf 수정 : dynamodb_table = "terraform-lock" 주석 제거
...
backend "s3" {
bucket = "gasida-hello-t1014-remote-backend"
key = "terraform/state-test/terraform.tfstate"
region = "ap-northeast-2"
dynamodb_table = "terraform-lock"
}
...
# backend설정이 달라졌으므로 terraform init 으로 적용
# Reconfigure a backend, and attempt to migrate any existing state.
terraform init -migrate-state
VPC tag 수정 후 apply 와서 Locking 확인 : 예전과 다르게 md5 Item은 생성되지 않는듯..
# main.tf 수정 : '2' 추가
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "terraform VPC 2"
}
}
# apply 후 DynamoDB 테이블 확인
terraform apply
...
Enter a value: <입력하지 않고 대기>
# 아래 LockID 정보 확인 후 apply
# apply 완료 후 다시 DynamoDB 테이블 확인 : item 없음 확인
동시에 apply 못한다.
S3 버저닝 정보 확인
# main.tf 수정 : '3' 추가
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "terraform VPC 3"
}
}
# apply
terraform apply -auto-approve
# S3 버킷에 파일 확인
aws s3 ls s3://$MYBUCKET --recursive --human-readable --summarize
# 버저닝된 파일 확인
aws s3api list-object-versions --bucket $MYBUCKET | egrep "Key|VersionId|LastModified"
"Key": "dev/terraform.tfstate",
"VersionId": "oyo59fIIQ239_tVTY88upFoVgnp630BC",
"LastModified": "2022-10-23T08:54:04+00:00",
"Key": "dev/terraform.tfstate",
"VersionId": "vlOO1wCPEy3mzAOB7W76171u_i3WSG8r",
"LastModified": "2022-10-23T08:53:04+00:00",
"Key": "dev/terraform.tfstate",
"VersionId": "ukF5F_CMKQhoF_jDGftbsMO0eNIGLmDV",
"LastModified": "2022-10-23T08:51:55+00:00",
실습 리소스 삭제
# 테라폼 배포 리소스 삭제 : 현재 vpc 디렉터리
terraform destroy -auto-approve
# DynamoDB 삭제
cd ../dynamodb
terraform destroy -auto-approve
# S3 삭제
cd ../s3_backend
terraform destroy -auto-approve
# S3 버킷에 객체 삭제
aws s3 rm s3://$MYBUCKET --recursive
# S3 버킷에 버저닝 객체 삭제
aws s3api delete-objects \
--bucket $MYBUCKET \
--delete "$(aws s3api list-object-versions \
--bucket "$MYBUCKET" \
--output=json \
--query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}')"
# S3 버킷에 삭제마커 삭제
aws s3api delete-objects --bucket $MYBUCKET \
--delete "$(aws s3api list-object-versions --bucket "$MYBUCKET" \
--query='{Objects: DeleteMarkers[].{Key:Key,VersionId:VersionId}}')"
# S3 삭제
terraform destroy -auto-approve
워크스페이스
소개 : State를 관리하는 논리적인 가상 공간을 워크스페이스라고 한다 - 링크
- 테라폼 구성 파일은 동일하지만 작업자는 서로 다른 State를 갖는 실제 대상을 프로비저닝할 수 있다.
- 워크스페이스는 기본 default로 정의된다. 로컬 작업 환경의 워크스페이스 관리를 위한 CLI 명령어로 workspace가 있다.
mkdir 5.3 && cd 5.3
touch main.tf
resource "aws_instance" "mysrv1" {
ami = "ami-0ea4d4b8dc1e46212"
instance_type = "t2.micro"
tags = {
Name = "t101-study"
}
}
실행
# [분할/터미널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 workspace list
# graph 확인
terraform graph > graph.dot
신규 워크스페이스 생성 및 확인
# 새 작업 공간 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
워크스페이스 생성
워크스페이스를 변경한 후
apply 하면 아래 파일이 생성된다
다시 워크스페이스 생성
tf state파일이 또 다시 생성된다
'study > T101 4기' 카테고리의 다른 글
T101 4기 5주차 두번째 (0) | 2024.07.07 |
---|---|
T101 4기 5주차 첫번째 (0) | 2024.07.07 |
T101 4기 4주차 첫번째 (0) | 2024.06.30 |
T101 4기 3주차 두번째 (0) | 2024.06.29 |
T101 4기 3주차 첫번째 (0) | 2024.06.29 |