brunch

You can make anything
by writing

C.S.Lewis

by Master Seo Aug 18. 2023

14. 테라폼 -프로비저닝 파이프라인-깃헙 액션  



사전 준비

aws로그인  https://console.aws.amazon.com/

명령서버에서 사용할 pem키 필요

access-key 필요

secret-key 필요

cloudformation으로 명령 서버 1대를 만든다.



<1> 프로비저닝 파이프라인 설계 - 깃허브

<2> 백엔드를 활성화 하자.

<3> 책 연습문제1, P259 - 브렌치 하나 따서 작업한다.




<1> 프로비저닝 파이프라인 설계 - 깃허브


1

프로비저닝 파이프라인 + Github Action 준비

실습 실패~

작업 순서는 확인하자.


2

실제 서비스가 실행되는 대상을 프로비저닝하면 테라폼의 Plan과 Apply 과정상에 추가로 코드 검증, 실행 계획 검증, 실행 후 결과 확인과 같은 추가 동작을 자동화.

도구 : 젠킨스, Github Action, TFC/TFE


3

저장소 포크 : https://github.com/terraform101/terraform-aws-github-action


topasvga@naver.com


4

Github Action은 별도의 State 저장소를 제공하지 않기 때문에 테라폼 실행으로 생성되는 State가 항상 초기화되어 프로비저닝 결과를 유지할 수 없다.

백엔드를 활성화 하자.




<2> 백엔드를 활성화 하자.



1

리모트 저장소를 로컬 환경에 복제


MyGit=<각자 자신의 깃허브 계정>

MyGit=topasvga

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


# 확인

tree terraform-aws-github-action


terraform-aws-github-action

├── files

│   └── deploy_app.sh

├── LICENSE

├── main.tf

├── outputs.tf

├── README.md

└── variables.tf



cd terraform-aws-github-action

git remote get-url origin



2

토큰 정보 확인

https://github.com/topasvga

gb1!

설정 토큰 확인

오른쪽위 개인 아이콘 > Setting > 왼쪽 맨 아래  Developer settings   > Personal access tokens Tockens(classic) > Generate new token  클릭 >  맨 아래 Generate new token (classic)

test-seo1

repo체크

Generate token


(Personal access tokens (classic) 을  복사해두자)


깃헙 액션 파이프라인 에러가 발생하시는 분은

레포지토리 Settings -> Actions -> General -> 최하단 Workflow permissions을 read and write permissions로 변경해보시고 재실행 해보세요.



3

push test?


#

echo "T101 Study" >> test.txt


git add test.txt

git commit -m "first commit"

git push

(정보를 넣어야 하는데 정보를 모른다)



# 우선 Git 자격 증명 설정이 필요하다.

git config --global user.name $MyGit

git config --global user.email <깃허브 가입 이메일주소>

git config --global user.email  topasvga@naver.com

cat ~/.gitconfig



# push 실행을 위해서 로그인 정보 입력

git push

Username for 'https://github.com': <깃허브 계정 정보>

Password for 'https://topasvga@github.com': <토큰 정보>


Username for 'https://github.com': topasvga

Password for 'https://topasvga@github.com': <토큰 정보>


콘솔에서 확인

https://github.com/topasvga/terraform-aws-github-action




5

테라폼 클라우드를 사용할수 있도록 하자~


main.tf의 terraform 블록에서 사용자의 TFC 설정 organization으로 변경


확인 ?

cat ~/.terraform.d/credentials.tfrc.json | jq


참고 

테라폼 클라우드 토큰 받기

https://brunch.co.kr/@topasvga/3395


3

main.tf 내용 수정


terraform {

  cloud {

    organization = "<MY_ORG_NAME>"         # 생성한 ORG 이름 지정 topasvga-org

hostname     = "app.terraform.io"      # default

    workspaces {

      name = "terraform-aws-github-action"

    }

  }

...



4

.github/workflow/action.yml 내용 수정

vi /root/terraform-aws-github-action/.github/workflows/action.yml


env:

  MY_PREFIX: DEV

  TF_VERSION: 1.2.6 # 1.2.5에서 변경  

// 테라폼이 로컬에서 실행되는건 아니고, 깃허브 액션에서 실행된다.    



5

push

git add main.tf

git add .github/workflow/action.yml

git commit -m "init"

git push


.github/workflow/action.yml 파일 push 시 에러 발생 시 

→  깃허브 콘솔 > 세팅 >  해당 토큰에 workflow 권한 추가 후 다시 push 할 것 . 



6

지정된 Terraform Cloud 백엔드 활성화를 위해 terraform init을 수행


cd /root/terraform-aws-github-action

terraform init

tree .terraform



7

생성된 TFC 간다.

워크스페이스 >  실행 모드 Execution mode를 Local로 수정  (저장소만 동기화해 사용함) > 저장

terraform-aws-github-action 워크스페이스(State 백엔드 역할만 수행) 확인 → 

선택 후 좌측에 Settings 클릭 → General -> Local로 수정 > 저장



8

동작의 설명 ?


github에서 풀리퀘스트 PR 하면  깃허브 액션이 돌아간다.  

SCAN - 테라폼 ---- Main 브랜치에서 PR 승인 ---- SCAN --테라폼- APPLY--- AWS 리소스 생성




9

action.yml  파일 내용을 보라.

jobs ?

SCAN 실행됨. 검증하는 부분임.



Terrafrom  테라폼.

- Job 

Scan : 테라폼 코드 검증

    - Check out code : 검증을 위해 저장소의 코드를 체크아웃

    - Run terrascan : 테라폼 코드 검증 도구인 Terrascan을 실행        

        https://runterrascan.io/        

        https://runterrascan.io/docs/getting-started/        

        https://runterrascan.io/docs/integrations/cicd/        

    - Upload SARIF file : 검증의 결과(정적 분석 결과 표준 포맷)을 업로드

- Job ‘Terraform’ : 테라폼 실행 ← Job ‘Scan’ 이후 실행

    - Check out code : 검증을 위해 저장소의 코드를 체크아웃

    - Configure AWS credentials : AWS 환경을 프로비저닝하기 위한 Credential 설정

    - Terraform Fmt : 표준 스타일 수정 대상 확인

    - Terraform init : 테라폼 실행을 위한 init 수행

    - Terraform validate : 코드 문법 오류 검사

    - Terraform plan : 실행 계획 확인

        - env.TF_LOG: info : 로그 수즌을 info로 출력해 실행 디버깅

    - Plan output : 풀 리퀘스트인 경우 실행 계획을 정리해 출력

    - Terraform apply : 메인 브랜치 변경 시에만 Apply 수행

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

- 코드 내용 설명




10

action.yml : Github Action의 구성은 .github/workflows의 yml 파일 형태로 작성

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



10. 

main.tf 

: 프로비저닝의 실행은 작업자나 Github Action에서 발생하더라도 동일한 State유지를 위해 백엔드 구성 추가



11

Github Action 과정에서 필요로 하는 State 공유를 위한 Terraform Cloud의 토큰, AWS 프로비저닝을 위한 AWS Credential과 같은 민감 데이터를 저장소에서 민감 변수로 처리할 수 있다.


(옵션) AWS IAM 계정 생성 및 자격증명 획득

aws iam create-user --user-name testuser

aws iam create-access-key --user-name testuser

aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --user-name testuser

"AccessKeyId": "AKIWPLWXCWW",

"SecretAccessKey": "1K/h1h231kGQBDs+PHhxF/M"




12

깃허브 액션 에서

해당  repository 저장소의 [Setting] → [Secrets and variables - Actions] 선택 ⇒ 3가지 새로운 민감 변수 등록 

[New repository secret] 


Name : 

TF_API_TOKEN

Secret : <각자 자신의 TFC Token>

AWS_ACCESS_KEY_ID

: AWS Access Key 입력

AWS_SECRET_ACCESS_KEY 

: AWS Secret Access Key 입력




13

깃허브 액션이 기본 비활성화이다.

본인 깃허브 계정것을 활성화 하자.


포크되어 비활성화되어 있는 저장소의 [Actions] 탭으로 이동해

 [I understand my workflows, go ahead and enable them] 버튼을 클릭, 활성화한다  




<3> 책 연습문제1, P259 - 브렌치 하나 따서 작업한다.


1

Automate Terraform with GitHub Actions 가이드 참고해서 토큰 생성 하고 실습 진행


2

브렌치 하나 따서 작업한다.


- 브랜치 이름 : add-env-variable

테라폼 입력 변수 추가

    - 이름 : environment

    - 설명 : Define infrastructure’s environment

    - 타입 : string

    - 기본값 : dev

    - 변수 확인

        - 조건 : dev, qa, prod 인 경우 허용

        - 에러 메시지 : The environment value must be dev, qa, or prod.

- **aws_vpc**의 **tags.environment**를 입력 변수 **environment** 값으로 선언

- 새로운 브랜치의 변경 내용을 커밋, 푸시하고 깃허브 웹페이지에서 **풀 리퀘스트**를 생성한다 ← 주의: 자신의 저장소로 요청하는지 꼭 확인

- Github Action의 동작 조건은 메인 브랜치에 푸시가 발생하거나 풀 리퀘스트가 발생하는 경우로 정의되어 있다.



3

# Github Action의 실행 조건 : ./github/workflows/action.yml


on:

  push:

    branches:

      - main

  pull_request:


// main 프렌치에 push 되거나 pull_request 될때 ,  Github Action이 실행된다.



4

해결 ?


브랜치 생성 : add-env-variable


cd /root/terraform-aws-github-action

git branch

git branch -M add-env-variable


vi 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 "environment  정보 가져온다.

사용을 위해서는 아래 variable 만들어 줘야 한다!!




5

vi variables.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."

  }

}



6

push

terraform fmt

git add .

git commit -m "add env variable"

git push origin HEAD



7

아래 링크로 간다~

remote:

remote: Create a pull request for 'add-env-variable' on GitHub by visiting:

remote:      https://github.com/topasvga/terraform-aws-github-action/pull/new/add-env-variable

remote:

To https://github.com/topasvga/terraform-aws-github-action

 * [new branch]      HEAD -> add-env-variable



8

반드시 본인의 저장소로 변경해야 한다.

// 본인 레파지토리 저장소로 하자.


9

PR을 만들자.

create pr


Create pull  request



7

Github에 Action 에 가서 확인하자 


콘솔에서 action을 보자~~


scan 보자.

깃허브 action에 있는 sandbox 환경에서 돌아가고 있는것이다.




Terraform plan에서 에러가 난다.


# 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/



9

동작 성공 시 → Main RP 병합 수행 ⇒ Github Action 에서 Apply 수행

- AWS 서울 리전에 리소스 생성 확인

- Github Action 확인

- Github Security 에 정적 코드 분석 내용 확인 : [runterrascan.io](http://runterrascan.io)



동작 실패로 관련 리소스 삭제 


1. Github Repo 삭제 ?

 레파지토리 https://github.com/topasvga/terraform-aws-github-action > 세팅 > 맨아래 > 삭제 



2. TFC Workspace 삭제 ?

 workspace > 해당 워크스페이스 terraform-aws-github-action   > Destruction and Deletion >   terraform-aws-github-action



3. 로컬에 코드 폴더 삭제

rm -rf terraform-aws-collaboration

rm -rf terraform-aws-github-action




4

추가 자료

악분님 자료 참고

https://github.com/sungwook-practice/intergreation_TFC


깃헙 액션 파이프라인 에러가 발생하시는 분은

레포지토리 Settings -> Actions -> General -> 최하단 Workflow permissions을 read and write permissions로 변경해보시고 재실행 해보세요.




다음과정

https://brunch.co.kr/@topasvga/3409


다음은 주말 CloudNet 테라폼 스터디 내용 참고하여  정리한 부분입니다.

https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863  



감사합니다.


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari