1
테라폼은 Stateful 애플리케이션. 프로비저닝 결과 State를 저장하고 추적에 활용
2
개인 1인 : 로컬 환경으로 terraform.tfstate 파일에 JSON 형태로 저장
팀이나 조직 : 공동 관리를 위해 원격 저장소에 저장해 공유 - 링크
State에는 작업자가 정의한 코드와 실제 반영된 프로비저닝 결과를 저장하고, 이 정보를 토대로 이후의 리소스 생성, 수정, 삭제에 대한 동작 판단 작업을 수행
1
cd
mkdir 51
cd 51
vi main.tf
resource "random_password" "mypw" {
length = 16
special = true
override_special = "!#$%"
}
2
random
랜덤 프로바이더
https://registry.terraform.io/providers/hashicorp/random/latest
랜덤 프로바이더는 테라폼 구성 내에서 무작위로 기입해야 되는 숫자, 패스워드, 문자열 등의 값을 생성하는 데 사용.
3
terraform init && terraform plan
ls *.tfstate
terraform apply -auto-approve
terraform state list
terraform state show random_password.mypw
// 결과는 안보임
ls *.tfstate
cat terraform.tfstate | jq
// 결과 보임
cat terraform.tfstate | jq | grep result
YLGmKyb3jOuI8sEf
// 결과 보임
# (참고) sensitive value 내용은 테라폼 콘솔에서 보일까요?
echo "random_password.mypw" | terraform console
echo "random_password.mypw.result" | terraform console
테라폼에서는 type과 name으로 고유한 리소스를 분류하며, 해당 리소스의 속성과 인수를 구성과 비교해 대상 리소스를 생성, 수정, 삭제한다.
4
refresh ?
# 실행 계획 생성 시 저장되어 있는 State와 실제 형상을 비교하는 기본 실행
plan을 하면 실제 상황과 state 파일과 비교를 한다는 것이다.
time terraform plan
# 실행 계획 생성 시 실제 형상과 비교하지 않고 실행 계획을 생성하는 -refresh=false 옵션
time terraform plan -refresh=false
기본적으로 refresh 되도록 하자!!!
5
출처 https://kschoi728.tistory.com/135
6
Replace 동작은 기본값을 삭제 후 생성하지만 lifecycle의 create_before_destroy 옵션을 통해 생성 후 삭제 설정 가능하다.
1
유형 1 : 신규 리소스 정의 → Apply ⇒ 리소스 생성
cd
mkdir 52 && cd 52
vi main.tf
locals {
name = "mytest"
}
resource "aws_iam_user" "myiamuser1" {
name = "${local.name}1"
}
resource "aws_iam_user" "myiamuser2" {
name = "${local.name}2"
}
// locals로 정의하고, local로 변수로 받는다.
#
terraform init && terraform apply -auto-approve
terraform state list
terraform state show aws_iam_user.myiamuser1
#
ls *.tfstate
cat terraform.tfstate | jq
ls -al
# apply 한번 더 하면 백업 파일이 생성된다.
terraform apply -auto-approve
ls *.tfstate
# iam 사용자 리스트 확인
aws iam list-users | jq
ls -al
backup file 이 생긴다.
2
유형 2 : 콘솔에서 user1 삭제 시?
terraform plan을 하니 생성한다고 함.
Real(실제)이 없고 , 리소스 설정이나 상태 파일(*.tfstate)에 있으면 생성됨.
# 실제 리소스 수동 제거
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
유형 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
유형 4 : 코드에서 일부 리소스 삭제 → Apply
삭제됨.
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 파일 삭제. 백업도 삭제 된 상태.
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
6
위 상황에서 복구하는 방법은? import 등 방법이 있습니다!
1
상태 파일 격리 필요
격리하지 않았을 때 생기는 일
https://charity.wtf/2016/03/30/terraform-vpc-and-why-you-want-a-tfstate-file-per-env/
2
상태 파일은 파일 레이아웃을 이용한 격리를 권고 한다. - Isolation via file layout
그림
4
기본은 디폴트 워크스페이스 사용했다.
terraform workspace list
* default
5
cd
mkdir 53 && cd 53
vi main.tf
resource "aws_instance" "mysrv1" {
ami = "ami-0ea4d4b8dc1e46212"
instance_type = "t2.micro"
tags = {
Name = "t101-week4"
}
}
6
# [분할/터미널 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
# graph 확인
terraform graph > graph.dot
1
terraform.tfstate.d 가 만들어짐
2
# 새 작업 공간 workspace 생성 : mywork1
terraform workspace new mywork1
terraform workspace show
현재 mywork1 에 있다.
# 서브 디렉터리 확인
tree terraform.tfstate.d
terraform.tfstate.d
└── mywork1
# plan 시 어떤 결과 내용이 출력되나요?
terraform plan
# apply 해보자!
terraform apply -auto-approve
인스턴스가 하나더 만들어진다.
# 워크스페이스 확인
terraform workspace list
격리가 되어 있다.
상태 파일이 다르다.
그래서 인스턴스가 새로 만들어진다!!!
tree terraform.tfstate.d
#
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
3
# 새 작업 공간 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
4
장점 ?
하나의 루트 모듈에서 다른 환경을 위한 리소스를 동일한 테라폼 구성으로 프로비저닝하고 관리한다.
상태파일을 서로 다른것을 사용한다.
main.tf 파일을 각각 격리된 환경에서 배포한다.
하나의 루트 모듈에서 다른 환경을 위한 리소스를 동일한 테라폼 구성으로 프로비저닝하고 관리
단점 ?
State가 동일한 저장소(로컬 또는 백엔드)에 저장되어 State 접근 권한 관리가 불가능
완벽한 격리가 불가능. 실무에서 잘 사용하지 않는다?
5
# workspace 프롬프트 사용하기 툴 - (옵션) Terraform Workspace Prompt
terraform-bash-workspace-prompt.sh
#!/usr/bin/env bash
# dozy.io 2020
# Download latest version from https://github.com/dozyio/terraform-bash-workspace-prompt
RESETCOLOR="$(echo -e "\001\033[0m\002")"
PURPLETEXT="$(echo -e "\001\033[35m\002")"
REDBGWHITETEXT="$(echo -e "\001\033[1;41;97m\002")"
GREENTEXT="$(echo -e "\001\033[1;32m\002")"
BOLDTEXT="$(echo -e "\001\033[1m\002")"
TFPURPLE="$(echo -e "$PURPLETEXT(TF:$RESETCOLOR")"
TFPURPLEEND="$(echo -e "$PURPLETEXT)$RESETCOLOR")"
function terraform_workspace_prompt()
{
if [ -d .terraform ]; then
terraform_workspace="$(command terraform workspace show 2>/dev/null)"
if [[ $terraform_workspace == "prod"* ]] || \
[[ $terraform_workspace == "PROD"* ]] || \
[[ $terraform_workspace == "Prod"* ]]; then
echo -e " $TFPURPLE$REDBGWHITETEXT${terraform_workspace}$RESETCOLOR$TFPURPLEEND"
elif [[ $terraform_workspace == "dev"* ]] || \
[[ $terraform_workspace == "DEV"* ]] || \
[[ $terraform_workspace == "Dev"* ]]; then
echo -e " $TFPURPLE$GREENTEXT${terraform_workspace}$RESETCOLOR$TFPURPLEEND"
else
echo -e " $TFPURPLE$BOLDTEXT${terraform_workspace}$RESETCOLOR$TFPURPLEEND"
fi
fi
}
# Determine our shell
if [ "${ZSH_VERSION-}" ]; then
TF_PS1_SHELL="zsh"
elif [ "${BASH_VERSION-}" ]; then
TF_PS1_SHELL="bash"
fi
위 코드를 특정 디렉토리에 생성하시고, .zshrc 또는 .bashrc에 아래 코드를 추가로 삽입하시면 됩니다.
# terraform-ps1 for terraform workspace
source /usr/local/bin/terraform-bash-workspace-prompt.sh
if [[ "$TF_PS1_SHELL" == "zsh" ]]; then
PS1='$(terraform_workspace_prompt)'$PS1
elif [[ "$TF_PS1_SHELL" == "bash" ]]; then
if [[ "$OSTYPE" == "darwin"* ]]; then
export PS1=${PS1/ \\\u\\\$/\$(terraform_workspace_prompt) \\\u\\\$}
elif [[ "$OSTYPE" == "linux-gnu" ]]; then
export PS1=${PS1/\\\$/\$(terraform_workspace_prompt) \\\$}
fi
fi
https://vclock.kr/timer/#countdown=00:10:00&enabled=0&seconds=0&sound=xylophone&loop=1
다음 보기
https://brunch.co.kr/@topasvga/3383
전체 보기
https://brunch.co.kr/@topasvga/3347
https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863
감사합니다.