오버라이드 파일

오버라이드 파일 (Override Files)

Terraform이 특정 구성 객체의 일부를 별도 파일로 재정의하는 오버라이드(override) 메커니즘을 설명해 드릴게요. 특수한 상황에서만 쓰는 기능이니 주의해서 사용해야 해요.

출처: 문서

본문

Terraform은 보통 디렉터리 안의 모든 .tf.tf.json 파일을 로드하고, 각각이 서로 다른 구성 객체 집합을 정의하기를 기대해요. 두 파일이 같은 객체를 정의하려고 하면 Terraform은 오류를 반환해요.

드문 경우지만, 별도 파일에서 기존 구성 객체의 특정 부분을 재정의할 수 있는 것이 편리할 때가 있어요. 예를 들어 Terraform 언어 네이티브 문법으로 사람이 편집한 구성 파일을, JSON 문법으로 프로그램이 생성한 파일로 부분적으로 재정의할 수 있어요.

이런 드문 상황을 위해 Terraform은 이름이 _override.tf 또는 _override.tf.json로 끝나는 구성 파일을 특별히 처리해요. 이 특별 처리는 말 그대로 override.tf 또는 override.tf.json라는 이름의 파일에도 적용돼요.

Terraform은 구성 로드 시 이 오버라이드 파일들을 처음에 건너뛰고, 그 후 각각을 (사전식 순서로) 처리해요. 오버라이드 파일에 정의된 각 최상위 블록에 대해 Terraform은 해당 블록에 대응하는 이미 정의된 객체를 찾으려 시도한 뒤, 오버라이드 블록 내용을 기존 객체에 병합해요.

오버라이드 파일은 특수한 상황에서만 사용해요. 오버라이드 파일을 과도하게 쓰면 가독성을 해쳐요. 원본 파일만 보는 독자는 존재하는 모든 오버라이드 파일을 확인하지 않고서는 원본의 일부가 재정의되었음을 쉽게 알 수 없으니까요. 오버라이드 파일을 쓸 때는 원본 파일에 주석을 사용해 이후 독자에게 어떤 오버라이드 파일이 각 블록에 변경을 적용하는지 경고해 주는 것이 좋아요.

예시 (Example)

example.tf라는 Terraform 구성에 다음 내용이 있다고 해요:

resource "aws_instance" "web" {
  instance_type = "t2.micro"
  ami           = "ami-408c7f28"
}

...그리고 다음 내용을 담은 override.tf 파일을 만들었다면:

resource "aws_instance" "web" {
  ami = "foo"
}

Terraform은 후자를 전자에 병합해서, 원래 구성이 다음과 같았던 것처럼 동작해요:

resource "aws_instance" "web" {
  instance_type = "t2.micro"
  ami           = "foo"
}

병합 동작 (Merging Behavior)

병합 동작은 블록 유형마다 약간 다르며, 특정 블록 안의 일부 특수 구문은 특별한 방식으로 병합돼요. 대부분의 경우에 적용되는 일반 규칙은 다음과 같아요:

  • 오버라이드 파일의 최상위 블록은 같은 블록 헤더(블록 유형과 뒤따르는 인용 라벨)를 가진 일반 구성 파일의 블록과 병합돼요.
  • 최상위 블록 안에서, 오버라이드 블록의 속성 인자는 원본 블록의 같은 이름 인자를 대체해요.
  • 최상위 블록 안에서, 오버라이드 블록의 중첩 블록은 원본 블록의 같은 유형 블록을 모두 대체해요. 오버라이드 블록에 나타나지 않는 블록 유형은 원본 블록에서 유지돼요.
  • 중첩 구성 블록의 내용은 병합되지 않아요.
  • 병합 결과 블록은 해당 블록 유형에 적용되는 모든 검증 규칙을 여전히 준수해야 해요.

둘 이상의 오버라이드 파일이 같은 최상위 블록을 정의하면 재정의 효과가 중첩되는데, 나중 블록이 이전 블록보다 우선해요. 오버라이드는 먼저 파일 이름(사전식 순서), 그 다음 각 파일의 위치 순으로 처리돼요.

아래 섹션들은 특정 최상위 블록 유형 안의 특정 인자에 적용되는 특별한 병합 동작을 설명해요.

resourcedata 블록 병합

resource 블록 안에서 lifecycle 중첩 블록의 내용은 인자 단위로 병합돼요. 예를 들어 오버라이드 블록이 create_before_destroy 인자만 설정하면 원본 블록의 ignore_changes 인자는 보존돼요.

재정의하는 resource 블록이 provisioner 블록을 하나 이상 포함하면 원본 블록의 provisioner 블록은 무시돼요. 재정의하는 resource 블록이 connection 블록을 포함하면 원본 블록에 있는 connection 블록을 완전히 대체해요. depends_on 메타-인자는 오버라이드 블록에서 사용할 수 없으며, 사용하면 오류가 발생해요.

variable 블록 병합

variable 블록 안의 인자는 위에서 설명한 표준 방식으로 병합되지만, typedefault 인자 간의 상호작용 때문에 몇 가지 특별한 고려 사항이 적용돼요.

원본 블록이 default 값을 정의하고 오버라이드 블록이 변수의 type을 변경하면, Terraform은 기본값을 오버라이드된 타입으로 변환하려 시도하고, 변환이 불가능하면 오류를 발생시켜요. 반대로 원본 블록이 type을 정의하고 오버라이드 블록이 default를 변경하면, 오버라이드된 기본값은 원본 타입 사양과 호환되어야 해요.

output 블록 병합

depends_on 메타-인자는 오버라이드 블록에서 사용할 수 없으며, 사용하면 오류가 발생해요.

locals 블록 병합

locals 블록은 여러 이름 있는 값을 정의해요. 오버라이드가 값 단위로 적용되며, 값이 정의된 locals 블록은 무시돼요.

terraform 블록 병합

terraform 블록 안의 설정은 병합할 때 개별적으로 고려돼요.

required_providers 인자가 설정되면 그 값은 요소 단위로 병합되는데, 이는 오버라이드 블록이 다른 프로바이더의 제약에 영향을 주지 않고 단일 프로바이더의 제약을 조정할 수 있게 해요. required_versionrequired_providers 설정 모두에서 각 오버라이드 제약은 원본 블록의 같은 구성 요소에 대한 제약을 완전히 대체해요. 기본 블록과 오버라이드 블록이 모두 required_version을 설정하면 기본 블록의 제약은 완전히 무시돼요.

백엔드를 정의하는 블록(cloud 또는 backend)이 오버라이드 파일에 있으면 항상 원본 구성에서 백엔드를 정의하는 블록보다 우선해요. 즉 원본 구성에 cloud 블록을 설정하고 오버라이드 파일에 backend 블록을 설정했다면, Terraform은 병합 시 오버라이드 파일에 지정된 backend 블록을 사용해요. 마찬가지로 원본 구성에 backend 블록을, 오버라이드 파일에 cloud 블록을 설정했다면 Terraform은 병합 시 오버라이드 파일에 지정된 cloud 블록을 사용해요.

더 알아보기 (Learn more)