[CI/CD] GitOps 환경 구축하기(2) GitHub

우노·2024년 9월 15일
0

Practice & Trouble Shooting

목록 보기
15/20

GitOps라면 역시 Git을 써야한다. Git을 활용하여 명시적인 선언으로 프로젝트 코드와 상태, 형상 등을 명시적으로 관리할 수 있도록 한다. GitLab, BitBucket 등 다양한 Git 저장소가 있지만 프로젝트 기간이 짧고 따로 Git 서버를 구축할 시간적, 금전적 여유가 없어 가장 익숙한 GitHub를 저장소/플랫폼으로 골라 GitOps를 시작했다. 구현한 CI/CD GitOps 아키텍처는 아래와 같다.

아키텍처


아키텍처를 살펴보면 GitHub에서 변경 사항이 생기면 Jenkins와 ArgoCD가 수정사항을 인지하는 어떤 방법이 필요하다는 것이다. 그래서 환경 구축 과정을 GitHub부터 시작해보려고 한다.

GitHub

GitOps에서 GitHub는 코드를 선언하는 저장소 역할을 맡는다. 설정과 애플리케이션을 코드로 선언하여 실제 배포와의 싱크를 확인하거나 인프라 프로비저닝에 활용했다. 모든 프로세스의 중심에 GitHub이 있다고 해도 과언이 아니다. 아래부터는 이번 프로젝트에서 GitHub의 활용 방법을 서술해보겠다.

Project Code

프론트엔드, 백엔드, 인공지능의 코드를 업로드하여 버전 관리와 코드 통합 담당했다. 백엔드는 Git Submodule로 config를 프라이빗하게 관리했고 운영에서는 인프라 관련 파일을 저장하는 INFRA 레포와 K8s 메니페스트 레포인 CD 레포를 가져갔다. 나는 운영을 담당하여 개발에는 거의 관여하지 않았지만 해당 레포에 사용하는 프레임워크와 언어에 맞게 빠르게 Dockerfile을 작성하였다. 그리고 Jenkinsfile을 업로드하여 Jenkins에서 끌어서 쓸 수 있도록, CI/CD 파이프라인을 명시적으로 확인할 수 있도록 했다.

Infra; Terraform

PAPERPLE-INFRAmodules 참고
AWS 리소스를 활용했고 이를 테라폼으로 관리하여 GitHub에 업로드하였다. 테라폼 코드는 Best Practice를 찾으며 모듈을 분리하고 필요한 리소스가 생길 때마다 공식 레지스트리를 샅샅히 읽어보며 작성했다.
사실 Terraform 코드는 굳이 업로드할 필요는 없을 것 같다. 하지만 리소스를 명시적으로 관리하여 콘솔에 접근하지 않아도 현재 리소스와 상태를 확인할 수 있다는 점을 개발팀과 공유하고 싶었기에 GitHub에 지속적으로 업데이트했다.

CI; Jenkins

Jenkins에서는 GitOps의 Push 타입을 활용하여 Github의 변경사항이 생기면 이를 알리도록 구성하였다.

먼저 Github Server를 등록하여 Jenkins와 Github을 연결하기 위해 Github 계정의 토큰을 등록하여 검증하고 hook URL을 생성한다.
http://ip:port/github-webhook/

그리고 필요한 레포지토리에 Github Webhook에 Jenkins를 등록하여 변경사항이 발생하면 Jenkins에서 빌드 파이프라인을 자동으로 시작하도록 설정했다. Github Webhook은 Redirection을 허용하지 않기 때문에 https가 아닌 http로 ip 그대로를 등록해주었다. proxy_pass로 80포트에서 접근이 가능하다면 포트는 쓰지 않아도 무관하다.

백엔드에서 config를 저장하는 Github Submodule을 사용하는만큼 크레덴셜을 생성하여 https가 아닌 ssh로 config 레포지토리와 함께 백엔드 레포지토리를 가져왔다.

stage('Checkout') {
    steps {
        script {
            git url: "git@github.com:${env.REPO}.git", branch: 'main', credentialsId: 'jenkins-ssh'
        }
    }
}

stage('Initialize Submodule') {
    steps {
        script {
            sh '''
                git submodule init
                git submodule update --remote --merge
            '''
        }
    }
}

CD; ArgoCD

ArgoCD에서는 GitOps의 Pull 타입을 활용하여 PAPERPLE-CD 라는 manifest 레포지토리를 지속적으로 추적하고 변경사항이 생기면 설정에 따라 Sync를 관리한다. ArgoCD에서는 레포의 yaml 파일을 긁어서 클러스터의 현재 상태와 비교하기 때문에 변경이 생기는 deployment, service, hpa(horizontal pod autoscaler)를 담은 manifest만 레포에 등록해두었다.
초기에는 CD 완전 자동화를 위해 AutoSync를 켜두었는데 hpa와 autosync가 충돌하면서 hpa가 무력화되어 autosync를 끄게 되었다.

아키텍처 및 코드

클러스터에 애플리케이션 구성은 아래 아키텍처와 같다.

이를 위해 다음 레포지토리에 백엔드, AI 각각의 Deployment, Service, HPA를 코드로 구성하여 레포지토리에 업로드하였다. 이외에도 PAPERPLE-INFRA에 ingress와 clusterissuer 코드를 남겨두어 트러블슈팅에 활용하였다.

마무리

트러블슈팅이 필요하면 바로 INFRA, CD 레포지토리를 확인하고나서 고치기 시작하면서 모든 상태와 설정을 코드로 관리하는 IaC의 장점을 느낄 수 있었던 것 같다.
다음 글은 CI/CD를 위해 사용했던 Jenkins, ArgoCD로 이어진다!

부족하거나 잘못된 부분이 있다면 편하게 조언, 지적 부탁드립니다. 🙇🏻‍♀️

profile
기록하는 감자

0개의 댓글