Jenkins, ArgoCD, Harbor로 CI/CD 파이프라인 구성하기 (홈랩 k8s 구축기 4편)

munilive
munilive
Jenkins, ArgoCD, Harbor로 CI/CD 파이프라인 구성하기 (홈랩 k8s 구축기 4편)

지난 편에서 네트워크와 스토리지를 구성했다. 이번에는 코드를 빌드하고 클러스터에 배포하는 파이프라인을 만드는 차례다.

CI/CD를 왜 직접 구성하는가

GitHub Actions를 쓰면 간단하다. 레포에 .github/workflows/를 만들고 빌드, 푸시, 배포 스텝을 작성하면 된다. 그런데 홈랩을 구성하는 이유 중 하나가 이런 것들을 직접 해보는 것이었다. CI 서버가 실제로 어떻게 동작하는지, GitOps가 어떤 개념인지 직접 구성해보면서 이해하는 것.

그래서 Jenkins와 ArgoCD를 선택했다.

Jenkins

Jenkins는 CI 역할이다. 코드가 푸시되면 Jenkins 파이프라인이 실행되어 빌드하고, 컨테이너 이미지를 만들어 레지스트리에 올린다.

Kubernetes 위에 Jenkins를 올리면 흥미로운 점이 하나 있다. 빌드가 시작될 때 k8s에 agent Pod을 동적으로 생성하고, 빌드가 끝나면 자동으로 삭제한다. 유휴 상태에서는 리소스를 거의 쓰지 않는다. 홈랩처럼 리소스가 제한된 환경에 잘 맞는 방식이다.

helm install jenkins jenkins/jenkins \
  -n cicd \
  -f kubernetes/cicd/jenkins/values.yaml \
  --version 5.9.9

처음 접속하면 초기 비밀번호를 확인해야 한다.

kubectl get secret jenkins -n cicd \
  -o jsonpath="{.data.jenkins-admin-password}" | base64 -d && echo

ArgoCD

ArgoCD는 CD 역할이다. Git 레포를 바라보고 있다가, 변경이 감지되면 클러스터에 자동으로 반영해준다. 이게 GitOps의 핵심이다. 클러스터 상태가 항상 Git 레포의 내용과 일치하도록 유지한다는 것.

Jenkins가 이미지를 빌드해서 올리고, 이미지 태그가 변경된 매니페스트를 Git에 커밋하면, ArgoCD가 그것을 감지해서 클러스터에 적용하는 흐름이다. 클러스터에 직접 kubectl apply를 실행하는 것이 아니라, Git이 진실의 원천이 되는 것이다.

helm install argocd argo/argo-cd \
  -n cicd \
  -f kubernetes/cicd/argocd/values.yaml \
  --version 9.4.15

초기 비밀번호는 자동 생성된 secret에서 확인한다. 확인 후에 바로 변경하고, 초기 secret은 삭제해두는 것이 좋다. 클러스터 접근 권한이 있는 누구나 그 secret을 조회할 수 있기 때문이다.

kubectl -n cicd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d && echo
kubectl delete secret argocd-initial-admin-secret -n cicd

Harbor

처음에는 이미지 레지스트리로 GHCR(GitHub Container Registry)을 쓸 생각이었다. 그런데 GHCR은 private 레포지토리 기준으로 무료 스토리지가 500MB밖에 되지 않는다. 컨테이너 이미지는 생각보다 금방 쌓이는데, 그 한도를 넘어서면 비용이 발생한다. 홈랩을 구성한 이유 중 하나가 클라우드 비용을 줄이는 것이었으니, 레지스트리 때문에 비용이 나가는 건 본래 취지에 맞지 않았다. 클러스터 안에 레지스트리를 두면 용량 걱정 없이 쓸 수 있고, 외부 서비스에 의존하지 않고 완전히 자체적으로 운영할 수 있다는 점도 마음에 들었다.

Harbor는 Docker Hub 같은 컨테이너 이미지 레지스트리인데, 취약점 스캐너(Trivy)와 이미지 서명 기능까지 포함되어 있다. 홈랩 용도로는 오버스펙이긴 하지만, 있으면 유용한 기능들이다.

helm install harbor harbor/harbor \
  -n cicd \
  -f kubernetes/cicd/harbor/values.yaml \
  --version 1.18.3

설치 중에 한 가지 삽질이 있었다. Harbor 웹 UI에 접근하면 404가 떴다. Helm 차트가 Ingress에 ingressClassName을 자동으로 설정해주지 않아서였는데, values.yaml에 명시적으로 추가하고 나서야 해결됐다.

expose:
  ingress:
    className: nginx
    annotations:
      nginx.ingress.kubernetes.io/ssl-redirect: 'false'

설치 후에는 웹 UI에서 비밀번호를 변경하고, 이미지를 저장할 프로젝트를 하나 만들어두었다. Jenkins 파이프라인이 이미지를 올릴 목적지가 된다.

세 가지의 연결

Jenkins, ArgoCD, Harbor는 따로 구성했지만 결국 하나의 흐름으로 이어진다.

  1. 코드 변경 → GitHub에 푸시
  2. Jenkins가 감지 → 빌드 + 이미지 생성 → Harbor에 푸시
  3. Jenkins가 k8s 매니페스트의 이미지 태그 변경 → Git에 커밋
  4. ArgoCD가 감지 → 클러스터에 자동 배포

이 흐름이 완성되면 코드를 푸시하는 것만으로 클러스터에 자동으로 배포된다. 아직 실제 서비스 앱은 올리지 않았지만, 파이프라인은 준비가 됐다.

다음 편에서는 모니터링 스택을 올리면서 겪은 삽질을 이야기 하겠다.

munilive

munilive

Backend Application Developer

Share

Comments

Related Posts

집에 Kubernetes 클러스터를 구축해 봤습니다

집에 Kubernetes 클러스터를 구축해 봤습니다

퇴근하고 집에 돌아와 미니 PC 한 대를 책상 위에 올려두고는 여기다가 Kubernetes 클러스터를 직접 구축해 보겠다고 마음먹은 게 몇 달 전이었다. 그리고 지금, 그 미니 P…

munilive munilive ·
Prometheus, Grafana, Loki로 모니터링 구성하기 (홈랩 k8s 구축기 5편)

Prometheus, Grafana, Loki로 모니터링 구성하기 (홈랩 k8s 구축기 5편)

지난 편에서 CI/CD 파이프라인을 구성했다. 이번 편은 모니터링이다. 클러스터가 잘 돌아가고 있는지, 어디서 문제가 생겼는지 파악하려면 메트릭과 로그를 봐야 한다. 그리고 이번…

munilive munilive ·
MetalLB, ingress-nginx, Longhorn으로 네트워크와 스토리지 구성하기 (홈랩 k8s 구축기 3편)

MetalLB, ingress-nginx, Longhorn으로 네트워크와 스토리지 구성하기 (홈랩 k8s 구축기 3편)

지난 편에서 Ansible로 Kubernetes 클러스터를 구성했다. 클러스터는 올라왔지만, 이 상태로는 아무것도 할 수 없다. 외부에서 트래픽을 받는 방법도 없고, 데이터를 저장…

munilive munilive ·