본문으로 바로가기

Contents

    개요

    Terragrunt와 Terraform 상용버전인 Terraform Cloud (이하 TFC)를 연동하여 어떤 점에서 이점을 가져갈 수 있는지 알아보자.

    Terraform Cloud?

    TFC는 Hashicorp에서 제공하는 Terraform의 상용 제품이다. 프리티어가 있지만 한 조직에 5명 을 초과되면 사용자를 추가하려면 추가 결제가 필요하다.

    TFC에서 제공하는 핵심적인 기능은 대략 다음과 같다.

    1. Remote Backend
    2. Code Repository
    3. Terraform 실행을 위한 CI/CD 파이프라인

    위 기능 중 가장 유용하다고 생각했던 기능은 세 번째 항목인 Terraform 실행을 위한 CI/CD 파이프라인 이다.

    서비스의 모든 인프라를 Terraform으로 관리하게 되면 예상치 못한 변경사항을 방지하기 위해서는 CI/CD 파이프라인에서 Terraform 명령어를 실행하게 하고 변경사항을 최종 적용하도록 하는게 일반적일것이다.

    그 파이프라인의 흐름은 대략적으로 다음과 같을것 이다.

    1. plan 으로 예상 결과를 먼저 확인
    2. 팀 구성원(들)이 plan의 결과를 확인 후 승인
    3. 승인 후 applydestroy 실행

    그러나 기존에는 첫번째, 두번째 항목을 구성하려면 별도의 Gitflow를 구성하거나 아니면 서드파티 툴인 Atlantis 를 구성해야만 했었다.

    Gitflow 구성은 복잡하기도 하고 Atlantis를 사용하자니 서버 관리에 대한 부담도 있다. (인스턴스 비용은 덤이다.)

    그러나 Hashicorp 매니지드 서비스인 TFC를 사용하게 된다면 무료로 (Terraform을 사용하는 팀의 구성원이 5명 이하일 경우) 위 기능을 간편하게 사용할 수 있다.

    그러면 이제 Terragrunt와 TFC를 연동해보자.

    연동 전 유의사항

    Terragrunt와 TFC를 연동하기 전 유의해야 할 사항이다.

     

    Terragrunt의 inputs 블록의 사용이 불가능하다.

    • Terragrunt에서는 Terraform으로 변수 전달을 inputs 블록을 이용하여 전달하는데 TFC에서는 해당 메커니즘으로 변수 전달을 하지 못한다.
      • TFC는 Terraform 명령만 인식할 수 있기 때문
    • 따라서 Terraform에서 변수를 전달하는 방식을 사용해야 한다.
      • 여기서는 Gruntwork Docs에서 나온 예시인 generate 블록에 이용하여 terragrunt.auto.tfvars 파일을 만든 후 변수를 주입한다.

     

    연동 해보기

    1️⃣ TFC 계정 생성

    • 링크에서 계정을 생성한다.

    2️⃣ 조직 만들기

    • 좌측 메뉴에서 Organizations 클릭

    • ‘Create New Organization’ 클릭

    • 가입 시 기입했던 이메일에 발송온 확인 이메일 클릭

    3️⃣ Token 생성

    • Terraform login
    > terraform login
    Terraform will request an API token for app.terraform.io using your browser.
    
    If login is successful, Terraform will store the token in plain text in
    the following file for use by subsequent commands:
        /Users/shin/.terraform.d/credentials.tfrc.json
    
    Do you want to proceed?
      Only 'yes' will be accepted to confirm.
    
      Enter a value: yes
    • Token 생성

    • Token 값 복사

    • CLI 창에 Token 값 입력
    Terraform must now open a web browser to the tokens page for app.terraform.io.
    
    If a browser does not open this automatically, open the following URL to proceed:
        https://app.terraform.io/app/settings/tokens?source=terraform-login
    
    
    ---------------------------------------------------------------------------------
    
    Generate a token using your browser, and copy-paste it into this prompt.
    
    Terraform will store the token in plain text in the following file
    for use by subsequent commands:
        /Users/shin/.terraform.d/credentials.tfrc.json
    
    Token for app.terraform.io:
      Enter a value:
    
    
    Retrieved token for user redacted
    
    Welcome to Terraform Cloud!

     

    4️⃣ Terragrunt 설정파일 수정

    Terragrunt의 실행을 TFC에서 실행되게 하려면 일부 설정파일의 수정이 필요하다. (필수 작업)

     

    1. remote_state 수정

    • 수정 전
    remote_state {
      backend = "s3"
      generate = {
        path      = "backend.tf"
        if_exists = "overwrite_terragrunt"
      }
      config = {
        profile = local.backend_s3_profile_name
        region  = "ap-northeast-2"
        bucket  = local.backend_s3_bucket_name
        dynamodb_table = local.backend_dynamodb_table_name
        key     = "${local.region}/${path_relative_to_include()}/terraform.tfstate"
        encrypt = true
      }
    }
    • 수정 후
      • workspace는 미리 생성이 되어 있어야 하지만 생성의 자동화가 가능하다.
      • workspaces의 네이밍은 기존에 조직에서 관리하던 네이밍 규칙이 있으면 그 규칙에 따르면 된다.
    generate "remote_state" {
      path      = "backend.tf"
      if_exists = "overwrite_terragrunt"
      contents = <<EOF
    terraform {
      backend "remote" {
        hostname = "app.terraform.io"
        organization = "tfc-test"
        workspaces {
          name = "${local.region}/${path_relative_to_include()}"
        }
      }
    }
    EOF
    }

    2. inputs 블록 수정

    • 수정 전
    locals {
      force_delete = {
        develop = true
        staging = false
        production = false
      }
      scan_on_push = {
        develop = true
        staging = false
        production = false
      }
    }
    
    inputs = {
      tags         = local.tags
      name_prefix  = local.name_prefix[local.environment]
      force_delete = local.force_delete[local.environment]
      scan_on_push = local.scan_on_push[local.environment]
    }

     

    • 수정 후
      • Terragrunt의 generate 블록을 사용하여 terraform.auto.vars 파일을 만들어준다.
    locals {
      force_delete = {
        develop = true
        staging = false
        production = false
      }
      scan_on_push = {
        develop = true
        staging = false
        production = false
      }
    }
    
    generate "tfvars" {
      path      = "terragrunt.auto.tfvars"
      if_exists = "overwrite"
      disable_signature = true
      contents = <<-EOF
    tags         = {
        ${join(",", [for k, v in "${local.tags}" : "${k} = \"${v}\""])}
      }
    name_prefix  = "${local.name_prefix[local.environment]}"
    force_delete = "${local.force_delete[local.environment]}"
    scan_on_push = "${local.scan_on_push[local.environment]}"
    EOF
    }

    5️⃣ AWS Credentials 전달 방식 변경

    TFC는 Terraform 실행을 로컬 PC가 아닌 가상서버에서 실행하기 때문에 기존에 AWS 인증정보를 Profile로 전달하는 방식을 사용하였다면 인식하지 못한다.

    • 웹에서 TFC Workspace 접근
    • 좌측 메뉴에서 Variables 클릭

    • Workspace varialbes에 아래의 변수 추가
      • AWS_ACCESS_KEY_ID
      • AWS_SECRET_ACCESS_KEY

    • 추가된 모습

    6️⃣ 실행

    이제 구성이 다 완료되었다. terragrunt apply로 실행시켜 보자.

    • terragrunt apply 실행
      • apply에 대한 승인을 TFC 사이트에서 승인할 수도 있고 CLI에서도 승인을 할 수 있다.
    > terragrunt apply
    Running apply in the remote backend. Output will stream here. Pressing Ctrl-C
    will cancel the remote apply if it's still pending. If the apply started it
    will stop streaming the logs, but will not stop the apply running remotely.
    
    Preparing the remote apply...
    
    To view this run in a browser, visit:
    https://app.terraform.io/app/<secret>
    
    Waiting for the plan to start...
    
    Terraform v1.3.6
    on linux_amd64
    Initializing plugins and modules...
    aws_ecr_repository.main: Refreshing state... [id=tfc-test-api-develop]
    aws_ecr_lifecycle_policy.delete_untagged_all_image: Refreshing state... [id=tfc-test-api-develop]
    
    Terraform used the selected providers to generate the following execution
    plan. Resource actions are indicated with the following symbols:
      ~ update in-place
    
    Terraform will perform the following actions:
    
      # aws_ecr_repository.main will be updated in-place
      ~ resource "aws_ecr_repository" "main" {
            id                   = "tfc-test-api-develop"
            name                 = "tfc-test-api-develop"
          ~ tags                 = {
              ~ "Terraform"   = "false" -> "true"
                # (4 unchanged elements hidden)
            }
          ~ tags_all             = {
              ~ "Terraform"   = "false" -> "true"
                # (4 unchanged elements hidden)
            }
            # (5 unchanged attributes hidden)
    
            # (2 unchanged blocks hidden)
        }
    
    Plan: 0 to add, 1 to change, 0 to destroy.
    
    ------------------------------------------------------------------------
    
    Cost estimation:
    
    Resources: 0 of 1 estimated
               $0.0/mo +$0.0
    
    ------------------------------------------------------------------------
    
    Do you want to perform these actions in workspace "<secret>?
      Terraform will perform the actions described above.
      Only 'yes' will be accepted to approve.
    
      Enter a value:
    • TFC에서 확인
      • terraform plan에 대한 결과를 브라우저에서 확인할 수 있게된다.
      • 팀원들은 Apply pending 단계에서 Confirm & Apply에서 최종 승인을 할 수 있다.

    • Confirm & Apply
      • 코멘트를 작성하고 Confirm Plan 을 누른다.

     

    • 큐에 쌓인 Apply는 곧 Running이 된다.

    • Apply 완료
    • Slack에 알람설정 (선택)
      • 트리거가 발생하면 Slack Webhook을 사용하여 알람을 발송시킬 수도 있다.

    마치며

    Terragrunt와 TFC를 연동하여 TFC를 사용했을 때의 이점을 알아보았다.

    이 글에서는 TFC의 workspace를 수동으로 생성해줘야 했지만 추후에는 TFC workspace를 생성하는 Terraform 리소스를 작성해주면 좀 더 유연하게 사용할 수 있을 것 같다.

    비록 유저가 5명 이상일 경우 결제가 필요하고 Terragrunt의 일부 설정파일을 설정해줘야 하는 번거로움이 있지만 TFC의 프리티어에서 제공해주는 기능만으로도 충분히 사용할만한 가치가 있다고 생각한다.

     

    Reference