메인 콘텐츠로 이동하기
  1. Posts/

Terramate 병렬 terraform init 시 AWS Provider 손상 문제 해결

·2 분

문제 상황 #

Terramate로 여러 스택을 관리하는 프로젝트에서, 병렬로 terraform init을 실행하면 이후 terraform plan 시 다음과 같은 에러가 발생했습니다.

Error: Failed to load plugin schemas

Error while loading schemas for plugin components: Failed to obtain provider schema:
Could not load the schema for provider registry.terraform.io/hashicorp/aws:
failed to instantiate provider "registry.terraform.io/hashicorp/aws" to obtain schema:
Unrecognized remote plugin message:
Failed to read any lines from plugin's stdout

신기하게도:

  • 개별 init → 정상 작동
  • 병렬 init → Provider 손상

원인 분석 #

1. --enable-sharing 옵션 #

Terramate의 output sharing 기능(--enable-sharing --mock-on-fail)이 init에 포함되어 있었습니다. 이 옵션은 스택 간 output을 공유하기 위한 것인데, init 단계에서는 불필요합니다.

# 문제가 된 설정
TM_OPTS := --enable-sharing --mock-on-fail ...
terramate run --tags=$(TAGS) $(TM_OPTS) -- terraform init

2. Plugin Cache Race Condition #

병렬로 여러 스택이 동시에 같은 Provider를 다운로드하면 파일이 손상될 수 있습니다. 특히 AWS Provider는 크기가 ~300MB로 커서 race condition 발생 확률이 높습니다.

해결 방법 #

1. init에서 sharing 옵션 분리 #

# 수정된 Makefile
TM_COMMON := $(if $(filter P,$(MAKECMDGOALS)),$(if $(PNUM),-j $(PNUM),--parallel),) \
  $(if $(filter C,$(MAKECMDGOALS)),--changed,)
TM_OPTS := --enable-sharing --mock-on-fail $(TM_COMMON)

# init은 TM_COMMON만 사용
init:
    terramate run --tags=$(TAGS) $(TM_COMMON) -- terraform init $(INIT_OPTS)

# plan/apply는 TM_OPTS 사용 (sharing 포함)
plan:
    terramate run --tags=$(TAGS) $(TM_OPTS) -- terraform plan

2. 글로벌 Plugin Cache 설정 #

~/.terraformrc에 글로벌 캐시를 설정하면 Provider를 한 번만 다운로드하고 모든 프로젝트에서 공유합니다.

# ~/.terraformrc
plugin_cache_dir = "$HOME/.terraform.d/plugin-cache"
# 캐시 디렉토리 생성
mkdir -p ~/.terraform.d/plugin-cache

3. Lock 파일 체크섬 무시 설정 #

캐시 사용 시 체크섬 불일치 에러가 발생할 수 있습니다. Terramate 설정에 환경변수를 추가합니다.

# terramate.tm.hcl
terramate {
  config {
    run {
      env {
        TF_PLUGIN_CACHE_MAY_BREAK_DEPENDENCY_LOCK_FILE = "true"
      }
    }
  }
}

최종 설정 #

~/.terraformrc #

plugin_cache_dir = "$HOME/.terraform.d/plugin-cache"

terramate.tm.hcl #

terramate {
  config {
    run {
      env {
        TF_PLUGIN_CACHE_MAY_BREAK_DEPENDENCY_LOCK_FILE = "true"
      }
    }
  }
}

Makefile #

TM_COMMON := $(if $(filter P,$(MAKECMDGOALS)),$(if $(PNUM),-j $(PNUM),--parallel),) \
  $(if $(filter C,$(MAKECMDGOALS)),--changed,)
TM_OPTS := --enable-sharing --mock-on-fail $(TM_COMMON)

init:
    terramate run --tags=$(TAGS) $(TM_COMMON) -- terraform init $(INIT_OPTS)

plan:
    terramate run --tags=$(TAGS) $(TM_OPTS) -- terraform plan

TL;DR #

문제해결책
init에 불필요한 --enable-sharinginit과 plan/apply 옵션 분리
병렬 다운로드 시 Provider 손상글로벌 plugin cache 사용
캐시 체크섬 불일치TF_PLUGIN_CACHE_MAY_BREAK_DEPENDENCY_LOCK_FILE=true

이 설정으로 make init dev P 5처럼 병렬 init이 정상 작동합니다.