Post

배포 자동화 리팩토링, 젠킨스에서 ArgoCD로 (1) — 왜, 그리고 어디까지

시리즈를 시작하며

천재교육 AIDT LMS 플랫폼을 운영하면서, 배포 파이프라인을 젠킨스 중심에서 ArgoCD 기반 GitOps로 옮기는 작업을 진행 중이다. 아직 끝난 프로젝트가 아니라 지금도 진행 중인 전환기이다. 이 글은 완성된 결과물을 자랑하는 글이 아니라 왜 이렇게 설계했고 어디서 무엇을 배웠는지를 기록하는 글에 가깝다. 이번 편은 왜 이 작업을 시작했는지, 지금까지 만든 전체 그림이 어떻게 생겼는지, 그리고 지금 이 시리즈를 읽을 때 알아둬야 할 적용 범위의 한계까지 먼저 짚고 간다.

시리즈 구성은 이렇다.

  1. 왜, 그리고 어디까지 (이 글) — 배경, 전체 아키텍처, 적용 범위
  2. ArgoCD 개념 학습과 첫 PoC — Application/Project/RBAC 개념, 예제 앱으로 배포 흐름 검증
  3. 실전 설계 — AS-IS 전수조사와 values 구조 — 실제 서비스의 젠킨스 스크립트를 뜯어보며 값을 추출한 과정
  4. 실제 적용과 트러블슈팅 — 릴리즈 편입 문제, 브랜치 버그, 단계적 자동화까지
  5. 지금까지의 성과와 앞으로 — 한계, 로드맵, 회고

문제의식 — 진실의 원천이 Git이 아니었다

AIDT LMS의 백엔드 서비스 하나(이 글에서는 aidt-lm-service라고 부르겠다)는 지금까지 젠킨스가 배포 시점에 helm upgrade --install을 직접 실행하는 방식으로 배포돼왔다. 문제는 이 배포에 필요한 값 대부분 — Vault 연동 여부, Istio 서비스 메시 설정, replica 수, 리소스 제한치 같은 것들 — 이 헬름 차트의 values.yaml이 아니라 젠킨스 groovy 스크립트 안에서 조건 분기로 조립되고 있었다는 거다.

실제로 스크립트를 열어서 세어보니, 환경(스테이징/운영)과 배포 대상(수학/영어 등 교과목별 도메인)에 따라 스크립트 안에서 계산되는 값이 30개 가까이 됐다. 이 값들은 배포가 실행되는 순간에만 heredoc으로 조립돼서 임시 파일로 만들어졌다가, helm upgrade 한 번 실행되고 나면 사라진다. 즉:

지금까지 이 서비스의 “진짜 배포 설정”이 뭐였는지는, Git이 아니라 젠킨스 스크립트를 읽어야만 알 수 있었다.

이 상태가 만드는 문제는 이렇다.

  • 배포 설정이 언제 어떻게 바뀌었는지 Git 히스토리로 추적이 안 된다. 젠킨스 스크립트 diff로 유추해야 하는데, 가독성이 떨어진다.
  • 젠킨스가 배포 도중 실패하거나, 클러스터 상태가 어떤 이유로든 “있어야 할 상태”와 어긋나도, 아무도 자동으로 감지하거나 되돌려주지 않는다.
  • 배포 로직(무엇을 어떻게 배포할지)과 실행 로직(빌드, 테스트)이 같은 스크립트 안에 계속 뒤섞이면서, 스크립트 자체가 1,000줄이 넘게 비대해져 있었다.

목표 — Git을 진실의 원천으로

이번 전환의 목표를 한 문장으로 요약하면 이렇다.

배포 설정은 전부 Git으로 관리하고, ArgoCD가 그 상태를 상시 감시·동기화하게 하며, 젠킨스는 “빌드 → 이미지 푸시 → 이미지 태그를 Git에 반영”까지만 하도록 역할을 확 줄인다.

여기서 중요한 건 “젠킨스를 없앤다”가 아니라는 점이다. 젠킨스는 여전히 필요하다 — 소스 빌드, 컨테이너 이미지 빌드, 이런 CI 영역은 그대로 젠킨스 몫이다. 다만 “이 이미지를 실제로 클러스터에 어떻게 배포할지” 결정하는 권한을 젠킨스에서 떼어내서 ArgoCD와 Git 쪽으로 완전히 옮기는 것이다.

전체 아키텍처 — 레포 3개로 역할을 나눴다

설계하면서 가장 먼저 부딪힌 질문은 “무엇을 어느 Git 레포에 둘 것인가”였다. 최종적으로 레포를 역할별로 세 개로 나눴다.

레포 구조

각 레포가 왜 그렇게 나뉘었는지 정리하면:

레포담는 것이유
ArgoCD 설치용 레포 + addon/ArgoCD 자신의 설치 설정 + Application/Project 매니페스토“ArgoCD를 어떻게 운영할지”는 ArgoCD 자체 관심사라, 서비스 코드/설정과 섞이면 헷갈린다
인프라 헬름 차트 레포실제 서비스의 헬름 차트 + values원래도 운영 중인 차트가 있던 곳. 별도 사본을 새로 만들지 않고, 여기에 GitOps 값을 직접 얹기로 했다
학습·PoC 레포개념 검증용 샘플 애플리케이션실제 서비스가 아니라 ArgoCD 자체 동작을 먼저 익히고 검증해본 곳

세 번째(PoC 레포)가 왜 필요했는지는 다음 편에서 자세히 다루는데, 결론만 먼저 말하면 — 실제 서비스로 바로 시작하지 않고, 아무 상관 없는 샘플 앱으로 먼저 ArgoCD가 어떻게 동작하는지 손으로 만져보는 단계를 거쳤다. 이유는 이 시리즈 전체를 관통하는 원칙이기도 한데, 뒤에서 다시 짚는다.

배포 플로우 — AS-IS와 TO-BE

AS-IS (지금까지)

AS-IS

TO-BE (지금 만들고 있는 구조)

TO-BE

가장 핵심적인 차이는 이거다. AS-IS는 “젠킨스가 배포 그 순간에 한 번 밀어넣고 끝”인 이벤트성 구조였고, TO-BE는 “ArgoCD가 상시 감시하다가, Git과 클러스터가 다르면 알아서 맞춘다”는 지속적 구조다. 이 차이 하나가 이번 전환의 거의 전부라고 해도 될 정도로 중요하다 — 앞으로 이어질 글에서 이 차이 때문에 실제로 무엇이 달라졌는지 계속 다루게 될 거다.

지금 이 시리즈를 읽을 때 알아둬야 할 것 — 적용 범위

여기서부터는 “다 됐다”는 인상을 주지 않기 위해 분명히 짚고 넘어가야 할 부분이다.

아직 백엔드에만 적용했다. 프론트엔드는 별도의 빌드·배포 방식을 쓰고 있어서 이번 구조를 그대로 적용할 수 있을지 확인이 필요한 상황이다. 이 부분은 아키텍처를 따로 검토 중이고, 검토가 끝나면 이 시리즈에서 별도로 다룰 생각이다.

아직 개발 환경에만 반영했다. 지금 이 시리즈에서 다루는 모든 검증은 개발 클러스터 기준이다. 이 아키텍처가 충분히 안정적이라고 판단되면, 그다음 스테이징 → 운영 순서로 확대할 계획이다. 순서를 건너뛰지 않는 이유는 뒤에서 계속 나오겠지만 — 검증 안 된 변경을 운영에 먼저 들이지 않는다는 원칙을 계속 지키고 있어서다.

의도적으로 점진적으로 가고 있다. 팀 안에서 ArgoCD/GitOps 자체가 생소한 개념이라, 러닝 커브를 감안해서 한 번에 다 바꾸지 않고 단계별로 적용 범위를 넓히는 중이다.

RBAC이나 세부 권한 설정은 지금 단계에서 깊게 안 들어갔다. 배포 대상 애플리케이션 수가 아직 적고, ArgoCD를 실제로 쓰는 사람도 팀 안에서 나와 팀장님 정도라 — 여러 팀이 나눠 쓰는 조직 규모에서 필요한 수준의 정교한 권한 분리는 지금 단계에선 과했다. 이 판단 기준과, 나중에 규모가 커지면 어떻게 다시 조일 계획인지는 4편에서 다룬다.

이렇게 스코프를 명확히 해두는 이유는 간단하다 — 이 시리즈가 “완성된 모범 사례”가 아니라 지금 실제로 겪고 있는 판단과 트레이드오프의 기록이라는 걸 분명히 하고 싶어서다.

다음 편 예고

다음 편에서는 실제 서비스를 건드리기 전에, ArgoCD가 뭔지도 모르는 상태에서 어떻게 개념을 익혔는지 — Application, Project, RBAC 같은 핵심 개념을 아무 상관 없는 샘플 애플리케이션으로 직접 배포해보면서 감을 잡아간 과정을 다룬다. 특히 “왜 처음부터 실제 서비스로 안 하고 굳이 샘플로 먼저 했는가”에 대한 답이 이 시리즈 전체의 접근 방식을 설명해줄 거다.

(회사·인프라 관련 실명, 클러스터 식별자, 내부 호스트 주소 등은 전부 임의로 재구성해 게시했다.)

This post is licensed under CC BY 4.0 by the author.

© noah. Some rights reserved.