일반적인 스타일 및 구조 권장사항

이 문서에서는 Terraform 구성을 위한 기본 스타일과 구조 관련 권장사항을 제공합니다. 이러한 권장사항은 재사용 가능한 Terraform 모듈 및 루트 구성에 적용됩니다.

이 가이드는 Terraform 소개 내용이 아닙니다. Google Cloud에서 Terraform 사용에 대한 소개는 정보는 Terraform 시작하기를 참조하세요.

표준 모듈 구조 따르기

  • Terraform 모듈은 표준 모듈 구조를 따라야 합니다.
  • 기본적으로 리소스가 있는 위치인 main.tf 파일로부터 모든 모듈을 시작합니다.
  • 모든 모듈에서 마크다운 형식에 README.md 파일을 포함합니다. README.md 파일에서 모듈에 대한 기본 문서를 포함합니다.
  • 각 예시에 대해 개별 하위 디렉터리를 사용해서 examples/ 폴더에 예시를 둡니다. 각 예시에 대해 자세한 README.md 파일을 포함합니다.
  • 자체 파일 및 network.tf, instances.tf, loadbalancer.tf와 같은 자세한 이름을 사용해서 리소스를 논리적 그룹으로 만듭니다.
    • 모든 리소스에 자체 파일을 제공하지 않습니다. 공유 목적에 따라 리소스를 그룹으로 묶습니다. 예를 들어 google_dns_managed_zonegoogle_dns_record_setdns.tf에 조합합니다.
  • 모듈의 루트 디렉터리에서 Terraform(*.tf) 및 저장소 메타데이터 파일(예: README.mdCHANGELOG.md)만 포함합니다.
  • 모든 추가 문서를 docs/ 하위 디렉터리에 둡니다.

이름 지정 규칙 채택

  • 단어 구분을 위한 밑줄을 사용해서 모든 구성 객체의 이름을 지정합니다. 이렇게 하면 리소스 유형, 데이터 소스 유형, 기타 사전 정의된 값에 대해 이름 지정 규칙을 일관적으로 사용할 수 있습니다. 인수 이름 지정에는 이 규칙이 적용되지 않습니다.

    다음을 권장합니다.

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

    다음은 권장하지 않습니다.

    resource "google_compute_instance" "web-server" {
      name = "web-server"
    }
    
  • 단독 유형의 리소스 참조를 단순화하기 위해서는(예: 전체 모듈의 단일 부하 분산기) 리소스 이름을 main으로 지정합니다.

    • some_google_resource.my_special_resource.idsome_google_resource.main.id를 구분해서 기억하기 위해서는 정신적으로 추가적인 주의가 필요합니다.
  • 동일 유형의 리소스를 서로 구분하기 위해(예: primarysecondary) 의미 있는 리소스 이름을 제공합니다.

  • 리소스 이름을 단수로 만듭니다.

  • 리소스 이름에 리소스 유형을 반복하지 않습니다. 예를 들면 다음과 같습니다.

    다음을 권장합니다.

    resource "google_compute_global_address" "main" { ... }
    

    다음은 권장하지 않습니다.

    resource "google_compute_global_address" "main_global_address" { … }
    

변수를 신중하게 사용

  • variables.tf의 모든 변수를 선언합니다.
  • 변수 용도 또는 목적과 관련해서 자세한 이름을 변수에 지정합니다.
    • 디스크 크기 또는 RAM 크기와 같은 숫자 값을 나타내는 입력, 로컬 변수, 출력은 ram_size_gb와 같이 단위를 함께 사용해서 이름을 지정해야 합니다. Google Cloud API에는 표준 단위가 없으므로, 단위를 사용해서 변수 이름을 지정하여 구성 유지보수를 위한 예상 입력 단위를 명확하게 표현할 수 있습니다.
    • 스토리지 단위의 경우 바이너리(1,024의 거듭제곱) 단위 프리픽스(kibi, mebi, gibi)를 사용합니다. 다른 모든 측정 단위에 대해서는 십진수(1,000의 거듭제곱) 단위 프리픽스(kilo, mega, giga)를 사용합니다. 이러한 사용법은 Google Cloud 내에서의 사용법과 일치합니다.
    • 조건 논리를 단순화하기 위해 부울 변수에 명확한 이름을 지정합니다(예: enable_external_access).
  • 변수에는 설명이 있어야 합니다. 설명은 게시된 모듈의 자동 생성되는 문서에 자동으로 포함됩니다. 설명은 새로 투입되는 개발자를 위해 자세한 이름으로도 제공할 수 없는 추가적인 컨텍스트를 더해줍니다.
  • 변수에 정의된 유형을 지정합니다.
  • 필요한 경우 기본값을 제공합니다.
    • 디스크 크기와 같이 환경에 독립적인 값을 포함하는 변수의 경우 기본값을 제공합니다.
    • project_id와 같이 환경에 따라 달라지는 값을 포함하는 변수의 경우에는 기본값을 제공하지 않습니다. 이렇게 하면 호출 모듈이 의미 있는 값을 제공해야 합니다.
  • 변수를 비워 두어도 기본 API에서 거부되지 않는 경우에만 변수에 빈 기본값을 사용합니다(예: 빈 문자열 또는 목록).
  • 변수를 신중하게 사용합니다. 각 인스턴스 또는 환경에 따라 달라져야 하는 값만 매개변수화합니다. 변수를 노출할지 여부를 결정할 때는 해당 변수를 변경해야 하는 구체적인 사용 사례가 있어야 합니다. 변수가 필요할 가능성이 작을 때는 이를 노출하지 않습니다.
    • 기본값을 사용한 변수 추가는 하위 호환성을 갖습니다.
    • 변수 삭제는 하위 호환성을 갖지 않습니다.
    • 여러 장소에서 리터럴이 재사용되는 경우에는 이를 변수로 노출하지 않고 로컬 값을 사용할 수 있습니다.

출력 노출

  • 모든 출력을 outputs.tf 파일로 구성합니다.
  • 모든 출력에 의미 있는 설명을 제공합니다.
  • README.md 파일에 출력 설명을 기술합니다. terraform-docs와 같은 도구를 사용해서 커밋 시 설명을 자동 생성합니다.
  • 루트 모듈이 참조하거나 공유해야 할 수 있는 모든 유용한 값을 출력합니다. 특히 오픈소스 또는 매우 자주 사용되는 모듈의 경우 사용 가능성이 있는 모든 출력을 노출합니다.
  • 입력 변수를 통해 직접 출력을 전달하지 않습니다. 이렇게 하면 종속 항목 그래프에 올바르게 추가되지 않습니다. 암시적 종속 항목이 생성되도록 하려면 출력이 리소스의 속성을 참조하는지 확인합니다. 인스턴스에 대해 입력 변수를 직접 참조하는 대신 아래 표시된 대로 속성을 전달합니다.

    다음을 권장합니다.

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

    다음은 권장하지 않습니다.

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

데이터 소스 사용

  • 데이터 소스를 참조되는 리소스 옆에 둡니다. 예를 들어 인스턴스를 실행하는 데 사용할 이미지를 가져오는 경우에는 자체 파일에서 데이터 리소스를 수집하는 대신 해당 인스턴스와 함께 둡니다.
  • 데이터 소스 수가 많아지면 이를 전용 data.tf 파일로 이동할 수 있습니다.
  • 현재 환경을 기준으로 데이터를 가져오려면 변수 또는 리소스 보간을 사용합니다.

커스텀 스크립트 사용 제한

  • 스크립트는 필요한 경우에만 사용합니다. 스크립트를 통해 생성된 리소스 상태는 Terraform에서 고려되거나 관리되지 않습니다.
    • 가능하면 커스텀 스크립트 사용을 피합니다. Terraform 리소스에서 원하는 동작이 지원되지 않을 때만 스크립트를 사용합니다.
    • 사용된 커스텀 스크립트는 기존 항목에 대한 그리고 이상적으로는 지원 중단 계획까지 이유가 명확하게 기술되어 있어야 합니다.
  • Terraform은 로컬 실행 프로비저닝 도구를 포함하여 프로비저닝 도구를 통해 커스텀 스크립트를 호출할 수 있습니다.
  • Terraform에서 호출된 커스텀 스크립트는 scripts/ 디렉터리에 둡니다.

도우미 스크립트를 별도의 디렉터리에 포함

  • Terraform에서 호출되지 않는 도우미 스크립트는 helpers/ 디렉터리로 정리합니다.
  • 설명 및 예시 호출을 포함해서 도우미 스크립트 관련 내용을 README.md 파일에 기록합니다.
  • 도우미 스크립트에 인수가 사용될 경우 인수 검사 및 --help 출력을 제공합니다.

정적 파일을 별도의 디렉터리에 넣기

  • Terraform에서 참조되지만 실행되지는 않는 정적 파일(예: Compute Engine 인스턴스에 로드된 시작 스크립트)은 files/ 디렉터리에 정리해야 합니다.
  • HCL과 별개로 긴 HereDocs를 외부 파일에 둡니다. file() 함수를 사용하여 참조합니다.
  • Terraform templatefile 함수를 사용하여 읽히는 파일의 경우에는 .tftpl 파일 확장자를 사용합니다.
    • 템플릿은 templates/ 디렉터리에 두어야 합니다.

스테이트풀(Stateful) 리소스 보호

데이터베이스와 같은 스테이트풀(Stateful) 리소스에 대해 삭제 보호가 사용 설정되었는지 확인합니다. 예를 들면 다음과 같습니다.

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

  lifecycle {
    prevent_destroy = true
  }
}

기본 제공되는 형식 사용

모든 Terraform 파일은 terraform fmt 표준을 따라야 합니다.

표현식의 복잡성 제한

  • 개별 보간된 표현식의 복잡성을 제한합니다. 단일 표현식에 많은 함수가 필요하면 로컬 값을 사용해서 이를 여러 표현식으로 분할하는 것이 좋습니다.
  • 한 줄에 3항 연산을 두 개 이상 사용하지 마세요. 대신 로컬 변수를 여러 개 사용해서 논리를 쌓습니다.

조건부 값에 count 사용

리소스를 조건에 따라 인스턴스화하려면 count 메타 인수를 사용합니다. 예를 들면 다음과 같습니다.

variable "readers" {
  description = "..."
  type        = list
  default     = []
}

resource "resource_type" "reference_name" {
  // Do not create this resource if the list of readers is empty.
  count = length(var.readers) == 0 ? 0 : 1
  ...
}

사용자 지정 변수를 사용하여 리소스에 count 변수를 설정하는 방식은 가능한 한 아끼는 것이 좋습니다. 이러한 변수(project_id 등)에 리소스 속성이 제공되었고 해당 리소스가 아직 존재하지 않으면 Terraform이 계획을 생성할 수 없습니다. 대신 Terraform은 value of count cannot be computed 오류를 보고합니다. 이러한 경우에는 별도의 enable_x 변수를 사용해서 조건부 논리를 계산합니다.

반복되는 리소스에 for_each 사용

입력 리소스를 기준으로 여러 리소스 복사본을 만들려면 for_each 메타 인수를 사용합니다.

레지스트리에 모듈 게시

다음 단계