연재 시리즈

테라폼 시리즈 20편. 협업을 위한 테라폼 관리

악분 2022. 10. 29. 17:19
반응형

1. 테라폼 협업  관리란?

이제 협업을 위한 테라폼 공부를 할 때가 왔습니다. 여러 명이 테라폼을 사용하려면 2가지 문제를 해결해야 합니다.

  • 상태파일(tfstate)를 어떻게 동기화할지
  • 여러 명이 동시에 테라폼 코드를 실행하면, 어떻게 충돌을 막을지

테라폼 클라우드를 사용하면 별다른 고민 없이 테라폼 협업문제를 해결할 수 있습니다. 하지만 테라폼 클라우드는 부분 무료이기 때문에 상황에 따라 결재가 필요합니다.

 

2. backend를 이용한 상태파일 동기화

2.1 상태파일 동기화가 중요한 이유

상태파일은 테라폼코드가 인프라에 반영된 상태를 저장하고 있습니다. 그리고 인프라에 영향을 주는 terrform명령어를 실행하면, 테라폼 코드와 상태파일을 비교하여 인프라에 반영합니다. 그러므로 상태파일이 동기화되어 있지 않으면 다른 사람이 작업한 내용이 사라질 수 있거나 예상치 못한 결과를 초래할 수 있습니다.

 

2.2 해결방법

상태파일 동기화 문제는 테라폼 backend를 이용하여 해결할 수 있습니다. backend는 상태파일을 저장하는 위치를 설정합니다. 설정되지 않으면 로컬에 저장됩니다.

 

대표적인 원격 저장소는 aws s3입니다. s3이외에 Azure Blob Storage, Google Cloud Storage, Consul, Postgres database 등 지원합니다. 지원 backend는 테라폼 공식문서(https://developer.hashicorp.com/terraform/language/settings/backends/local)를 참고하시길 바랍니다.

 

s3버전 옵션을 활성화 했다면 state파일을 백업할 수 있습니다.

 

backend를 aws s3로 설정한 예입니다.

terraform {
  backend "s3" {
    bucket = "akbun-t101study-tfstate"
    key    = "terraform.tfstate"
    region = "ap-northeast-2"
  }
}

 

2.3 실습

aws s3를 먼저 생성해야 합니다. 저는 테라폼 코드로 미리 생성했습니다. bucket이름은 고유해야 하므로 버킷이름 수정이 필요합니다.

provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_s3_bucket" "mys3bucket" {
  bucket = "akbun-t101study-tfstate"
}

# Enable versioning so you can see the full revision history of your state files
resource "aws_s3_bucket_versioning" "mys3bucket_versioning" {
  bucket = aws_s3_bucket.mys3bucket.id
  versioning_configuration {
    status = "Enabled"
  }
}

output "s3_bucket_arn" {
  value       = aws_s3_bucket.mys3bucket.arn
  description = "The ARN of the S3 bucket"
}

 

s3를 생성한 폴더를 벗어나고 새로운 폴더에서 backend를 설정합니다.

terraform {
  backend "s3" {
    bucket = "akbun-t101study-tfstate"
    key    = "terraform.tfstate"
    region = "ap-northeast-2"
  }
}

 

테라폼 backend설정을 적용하려면 terraform init명령어를 실행해야 합니다.

terraform apply

 

이제 테라폼 상태파일은 s3에 자동저장됩니다. 정말 s3에 저장되는지 확인해보겠습니다. 제가 미리 만들어 놓은 테라폼 코드를 aws에 반영해보겠습니다. 테라폼 코드는 vpc, subnet, internet gateway, security group, EC2 Instance를 생성합니다.

github 링크: https://github.com/sungwook-practice/terraform-study/tree/main/week2/backend(s3_dynamoDB)/main

 

terrafrom apply명령어를 실행하여 테라폼 코드를 aws에 반영합니다.

terraform apply

 

terraform apply명령어 실행이 성공하면 tfstate파일이 로컬에 존재하지 않습니다. backend를 s3로 설정했기 때문에 s3에 tfstate파일이 존재합니다.

 

3. 동시쓰기 제한문제 해결 - locking

3.1 동시쓰기문제란?

테라폼 공식문서(https://developer.hashicorp.com/terraform/language/state/backends#state-locking)를 보면 backend를 사용하면 lokcing에 대한 책임이 필요하다고 설명합니다.

 

상태파일을 원격 backend로 해결하더라도, 동시에 여러명이 상태파일을 업데이트한다면 모든 사용자 작업이 꼬일 수 있습니다. 그러므로 운영체제 멀티쓰레드 locking처럼 동시에 상태파일 업데이트를 못하도록 막을 책임이 있습니다.

 

3.2 backend locking 설정

원격 backend를 어떤 거를 사용하느냐에 따라 locking작업이 달라지는데요. 아쉽게도 s3는 동시 쓰기 작업을 완벽히 막아주지 않는 것 같습니다.

출처: https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html#ConsistencyModel

 

테라폼 Issuse에서도 s3를 backend는 locking을 지원하지 않아 보조도구를 여전히 써야한다고 언급하고 있습니다.

출처: https://github.com/hashicorp/terraform/issues/27070#issuecomment-1294251198

 

3.3 실습

실습에서는 aws dynamodb을 이용하여 locking합니다. [챕터 2]에서 사용한 s3와 같이 사용해야 합니다.

 

먼저, dynamodb 테이블을 생성합니다.

provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_dynamodb_table" "mydynamodbtable" {
  name         = "terraform-locks"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }
}

output "dynamodb_table_name" {
  value       = aws_dynamodb_table.mydynamodbtable.name
  description = "The name of the DynamoDB table"
}

resource "aws_s3_bucket" "mys3bucket" {
  bucket = "akbun-t101study-tfstate"
}

# Enable versioning so you can see the full revision history of your state files
resource "aws_s3_bucket_versioning" "mys3bucket_versioning" {
  bucket = aws_s3_bucket.mys3bucket.id
  versioning_configuration {
    status = "Enabled"
  }
}

output "s3_bucket_arn" {
  value       = aws_s3_bucket.mys3bucket.arn
  description = "The ARN of the S3 bucket"
}

 

dynamodb에서 테이블이 잘 생성되었는지 확인합니다.

 

backend에 dynamodb를 추가합니다.

terraform {
  backend "s3" {
    bucket = "akbun-t101study-tfstate"
    key    = "terraform.tfstate"
    region = "ap-northeast-2"
    dynamodb_table = "terraform-locks"
  }
}

 

테라폼 backend를 적용하기 위해 terraform init명령어를 실행합니다.

terraform init

 

이제 테라폼 코드를 인프라에 반영해볼게요. 제가 미리 준비한 테라폼 코드를 다운로드 받습니다. 

github 링크: https://github.com/sungwook-practice/terraform-study/tree/main/week2/backend(s3_dynamoDB)/main

 

terrform apply명령어를 실행하여 aws에 반영합니다.

terraform apply

 

dynamodb에 저장된 item목록을 보면 lock파일이 생성되었습니다. 테라폼 작업을 동시에 하지 못하도록 lock파일이 생성된겁니다.

 

lock을 소유하고 있는 작업이 끝나면 lock파일은 사라집니다.

 

반응형