Terraform CI/CD 구축 (1)

Manx·2025년 8월 5일

DevOps

목록 보기
14/14

배경

사내에서 Terraform을 도입하며, CI/CD를 구축하고자 했다.
이번에 Jenkins도 도입되었기 때문에, GithubAction보다는 Jenkins를 선택했다.

목적

목적은 다음 그림과 같은 Flow를 생성하는 것이다.

Flow

  1. 개발자가 Terraform Code를 수정하여 Github에 Pull Request를 올린다.
  2. Github에서 PR에 대한 Web Hook을 설정하여, Jenkins로 송신한다.
  3. Jenkins는 main 브랜치에 머지될 결과를 Terraform Plan으로 식별한다.
  4. Terraform Plan 결과를 해당 PR에 댓글로 남겨준다.
  5. 코드 리뷰 완료 후 main 브랜치로 Merge 한다.
  6. 관리자가 Jenkins에서 수동으로 CD(Terraform Apply)를 진행한다.

들어가며

DynamoDB, S3를 사용한 이유는 이렇다.

Terraform init을 하게 되면, terraform.tfstate 파일이 생성된다.
이 파일을 통해 코드가 변경되었을 때 Cloud 자원에 어떤 수정 사항이 생길지 결정하는 것이다.

S3

  • 상태 파일 저장 : terraform.tfstate 파일을 안전하게 보관할 수 있다.
    • 여러 사용자가 동일 상태 파일을 공유할 수 있다.
    • terraform.tfstate에는 sensitive로 선언한 변수여도, 모두 포함되기 때문에 형상관리는 절대 안된다.

DynamoDB

  • 동시성 제어 : 여러 사용자가 Terraform Apply 하는걸 Lock을 통해 방지한다.

# backend.tf

terraform {
  backend "s3" {
    bucket         = "mh-tfstate"
    key            = "security_group/mh_d_apnortheast2/terraform.tfstate"
    region         = "ap-northeast-2"
    encrypt        = true
    dynamodb_table = "terraform-lock-mh"
  }
}

그럼 이제 시작해보자.


1. GitHub Web Hook 설정

우선, Jenkins가 수신할 수 있게끔 Web Hook을 설정해야 한다.

Project - Settings - Webhooks - Add webhook

Payload URL : https://<jenkins-domain>/github-webhook/
Content type : application/json
Let me select individual events : Pull requests

이렇게 하면, Pull Request가 Open, Close 될 때마다 해당 Web Hook을 실행한다.
실행 내역을 보고 싶다면, Webhook을 클릭한 뒤 상단의 Recent Deliveries에서 확인할 수 있다.

WebHook 수신을 위해서는 443 포트 인바운드가 다음 IP 대역에서 허용되어 있어야 한다.
["192.30.252.0/22", "185.199.108.0/22", "140.82.112.0/20", "143.55.64.0/20"]


2. Jenkins 설정

Github의 Web Hook 설정이 끝났다면, 이제 Jenkins Pipeline을 생성할 차례이다.

우선 Plugin 설치가 필요하다.

  • GitHub Integration Plugin ( PR 감지 )
  • Pipeline GitHub Notify Step Plugin ( PR의 checks를 변경할 목적 )

이후 New Item -> Pipeline 선택

Configure 설정

General

Triggers

  • GitHub Pull Requests 선택 ( GitHub Integration 플러그인 설치 필요 )
    • Trigger Mode : Hooks with Persisted Data
    • Crontab line : 비워두기 ( 경고 떠도 상관 없다. Web Hook으로 수신할거니 )
    • Set status before build ( build 시작 전에 PR 상태를 Pending으로 만들어 준다. )

Pending된 PR 상태

Pipeline
Definition : Pipeline script from SCM ( 해당 설정은 프로젝트 디렉토리에서 jenkinsfile을 찾는다. )
SCM : Git
Repository URL : https://github.com/Test/Terraform.git
Credentails : 해당 디렉토리의 권한이 있는 Credentails 선택.


브랜치 선택 test -> main 으로 PR을 날렸다고 가정해보자. 어디 브랜치의 코드로 Terraform Plan을 보여줘야 할까? test ? main ?

정답은 main에 test가 merge된 브랜치이다.
github는 PR 생성 시 가상 브랜치를 만든다. ( refs/pull/<PR-Num>/merge )


Repositories의 고급 설정에서 다음과 같이 설정한다.

그러면, branch를 main에 test가 머지된 가상의 branch로 checkout 하게 된다.

  • refs/pull/<PR-Num>/merge를 로컬 저장소의 origin/pr/<PR-Num> 이름으로 저장

Script Path는 jenkinsFile이 있는 경로를 지정해 주면 된다. 나는 Project/scripts/jenkinsfile 에 있기 때문에 scripts/jenkinsfile 을 기입했다.

Configure 파일 정리

General
- ✅GitHub project
  - project url : https://github.com/Test/Terraform/
  
Trigger
- GitHub Pull Requests
  - Trigger Mode
    - Hooks with Persisted Data
    - ✅Set status before build
    - Trigger Events : Pull Request Opened


Pipeline
- Definition : Pipeline script form SCM
  - SCM : Git
    - Repositories
      - Repository URL : https://github.com/Test/Terraform.git
      - Credentails : (Select)
      
      - 고급
        - Refspec : +refs/pull/${GITHUB_PR_NUMBER}/head:refs/remotes/origin/pr/${GITHUB_PR_NUMBER}
        
      - Branches to build : origin/pr/${GITHUB_PR_NUMBER}

이제 모든 설정이 끝났으니, 다음 시간에는 Jenkins File을 작성하며 Pipeline을 만들어보자 !

0개의 댓글