brunch

You can make anything
by writing

C.S.Lewis

by Master Seo Aug 01. 2023

32탄-9. 4주 차-테라폼-State의 목적과 의미


<1> State 소개 및 확인

<2> 실습

<3> 유형별 실습

<4> 워크 스페이스

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




<1> State 소개 및 확인


1

테라폼은 Stateful 애플리케이션. 프로비저닝 결과 State를 저장하고 추적에 활용


2

개인 1인 : 로컬 환경으로 terraform.tfstate 파일에 JSON 형태로 저장

팀이나 조직 : 공동 관리를 위해 원격 저장소에 저장해 공유 - 링크

State에는 작업자가 정의한 코드와 실제 반영된 프로비저닝 결과를 저장하고, 이 정보를 토대로 이후의 리소스 생성, 수정, 삭제에 대한 동작 판단 작업을 수행




<2> 실습



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


 create

-   Destory

-/+   Replace 

~   업데이트      // ec2의 태그 업데이트 할 때 업데이트 한다!!




6

Replace 동작은 기본값을 삭제 후 생성하지만 lifecycle의 create_before_destroy 옵션을 통해 생성 후 삭제 설정 가능하다.





<3> 유형별 실습



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 등 방법이 있습니다!





<4> 워크 스페이스


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




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


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


다음은 주말 CloudNet 테라폼 스터디 내용 참고하여  정리한 부분입니다.

https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863  


감사합니다.



브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari