테라폼 상태와 격리

hyeongjun Jo·2023년 5월 26일
1

DevOps

목록 보기
8/11
post-thumbnail

이번 포스트는 요즘 제가 공부하고 있는 테라폼에 대해 다뤄보려 합니다. 테라폼은 현시점 가장 강력한 IaC 도구로 자리매김 하였죠. 오늘은 현업에서 테라폼을 사용할 때 환경을 어떻게 격리하는지, 모듈화는 어떻게 하는지 알아보겠습니다.

목차

  • 테라폼 상태란?
  • 상태 파일을 공유하기
    • 원격 백엔드
    • S3를 원격 백엔드로 사용
    • 테라폼 백엔드의 단점
  • 격리
    • 테라폼 작업 공간을 통한 격리
      • 테라폼 작업 공간의 단점
    • 파일 레이아웃을 이용한 격리
      • 파일 레이아웃을 이용한 격리의 단점

테라폼 상태란?

테라폼을 실행할 때마다 테라폼은 생성한 인프라에 대한 정보를 테라폼 상태 파일에 기록합니다.
이 파일에는 구성파일(.tf)의 테라폼 리소스가 실제 리소스의 표현으로 매핑되는 내용을 기록하는 사용자 정의 JSON 형식이 포함되어 있습니다.

terraform.tfstate의 예시

테라폼을 실행할 때마다 상태 파일의 ID를 통해 발견된 컴퓨터의 코드와 실제 세계에 배포된 인프라 간의 차이를 확인합니다. (terraform plan)

상태파일은 배포할 때마다 변경되는 프라이빗 API로 오직 테라폼 내부에서 사용하기 위한 것.
테라폼 상태 파일을 직접 편집하거나 직접 읽는 코드를 작성해서는 안됨

상태 파일을 공유하기

가장 대표적인 파일 공유방법은 Git과 같은 버전 관리 시스템에 두는 것인데 terraform.tfstate를 버전 관리 시스템에 두면 안되는 이유는 다음과 같습니다.

  1. 수동 오류
    최신 변경사항을 가져오고 push하는 것을 잊기 쉽습니다.

  2. 잠금
    여러명의 팀원이 동시에 하나의 상태 파일에 terraform apply 명령을 실행하지 못하게 하는 잠금 기능을 제공하지 않습니다.

  3. 시크릿
    특정 테라폼 리소스에 중요한 데이터를 저장해야 할 때 문제가 발생합니다.

버전 관리 시스템대신 테라폼에 내장된 원격 백엔드 기능을 사용할 수 있습니다.

원격 백엔드

테라폼의 기본 백엔드는 로컬 백엔드로써 로컬 디스크에 상태파일을 저장합니다.
원격 백엔드를 사용하면 상태파일을 원격 공유 저장소에 저장할 수 있습니다. 아마존 S3와 애저 스토리지, 구글 클라우드 스토리지, 해시코프의 테라폼 클라우드, 테라폼 프로, 테라폼 엔터프라이즈 등 다양한 원격 백엔드가 지원됩니다.
본 실습에서는 아마존 S3를 사용하겠습니다.

S3를 원격 백엔드로 사용

먼저 S3를 생성합니다.

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

resource "aws_s3_bucket" "terraform_state" {
  bucket = "terraform-up-and-running-state-hyeongjun"

  # 중요한 리소스를 실수로 destroy 하지 않게 destroy 중 오류 발생
  lifecycle {
    prevent_destroy = true
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "example" {
  bucket = aws_s3_bucket.terraform_state.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm     = "AES256"
    }
  }
}

resource "aws_s3_bucket_versioning" "versioning_example" {
  bucket = aws_s3_bucket.terraform_state.id

  versioning_configuration {
    status = "Enabled"
  }
}

그리고 잠금에 사용할 다이나모 DB 테이블을 생성합니다.

resource "aws_dynamodb_table" "terraform_lock" {
  hash_key = "LockID"
  name = "terraform-up-and-running-locks"
  billing_mode = "PAY_PER_REQUEST"

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

S3와 Lock에 사용할 DynamoDB 테이블이 생성된 것을 확인 가능합니다.
이제 이 S3를 terraform backend로 사용하기 위해 backend 구성을 설정합니다.


terraform {
  backend "s3" {
    bucket = "terraform-up-and-running-state-hyeongjun"
    key = "stage/services/webserver-cluster/terraform.tfstate"
    region = "ap-northeast-2"

    dynamodb_table = "terraform-up-and-running-locks"
    encrypt = true
  }
}

그리고 다시 terraform init 명령을 실행하면 테라폼은 로컬 디스크에 이미 상태 파일이 있음을 자동으로 감지해 새로운 S3 백엔드에 복사한다는 메시지를 표시합니다.

yes를 입력하면 S3 버킷에 상태파일이 생성된 것을 확인 가능합니다.

백엔드가 활성화되면 테라폼은 명령(terraform apply)을 실행하기 전에 이 S3 버킷에서 최신 상태를 자동으로 가져옵니다. 그리고 명령을 실행한 후에는 최신 상태를 s3 버킷에 자동으로 푸시합니다.

테라폼 백엔드의 단점

테라폼 백엔드에는 몇 가지 단점이 있는데
1. S3 버킷과 DynamoDB 테이블을 먼저 생성하고 backend 구성을 추가해야 합니다.
2. 테라폼의 backend 블록에는 변수나 참조를 사용할 수 없습니다.
backend 블록을 다시 보면


terraform {
backend "s3" {
  bucket = "terraform-up-and-running-state-hyeongjun"
  key = "stage/services/webserver-cluster/terraform.tfstate"
  region = "ap-northeast-2"

  dynamodb_table = "terraform-up-and-running-locks"
  encrypt = true
  }
}

수동으로 입력해야하는 "" 값들이 굉장히 많습니다.
key 값은 테라폼 모듈마다 고유해야 하고 실수로 다른 모듈을 덮어 쓰지 않도록 해야 합니다.


격리

모든 인프라를 단 하나의 테라폼 파일로 정의하면 실수로 전체를 날려버릴 수 있습니다.
보통 개발환경은 Prod, Dev, Stage, Test 등등 여러가지로 나뉘는데 테스트 중 실수로 Prod 환경의 인프라까지 사라진다면 큰 낭패입니다.
따라서 현업에서 상태 파일의 격리는 필수입니다.
상태 파일을 격리하는 방법은 두 가지 방법이 있는데
1. 테라폼 작업 공간(work space)을 통한 격리
2. 파일 레이아웃을 이용한 격리
가 있습니다.

테라폼 작업 공간을 통한 격리

테라폼은 테라폼 작업 공간(Terraform workspace)을 통해 테라폼 상태를 여러 개의 작업 공간에 저장할 수 있습니다.
원래는 default 라는 기본 작업 공간에서 사용합니다.
terraform workspace 명령으로 테라폼 작업공간을 관리할 수 있습니다.

테라폼 작업 공간의 단점

  1. 모든 작업 공간의 상태파일이 동일한 백엔드(s3)에 저장되므로 같은 인증 메커니즘을 사용합니다.
  2. terraform workspace 명령어를 통해서만 작업 공간의 정보를 알 수 있으므로 인프라를 제대로 파악 못하고 작업을 할 가능성이 있습니다.

파일 레이아웃을 이용한 격리

테라폼 작업 공간의 단점을 극복하고 환경을 완전히 격리하려면 각 테라폼 구성파일을 분리된 폴더에 넣는 방법이 있습니다.

일반적인 환경의 예시

  • stage 테스트 환경과 같은 사전 프로덕션 워크로드 환경
  • prod 사용자용 맵 같은 프로덕션 워크로드 환경
  • mgmt 베스천 호스트나 젠킨스와 같은 데브옵스 도구 환경
  • global S3, IAM과 같이 모든 환경에서 사용되는 리소스를 배치하는 장소

각 환경에서의 일반적인 구성 요소

  • vpc 해당 환경을 위한 네트워크 토폴로지
  • services 해당 환경에서 서비스되는 애플리케이션 또는 마이크로서비스
  • data-storage 해당 환경에서 실행할 데이터 저장소

각 구성 요소에서의 일반적인 테라폼 구성 파일

  • variables.tf 입력변수
  • outputs.tf 출력변수
  • main.tf 리소스

파일 레이아웃을 이용한 격리의 단점

  • 한 번의 명령으로 전체 인프라를 만들지 못하고 각 폴더에서 terraform apply를 진행해야 합니다.
    • 테라그런트를 사용하면 apply-all 명령 사용 가능합니다.
  • 리소스 종속성을 사용하기 어렵습니다.
    • 다른 폴더에 있으면 서로 접근하기 어렵습니다.
    • 현재 예제에서는 웹 서비스가 다른 폴더에 있는 DB의 정보를 직접 가져올 수 없습니다.
      • 즉 web을 담당하는 terraform과 db를 담당하는 terraform이 격리되어 액세스가 불가능합니다.
    • 이것을 해결하는 방법은 terraform_remote_state를 이용하는 것입니다.

terraform_remote_state

다른 테라폼 구성 세트에 완전한 읽기 전용 방식으로 (s3에) 저장된 테라폼 상태 파일을 가져올 수 있습니다.
물론 output으로 변수를 terraform.tfstate에 저장해야 합니다.

data.terraform_remote_state.<NAME>.outputs.<ATTRIBUTE>
형식으로 사용할 수 있습니다.

실습

https://hyeongjun-hub.notion.site/Chap03-bd42ae366c044a17a306fc60585fad98


Reference

https://github.com/brikis98/terraform-up-and-running-code

profile
DevOps Engineer

0개의 댓글