IaC

테라폼 스터디 - 4주차

wath1457 2024. 12. 29. 02:23

Terraform State

테라폼 상태 파일 (tfstate)

-> terraform이 실제 인프라와 비교, 변경사항을 추적, 리소스의 현재 상태를 알 수 있게 해주는 파일

 

 

상태 파일은 Json에 불과하지만, 상태를 직접 수정하는 것은 권장되지 않음

Terraform CLI는 terraform state 명령어를 통해 상태를 수정할 수 있게 제공

 

  • 인프라 리소스의 추적
    • 리소스 ID, 속성, 리소스 간의 관계등이 포함되어 있음
  • 변경사항 추적
    • 상태(state)파일을 기반으로 실제 인프라와 현재 상태를 비교하고, 이를 통해 리소스를 변경한다.
  • 병렬 실행 최적화
    • 리소스 간의 의존 관계를 알 수 있기에, 상태 파일의 정보를 토대로 효율적인 병렬 작업 실행
  • 원격 상태 관리
    • 로컬 상태 파일 외에도 원격 상태 백엔드를 설정 하여, 여러 사람이 동일한 인프라를 관리하는 경우에도 충돌을 방지할 수 있음

 


 

Terraform 상태 파일 공유

 

상태 파일은 기본적으로 terraform.tfstate라는 로컬 파일에 저장되지만, 버전 관리와 암호화를 위해서 다양한 클라우드 플랫폼을 사용할 수 있음

 

 

terraform backend

상태 파일(tfstate)을 저장하고 관리하는 방식을 정의하는 설정

 

  • 백엔드 설정은 상태 파일의 저장 위치와 관리 방식을 정의
  • 로컬 백엔드 : 상태 파일을 로컬 디스크에 저장(default)
  • 원격 백엔드 : 상태 파일을 원격 저장소에 저장 / AWS S3, Azure Blob Storage, Google Cloud Storage, Terraform Cloud
  • 백엔드는 상태 파일 관리와 동시 작업 처리를 위한 락킹 기능과 상태 파일의 버전 관리를 지원함

 

백엔드 설정 예시

terraform {
  backend "s3" {
    bucket = "my-terraform-state-bucket"
    key    = "path/to/my/terraform.tfstate"
    region = "us-west-2"
    dynamodb_table = "my-terraform-locks"
    encrypt = true
  }
}

 

 

백엔드 설정 시 주의 사항

  • 백엔드 설정은 한 번만 정의해야 하며, 이를 변경하면 기존 상태 파일을 새 백엔드로 마이크레이션 하는 과정이 필요
  • 백엔드 설정 후 -> terraform init 명령어를 통해 백엔드를 초기화해야 한다.
    • 테라폼 버전이 변경된 경우, 상태 파일이 호환되지 않을 수 있으므로, terraform init 명령어를 통해 설정 초기화 및 상태 파일의 버전 마이그레이션을 진행해야 한다.

 

 

manual state pull & push

terraform state 명령어를 통해 pull과 push를 통해 상태를 로드하거나 덮어쓸 수 있다.

 

다만, 덮어쓰는 행위 자체는 매우 위험하므로 가능하면 피해야하는 행위이다.

 

테라폼은 이러한 위험 행위를 방지하기 위한 두 가지 규칙을 정의한다.

 

  • Differing Lineage (다른 혈통)
    • 혈통은 상태가 생성될 때 할당된 고유한 ID이며, 혈통이 다르다면, 상태가 서로 다른 시간에 생성되었다는 의미이므로 다른 상태를 수정하고 있을 가능성이 매우 높기에, terraform은 이를 방지한다.
  • Higher serial (높은 시리얼 번호)
    • 모든 상태는 증가하는 일련번호를 갖는다. 대상 상태에 더 높은 일련번호가 있는 경우, terraform은 수정을 허용하지 않는다. 이는 작성하려는 상태 이후에 변경 사항이 발생했음을 의미하기 때문이다.

 


 

terraform_remote_state

다른 terraform 작업의 상태 파일을 참조할 수 있게 해주는 기능 - 상태 파일을 원격에서 가져와서 사용할 수 있게 해줌

 

 

사용 예시

 

작업 A : VPC 생성

작업 B : EC2 인스턴스 생성

 

VPC 생성 후에 EC2 인스턴스 생성이 가능하므로, VPC 작업의 출력 값을 참조하여 EC2 작업에서 사용하기 위해 terraform_remote_state 이용하여 VPC의 상태를 EC2 작업에서 가져오는 방식으로 활용할 수 있다.

 

 

사용 시나리오

  • 모듈화된 인프라 : 서로 다른 프로젝트나 환경에서 상태 파일을 공유하여 모듈화된 방식으로 인프라를 관리할 수 있다.
  • 다중 환경 관리 : 개발, 테스트, 프로덕션 환경 등 여러 환경을 따로 관리하는 경우, 각 환경에 대한 상태 파일을 공유하거나 참조하여 환경 간에 의존성을 관리할 수 있다.

 

 

terraform_remote_state 사용 예시 - 원격

data "terraform_remote_state" "vpc" {
  backend = "remote"

  config = {
    organization = "hashicorp"
    workspaces = {
      name = "vpc-prod"
    }
  }
}

# Terraform >= 0.12
resource "aws_instance" "foo" {
  # ...
  subnet_id = data.terraform_remote_state.vpc.outputs.subnet_id
}

# Terraform <= 0.11
resource "aws_instance" "foo" {
  # ...
  subnet_id = "${data.terraform_remote_state.vpc.subnet_id}"
}

 

  1. terraform_remote_state 데이터 소스를 통해  Terraform cloud의 vpc-prod의 워크스페이스에서 VPC 상태 파일을 읽어옴
  2. vpc-prod 워크스페이스에서 생성된 subnet_id를 EC2 instance에 사용하여, 해당 서브넷에 EC2 인스턴스 배치

 

 

terraform_remote_state 사용 예시 - local

data "terraform_remote_state" "vpc" {
  backend = "local"

  config = {
    path = "..."
  }
}

# Terraform >= 0.12
resource "aws_instance" "foo" {
  # ...
  subnet_id = data.terraform_remote_state.vpc.outputs.subnet_id
}

# Terraform <= 0.11
resource "aws_instance" "foo" {
  # ...
  subnet_id = "${data.terraform_remote_state.vpc.subnet_id}"
}

 

 


 

Root Outputs Only

 

  • root 모듈 : terraform 명령어를 실행하는 위치에 있는 terraform 설정 파일들이 정의된 모듈 / main.tf 파일을 포함하는 디렉토리에서 terraform apply를 실행하면, 그 디렉토리는 root 모듈이 된다.
  • nested 모듈 : root 모듈 내에서 다른 모듈을 호출할 때, 호출되는 모듈 / main.tf에서 app이라는 모듈을 호출하면, app 모듈은 nested 모듈이 된다.

 

 

module "app" {
  source = "..."
}

output "app_value" {
  # This syntax is for Terraform 0.12 or later.
  value = module.app.example
}

 

remote_state 파일에서 root 레벨의 모듈에서 정의된 출력값만 가져올 수 있다.

 

nested module (하위 모듈)에서 output을 사용하기 위해선 root 모듈에서 그 값을 전달해야만 한다는 의미이다.

 

위의 예시처럼 작성하게 되면 app_value 라는 output이 root 모듈에 전달된다. (= app 모듈에서 example이라는 값을 app_value라는 output으로 root 모듈에 전달한다.)

 

terraform_remote_state를 사용하여 원격 상태 파일을 가져올 때, 원격 상태 파일의 출력 값은
오직 "root 모듈"에서 정의된 출력 값만 다른 모듈에서 사용할 수 있도록 제공됩니다. 즉, 중첩된(nested) 모듈에서의 출력 값은 자동으로 전달되지 않습니다.

 

 

 

예시

app 모듈 내에서 example 이라는 값을 출력하기

 

 

modules/app/main.tf

output "example" {
  value = "some_value"
}

 

 

main.tf

module "app" {
  source = "./modules/app"
}

output "app_value" {
  value = module.app.example
}

 

 

root 모듈에서 app 모듈의 output인 example을 참조하기 위해서 위와 같이 작성해야 한다.

 

 

이제 terraform_remote_state에서 app_value를 사용할 수 있게 된다.

 

data "terraform_remote_state" "vpc" {
  backend = "remote"

  config = {
    organization = "hashicorp"
    workspace = {
      name = "vpc-prod"
    }
  }
}

resource "aws_instance" "foo" {
  subnet_id = data.terraform_remote_state.vpc.outputs.app_value
}

 

data.terraform_remote_state.vpc.outputs.app_value는 원격 상태 파일에서 app_value 값을 가져온다. 이 값을 subnet_id에 사용하게 된다.