테라폼을 실행할 때마다 테라폼은 생성한 인프라에 대한 정보를 테라폼 상태 파일에 기록함.
기본적으로 /jaehan/hi 폴더에서 테라폼을 실행하면 테라폼은 /jaehan/hi/terraform.tfstate 파일을 생성함.
해당 파일에는 tf 확장자를 가진 파일의 테라폼 리소스가 실제 리소스의 표현으로 매핑되는 내용을 기록하는 JSON 형식이 포함됨.
**ALB 실습 시 생성된 terraform.tfstate**
{
"version": 4,
"terraform_version": "1.3.9",
"serial": 83,
"lineage": "437cff4a-6990-cf45-4876-0dcc4fb63f30",
"outputs": {
"latest_ami_id": {
"value": "ami-034000b759564de42",
"type": "string"
}
},
"resources": [
{
"mode": "data",
"type": "aws_ami",
"name": "ubuntu",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"architecture": "x86_64",
"arn": "arn:aws:ec2:ap-northeast-2::image/ami-034000b759564de42",
"block_device_mappings": [
.
.
.
.
테라폼은 위 상태파일을 기준으로 리소스의 ID를 이용해 최신상태를 가져와서 테라폼의 구성과 비교하여 어느 변경 사항을 적용해야 하는지 결정.
때문에, 여러 명이 테라폼을 사용하게 되면 동기화 문제와 동시쓰기 문제가 발생함.
협업하는 과정에서 상태파일이 동기화되어 있지 않으면 다른 사람이 작업한 내용이 사라질 수 있거나 예상치 못한 결과를 초래할 수 있음.
상태파일 동기화 문제는 테라폼 backend를 이용하여 해결할 수 있음.
backend는 상태파일을 저장하는 위치를 설정.
원격 저장소의 예
AWS S3, Azure Blob Storage, Google Cloud Storage, Consul, Postgres database 등
먼저 S3를 생성해야 함.
resource "aws_s3_bucket" "terraform-state" {
bucket = "terraform-jaehan-state"
# 실수로 S3 버킷을 삭제하는 것을 방지
lifecycle {
prevent_destroy = true
}
# 코드 이력을 관리하기 위해 상태 파일의 버전 관리를 활성화
versioning {
enabled = true
}
# 서버 측 암호화를 활성화
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
}
앞선 실습 ASG 폴더에 backend.tf 생성
terraform {
backend "s3" {
bucket = "terraform-jaehan-state"
key = "terraform.tfstate"
region = "ap-northeast-2"
}
}
tf init 명령어 실행!
이후에 terraform apply 명령어를 수행할 시 아래 사진처럼 상태파일이 더이상 로컬에 생성되지 않고,
backend로 지정한 S3에 생성되는 것을 확인할 수 있다.
상태파일 동기화 문제에 이어 **동시에 여러 사용자가 상태파일을 업데이트**
할 시
충돌을 일으켜 예상치 않은, 원하지 않는 문제가 발생할 수 있다.
⇒ 잠금 기능(Locking) 필요
대부분의 backend는 기본적으로 잠금 기능을 지원.
But, AWS의 S3는 앞선 문제를 해결해주지 않고, 다이나모 DB를 곁들여서 사용
먼저, S3(backend)와 DynamoDB(locks) 사전생성
provider "aws" {
profile = "example"
region = "ap-northeast-2"
}
# S3 Bucket 생성
resource "aws_s3_bucket" "terraform-state" {
bucket = "terraform-jaehan-state"
lifecycle {
prevent_destroy = true
}
versioning {
enabled = true
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
}
# DynamoDB 생성
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform_jaehan_locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
output "dynamodb_table_name" {
value = aws_dynamodb_table.terraform_locks.name
description = "The name of DynamoDB table"
}
단일 웹서버 Terraform 코드 apply 중 DynamoDB 테이블 화면
apply 후
**테라폼의 backend 블록에서는 변수나 참조를 사용할 수 없다!**
# 실행되지 않는 코드
terraform {
backend "s3" {
profile = "example"
bucket = var.bucket
key = "terraform.tfstate"
region = var.region
dynamodb_table = var.dynamodb_table
encrypt = true
}
}
즉, 관련된 모든 이름 등을 테라폼 백엔드를 구성할 때마다 수동으로 복사해서 붙여넣어야 한다.
⇒ 복사해서 수동 변경 작업을 자주 하면 에러 발생 확률 Up!
backend.hcl
파일 활용
# backend.hcl
bucket = "terraform-jaehan-state"
region = "ap-northeast-2"
dynamodb_table = "terraform_jaehan_locks"
encrypt = true
모듈(이후 나올 예정)마다 서로 다른 key 값을 설정해야 하기 때문에 일단은 key만 남겨둔다고 한다.
그 외에 인수는 다 제거~
terraform {
backend "s3" {
profile = "example"
key = "workspace/terraform.tfstate"
}
}
이후 구성한 것들을 결합하여 init 명령어 실행
$ tf init -backend-config=backend.hcl