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 백엔드를 제공합니다.
Terraform 상태 백엔드는 GitLab 인스턴스에서 관리하는 상태 파일의 자동 버전 관리 및 암호화를 제공합니다.

caution
재해 복구 계획
Terraform 상태 파일은 디스크의 대기 및 객체 저장소에서 lockbox Ruby gem으로 암호화되며, db_key_base 애플리케이션 설정에서 파생된 키를 사용합니다.
상태 파일을 복호화하려면 GitLab이 사용 가능해야 합니다.
오프라인 상태일 경우, GitLab이 필요한 인프라를 배포하는 데 GitLab을 사용하는 경우(예: 가상 머신, Kubernetes 클러스터 또는 네트워크 구성 요소), 상태 파일에 쉽게 접근하거나 복호화할 수 없습니다.
또한, GitLab이 GitLab을 부트스트랩하는 데 필요한 Terraform 모듈이나 기타 종속성을 제공하는 경우, 이들은 접근할 수 없습니다. 이 문제를 해결하기 위해 해당 종속성을 호스팅하거나 백업하기 위한 다른 방법을 마련하거나,
공유 실패 지점이 없는 별도의 GitLab 인스턴스를 사용하는 것을 고려하십시오.

전제 조건

자체 관리 GitLab의 경우, Terraform 상태 파일에 대해 GitLab을 사용하기 전에:

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

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

전제 조건:

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

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

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

    terraform {  
      backend "http" {  
      }  
    }  
    
  2. 프로젝트 리포지토리의 루트 디렉터리에 .gitlab-ci.yml 파일을 생성합니다. .gitlab-ci.yml에서 OpenTofu CI/CD 구성 요소를 사용합니다.
    OpenTofu 대신 Terraform을 사용하려면 Terraform 템플릿 레시피 문서를 따르세요.

  3. 프로젝트를 GitLab에 푸시합니다. 이 작업은 gitlab-tofu init, gitlab-tofu validate, 및 gitlab-tofu plan 명령을 실행하는
    파이프라인을 트리거합니다.

  4. 이전 파이프라인에서 수동으로 deploy 작업을 트리거하고, 이 작업을 실행하여 정의된 인프라를 프로비저닝하는 gitlab-tofu apply 명령을 실행합니다.

위 명령에서 출력된 내용은 작업 로그에서 볼 수 있어야 합니다.

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

Terraform 환경 변수를 사용자 정의하기

CI/CD 작업을 정의할 때 Terraform HTTP 설정 변수를 사용할 수 있습니다.

init를 사용자 정의하고 Terraform 구성을 재정의하려면, init -backend-config=... 접근 방식 대신 환경 변수를 사용하세요.

-backend-config를 사용할 때, 구성은 다음과 같습니다:

  • plan 명령의 출력에 캐시됩니다.
  • 일반적으로 apply 명령으로 전달됩니다.

이 구성은 CI 작업에서 상태 파일을 잠글 수 없는 문제를 일으킬 수 있습니다.

로컬 머신에서 상태에 액세스하기

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

경고: 클러스터 배포의 GitLab에서는 로컬 저장소를 사용하지 말아야 합니다. 노드 간에 상태가 분할될 수 있어, 이후 Terraform 실행이 일관성 없게 됩니다. 대신, 원격 저장소 리소스를 사용하세요.

  1. Terraform 상태가 CI/CD를 위해 초기화되었는지 확인하세요.
  2. 미리 채워진 Terraform init 명령을 복사합니다:

    1. 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
    2. 작업 > Terraform 상태를 선택합니다.
    3. 사용하려는 환경 옆에서 작업 ( )을 선택하고 Terraform init 명령 복사를 선택합니다.
  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이 성공적으로 초기화되었습니다!

이제 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은 백엔드에 대해 지정된 구성이 변경되었음을 감지했습니다.

Terraform은 이제 백엔드의 기존 상태를 확인합니다.


상태 잠금을 획득하는 중입니다. 잠시 시간이 걸릴 수 있습니다...
기존 상태를 새 백엔드로 복사하시겠습니까?
  이전 "http" 백엔드에서 새롭게 구성된 "http" 백엔드로 마이그레이션하는 동안 기존 상태가 발견되었습니다.
  새롭게 구성된 "http" 백엔드에서 기존 상태가 발견되지 않았습니다.
  이 상태를 새 "http" 백엔드로 복사하시겠습니까? "yes"를 입력하여 복사하고, "no"를 입력하여 빈 상태로 시작하세요.

  값을 입력하세요: yes


"기존의 http" 백엔드가 성공적으로 구성되었습니다! 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 원격 상태 파일 주소"
    }
    
    variable "example_username" {
      type = string
      description = "원격 상태를 쿼리할 Gitlab 사용자 이름"
    }
    
    variable "example_access_token" {
      type = string
      description = "원격 상태를 쿼리할 GitLab 액세스 토큰"
    }
    
  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 사용자 이름>"
    example_access_token = "<GitLab 개인 액세스 토큰>"
    
  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. 왼쪽 사이드바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
  2. Operate > 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>"

유지 관리자 역할 이상이 있는 경우, 일련 번호를 사용하여 상태 버전을 제거할 수 있습니다:

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>"

상태 파일 제거

유지 관리자 역할 이상이 있는 경우, 상태 파일을 제거할 수 있습니다.

  1. 왼쪽 사이드바에서 Operate > Terraform states를 선택합니다.
  2. Actions 열에서 Actions ( )를 선택한 다음 Remove state file and versions를 선택합니다.

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 작업 토큰 및 기본 인증을 사용할 수도 있습니다:

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를 사용할 수도 있습니다.

관련 주제