CI/CD

배포. 한 번 빌드한 이미지를 dev와 stg에 GitOps로

← HomeLab

GitLab CI가 cgv-onprem(앱 소스) main 머지마다 이미지를 한 번 빌드하고, 검사를 통과하면 등록합니다. dev 자동 배포, stg는 수동 job publish-ecr로 같은 이미지를 ECR에 승격. image-updater가 새 태그를 cgv-infra(배포 정의)에 커밋하면 노트북 ArgoCD 허브가 두 클러스터에 동기화.

CI/CD 흐름

개발자 main 머지 GitLab CI cgv-onprem check, test, scan 자동 수동 GitLab 레지스트리 dev 이미지 ECR 수동 승격 폴링 image-updater 새 태그 감지 태그 커밋 cgv-infra envs/dev, envs/stg webhook 3초 ArgoCD 허브 노트북 k3s k3s dev 노드 3대 EKS stg 노드 7대 이미지 pull 이미지 pull 이미지 배포 정의와 동기화 폴링 EKS API
image-updater와 허브는 노트북 k3s, GitLab(CI, 레지스트리, cgv-infra)은 데스크탑.

설계 결정

항목선택이유
Git 서버 위치GitLab을 클러스터 밖 데스크탑에 두고 러너와 레지스트리도 함께클러스터 안이면 장애가 나면 함께 멈추고 빌드 I/O가 부하 측정에 간섭. GitHub은 사설망 webhook이 안 됨
CI와 CD분리. CI는 이미지 빌드(cgv-onprem)와 배포 정의 검사(cgv-infra)까지, 배포는 ArgoCD파이프라인이 배포하면 러너에 클러스터 전권 자격이 필요. 분리하면 배포 자격은 허브 ArgoCD에만
브랜치와 환경두 저장소 모두 trunk 하나(main), 환경은 cgv-infra envs/<환경>/ 폴더브랜치를 환경으로 쓰면 환경 구분이 브랜치와 폴더 두 곳에 생김. 승격은 merge 대신 태그 커밋 한 줄
취약점 게이트수정판 있는 HIGH 이상만 차단. 소스(빌드 전)와 이미지(등록 전) 두 겹수정판 없는 취약점까지 막으면 고칠 수단 없이 파이프라인이 상시 실패
승격1회 빌드로 같은 이미지를 ECR로, 게이트는 수동 job publish-ecr환경별로 빌드하면 부하 결과 차이의 원인을 구분할 수 없음. 버튼 실행 기록이 곧 승격 기록
원격 클러스터집 허브가 EKS를 클러스터 이름으로 배포EKS에서 사설망 GitLab 저장소와 레지스트리에 닿지 못함. 이름 지정이라 클러스터를 재생성해도 주소를 바꿀 필요가 없음
배포 권한과 자격AppProject로 배포 범위 제한, dev는 SealedSecret, stg는 생성 뒤 스크립트로 주입제한이 없으면 Application 하나로 전 자원을 만들 수 있음. 봉인본은 dev 클러스터 개인키로만 복호화

트러블슈팅

증상원인조치
취약점 스캔 첫 적용 시 72건서비스 3개 모두 버전을 고정한 뒤 갱신하지 않음. Go 간접 의존 2건, Spring Boot 부모 37건, 갱신이 끊긴 nginx 태그 33건간접 의존 상향, 부모 3.5.16과 netty 지정, nginx 1.31로 올려 0건
파이프라인 1회 10분 15초job 컨테이너가 매번 새로 떠 의존성과 취약점 DB를 다시 받음. docker build 안쪽은 러너 볼륨이 닿지 않음러너 볼륨과 BuildKit 캐시 마운트, 동시 실행 2로 1분 54초
ECR push가 레이어 업로드 후 마지막에 403push 정책에 BatchGetImage가 없음. 매니페스트 등록 전 존재 확인(HEAD)을 ECR이 읽기로 판정ci-push 정책에 BatchGetImage 추가

결과

  • 머지부터 dev, stg 배포까지 GitOps 경로 완성: 배포에 kubectl 0회, stg는 승격 버튼 1회. ECR 등록 93초 뒤 태그 커밋, 21초 뒤 동기화 완료
  • CI 파이프라인의 검사와 차단 동작 확인: 새로 공개된 취약점 grpc HIGH와 netty CRITICAL을 등록 전에 차단, 버전 상향 후 통과
  • 배포 저장소에 평문 시크릿 0건: cgv-infra의 시크릿 매니페스트 19종 전부 SealedSecret 봉인본

한계

  • 자동화 토큰 3개는 수동 갱신: 노드 이미지 pull, image-updater 태그 조회, 저장소 읽기와 태그 되쓰기용. 만료 2026-11-01
  • stg 이미지 롤백 불가: image-updater가 항상 최신 빌드를 고르므로, 문제가 생기면 수정 후 재빌드
  • ECR 자격이 IAM 사용자 장기 키 둘: CI push와 image-updater 조회용. GitLab이 사설 IP라 OIDC 페더레이션을 쓸 수 없음
  • 허브가 가진 EKS 자격이 만료 없는 cluster-admin 토큰: 교체는 수동이고, 허브가 침해되면 EKS 전권이 노출

기술 스택

GitLab CE, GitLab Runner, Docker, Trivy, gitleaks, SpotBugs, ArgoCD, argocd-image-updater, Sealed Secrets, ECR, Secrets Manager