본문 바로가기

DevOps/Terraform

[T102 7주차] (18) Github Action과 TFC 연동 방법

cloudNet@ 팀의 가시다 님이 진행하는 테라폼 102 스터디 7주차 정리입니다.

1. Github Action 실습


✅ Fork 후 소스코드를 클론 받는다.

git clone https://github.com/themapisto/terraform-aws-github-action


✅ terraform login 시 .terraform.d/credential.json 파일 생성 

mzc01-kook@MZC01-KOOK 0808 % cat ~/.terraform.d/credentials.tfrc.json 
{
  "credentials": {
    "app.terraform.io": {
      "token": "iAmSfGJz6pPzUg.atlasv1.gBnYkvcrEHiIQnxR41WeVePAUUIq2VjfJzwly8wULgK3TwGVPu6o8SdhFSl9k8W2z4c"
    }
  }
}%

✅ main.tf 변경을 통해 terraform cloud의 org 정보를 입력한다.

terraform {
  cloud {
    organization = "themapisto-org"
    hostname     = "app.terraform.io" # default

    workspaces {
      name = "terraform-aws-github-action"
    }
  • workspaces는 자동으로 생성

✅  .github/workflows > action.yml 수정 후 푸시

 

env:
  MY_PREFIX: DEV
  TF_VERSION: 1.2.6 # 1.2.5에서 변경
git add main.tf
git add .github/workflow/action.yml
git commit -m "init"
git push

✅ git token 받기  -> workflow check 

✅ 테라폼 init 후 워크스페이스 생성 확인

terraform init

✅ 테라폼 cloud workspace의 Local 세팅 변경


2. Github Action 동작 방식 

  • feature branch : 작업 브랜치
  • main branch : 메인 브랜치 ( 개발PM 또는 다른 개발자가 코드 리뷰 후 Merge 결정 )
  • PR을 통해 Merge 하는 방식 
  • Github action에서는 SCAN / Terraform plan 과 SCAN / Terraform Apply / Backend State 저장 등이 진행됨 


3. Github Action Job 

name: Terraform DEV

on:
  push:
    branches:
      - main
  pull_request:

env:
  MY_PREFIX: DEV
  TF_VERSION: 1.2.5

jobs:
  SCAN:
    name: SCAN
    runs-on: ubuntu-latest
    # env:
    #   working-directory: terraform
    #   TF_WORKSPACE: my-workspace
    steps:
      # - name: Configure AWS credentials
      #   uses: aws-actions/configure-aws-credentials@v1
      #   with:
      #     aws-region: eu-west-1

      - name: Check out code
        uses: actions/checkout@v3
        
      - name: Run Terrascan
        id: terrascan
        uses: tenable/terrascan-action@main
        with:
          iac_type: 'terraform'
          iac_version: 'v14'
          policy_type: 'aws'
          only_warn: true
          sarif_upload: true

      - name: Upload SARIF file
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: terrascan.sarif  
  Terraform:
    needs: SCAN
    name: Terraform
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v3

      - uses: hashicorp/setup-terraform@v2
        with:
          terraform_version: $TF_VERSION
          cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}

      - name: Terraform Fmt
        id: fmt
        run: terraform fmt -recursive -check
        continue-on-error: true

      - name: Terraform init
        id: init
        run: terraform init -upgrade
        # working-directory: ${{ env.working-directory }}

      - name: Terraform validate
        id: validate
        run: terraform validate -no-color

      - name: Terraform plan
        id: plan
        run: terraform plan -no-color -var=prefix="$MY_PREFIX"
        # working-directory: ${{ env.working-directory }}
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          TF_LOG: info

      - name: Plan output
        id: output
        uses: actions/github-script@v3
        if: github.event_name == 'pull_request'
        env:
          PLAN: "terraform\n${{ steps.plan.outputs.stdout }}"
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const output = `#### Terraform Format and Style 🖌\`${{ steps.fmt.outcome }}\`
            #### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\`
            #### Terraform Plan 📖\`${{ steps.plan.outcome }}\`
            <details><summary>Show Plan</summary>
            \`\`\`hcl
            ${process.env.PLAN}
            \`\`\`
            </details>
            **Pusher**: @${{ github.actor }}
            **Action**: ${{ github.event_name }}
            `;
            github.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: output
            })

      - name: Terraform apply
        id: apply
        if: github.ref == 'refs/heads/main' && github.event_name == 'push'
        run: terraform apply -auto-approve -var=prefix="$MY_PREFIX" -input=false
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

✅ Scan

  • 테라폼 코드 검증 도구인 Terrascan을 활용한다. 
  • Terrascan 툴을 이용하여 테라폼 코드를 검증한다.

 

✅ Terraform

  • Job ‘Scan’ 이후 테라폼 Job 실행
  • Configure AWS credentials : AWS 환경을 프로비저닝하기 위한 Credential 설정
    • github action이 자격증명을 가지고 있어야 함 
    • 민감 변수는 따로 Github에 등록해 놓고 환경변수로 사용함 
       env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
  • github repo - settings - secrets and variable

  • 민감 변수 등록

  • TF_API_TOKEN = 테라폼 API 토큰 발급 방법 

  • 테라폼 Fmt, init , validate, plan 등 
  • 예시의 동작 외에도 프로비저닝 이후의 테스트를 위한 terratest 도구와 비용 예측을 위한 terracost, infracost 도구들도 추가해볼 수 있다.

✅ github-action 동작 조건 

  • Github Action의 동작 조건은 메인 브랜치에 푸시가 발생하거나 풀 리퀘스트가 발생하는 경우로 정의되어 있다
# Github Action의 실행 조건 : ./github/workflows/action.yml
on:
  push:
    branches:
      - main
  pull_request:
..
  • 브랜치 생성
git branch
git branch -M add-env-variable
  • main. tf 수정
  •  
resource "aws_vpc" "hashicat" {
  cidr_block           = var.address_space
  enable_dns_hostnames = true

  tags = {
    name        = "${var.prefix}-vpc-${var.region}"
    environment = var.environment  # 원래 값 Production
  }
}
  • variable.tf 수정
  •  
variable "environment" {
  type        = string
  description = "Define infrastructure’s environment"
  default     = "dev"

  validation {
    condition     = contains(["dev", "qa", "prod"], var.environment)
    error_message = "The environment value must be dev, qa, or prod."
  }
}
  • push
terraform fmt
git add .
git commit -m "add env variable"
git push origin HEAD

❌ github action 실패 

# error 메시지
Terraform Unhandled error: HttpError: Resource not accessible by integration
Terraform The following actions uses node12 which is deprecated and will be forced to run on node16: actions/github-script@v3. For more info: https://github.blog/changelog/2023-06-13-github-actions-all-actions-will-run-on-node16-instead-of-node12-by-default/

 

❌ github action 실패 원인 분석중