본문 바로가기

IaC

테라폼 사용 권장사항

https://cloud.google.com/docs/terraform/best-practices-for-terraform?hl=ko#security

 

Terraform 사용 권장사항  |  Google Cloud

의견 보내기 Terraform 사용 권장사항 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 이 문서에서는 여러 팀 멤버와 작업 스트림 간의 Terraform을 사용한 효율적

cloud.google.com

 

GCP에서 제공하는 테라폼 사용 권장사항의 일부를 정리하였습니다.

 

일반 스타일  구조 가이드라인

> 단어 구분을 위한 밑줄을 이용해서 모든 구성 객체의 이름을 지정합니다.

 

-> "web_server"

resource "google_compute_instance" "web_server" {
  name = "web-server"
}

 


 

> 소스 이름에 리소스 유형을 반복하지 않습니다.

 

-> 아래의 예시처럼 리소스 이름을 지정하지 않습니다.

resource "google_compute_global_address" "main_global_address" { … }

 


 

> 입력 변수를 통해 직접 출력을 전달하지 않습니다.

 

-> 이렇게 값을 직접 전달하는 것은 권장되지 않습니다.

output "name" {
  description = "Name of instance"
  value       = var.name
}

 

-> 출력이 리소스를 참조하여 속성을 전달합니다.

output "name" {
  description = "Name of instance"
  value       = google_compute_instance.main.name
}

 


 

> stateful한 리소스를 보호합니다.

 

-> 데이터베이스와 같은 스테이트풀(Stateful) 리소스에 대해 삭제보호가 적용되어 있는지 확인합니다.

resource "google_sql_database_instance" "main" {
  name = "primary-instance"
  settings {
    tier = "D0"
  }

  lifecycle {
    prevent_destroy = true
  }
}

 


 

> 애플리케이션을 환경별 하위 디렉터리로 분할합니다.

 

-> 서비스를 배포할 때 해당 서비스의 Terraform 구성을 2개의 최상위 디렉터리로 분할합니다. 하나는 서비스의 실제 구성이 포함된 modules 디렉터리이고 다른 하나는 각 환경의 루트 구성이 포함된 environments 디렉터리입니다.

-- SERVICE-DIRECTORY/
   -- OWNERS
   -- modules/
      -- <service-name>/
         -- main.tf
         -- variables.tf
         -- outputs.tf
         -- provider.tf
         -- README
      -- ...other…
   -- environments/
      -- dev/
         -- backend.tf
         -- main.tf

      -- qa/
         -- backend.tf
         -- main.tf

      -- prod/
         -- backend.tf
         -- main.tf

 


 

> 저장소 구성

 

기본 저장소

  • 이 저장소에서는 각 주요 구성요소(예: 폴더, 네트워크 등)에 대한 디렉터리를 포함합니다.
  • 구성요소 디렉터리에서는 앞에서 설명한 디렉터리 구조 가이드에 따라 각 환경에 대해 개별 폴더를 포함합니다.

 

 

애플리케이션 및 팀별 저장소

 

각 팀이 고유한 애플리케이션별 Terraform 구성을 관리할 수 있도록 애플리케이션 및 팀별 저장소를 개별적으로 배포합니다.

 

 


테스트 런타임 최적화

 

  • 테스트를 병렬로 실행합니다. 일부 테스트 프레임워크에서는 여러 Terraform 테스트의 동시 실행이 지원됩니다.
    • 예를 들어 Terratest의 경우 테스트 기능 정의 후 t.Parallel()을 추가할 수 있습니다.
  • 단계별로 테스트합니다. 개별적으로 테스트할 수 있는 독립적인 구성으로 테스트를 구분합니다. 이렇게 하면 테스트를 실행할 때 모든 단계를 진행할 필요가 없고 반복적인 개발 주기를 빠르게 진행할 수 있습니다.
    • 예를 들어 Kitchen-Terraform에서는 테스트를 개별 모음으로 분할합니다. 반복 시에는 각 모음을 독립적으로 실행합니다.
    • 마찬가지로 Terratest를 사용할 때는 stage(t, STAGE_NAME, CORRESPONDING_TESTFUNCTION)을 사용해서 테스트의 각 단계를 래핑합니다. 실행할 테스트를 나타내는 환경 변수를 설정합니다. 예를 들면 SKIP STAGE_NAME="true"입니다.
package test

import (
	"testing"
	"time"
	"os"

	"github.com/stretchr/testify/assert"
	"github.com/gruntwork-io/terratest/modules/logger"
	"github.com/gruntwork-io/terratest/modules/stage"
	"github.com/gruntwork-io/terratest/modules/terraform"
)

func TestTerraformDeployment(t *testing.T) {
	t.Parallel() // 병렬 실행 가능하도록 설정

	// Terraform 옵션 정의
	terraformOptions := &terraform.Options{
		TerraformDir: "../terraform", // Terraform 코드 경로
	}

	// STEP 1: Terraform Init & Apply
	stage(t, "deploy", func() {
		logger.Logf(t, "🚀 Deploying Terraform...")
		terraform.InitAndApply(t, terraformOptions)
	})

	// STEP 2: 배포 확인 테스트
	stage(t, "validate", func() {
		logger.Logf(t, "🔍 Validating deployment...")

		// 예제: 특정 output 값이 기대값과 일치하는지 확인
		vpcID := terraform.Output(t, terraformOptions, "vpc_id")
		assert.NotEmpty(t, vpcID, "VPC ID should not be empty!")
	})

	// STEP 3: 정리 (Terraform Destroy)
	stage(t, "cleanup", func() {
		logger.Logf(t, "🧹 Cleaning up resources...")
		terraform.Destroy(t, terraformOptions)
	})
}

 

 

환경 변수로 특정 단계(stage) 건너뛰기

# 배포 단계 건너뛰기
export SKIPdeploy="true"
go test -v