GitLab 관리 Terraform 상태

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-Managed, GitLab Dedicated
  • GitLab 15.7에서 도입된 점을 포함한 상태 이름을 지원합니다. 이를 위해 플래그allow_dots_on_tf_state_names가 소개되었습니다. 기본적으로 비활성화됩니다.
  • GitLab 16.0에서 일반적으로 사용 가능한 상태 이름을 지원합니다. 피처 플래그 allow_dots_on_tf_state_names가 제거되었습니다.

Terraform은 인프라 구성에 대한 세부 정보를 저장하기 위해 상태 파일을 사용합니다. Terraform 원격 백엔드를 사용하여 상태 파일을 원격 및 공유 리포지터리에 저장할 수 있습니다.

GitLab은 Terraform HTTP 백엔드를 제공하여 최소한의 구성으로 상태 파일을 안전하게 저장할 수 있습니다.

GitLab에서 다음과 같은 작업을 수행할 수 있습니다.

  • Terraform 상태 파일의 버전을 관리합니다.
  • 상태 파일을 이동 및 정지합니다.
  • 원격으로 terraform planterraform apply 명령을 실행합니다.
caution
재해 복구 계획 Terraform 상태 파일은 디스크와 객체 리포지터리에서 휴식 중에 lockbox Ruby gem을 사용하여 암호화됩니다. 상태 파일을 복호화하려면 GitLab이 사용 가능해야 합니다. 오프라인 상태에서 GitLab을 사용하여 GitLab에서 필요로 하는 인프라를 배포하는 경우 (가상 머신, Kubernetes 클러스터 또는 네트워크 컴포넌트 등) 상태 파일에 쉽게 액세스하거나 복호화할 수 없습니다. 또한, GitLab이 GitLab을 부트스트랩하는 데 필요한 Terraform 모듈이나 기타 의존성을 제공하는 경우, 이러한 항목에 액세스할 수 없습니다. 이 문제를 해결하기 위해 이러한 의존성을 호스팅하거나 백업할 수 있는 다른 방법을 찾거나 공유 지점이 없는 별도의 GitLab 인스턴스를 사용하는 것을 고려해보세요.

전제 조건

Self-Managed형 GitLab의 경우, Terraform 상태 파일에 GitLab을 사용하기 전에 다음이 준수되어야 합니다.

  • 관리자는 Terraform 상태 리포지터리를 설정해야 합니다.
  • 프로젝트에서 Settings > General로 이동하여 Visibility, project features, permissions을 확장하고, Infrastructure 아래에서 토글을 켜 GitLab에 대한 Infrastructure 메뉴를 활성화해야 합니다.

GitLab CI/CD를 사용하여 백엔드로 Terraform 상태 초기화

terraform init 명령을 실행한 후, GitLab CI/CD를 사용하여 terraform 명령을 실행할 수 있습니다.

전제 조건:

  • terraform apply를 사용하여 상태를 잠그고 잠금 해제 및 기록하기 위해 적어도 Maintainer 역할이 필요합니다.
  • terraform plan -lock=false를 사용하여 상태를 읽기 위해서는 적어도 Developer 역할이 필요합니다.
caution
기타 작업 결과와 마찬가지로 Terraform 계획 데이터는 리포지터리에 대한 Guest 역할이 있는 사람에 의해 볼 수 있습니다. Terraform이나 GitLab은 기본적으로 계획 파일을 암호화하지 않습니다. Terraform plan.json이나 plan.cache 파일에 암호, 액세스 토큰 또는 인증서와 같은 민감한 데이터가 포함된 경우 계획 출력을 암호화하거나 프로젝트 가시성 설정을 수정해야 합니다. 또한, 공개 파이프라인비활성화하고 artifact의 public 플래그를 false(public: false)로 설정해야 합니다. 이러한 설정은 artifact에 관리자가 아닌 GitLab 관리자와 적어도 Reporter 역할이 있는 프로젝트 구성원만 액세스할 수 있도록 합니다.

GitLab CI/CD를 백엔드로 구성하려면:

  1. Terraform 프로젝트에서 .tf 파일(예: backend.tf)에 HTTP 백엔드를 정의합니다:

    terraform {
      backend "http" {
      }
    }
    
  2. 프로젝트 리포지터리의 루트 디렉터리에 .gitlab-ci.yml 파일을 만듭니다. 해당 파일을 채우기 위해 Terraform.gitlab-ci.yml 템플릿을 사용합니다.
  3. 프로젝트를 GitLab에 푸시합니다. 이 작업은 gitlab-terraform init, gitlab-terraform validate, gitlab-terraform plan 명령을 실행하는 파이프라인을 트리거합니다.
  4. 이전 파이프라인에서 매뉴얼으로 deploy 작업을 트리거합니다. 이는 정의된 인프라를 프로비저닝하는 gitlab-terraform apply 명령을 실행합니다.

상기 terraform 명령의 출력은 작업 로그에서 볼 수 있어야 합니다.

gitlab-terraform CLI는 terraform CLI의 래퍼입니다. 자세한 내용은 GitLab Terraform 도우미를 참조하거나 gitlab-terraform의 소스 코드를 확인하세요.

terraform 명령을 명시적으로 호출하는 것을 선호하는 경우 템플릿을 재정의하고 목표를 달성할 수 있는지 참조로 사용할 수 있습니다.

Terraform 환경 변수 사용자 정의

Terraform.gitlab-ci.yml 템플릿을 사용하는 경우 Terraform HTTP 구성 변수를 정의하는 CI/CD 작업을 사용할 수 있습니다.

terraform init -backend-config=... 접근법 대신에 환경 변수를 사용하여 terraform init를 사용자 정의하고 Terraform 구성을 재정의할 수 있습니다. -backend-config를 사용하면 구성이:

  • terraform plan 명령의 출력에 캐시됨.
  • 일반적으로 terraform apply 명령으로 전달됨.

이렇게 구성하면 이전 작업에서 생성된 계획을 사용하여 Terraform apply에서 Terraform 상태 파일을 잠글 수 없는 문제 등의 문제가 발생할 수 있습니다.

로컬 머신에서 상태 액세스

로컬 머신에서 GitLab 관리 Terraform 상태에 액세스할 수 있습니다.

caution
GitLab의 클러스터화된 배포에는 로컬 리포지터리를 사용하면 안 됩니다. 노드 간에 분할된 상태가 발생하여 이후의 Terraform 실행이 불일치할 수 있습니다. 대신, 원격 리포지터리 리소스를 사용하세요.
  1. CI/CD를 위해 Terraform 상태가 초기화되었는지 확인하세요.
  2. 사전 채워진 Terraform init 명령을 복사하세요:
    1. 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
    2. 운영 > Terraform 상태를 선택합니다.
    3. 사용하려는 환경 옆에서 작업 ()을 선택하고 Terraform 초기화 명령 복사를 선택합니다.
  3. 터미널을 열고 로컬 머신에서 이 명령을 실행합니다.

GitLab 관리 Terraform 상태로 마이그레이션

Terraform은 백엔드가 변경되거나 다시 구성될 때 상태를 복사하는 것을 지원합니다. 다른 백엔드에서 GitLab 관리 Terraform 상태로 마이그레이션하기 위한 작업에는 이러한 조치를 사용하세요.

GitLab 관리 Terraform 상태로 이동하기 위해서 필요한 명령을 실행하기 위해 로컬 터미널을 사용해야 합니다.

아래 예에서는 상태 이름을 변경하는 방법을 보여줍니다. 동일한 작업 흐름이 다른 상태 리포지터리 백엔드에서 GitLab 관리 Terraform 상태로 마이그레이션하기 위해서 필요합니다.

초기 백엔드 설정하기

PROJECT_ID="<gitlab-project-id>"
TF_USERNAME="<gitlab-username>"
TF_PASSWORD="<gitlab-personal-access-token>"
TF_ADDRESS="https://gitlab.com/api/v4/projects/${PROJECT_ID}/terraform/state/old-state-name"

terraform init \
  -backend-config=address=${TF_ADDRESS} \
  -backend-config=lock_address=${TF_ADDRESS}/lock \
  -backend-config=unlock_address=${TF_ADDRESS}/lock \
  -backend-config=username=${TF_USERNAME} \
  -backend-config=password=${TF_PASSWORD} \
  -backend-config=lock_method=POST \
  -backend-config=unlock_method=DELETE \
  -backend-config=retry_wait_min=5
백엔드 초기화 중...

백엔드 "http"가 성공적으로 구성되었습니다! 버킷은
백엔드가 변경되지 않는 한 자동으로 사용하게 됩니다.

제공자 플러그인 초기화 중...

제공자 플러그인 구성을 성공적으로 하였습니다!

이제 Terraform으로 작업을 시작할 수 있습니다. 인프라에 대해 필요한 변경 사항을 보려면 "terraform plan"을 실행하세요. 모든 Terraform 명령이 이제 작동해야 합니다.

만약 Terraform을 위한 모듈이나 백엔드 구성을 설정하거나 변경한 경우 작업 디렉터리를 다시 초기화하도록 합니다. 단, 잊어버릴 경우 다른 명령이 이를 감지하고 필요시 여러분에게 상기시키게 될 것입니다.

백엔드 변경

이제 terraform init이 이전 상태를 알고 있는 .terraform/ 디렉터리를 생성했으므로 새 위치에 대해 알려줄 수 있습니다:

TF_ADDRESS="https://gitlab.com/api/v4/projects/${PROJECT_ID}/terraform/state/new-state-name"

terraform init \
  -migrate-state \
  -backend-config=address=${TF_ADDRESS} \
  -backend-config=lock_address=${TF_ADDRESS}/lock \
  -backend-config=unlock_address=${TF_ADDRESS}/lock \
  -backend-config=username=${TF_USERNAME} \
  -backend-config=password=${TF_PASSWORD} \
  -backend-config=lock_method=POST \
  -backend-config=unlock_method=DELETE \
  -backend-config=retry_wait_min=5
백엔드 초기화 중...
백엔드 구성이 변경되었습니다!

Terraform이 백엔드에서 기존 상태를 확인할 것입니다.


상태 잠금 가져오는 중. 시간이 걸릴 수 있습니다...
기존 상태를 새 백엔드로 복사하시겠습니까?
  이전 "http" 백엔드를 새로 구성된 "http" 백엔드로 마이그레이션하는 동안 기존 상태가 발견되었습니다.
  새로 구성된 "http" 백엔드에 기존 상태가 발견되지 않았습니다. 이 상태를 새 "http" 백엔드로 복사하시겠습니까?
  "yes"를 입력하면 복사, "no"를 입력하면 초기 상태로 시작합니다.
  
  값 입력: yes


백엔드 "http" 구성 완료! Terraform은 이 백엔드를 자동으로 사용하게 됩니다. 백엔드 구성이 변경되지 않는 한 Terraform 명령어가 자동으로 이 백엔드를 사용합니다.

제공자 플러그인 초기화 중...

Terraform 초기화가 성공적으로 완료되었습니다!

이제 Terraform을 사용하여 작업을 시작할 수 있습니다. 인프라를 위해 필요한 변경 사항을 보려면 "terraform plan" 명령을 실행해 보세요. 이제 모든 Terraform 명령어가 작동해야 합니다.

Terraform 모듈이나 백엔드 구성을 설정하거나 변경하는 경우 작업 디렉터리를 다시 초기화하려면 이 명령을 다시 실행하십시오. 까먹은 경우에는 다른 명령어가 이를 감지하고 필요한 경우 알림을 표시할 것입니다.

yes를 입력하면 이전 위치에서 새 위치로 상태가 복사됩니다. 그 후에는 GitLab CI/CD에서 다시 실행할 수 있습니다.

GitLab 백엔드를 원격 데이터 소스로 사용하기

GitLab에서 관리하는 Terraform 상태 백엔드를 Terraform 데이터 소스로 사용할 수 있습니다.

  1. main.tf 또는 기타 관련 파일에서 이러한 변수를 선언하세요. 값은 비워두십시오.

    variable "example_remote_state_address" {
      type = string
      description = "Gitlab remote state file address"
    }
       
    variable "example_username" {
      type = string
      description = "Gitlab username to query remote state"
    }
       
    variable "example_access_token" {
      type = string
      description = "GitLab access token to query remote state"
    }
    
  2. 이전 단계에서의 값을 덮어쓰려면 example.auto.tfvars란 이름의 파일을 만드세요. 이 파일은 프로젝트 리포지터리에서 버전 관리되지 않아야 합니다.

    example_remote_state_address = "https://gitlab.com/api/v4/projects/<TARGET-PROJECT-ID>/terraform/state/<TARGET-STATE-NAME>"
    example_username = "<GitLab username>"
    example_access_token = "<GitLab Personal Access Token>"
    
  3. .tf 파일에서 Terraform 입력 변수를 사용하여 데이터 소스를 정의하세요:

    data "terraform_remote_state" "example" {
      backend = "http"
         
      config = {
        address = var.example_remote_state_address
        username = var.example_username
        password = var.example_access_token
      }
    }
    
    • address: 데이터 소스로 사용하고자 하는 원격 상태 백엔드의 URL입니다. 예를 들어, https://gitlab.com/api/v4/projects/<TARGET-PROJECT-ID>/terraform/state/<TARGET-STATE-NAME>.
    • username: 데이터 소스와 인증하기 위한 사용자 이름입니다. 개인 액세스 토큰을 사용하여 인증하는 경우, 이 값은 GitLab 사용자 이름입니다. GitLab CI/CD를 사용하는 경우, 이 값은 'gitlab-ci-token'입니다.
    • password: 데이터 소스와 인증하기 위한 비밀번호입니다. 인증에 개인 액세스 토큰을 사용하는 경우, 이 값은 토큰 값입니다(토큰에는 API 스코프가 있어야 함). GitLab CI/CD를 사용하는 경우, 이 값은 ${CI_JOB_TOKEN} CI/CD 변수의 내용입니다.

데이터 소스의 출력은 이제 data.terraform_remote_state.example.outputs.<OUTPUT-NAME>를 사용하여 Terraform 리소스에서 참조할 수 있습니다.

대상 프로젝트에서 Terraform 상태를 읽으려면 최소한 개발자 역할이 필요합니다.

Terraform 상태 파일 관리

Terraform 상태 파일을 보려면:

  1. 왼쪽 사이드바에서 검색 또는 이동하여를 선택하고 프로젝트를 찾습니다.
  2. 운영 > Terraform states를 선택하세요.

이 UI 개선을 추적하는 업적이 있습니다.

개별 Terraform 상태 버전 관리

개별 상태 버전은 GitLab REST API를 사용하여 관리할 수 있습니다.

최소한 개발자 역할이 있는 경우, 각각의 일련 번호를 사용하여 상태 버전을 검색할 수 있습니다::

curl --header "Private-Token: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<your_project_id>/terraform/state/<your_state_name>/versions/<version-serial>"

최소한 Maintainer 역할이 있는 경우, 상태 버전을 일련 번호를 사용하여 제거할 수 있습니다:

curl --header "Private-Token: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/<your_project_id>/terraform/state/<your_state_name>/versions/<version-serial>"

상태 파일 제거

최소한 Maintainer 역할이 있는 경우, 상태 파일을 제거할 수 있습니다.

  1. 왼쪽 사이드바에서 운영 > Terraform states를 선택하세요.
  2. 동작()을 선택하고 상태 파일 및 버전 제거를 선택하세요.

API를 사용하여 상태 파일 제거

개인 액세스 토큰을 사용하여 REST API에 요청을 보내어 상태 파일을 제거할 수 있습니다:

curl --header "Private-Token: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/<your_project_id>/terraform/state/<your_state_name>"

또한 CI/CD job token과 기본 인증을 사용할 수 있습니다:

curl --user "gitlab-ci-token:$CI_JOB_TOKEN" --request DELETE "https://gitlab.example.com/api/v4/projects/<your_project_id>/terraform/state/<your_state_name>"

또는 GraphQL API를 사용할 수도 있습니다.

관련 주제