Terraform apply를 통해 리소스를 생성하면 실제 인프라에 terraform 코드 내용이 반영되어 리소스가 생성된다.
이렇게 apply로 생성한 리소스는 destroy로 삭제하는데, 만약 terraform으로 생성한 리소스를 웹 콘솔에서 임의로 삭제를 해버리면 어떻게 될까?
혹은 terraform으로 이미 생성한 리소스에 대해서 또 다시 apply를 적용시킨다면 어떨까?
더 나아가서 팀 이상의 단위로 인프라를 관리할 때 여러명이 동시에 같은 리소스에 접근하는 경우, 적용된 인프라 리소스가 충돌하는 상황이 발생할 수도 있다.
이런 문제를 해결하기위해 등장한 state와 backend 개념에 대해 알아보도록 한다.
tfstate
Terraform이 생성한 인프라 리소스의 상태 정보를 저장해둔 파일, 기본적으로 terraform의 state 파일은 terraform.tfstate라는 이름으로 저장된다.
state 파일이 필요한 이유로는 아래와 같다.
- provider와 그에 종속된 리소스들을 매핑하고, 추적/관리
- 리소스들 간의 의존성 추적/관리
- 리소스 롤백이나 복구
- 분리된 환경(dev, stg, prd)에서의 인프라 관리
Terraform 코드를 작성하고 apply를 하면 .tfstate파일이 생성이된다. 이렇게 로컬에 생성된 state 파일을 local state라고 불린다.
tfstate 파일은 json형식으로 구성되어있고, Terraform의 apply로 생성된 리소스들의 상태, 속성값, 리소스들 간의 의존성 내용이 적혀있는 것을 볼 수 있다.
이 파일을 직접 수정하는 것은 권장되지 않는다.
state의 수정을 위한 커맨드로 terraform state를 지원하므로 또한, terraform 외부에서 생성된 리소스(ex. 직접 웹 콘솔 등으로 생성한 리소스)를 terraform 내부로 가져오는 것도 terraform import 커맨드로 지원한다.
tfstate의 관리
위에서 이야기했듯이 여러 사용자가 state 파일에 접근해 변경하는 경우 충돌, 리소스 부정합성과 같은 문제가 발생할 수 있다.
따라서 이 state파일의 형상관리를 중앙화된 저장소 등에 해주는 것이 필요하다.
하지만 tfstate파일은 Git과 같은 Source Control에 보관하는 것은 권장되지 않는다.
Source Control에 state 파일을 저장하는 것을 권장하지 않는 이유는 크게 2가지가 존재한다.
먼저, state파일은 모든 데이터들이 평문으로 저장된다. 즉, 민감할 수 있는 실제 인프라에 적용된 상태와 내용, Secret값(AccessKey, RDS password 등)이 노출되기에 tfstate 파일을 git과 같은 공개된 장소로 노출시키는 것은 권장되지 않는다.
그 다음으로는 tfstate 저장에 git을 이용하는 경우 state locking을 지원하지 않는 점도 존재한다.
Locking : 여러 사용자가 동일한 state에 접근하는 것을 막는 기능
여러 terraform 프로세스가 동시에 동일한 state를 업데이트 → state파일의 부정합, Race Condition 발생
동시 작업에 의한 충돌을 막기 위해 AWS의 DynamoDB table 등을 이용해서 locking을 구현할 수 있다.
이러한 애로사항들을 해결해주기 위해 Terraform에서 backend라는 이름으로 state의 버전관리를 지원한다.
backend
terraform의 state파일을 어디에, 어떻게 저장할 것인지에 대한 설정
기본적으로 terraform의 state는 로컬에 저장된다. backend 설정으로 state의 저장경로를 원격으로 두어 협업 시에 관리를 편리하게 할 수 있다.
지원되는 backend는 크게 local과 remote 유형으로 나뉜다.
Local Backend
tfstate 파일을 로컬 disk에 저장하는 방식으로 terraform의 기본 backend 설정값이다.
혼자 작업하는 경우에는 주로 로컬에 state 파일을 저장한다.
Remote Backend
tfstate 파일을 로컬이 아닌 원격 공유 저장소에 저장시키는 방식으로 S3, Google Cloud Storage, Azure Blob Storage 등의 메이져한 퍼블릭 클라우드 스토리지 서비스를 비롯한 저장소에 저장을 지원한다.
이외에도 terraform이 공식 클라우드, Terraform Cloud를 지원해 이를 backend state 저장소로 사용할 수도 있다고 한다.
팀 내의 여러 인원이 참조할 수 있는 원격 저장소에 state 파일을 저장해, 실제 인프라에 적용된 요소를 쉽게 파악하고 추적할 수 있다.
S3를 backend로 하는 설정을 하고, 동시에 같은 state를 참조하지 못하도록 locking을 설정하는 DynamoDB Table을 생성해본다.
provider "aws" {
region = "ap-northeast-2"
}
# state 저장 버킷
resource "aws_s3_bucket" "tfstate_bucket" {
bucket = "terraform-backend-omoknooni"
}
resource "aws_s3_bucket_versioning" "tfstate_bucket_versioning" {
bucket = aws_s3_bucket.tfstate_bucket.id
versioning_configuration {
status = "Enabled"
}
}
# state lock을 위한 dynamodb 테이블
resource "aws_dynamodb_table" "tfstate_lock_table" {
name = "terraform-lock-omoknooni"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
output "bucket_name" {
value = aws_s3_bucket.tfstate_bucket.arn
description = "ARN of terraform backend bucket"
}
output "lock_table_name" {
value = aws_dynamodb_table.tfstate_lock_table.arn
description = "ARN of terraform backend lock table"
}
init → plan → apply를 적용하면 리소스가 생성됨을 볼 수 있다.
이렇게 생성한 backend용 bucket에 직접 state를 저장해본다.
여기서는 간단하게 ec2 인스턴스 하나를 올리는 코드를 적용해 state 파일을 생성한다. 즉, 위에서 backend용 버킷과 테이블을 만든 코드와 분리된 디렉토리에서 apply를 해주어야한다.
provider "aws" {
region = "ap-northeast-2"
}
terraform {
backend "s3" {
region = "ap-northeast-2"
bucket = "terraform-backend-omoknooni"
key = "terraform-study/terraform.tfstate"
dynamodb_table = "terraform-lock-omoknooni"
}
}
resource "aws_instance" "backend_test" {
ami = "ami-02288bc8778f3166f"
instance_type = "t2.micro"
key_name = aws_key_pair.backend_testkeypair.key_name
}
resource "tls_private_key" "backend_testkey" {
algorithm = "RSA"
rsa_bits = 4096
}
resource "local_file" "backend_test" {
content = tls_private_key.backend_testkey.private_key_pem
filename = "backend_test.pem"
}
resource "aws_key_pair" "backend_testkeypair" {
key_name = "backend_test"
public_key = tls_private_key.backend_testkey.public_key_openssh
}
state 내역이 s3와 dynamodb 테이블로 저장된 것을 볼 수 있다.
backend 블록은 수정될때마다 init을 진행해주어야한다.
이렇게 Terraform의 state 개념과 state를 저장하는 backend 설정까지 알아보았다.
다음으로 Terraform의 module을 알아보도록 한다.
사용된 코드는 Github으로
참고 URL
https://devopscube.com/setup-terraform-remote-state-s3-dynamodb/