[Terraform] state locking을 위한 s3, ddb 설정하기
Terraform의 경우 Github과 같은 VCS에서 프로젝트를 공유하기엔 한계가 있습니다.
AWS 환경을 테라폼으로 구축한다고 가정합시다.
terraform apply 명령어를 실행하는 경우, 테라폼은 연결되어 있는 계정을 통해 인프라스트럭처를 프로비저닝 합니다.
그런데, 여러명이 테라폼 프로젝트를 사용중이라면 어떨까요?
유저 A와 B는 Latest 버전의 테라폼 프로젝트에서 개발을 시작했습니다.
유저 A는 EC2 instance의 유형을 변경하고, 유저 B는 EC2 instance의 security group을 변경합니다.
이 때, 두 유저가 terraform apply 를 동시에 실행하여 한 계정에 적용을 시도합니다.
먼저 A와 B 모두 state 파일을 읽습니다.
그 후, B의 변경사항이 먼저 적용됩니다.
B는 변경사항에 대해 state 파일에 기록합니다.
이후 A의 변경사항이 적용됩니다.
A가 terraform.tfstate 기억하고 있는 state에서 변경된 사항을 추가로 기록합니다. 이 때 기존에 B가 작성한 state가 유실됩니다.
그럼 실제 구축 환경과 state 파일의 inconsistency가 발생하게 됩니다.
이런 문제 말고도 동시성 문제를 원인으로 나타나는 다양한 문제가 발생할 수 있으며, 이는 예기치 못한 장애로 이어질 수 있으므로 굉장히 위험합니다.
이런 문제를 방지하기 위해 VCS가 아닌 다른 방법을 이용해 terraform state 파일을 관리하는 것이 권장됩니다.
state locking 을 통해 state 파일을 관리하게 되는데, 어떤 유저가 terraform apply 명령어를 입력하면 lock 을 통해 다른 유저가 apply를 실행하지 못하도록 막음으로써 state를 관리하는 방법입니다.
state locking 을 구현하기 위한 방법은 여러가지가 있지만, 해당 게시글에서는 S3와 DynamoDB를 통해 구현하겠습니다.
S3 Bucket 구성과 DynamoDB Table 구성도 테라폼을 통해 생성 가능합니다. 하지만 해당 게시글에서는 아마존 관리 콘솔에서 구성하도록 하겠습니다.
1. S3 Bucket 구성하기
S3 버킷을 구성합니다. 이 때 public access는 차단하는 것을 권장합니다.
모두 기본 설정으로 두셔도 무관합니다.
2. DynamoDB Table 구성하기
DynamoDB Table을 구성합니다.
Table name은 본인이 원하는 이름으로 설정하셔도 됩니다.
파티션 키로 LockID 를 입력하고, 타입은 String 으로 두고 생성합니다.
3. Terraform Configuration
terraform.tf 파일을 생성한 후 다음을 입력합니다.
# terraform.tf
terraform {
backend "s3" {
bucket = "terraform-state-bucket01"
key = "server/terraform.tfstate"
region = "ap-northeast-2"
dynamodb_table = "state-locking"
}
}
backend "s3" : s3를 이용해 terraform state를 관리하겠다는 의미입니다.
bucket : 1번에서 생성한 버킷 이름을 입력합니다.
key : 버킷 내에 저장할 state 오브젝트의 이름입니다.
region : 서울 리전을 입력합니다.
dynamodb_table : 2번에서 생성한 테이블 이름을 입력합니다.
지금까지 구현을 마치시면 terraform init 을 통해 구현을 완료합니다.
이후 terraform apply 를 실행하면 콘솔에서 locking이 되는 것을 확인할 수 있습니다.
다른 유저가 동시에 terraform apply 를 실행하면 다음과 같은 에러 메세지가 나오며 실행되지 않게 됩니다.