Pre-commit-terraform 구성 및 사용 방법

TL;DR

테라폼코드 작성 후 커밋시, 포맷팅/유효성검증/설명문서/비용분석 자동화 스크립트


1. Intro

테라폼 코드의 실행에 대한 Pipeline을 고민하던 중, pre-commit-terraform 도구를 알게되었다.

Git repository를 사용해 코드를 관리한다면, 코드 작성을 완료하고 git commit을 수행하여야 할것이다. 커밋이 실행되기 이전에 일련의 검증 스크립트를 수행(hook)하여 통과되었을 경우에만 commit을 수행되도록 파이프라인을 구성하면, 통일성 유지에 도움이 될 것이라고 생각한다.

pre-commit-terraform hook은 커밋 메시지를 작성하기 전에 수행된다. terraform fmt, validate, tflint 등 유효성 체크와 lint 검사등을 자동화 할 수 있다. 검사가 성공적으로 수행되지 않으면 사용자가 요청한 커밋은 취소된다.

본 글에서는 pre-commit-terraform 소개 및 초기 설정, 사용 예시등을 다루고자한다.


2. Pre-commit

pre-commit 훅은 커밋할 때 가장 먼저 호출되는 훅으로 커밋 메시지를 작성하기 전에 호출된다. 이 훅에서 커밋하는 Snapshot을 점검한다. 빠트린 것은 없는지, 테스트는 확실히 했는지 등을 검사한다. 커밋할 때 꼭 확인해야 할 게 있으면 이 훅으로 확인한다. 그리고 이 훅의 Exit 코드가 0이 아니면 커밋은 취소된다. 물론 git commit --no-verify 라고 실행하면 이 훅을 일시적으로 생략할 수 있다. lint 같은 프로그램으로 코드 스타일을 검사하거나, 라인 끝의 공백 문자를 검사하거나(예제로 들어 있는 pre-commit 훅이 하는 게 이 일이다), 새로 추가한 코드에 주석을 달았는지 검사하는 일은 이 훅으로 하는 것이 좋다.

Git doc – Git hooks

이름에서 볼 수 있듯, git commit 수행 전에 자동으로 특정 작업을 수행하도록 해주는 기능이다.

작동방식 (Git hooks docs)

Git도 다른 버전 관리 시스템처럼 어떤 이벤트가 생겼을 때 자동으로 특정 스크립트를 실행하도록 할 수 있다. 이 훅은 클라이언트 훅과 서버 훅으로 나눌 수 있다. 클라이언트 훅은 커밋이나 Merge 할 때 실행되고 서버 훅은 Push 할 때 서버에서 실행된다.

설치

훅은 Git 디렉토리 밑에 hooks 라는 디렉토리에 저장한다. 기본 훅 디렉토리는 .git/hooks 이다. 이 디렉토리에 가보면 Git이 자동으로 넣어준 매우 유용한 스크립트 예제가 몇 개 있다. 그리고 스크립트가 입력받는 값이 어떤 값인지 파일 안에 자세히 설명돼 있다. 모든 예제는 쉘과 Perl 스크립트로 작성돼 있지만 실행할 수만 있으면 되고 Ruby나 Python같은 익숙한 언어로 만들어도 된다. 예제 스크립트의 파일 이름에는 .sample 이라는 확장자가 붙어 있다. 그래서 이름만 바꿔주면 그 훅을 바로 사용할 수 있다.


3. Pre-commit-terraform

앞서 설명한 pre-commit 훅을 활용한 pre-commit-terraform 이다. (링크)

설정옵션

230204 v1.77.1 기준, 설정할 수 있는 도구/옵션은 다음과 같다.

  • checkov
    • 정책기반으로 작동하는  IaC 구성오류(misconfiguration) 정적 분석 도구
  • terraform-docs
    • 여러 형식으로 테라폼 모듈 정보 문서를 생성
  • terragrunt
    • 추가적인 리소스 블록을 사용해, 구성 코드의 반복을 간소화
  • terrascan
    • Compliance & Security violation 정적분석 도구
  • TFLint
    • 테라폼 린트(코드 컨벤션/에러 검사)
  • TFSec
    • 정책기반 코드 구성 오류 탐지
  • infracost
    • 테라폼 구성코드 기반 비용 분석
  • jq
    • json 처리를 위한 cli 도구
  • tfupdate
    • 테라폼 및 프로바이더, 모듈 최신화
  • HCLedit
    • HCL(테라폼문법) 작성 및 편집 CLI

4. Demo

4.1. 설치 과정

pre-commit-terraform의 설치 페이지를 참고하여 구성할 것이다.

dependency 설치

pre-commit-terraform의 작동을 위해서는 pre-commit, terraform 및 관련 연관 도구의 설치가 필요하다.

pre-commit의 경우, 설치 페이지를 참고하여 사용자의 환경에 맞게 설치한다.

pre-commit & terraform tools (MacOS)

# brew를 사용한 pre-commit 설치 및 버전 확인

brew install pre-commit
pre-commit –version

# 관련 도구들 (필요한 도구만 골라서 설치할 것)

brew install pre-commit terraform-docs tflint tfsec checkov terrascan infracost tfupdate minamijoyo/hcledit/hcledit jq

pre-commit & terraform tools (Linux)

# pip을 사용한 pre-commit 설치 및 버전 확인

pip install pre-commit
pre-commit –version

# 관련 도구들 (필요한 도구만 골라서 설치할 것)

python3 -m pip install --upgrade pip
pip3 install --no-cache-dir pre-commit
pip3 install --no-cache-dir checkov
curl -L "$(curl -s https://api.github.com/repos/terraform-docs/terraform-docs/releases/latest | grep -o -E -m 1 "https://.+?-linux-amd64.tar.gz")" > terraform-docs.tgz && tar -xzf terraform-docs.tgz terraform-docs && rm terraform-docs.tgz && chmod +x terraform-docs && sudo mv terraform-docs /usr/bin/
curl -L "$(curl -s https://api.github.com/repos/tenable/terrascan/releases/latest | grep -o -E -m 1 "https://.+?_Linux_x86_64.tar.gz")" > terrascan.tar.gz && tar -xzf terrascan.tar.gz terrascan && rm terrascan.tar.gz && sudo mv terrascan /usr/bin/ && terrascan init
curl -L "$(curl -s https://api.github.com/repos/terraform-linters/tflint/releases/latest | grep -o -E -m 1 "https://.+?_linux_amd64.zip")" > tflint.zip && unzip tflint.zip && rm tflint.zip && sudo mv tflint /usr/bin/
curl -L "$(curl -s https://api.github.com/repos/aquasecurity/tfsec/releases/latest | grep -o -E -m 1 "https://.+?tfsec-linux-amd64")" > tfsec && chmod +x tfsec && sudo mv tfsec /usr/bin/
sudo apt install -y jq && \
curl -L "$(curl -s https://api.github.com/repos/infracost/infracost/releases/latest | grep -o -E -m 1 "https://.+?-linux-amd64.tar.gz")" > infracost.tgz && tar -xzf infracost.tgz && rm infracost.tgz && sudo mv infracost-linux-amd64 /usr/bin/infracost && infracost register
curl -L "$(curl -s https://api.github.com/repos/minamijoyo/tfupdate/releases/latest | grep -o -E -m 1 "https://.+?_linux_amd64.tar.gz")" > tfupdate.tar.gz && tar -xzf tfupdate.tar.gz tfupdate && rm tfupdate.tar.gz && sudo mv tfupdate /usr/bin/
curl -L "$(curl -s https://api.github.com/repos/minamijoyo/hcledit/releases/latest | grep -o -E -m 1 "https://.+?_linux_amd64.tar.gz")" > hcledit.tar.gz && tar -xzf hcledit.tar.gz hcledit && rm hcledit.tar.gz && sudo mv hcledit /usr/bin/

pre-commit-hook 사용 설정

DIR=~/.git-template
git config --global init.templateDir ${DIR}
pre-commit init-templatedir -t pre-commit ${DIR}

hook 구성

프로젝트의 root directory에 .pre-commit-config.yaml 을 생성하고, pre-commit install 명령어를 사용하여 구성한다.

fail_fast: true
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
  rev: v1.77.1 # Get the latest from: https://github.com/antonbabenko/pre-commit-terraform/releases
  hooks:
    - id: terraform_fmt # terraform fmt 명령어 수행
    - id: terraform_validate # terraform validate 명령어 수행
    - id: terraform_docs # 구성된 테라폼 input, output을 정리하여 README.md 작성 및 업데이트
      args:
        - --hook-config=--path-to-file=README.md
        - --hook-config=--add-to-existing-file=true
        - --hook-config=--create-file-if-not-exist=true
    - id: infracost_breakdown # 현재 디렉토리의 테라폼 코드 기반 비용 분석
      verbose: true # 항상 비용 표시
      args:
        - --args=--path=./terraform/1lb2ec2+1nat
pre-commit install
# pre-commit installed at .git/hooks/pre-commit

4.2. 사용 예시

위와 같이 hook을 구성하면, 이후 커밋시에 다음의 순서로 체크가 진행되고, 단계별로 실패 시 커밋이 수행되지 않는다.

  • terraform fmt
  • terraform validate
  • terraform_docs
  • infracost breakdown

terraform fmt

아래 예시와 같이 들여쓰기등의 서식이 맞지 않을 경우, 현재 커밋을 취소하고 자동으로 terraform fmt 명령어를 수행해 내용을 수정한다.

terraform fmt 예시

terraform validate

아래 예시와 같이 HCL 문법등의 유효성 검증에 실패할 경우, 현재 커밋을 취소하고 terraform validate 결과에 따른 수정이 필요한 부분을 알려준다.

terraform validate 예시

terraform-docs

아래 예시와 같이, 리소스/모듈의 변화가 있어 terraform docs의 변경이 발생한 경우 README.md 파일을 업데이트한다.

생성된 terraform docs의 예시 (링크)

infracost breakdown

아래 예시와 같이, 위의 모든 검증을 통과하면 커밋이 성공적으로 수행된다. 구성된 코드 기반 비용 예측을 수행하고, 결과를 summary로 요약하여 보여준다.

infracost breakdown 예시


5. Outro

혼자(or 소수의 팀) terraform을 사용한다면 이런 pre-commit tool의 사용은 조금 번거로울 수 있다.

하지만 다수의 팀원이 있는 협업 환경이라면, 작업 결과 품질유지를 위해 이러한 pre-commit hook을 활용하는 것은 의미가 있을것이라고 생각된다.

다만 기본 명령어를 제외하고는 각 작업자의 환경에 추가 패키지 설치 / 구성과정이 필요하다. 다라서 설정 가능한 모든 도구를 사용하지는 않을것이라고 생각하고 필요한 기능만 잘 조합해야 할것이다.

추가 도구 중에서 terraform fmt / validate 와 terraform-docs 정도의 구성은 혼자or소수의 팀에서 도입하여 사용하여도 유용할듯 하다.

infracost의 경우 실제 작업환경에서는 긁어올 소스코드가 많아 pre-commit시 수행되는건 다소 시간이 소요되어 불편하였다. 해당 도구는 pre-commit 보다는 github action등으로 CI/CD 파이프라인에 구성하여 사용하는것이 더 유용할 듯 하다.

Leave a Reply