테라폼 스터디 - 4주차
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}"
}
- terraform_remote_state 데이터 소스를 통해 Terraform cloud의 vpc-prod의 워크스페이스에서 VPC 상태 파일을 읽어옴
- 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에 사용하게 된다.