연재 시리즈

테라폼 t102 스터디 - state

악분 2023. 7. 29. 16:53
반응형

안녕하세요. 이 글은 테라폼 스터디에서 공부한 state를 정리했습니다.

영상: https://youtu.be/E2n3bZrzpKE

 

1. state란?

테라폼은 대상에 배포한 결과를 state 관리합니다. 또한, 테라폼 실행 작업(생성/수정/삭제) 결정에 중요한 연할을 합니다. 예를 들어 state 없으면 테라폼은 리소스 생성 작업을 실행합니다.

 

2. state 업데이트는 언제 될까?

state 테라폼이 실행된 생성됩니다. terraform CLI에서는 terraform apply 실행한 state 생성됩니다. 이미 state 있다면 업데이트됩니다. state 업데이트 과정을 terraform refresh라고 부릅니다.

 

3. state 관리

3.1 state 포맷

state JSON 포맷입니다.

 

3.2 state 관리방법

테라폼 도구마다 state 관리하는 방법이 다릅니다. 테라폼 CLI state tfstate파일에 저장합니다.

 

3.3 예제

예제코드는 github 공개되어 있습니다.

git clone https://github.com/sungwook-practice/t101-study.git example
cd example/state/step2_vpc

 

예제코드는 vpc 생성합니다. vpc cidr 테라폼 변수로 입력 받습니다. 저는 terraform.tfvars 변수 값을 초기화 했습니다.

 

테라폼을 초기화 합니다.

terraform init

 

terraform apply 실행하여 vpc 생성합니다.

terraform apply

 

테라폼 실행 파일목록을 확인하면, terraform.tfstate파일이 있습니다. 파일 내용에는 json포맷인 state 있습니다. state에는 생성한 vpc정보(: vpc arn ) 있습니다.

cat terraform.tfstate

 

4. state 조회

4.1 조회 명령어

terraform state list/show 명령어로 state 조회할 있습니다. 명령어는 크기가 state 확인할 유용합니다. 리소스가 많아질수록 state크기도 커집니다.

 

4.2 예제

이전 챕터(3.3) 예제를 사용합니다.

 

terraform apply명령어를 실행하고 terraform.tfstate파일이 생성되었는지 확인합니다.

terraform apply
ls terraform.tfstate

 

state파일에는 테라폼이 생성한 vpc정보가 있습니다. 테라폼이 관리하는 리소스 갯수만큼 state 생성되고 name(block label) 구분합니다.

 

state 목록은 json필드를 찾아보거나 terraform state show명령어를 사용하면 됩니다.

terraform state list

 

 

state 값은 terraform state show 확인할 있습니다. state show명령어는 json필드 값과 동일합니다.

terraform state show aws_vpc.main

 

5. state 버전

state serial라는 필드로 버전을 관리합니다. state 업데이트될 때마다 serial 증가합니다.

cat terraform.tfstate

 

반응형

6. state의 테라폼 작업 영향도

6.1 영향도

테라폼은 state 대상 현재 상황을 비교하여 어떤 작업(생성/수정/삭제) 할지 수행합니다. state 대상 비교 과정을 terraform refresh라고 합니다.

 

terraform refresh 비교 과정 말고도 상태를 업데이트할 사용됩니다. 테라폼 실행 전에 refresh 실행되면 비교를 하고, 테라폼 실행 후에 refresh 실행되면 state 업데이트합니다. 아래 예제는 terraform destroy 실행하기 state 대상을 비교합니다.

 

6.2. 예제

테스트 예제는 s3버킷과 vpc코드를 사용합니다. 예제는 state 있을 때와 없을 어떻게 동작하는지 테스트합니다. 또한, 리소스가 유일해야하는 s3버킷과 유일하지 않아도 되는 vpc 어떻게 테라폼이 실행되는지 비교합니다.

 

6.2.1 첫번째 예제

첫번째 예제는 state 리소스가 없는 상태에서 테라폼 코드를 실행합니다. 예제코드는 버킷을 생성합니다.

 

예제코드는 github 공개되어 있습니다.

git clone https://github.com/sungwook-practice/t101-study.git example
cd example/state/step1_bucket

 

버킷 이름은 변수로 입력받습니다. 저는 tfvars파일로 변수 값을 초기화 했습니다. 예제를 실행할 버킷 이름을 변경해주세요.

cat terraform.tfstate

 

테라폼을 초기화 합니다.

terraform init

 

terraform apply 실행하면 버킷을 생성하는 메세지가 출력됩니다. state aws 버킷이 없기 때문에 테라폼은 버킷 생성 작업을 합니다.

terraform apply

 

생성한 버킷 정보는 state 관리되고 terraform.tfstate파일에 저장됩니다. 예를 들어 생성한 버킷 arn state 있습니다.

cat terraform.tfstate

 

6.2.2 두번째 예제

번째 예제는 state 없지만 리소스가 있을 테라폼을 실행합니다.

 

첫번째 예제를 실행 , tfstate파일 확장자를 tmp 변경합니다. tfstate파일이 없기 때문에 테라폼은 state파일이 없다고 판단합니다.

mv terraform.tfstate terraform.tfstate.tmp

 

terraform apply명령어를 실행하면 어떤 결과가 나올까요? state 없기 때문에 테라폼은 버킷을 생성하려고 합니다.

terraform apply

 

하지만 번째 예제에서 버킷을 생성했으므로 버킷 이름 중복 오류가 발생합니다. 그러므로 테라폼 실행도 실패합니다.

 

6.2.3 세번째 예제

번째 예제는 state 있고 리소스가 있을 테라폼을 실행합니다.

 

두번째 예제에서 확장자를 변경한 state파일을 원복합니다.

mv terraform.tfstate.tmp terraform.tfstate

 

terraform apply명령어를 실행하면 아무 변화가 없습니다. state에는 버킷이 있고 aws 이미 버킷( 번째 예제에서 생성) 있기 때문에, 테라폼은 아무런 동작을 했습니다.

terraform apply

 

6.2.4 네번째 예제

번째 예제는 번째 예제 상황을 반례를 예제입니다. state 없고 리소스가 있는 상황에서 테라폼을 실행하면, 테라폼 에러가 발생 안되는 상황이 있습니다. aws vpc처럼 세계 유일하지 않는 리소스는 에러가 발생하지 않고 리소스를 생성합니다.

 

실습으로 상황을 재현해볼까요? 예제코드는 github 공개되어 있습니다.

git clone https://github.com/sungwook-practice/t101-study.git example
cd example/state/step2_vpc

 

번째 예제코드는 vpc 생성합니다. vpc cidr 테라폼 변수로 입력 받습니다. 저는 terraform.tfvars 변수 값을 초기화 했습니다.

 

테라폼을 초기화 합니다.

terraform init

 

terraform apply 실행하여 vpc 생성합니다.

terraform apply

 

테라폼 코드 실행 생성한 vpc정보가 있는 state파일이 생성됩니다.

ls -l terraform.tfstate

 

state파일 확장자를 변경하여 state 없는 것처럼 상황을 만듭니다. 현재 두번째 예제처럼 state파일은 없고 리소스가 있는 상황을 만들었습니다.

mv terraform.tfstate terraform.tfstate.tmp

 

두번째 예제와 상황은 같지만 테라폼 실행결과는 다릅니다. terraform apply 실행하면 테라폼이 정상적으로 실행되고 vpc 생성됩니다. 그리고 생성한 vpc정보가 state파일에 저장됩니다. vpc 버킷과 다르게 이름이 유일하지 않기 때문에, 테라폼 생성 작업이 정상적으로 실행되었습니다.

terraform apply

 

7. terraform import

terraform import 명령어는 이미 존재하는 대상 리소스를 state 만들어줍니다. 테라폼으로 생성하지 않는 대상을 테라폼으로 관리하고 싶을 사용합니다.

 

terraform import 사용하기 위해서 테라폼 코드와 대상에 리소스가 존재해야 합니다. terraform import명령어를 실행하면 대상 리소스를 테라폼 코드에 매핑 시켜 state 업데이트 합니다.

 

사용방법은 아래와 같습니다.

terraform import block_type.block_name {대상 리소스 식별값}

 

아래 예제는 aws vpc_id 리소스 식별값으로 사용하여 terraform import 사용했습니다.


8. state 백엔드

state 저장하는 곳을 백엔드(backend)라고 합니다. 디폴트로 테라폼을 실행한 로컬에 파일로 저장합니다. 로컬이 아니라 원격에 state 저장하는 것을 remote state라고 합니다.

 

remote state 여러 사람과 협업할 설정해야 합니다. 앞서 예제에서 살펴본 것처럼 state 따라 테라폼 실행 결과가 달라집니다

 

예제에서는 remote state s3 저장합니다.

 

8.1 S3생성

테라폼 코드는 github 공개되어 있습니다.

git clone https://github.com/sungwook-practice/t101-study.git example
cd example/state/step3_remote_backend/s3_backend

 

main.tf s3 버킷과 버킷버전 설정을 하는 테라폼 코드가 있습니다. 버전 설정을 이유는 누군가 실수로 remote state 삭제하는 것을 방지하기 위해서입니다.

resource "aws_s3_bucket" "main" {
  bucket = var.bucket_name

  tags = {
    Name = "terraform test"
  }
}

resource "aws_s3_bucket_versioning" "main" {
  bucket = aws_s3_bucket.main.id

  versioning_configuration {
    status = "Enabled"
  }
}

 

버킷 이름은 변수로 입력받습니다. 저는 tfvars파일로 변수 값을 초기화 했습니다. 예제를 실행할 버킷 이름을 변경해주세요.

cat terraform.tfstate

 

테라폼 코드를 실행하여 버킷을 생성합니다.

terraform init && terraform apply

 

생성된 버킷은 versioning 활성화되어 있습니다.

 

8.2 backend 설정

생성한 s3 state 저장되도록 테라폼 코드에 backend 설정해야 합니다.

 

테라폼 코드는 github 공개되어 있습니다. 예제코드는 aws vpc 생성합니다

git clone https://github.com/sungwook-practice/t101-study.git example
cd example/state/step3_remote_backend/vpc

 

terraform block에서 backend설정을 있습니다. 예제코드에서 provider.tf terraform block 있습니다. backend block에는 버킷이름과 버킷경로, 리전을 설정합니다. 예제코드에서는 챕터 8.1에서 생성한 버킷을 사용했습니다.

# provider.tf
terraform {
  ...이하 생략
  backend "s3" {
    bucket = "hello-tf102-remote-backend"
    key    = "terraform/state-test/terraform.tfstate"
    region = "ap-northeast-2"
  }

}

 

테라폼을 초기화 과정에서 s3 연결되는지 확인합니다.

terraform init

 

곧이어 terraform apply 실행합니다.

terraform apply

 

terraform apply이후에 업데이트된 state s3 저장됩니다. s3경로는 테라폼 코드 backend 설정한 경로와 일치합니다.

 

8.3 locking

여러 사람과 remote_state 안전하게 관리하려면 locking 필요합니다. locking이란 동시에 state 업데이트 없도록 잠그는 기능입니다. 사람이 state 업데이트하기 locking 하면, 다른 사람이 state 업데이트할 locking 해제되기전까지 대기합니다.

 

locking 설정은 backend마다 다릅니다. s3 locking 지원하지 않아 DynamoDB 사용합니다. DynamoDB key/value유형 managed DB입니다.

 

이전 실습에서 생성한 s3 locking기능을 추가해보겠습니다. 먼저 DynamoDB table 생성해야 합니다. 예제코드는 github 공개되어 있습니다.

git clone https://github.com/sungwook-practice/t101-study.git example
cd example/state/step3_remote_backend/dynamodb

 

main.tf DynamoDB table이름과 key설정이 있습니다.

resource "aws_dynamodb_table" "terraform_state_lock" {
  name           = "terraform-lock" # table이름
  hash_key       = "LockID" # key 이름
  billing_mode   = "PAY_PER_REQUEST"

  attribute {
    name = "LockID"
    type = "S" # key 타입
  }
}

 

테라폼을 실행하여 DynamoDB table 생성합니다.

terraform apply

 

aws콘솔에서 생성한 DynamoDB table 있습니다.

 

state locking 하기 위해, 이전 실습 backend설정에 DynamoDB 추가해야 합니다.

terraform {
  ...이하생략

  backend "s3" {
    bucket         = "hello-tf102-remote-backend"
    key            = "terraform/state-test/terraform.tfstate"
    region         = "ap-northeast-2"
    dynamodb_table = "terraform-lock" # 추가된 코드
}
}

 

backend설정이 달라졌으므로 terraform init 해야 합니다.

terraform init -migrate-state

 

이제 s3 있는 remote_state 업데이트 하기 locking 통과해야 합니다. vpc이름을 수정해보고 terraform apply 실행해보세요. 그리고 동시에 DynamoDB table 필드를 관찰하면 locking필드가 생겼다가 없어집니다.

반응형