13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] 쿠버네티스 배포

  • [k8s] Helm 차트 관리의 진화: GitOps 시대의 베스트 프랙티스 분석

    [k8s] Helm 차트 관리의 진화: GitOps 시대의 베스트 프랙티스 분석

    안녕하세요, 13년차의 서버실입니다. 제가 처음 쿠버네티스(Kubernetes)를 접했을 때를 생각하면, 마치 새로운 대륙을 발견한 콜럼버스처럼 설레면서도 막막했던 기억이 나네요. 특히 애플리케이션 배포와 관리는 정말이지 끝없는 숙제 같았어요. 처음엔 kubectl apply -f 명령어로 YAML(야믈) 파일을 직접 하나하나 적용했었죠. 그러다 Helm(헬름, 쿠버네티스 패키지 매니저)을 만나고 나서야 비로소 숨통이 트이는 느낌이었습니다.

    Helm은 복잡한 쿠버네티스 애플리케이션을 패키징하고 배포하는 데 정말 혁신적인 도구였어요. 그런데 시간이 지나고 관리해야 할 차트(Chart)가 늘어나면서, 또 다른 고민이 생기더라고요. ‘이 많은 차트들을 어떻게 효과적으로 관리하고, 배포 이력을 추적하며, 안정적으로 운영할 수 있을까?’ 하는 문제였습니다. 수동으로 helm upgrade를 반복하는 건 실수 투성이였고, CI/CD(지속적 통합/지속적 배포) 파이프라인에 Helm 명령어를 넣는 것도 생각보다 손이 많이 갔거든요. ⚠️

    그러던 와중에 GitOps(깃옵스, Git 기반 운영 방식)라는 개념을 접하게 됐습니다. ‘아, 이거다!’ 싶었죠. 인프라와 애플리케이션의 상태를 Git 리포지토리(Repository)에 코드 형태로 정의하고, 이 Git을 유일한 진실의 원천(Single Source of Truth)으로 삼아 자동으로 클러스터 상태를 동기화하는 방식. 오늘은 이 GitOps 시대에 Helm 차트를 어떻게 하면 스마트하게 관리할 수 있는지, 제가 직접 홈랩에서 겪었던 경험과 함께 베스트 프랙티스(Best Practice)를 분석해 보려고 합니다. 여러분의 쿠버네티스 배포 여정에 이 글이 작은 등불이 되기를 바랍니다!

    GitOps 기반 Helm 차트 관리 아키텍처 개요 다이어그램

    GitOps 기반 Helm 차트 관리의 전체적인 아키텍처를 보여줍니다. 개발자가 Git에 변경사항을 푸시하면, GitOps 오퍼레이터(예: Flux CD)가 이를 감지하여 쿠버네티스 클러스터에 Helm 차트를 배포하는 흐름입니다.

    Helm과 GitOps, 그 관계를 파헤치다

    먼저 핵심 개념들을 잠시 짚고 넘어가 볼까요? 이미 잘 아시는 분도 많겠지만, 혹시 처음 접하는 분들을 위해 쉽게 설명해 드릴게요.

    • Helm (헬름): 쿠버네티스 패키지 매니저예요. 복잡한 애플리케이션을 차트(Chart)라는 패키지 형태로 정의하고, 이를 쉽게 설치, 업데이트, 삭제할 수 있도록 도와줍니다. 마치 리눅스의 apt나 yum처럼이죠. Deployment, Service, Ingress(인그레스, 외부 트래픽 진입점) 등 여러 쿠버네티스 리소스(Resource)들을 하나의 묶음으로 관리할 수 있게 해줘요.
    • GitOps (깃옵스): 쉽게 말해, Git을 중심으로 모든 것을 운영하는 방식입니다. 애플리케이션 코드뿐만 아니라, 인프라 구성(Infrastructure as Code)까지 전부 Git 리포지토리에 저장하고 관리합니다. 그리고 Git 리포지토리의 변경 사항이 감지되면, GitOps 에이전트(Agent)가 자동으로 쿠버네티스 클러스터에 배포하거나 상태를 동기화(Reconciliation)하는 구조예요. 사람이 직접 명령어를 입력할 필요 없이, Git에 커밋(Commit)만 하면 배포가 이뤄지는 거죠. 🎉

    그럼 Helm과 GitOps가 만나면 어떤 시너지를 낼까요? 기존에는 Helm 명령어를 CI/CD 파이프라인에서 실행하거나, 개발자가 직접 터미널에서 입력해서 배포했었죠. 하지만 GitOps를 도입하면, Helm 차트의 설정 파일(values.yaml)이나 차트 자체의 버전 변경을 Git에 커밋하는 것만으로 배포가 자동으로 트리거(Trigger)됩니다. ‘선언적(Declarative)’으로 상태를 정의하고, ‘자동으로 동기화(Automated Synchronization)’되는 거죠. 이 덕분에 배포의 투명성, 안정성, 감사(Audit) 용이성이 크게 향상됩니다. 제가 직접 해보니, 이게 진짜 편하더라고요!

    실전! GitOps 기반 Helm 차트 관리 구현: Flux CD를 중심으로

    홈랩에서 다양한 GitOps 툴을 실험해 봤는데, 개인적으로는 Flux CD(플럭스 CD)가 Helm 차트 관리에 참 잘 맞았어요. 물론 Argo CD(아르고 CD)도 훌륭한 대안이고요. 오늘은 Flux CD를 활용해서 GitOps 기반 Helm 차트 관리 환경을 구축하는 방법을 단계별로 설명해 드릴게요. 따라오시면 여러분도 쉽게 구현하실 수 있을 겁니다.

    1. Flux CD 설치 및 초기 설정

      먼저 쿠버네티스 클러스터(Cluster)에 Flux CD를 설치해야 합니다. Flux CLI(커맨드 라인 인터페이스)를 사용하면 정말 쉽게 설치할 수 있어요.

      
      # Flux CLI 설치 (macOS 기준, 다른 OS는 공식 문서 참고)
      brew install fluxcd/tap/flux
      
      # Flux CD 초기화 및 Git 리포지토리 연동
      # 여기서 your-git-repo는 GitOps 설정을 저장할 리포지토리 주소입니다.
      # --branch main은 기본 브랜치를 main으로 설정하는 것이고요.
      # --path clusters/my-cluster는 Flux가 모니터링할 Git 리포지토리 내 경로입니다.
      flux bootstrap git \
        --owner=<your-git-username> \
        --repository=<your-git-repo> \
        --branch=main \
        --path=clusters/my-cluster \
        --personal
              

      위 명령어를 실행하면 Flux CD가 필요한 컨트롤러(Controller)들을 쿠버네티스 클러스터에 설치하고, 지정된 Git 리포지토리와 연동합니다. 이제 Git 리포지토리 clusters/my-cluster 경로에 변경 사항이 생기면 Flux CD가 자동으로 감지하게 됩니다. ✅

    2. Git 리포지토리 구조 잡기

      GitOps의 핵심은 Git 리포지토리 구조를 잘 잡는 것입니다. 저는 보통 이런 식으로 구성합니다.

      
      .
      ├── clusters/
      │   └── my-cluster/ # Flux CD가 모니터링할 경로
      │       ├── flux-system/ # Flux CD가 생성한 리소스 (자동 관리)
      │       └── applications/ # 배포할 애플리케이션 HelmRelease 정의
      │           ├── nginx/
      │           │   └── nginx-helmrelease.yaml
      │           └── prometheus/
      │               └── prometheus-helmrelease.yaml
      └── helm-charts/ # 직접 만든 Helm 차트 (선택 사항, 외부 차트 사용 시 필요 없음)
          └── my-app/
              ├── Chart.yaml
              ├── values.yaml
              └── templates/
                  └── ...
              
    3. Helm 차트 정의 및 배포 (HelmRepository, HelmRelease)

      이제 애플리케이션을 배포해 볼까요? 예를 들어, 안정적인 Nginx(엔진엑스) Ingress Controller(인그레스 컨트롤러)를 배포한다고 가정해 봅시다. Flux CD에서는 HelmRepository와 HelmRelease라는 커스텀 리소스(Custom Resource)를 사용합니다.

      먼저 Helm 차트 저장소(Repository)를 정의합니다. Nginx Ingress Controller의 공식 Helm 저장소를 추가하는 HelmRepository 리소스입니다.

      
      # clusters/my-cluster/applications/nginx/nginx-helmrepository.yaml
      apiVersion: source.toolkit.fluxcd.io/v1beta2
      kind: HelmRepository
      metadata:
        name: ingress-nginx
        namespace: flux-system # Flux CD 시스템 네임스페이스
      spec:
        interval: 1h0m0s # 1시간마다 저장소 업데이트 확인
        url: https://kubernetes.github.io/ingress-nginx
              

      이 파일을 Git 리포지토리의 clusters/my-cluster/applications/nginx/ 경로에 저장하고 커밋(Commit)하면, Flux CD가 이를 감지하여 쿠버네티스 클러스터에 HelmRepository 리소스를 생성합니다. Flux CD는 이 저장소를 주기적으로 스캔하여 최신 차트 정보를 가져오게 됩니다. 💡

      Flux CD HelmRelease를 이용한 쿠버네티스 차트 배포 흐름

      Flux CD가 Git 리포토리의 HelmRelease 정의를 읽어 쿠버네티스 클러스터에 Helm 차트를 배포하는 과정을 시각화한 다이어그램입니다.

      다음으로, 실제로 Nginx Ingress Controller를 배포할 HelmRelease 리소스를 정의합니다. 여기에 어떤 차트를 어떤 버전으로, 어떤 값(values)으로 배포할지 상세하게 명시합니다.

      
      # clusters/my-cluster/applications/nginx/nginx-helmrelease.yaml
      apiVersion: helm.toolkit.fluxcd.io/v2beta1
      kind: HelmRelease
      metadata:
        name: ingress-nginx
        namespace: ingress-nginx # Nginx Ingress Controller가 배포될 네임스페이스
      spec:
        interval: 5m0s # 5분마다 상태 동기화 확인
        chart:
          spec:
            chart: ingress-nginx # HelmRepository에 정의된 차트 이름
            version: ">=4.0.0 <5.0.0" # 차트 버전 범위 지정
            sourceRef:
              kind: HelmRepository
              name: ingress-nginx # 위에서 정의한 HelmRepository 이름
              namespace: flux-system
        values: # values.yaml 내용과 동일
          controller:
            replicaCount: 2
            service:
              type: LoadBalancer
            nodeSelector:
              kubernetes.io/os: linux
          defaultBackend:
            enabled: true
              

      이 파일도 Git 리포지토리에 저장하고 커밋하면, Flux CD는 HelmRepository에서 차트를 가져와 이 HelmRelease 정의에 따라 Nginx Ingress Controller를 클러스터에 배포하게 됩니다. 와, 정말 깔끔하게 배포되는 거 보니까 속이 다 시원하더라고요! 이제 배포에 대한 모든 변경사항은 Git에서만 이뤄지게 됩니다. 🚀

    삽질 대잔치! 겪었던 문제와 해결 과정

    물론 이렇게 깔끔하게 설명했지만, 제가 이걸 처음 세팅할 때는 삽질 좀 했습니다 ㅎㅎ. 특히 몇 가지 문제로 머리를 싸맸던 기억이 나네요. 여러분은 저 같은 실수 하지 마시라고 몇 가지 팁을 공유해 드립니다. ⚠️

    • HelmRelease 동기화 실패:

      처음에는 Git에 커밋했는데도 클러스터에 아무런 변화가 없어서 당황했어요. 알고 보니 HelmRepository의 interval이나 HelmRelease의 interval 설정이 너무 길거나, Git 리포지토리 경로를 잘못 지정한 경우가 많았습니다. Flux CD의 로그를 꼼꼼히 확인하고, flux reconcile kustomization <kustomization-name> 명령어로 수동 동기화를 시도하면서 문제를 찾아냈습니다.

      
              # Flux CD Kustomization 상태 확인 (Git 리포지토리 동기화 상태)
              flux get kustomizations
      
              # Flux CD HelmRelease 상태 확인
              flux get hr -A # 모든 네임스페이스의 HelmRelease 확인
              
    • imagePullSecrets 적용 문제:

      프라이빗 레지스트리(Private Registry)에 있는 이미지를 사용해야 할 때, imagePullSecrets(이미지 풀 시크릿)을 ServiceAccount(서비스 어카운트)에 연결해야 하잖아요? 이걸 HelmRelease의 values에 직접 넣어도 되지만, 보안상 좋지 않거나 모든 ServiceAccount에 적용하고 싶을 때가 있습니다. 이럴 땐 Kustomize(커스터마이즈)를 활용하여 ServiceAccount에 imagePullSecrets를 패치(Patch)하는 방식으로 해결했습니다. Flux CD는 Kustomization 리소스도 지원해서, Helm과 Kustomize를 함께 사용하는 것도 가능합니다. (이건 다음 기회에 더 자세히 다뤄볼게요!)

    • 차트 버전 범위 지정 오류:

      HelmRelease에서 version: ">=4.0.0 <5.0.0"처럼 버전을 지정할 때, 세밀하게 지정하지 않으면 예상치 못한 마이너 버전 업데이트로 인해 문제가 생길 수 있습니다. 너무 넓은 범위보다는 안정성이 검증된 특정 버전이나, 패치 버전까지만 허용하는 것이 좋습니다.

    드디어! GitOps로 배포된 Helm 차트 확인

    이제 모든 설정이 완료되고 Git에 커밋까지 했다면, Flux CD가 자동으로 배포를 진행했을 겁니다. 배포가 제대로 되었는지 확인해 봐야겠죠? kubectl 명령어로 확인하면 됩니다.

    
    # Flux CD가 관리하는 Kustomization 리소스 상태 확인
    kubectl get kustomizations -n flux-system
    
    # Flux CD가 관리하는 HelmRelease 리소스 상태 확인
    kubectl get helmreleases -n ingress-nginx
    
    # Nginx Ingress Controller 파드(Pod) 확인
    kubectl get pods -n ingress-nginx
    

    helmreleases의 상태가 Ready이고, pods가 모두 Running 상태라면 성공입니다! 🎉 정말 깔끔하게 배포된 걸 보니까 속이 다 시원하더라고요. 이제 어떤 변경이든 Git 리포지토리에 반영하는 것만으로 배포가 자동으로 이뤄집니다. 롤백(Rollback)도 Git에서 이전 커밋으로 되돌리는 것만으로 가능하니, 얼마나 안정적이고 편리한지 몰라요.

    Kubernetes 클러스터에서 kubectl 명령어를 사용하여 Flux CD의 HelmRelease와 관련된 리소스들이 성공적으로 배포되고 실행 중인 상태를 보여주는 터미널 화면입니다.

    마무리하며: Helm GitOps, 더 나은 미래를 향해

    오늘은 13년차 인프라 엔지니어의 시선으로 Helm 차트 관리의 진화, 특히 GitOps 시대의 베스트 프랙티스를 Flux CD를 중심으로 알아봤습니다. 제가 직접 경험해 보니 GitOps는 단순히 도구를 사용하는 것을 넘어, 인프라 운영 방식 자체를 혁신하는 패러다임(Paradigm)이라는 생각이 들었습니다.

    GitOps 기반 Helm 차트 관리는 다음과 같은 장점들을 가져다줍니다.

    • 생산성 향상: 수동 작업 감소, 자동화된 배포.
    • 안정성 증대: Git을 통한 단일 진실의 원천, 쉬운 롤백.
    • 투명성 및 감사 용이성: 모든 변경 이력이 Git에 기록.
    • 협업 강화: 코드 리뷰(Code Review)를 통한 변경 사항 검증.
    전통적인 Helm 관리 방식과 GitOps 기반 Helm 관리 방식 비교표

    전통적인 Helm 관리 방식과 GitOps 기반 Helm 관리 방식을 주요 특징(자동화, 롤백, 투명성 등)별로 비교하는 인포그래픽 형태의 표입니다.

    물론 GitOps를 도입하는 것이 마냥 쉽지만은 않습니다. 초기 설정의 복잡성, Git 리포지토리 관리 전략 수립, 그리고 팀원들의 새로운 워크플로우(Workflow) 적응 등 넘어야 할 산들이 분명히 존재합니다. 하지만 그 모든 노력을 감수할 만큼의 가치가 충분하다고 저는 확신합니다. 결국 GitOps는 인프라 운영의 투명성과 안정성을 극대화하고, 개발팀과 운영팀 간의 협업을 더욱 매끄럽게 만드는 데 크게 기여할 겁니다.

    다음 글에서는 Flux CD의 고급 기능이나 다른 GitOps 툴인 Argo CD(아르고 CD)와의 비교, 또는 Kustomize를 활용한 Helm 차트 오버레이(Overlay) 방법에 대해서도 다뤄볼 예정입니다. 계속해서 “13년차의 서버실”에 많은 관심 부탁드립니다. 궁금한 점이나 여러분의 경험담이 있다면 댓글로 남겨주세요! 함께 고민하고 성장해 나가는 것이 저의 기쁨입니다. 😊

  • [k8s] ArgoCD GitOps CI/CD 구축: 쿠버네티스 자동 배포 완벽 가이드

    배포가 두려운 분들께 — GitOps가 바꿔놓은 제 일상

    솔직히 말씀드리면, 저도 예전에는 배포가 제일 무서웠어요. 스테이징에서는 멀쩡하던 게 프로덕션에 올리면 왜인지 모르게 터지고, “누가 언제 뭘 바꿨지?” 하고 kubectl로 이것저것 뒤지다 보면 어느새 새벽 2시가 되어 있는 그런 날들이요. 쿠버네티스를 도입하고 나서도 한동안은 이 상황이 크게 달라지지 않았습니다. 오히려 배포 방법이 늘어나면서 혼란이 더 심해지기도 했고요.

    그러다가 ArgoCD를 알게 됐습니다. 처음엔 “또 새로운 툴이네” 하고 반신반의했는데, 막상 써보니까 진짜 다르더라고요. GitOps 방식으로 쿠버네티스 배포를 자동화하면, Git 저장소가 클러스터의 “진실의 원천(Source of Truth)”이 됩니다. 코드를 푸시하면 ArgoCD가 알아서 클러스터 상태를 맞춰주는 거예요. 오늘은 제가 홈랩과 실무에서 직접 구축하면서 겪은 경험을 바탕으로, ArgoCD를 활용한 CI/CD 파이프라인 구축 방법을 처음부터 끝까지 같이 살펴보겠습니다.

    ArgoCD GitOps 전체 아키텍처 — Git 저장소 변경이 쿠버네티스 클러스터에 자동 반영되는 흐름

    GitOps와 ArgoCD, 쉽게 이해하기

    GitOps란 뭔가요?

    GitOps를 한 문장으로 정리하면 이렇습니다. “인프라와 애플리케이션의 원하는 상태(Desired State)를 Git에 선언적으로 저장하고, 자동화 도구가 실제 상태를 그것에 맞게 유지하는 방식”이에요.

    쉽게 말해서, 예전에는 “지금 클러스터에 뭐가 떠 있지?”를 확인하려면 kubectl get 명령어를 직접 쳐봐야 했잖아요. GitOps를 쓰면 Git 저장소만 봐도 현재 클러스터 상태를 알 수 있어요. 변경 이력도 다 남고, 롤백도 git revert 한 방이면 되고요.

    기존 CI/CD 방식과 무엇이 다른가요?

    구분 기존 Push 방식 CI/CD GitOps (ArgoCD Pull 방식)
    배포 트리거 CI 파이프라인이 kubectl apply 직접 실행 ArgoCD가 Git 변경 감지 후 자동 동기화
    클러스터 접근 권한 CI 서버가 클러스터 자격증명 보유 ArgoCD만 클러스터 내부에서 관리
    상태 추적 파이프라인 로그 확인 필요 Git 커밋 히스토리 = 배포 이력
    드리프트(Drift) 감지 수동 확인 필요 ArgoCD가 실시간 감지 및 알림
    롤백 파이프라인 재실행 or 수동 Git revert + 자동 동기화

    특히 드리프트(Drift) 감지가 저한테는 정말 킬러 피처였어요. 누군가 실수로 kubectl로 직접 설정을 바꿔놔도, ArgoCD가 “어? Git이랑 다른데?” 하고 바로 잡아주거든요. 이게 얼마나 안심되는지 모릅니다.

    ArgoCD 설치 — 생각보다 간단합니다

    사전 준비

    • 쿠버네티스 클러스터 (v1.19 이상 권장)
    • kubectl 설치 및 클러스터 접근 설정 완료
    • Git 저장소 (GitHub, GitLab, Bitbucket 모두 가능)
    • ArgoCD CLI (선택사항이지만 있으면 편해요)

    1단계: ArgoCD 네임스페이스 및 설치

    ArgoCD 공식 설치 방법은 정말 간단합니다. 공식 매니페스트를 그대로 적용하면 되거든요.

    # ArgoCD 전용 네임스페이스 생성
    kubectl create namespace argocd
    
    # ArgoCD 공식 매니페스트 적용
    kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
    
    # 설치 완료 확인 (모든 Pod가 Running 상태가 될 때까지 대기)
    kubectl get pods -n argocd -w

    처음에 저도 이게 너무 간단해서 “이게 맞나?” 싶었는데, 맞습니다 ㅎㅎ. 잠시 기다리면 아래와 같이 Pod들이 뜨기 시작해요.

    NAME                                                READY   STATUS    RESTARTS   AGE
    argocd-application-controller-0                     1/1     Running   0          2m
    argocd-applicationset-controller-xxx                1/1     Running   0          2m
    argocd-dex-server-xxx                               1/1     Running   0          2m
    argocd-notifications-controller-xxx                 1/1     Running   0          2m
    argocd-redis-xxx                                    1/1     Running   0          2m
    argocd-repo-server-xxx                              1/1     Running   0          2m
    argocd-server-xxx                                   1/1     Running   0          2m

    2단계: ArgoCD UI 접근 설정

    기본적으로 ArgoCD 서버는 외부에 노출되어 있지 않아요. 로컬에서 테스트할 때는 포트 포워딩을 쓰고, 실제 운영 환경에서는 Ingress를 설정하는 게 좋습니다.

    # 로컬 테스트용 포트 포워딩
    kubectl port-forward svc/argocd-server -n argocd 8080:443
    
    # 초기 admin 비밀번호 확인
    kubectl -n argocd get secret argocd-initial-admin-secret \
      -o jsonpath="{.data.password}" | base64 -d; echo

    💡 팁: 초기 비밀번호는 반드시 첫 로그인 후 바꿔주세요. 그리고 argocd-initial-admin-secret은 비밀번호 변경 후 삭제하는 게 보안상 좋습니다.

    3단계: ArgoCD CLI 설치 (선택 권장)

    # macOS
    brew install argocd
    
    # Linux
    curl -sSL -o /usr/local/bin/argocd \
      https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
    chmod +x /usr/local/bin/argocd
    
    # CLI로 ArgoCD 서버에 로그인
    argocd login localhost:8080 --username admin --password <위에서-확인한-비밀번호> --insecure

    ArgoCD 웹 UI 대시보드 — 애플리케이션 동기화 상태와 헬스 체크 결과를 한눈에 확인

    첫 번째 Application 등록 — 실전 GitOps 시작

    Git 저장소 구조 준비

    ArgoCD를 쓸 때 저장소 구조를 어떻게 잡느냐가 은근히 중요하더라고요. 저는 앱 코드와 쿠버네티스 매니페스트를 분리하는 방식을 선호합니다.

    my-gitops-repo/
    ├── apps/
    │   ├── dev/
    │   │   ├── deployment.yaml
    │   │   ├── service.yaml
    │   │   └── kustomization.yaml
    │   └── prod/
    │       ├── deployment.yaml
    │       ├── service.yaml
    │       └── kustomization.yaml
    └── README.md

    예시로 사용할 간단한 Deployment와 Service 매니페스트입니다.

    # apps/dev/deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sample-app
      namespace: default
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: sample-app
      template:
        metadata:
          labels:
            app: sample-app
        spec:
          containers:
          - name: sample-app
            image: nginx:1.25
            ports:
            - containerPort: 80
            resources:
              requests:
                cpu: 100m
                memory: 128Mi
              limits:
                cpu: 200m
                memory: 256Mi
    # apps/dev/service.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: sample-app-svc
      namespace: default
    spec:
      selector:
        app: sample-app
      ports:
      - protocol: TCP
        port: 80
        targetPort: 80
      type: ClusterIP

    ArgoCD Application 생성

    이제 핵심입니다. ArgoCD에게 “이 Git 저장소의 이 경로를 이 클러스터에 배포해줘”라고 알려주는 Application 리소스를 만들어야 해요. YAML로 선언적으로 만드는 걸 추천합니다 — 이것 자체도 Git으로 관리하면 더 좋고요.

    # argocd-application.yaml
    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: sample-app-dev
      namespace: argocd
    spec:
      project: default
      source:
        repoURL: https://github.com/your-username/my-gitops-repo.git
        targetRevision: HEAD
        path: apps/dev
      destination:
        server: https://kubernetes.default.svc
        namespace: default
      syncPolicy:
        automated:
          prune: true        # Git에서 삭제된 리소스 자동 제거
          selfHeal: true     # 드리프트 감지 시 자동 복구
        syncOptions:
        - CreateNamespace=true
    # Application 생성
    kubectl apply -f argocd-application.yaml
    
    # 동기화 상태 확인
    argocd app get sample-app-dev
    
    # 수동 동기화 (처음 한 번)
    argocd app sync sample-app-dev

    여기서 selfHeal: true 옵션이 제가 아까 말씀드린 드리프트 자동 복구 기능이에요. 누군가 실수로 kubectl로 직접 replica 수를 바꿔도, ArgoCD가 Git에 선언된 값으로 되돌려줍니다. 처음에 이게 동작하는 걸 보고 “오오…” 했던 기억이 나네요.

    Private 저장소 연결

    실무에서는 당연히 Private 저장소를 쓰죠. SSH 키나 Personal Access Token으로 연결할 수 있어요.

    # HTTPS + Personal Access Token 방식
    argocd repo add https://github.com/your-username/my-gitops-repo.git \
      --username your-username \
      --password your-personal-access-token
    
    # SSH 키 방식
    argocd repo add [email protected]:your-username/my-gitops-repo.git \
      --ssh-private-key-path ~/.ssh/id_rsa

    CI 파이프라인과 연동 — 이미지 태그 자동 업데이트

    ArgoCD는 CD(Continuous Delivery) 도구입니다. CI(Continuous Integration)는 별도 도구를 써야 해요. 저는 GitHub Actions를 주로 쓰는데, 흐름은 이렇습니다.

    1. 개발자가 앱 코드를 main 브랜치에 push
    2. GitHub Actions가 Docker 이미지를 빌드하고 레지스트리에 push
    3. GitHub Actions가 GitOps 저장소의 이미지 태그를 새 버전으로 업데이트
    4. ArgoCD가 GitOps 저장소 변경을 감지하고 자동으로 클러스터에 배포
    # .github/workflows/deploy.yaml
    name: Build and Update GitOps Repo
    
    on:
      push:
        branches: [main]
    
    jobs:
      build-and-push:
        runs-on: ubuntu-latest
        steps:
        - name: Checkout app code
          uses: actions/checkout@v3
    
        - name: Set up Docker Buildx
          uses: docker/setup-buildx-action@v2
    
        - name: Login to Container Registry
          uses: docker/login-action@v2
          with:
            registry: ghcr.io
            username: ${{ github.actor }}
            password: ${{ secrets.GITHUB_TOKEN }}
    
        - name: Build and push
          uses: docker/build-push-action@v4
          with:
            push: true
            tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
    
        - name: Update GitOps repo image tag
          run: |
            git clone https://x-access-token:${{ secrets.GITOPS_TOKEN }}@github.com/your-username/my-gitops-repo.git
            cd my-gitops-repo
            # sed로 이미지 태그 업데이트
            sed -i "s|image: ghcr.io/your-username/sample-app:.*|image: ghcr.io/your-username/sample-app:${{ github.sha }}|"\
              apps/dev/deployment.yaml
            git config user.email "[email protected]"
            git config user.name "CI Bot"
            git add apps/dev/deployment.yaml
            git commit -m "chore: update image tag to ${{ github.sha }}"
            git push

    근데 여기서 주의할 점이 있어요. 앱 코드 저장소와 GitOps(매니페스트) 저장소를 분리하는 게 좋습니다. 같은 저장소에 두면 앱 코드 변경과 인프라 변경 이력이 섞여서 나중에 관리가 복잡해지더라고요. 처음에 같이 뒀다가 나중에 분리하는 삽질을 했었는데… 처음부터 분리하세요 ㅎㅎ.

    CI/CD 전체 파이프라인 흐름 — GitHub Actions가 이미지를 빌드하고 GitOps 저장소를 업데이트하면 ArgoCD가 자동 배포

    ⚠️ 삽질 모음 — 이것만 알면 시간 아낍니다

    1. OutOfSync 상태가 계속 유지되는 문제

    분명히 Git이랑 같은 내용인데 ArgoCD에서 계속 OutOfSync라고 뜨는 경우가 있어요. 대부분 리소스 정규화(normalization) 문제입니다. 쿠버네티스가 자동으로 추가하는 필드들(creationTimestamp, status 등)이 Git에 없는 거예요.

    # Application에 ignoreDifferences 추가로 해결
    spec:
      ignoreDifferences:
      - group: apps
        kind: Deployment
        jsonPointers:
        - /spec/replicas  # HPA가 관리하는 경우 replica 수 무시
      - group: ""
        kind: Service
        jsonPointers:
        - /spec/clusterIP

    2. Helm 차트 사용 시 values 파일 관리

    Helm을 ArgoCD와 함께 쓸 때 values 파일을 Git에 두면 됩니다.

    spec:
      source:
        repoURL: https://github.com/your-username/my-gitops-repo.git
        path: charts/my-app
        helm:
          valueFiles:
          - values-dev.yaml
          - values-secrets.yaml  # Sealed Secrets 등으로 암호화된 파일

    3. 시크릿(Secret) 관리 — 절대 Git에 평문으로 넣지 마세요

    이건 정말 중요해요. DB 비밀번호 같은 민감 정보를 실수로 Git에 넣는 사고가 생각보다 많이 일어납니다. 저는 Sealed Secrets나 External Secrets Operator를 씁니다.

    • Sealed Secrets: 공개키로 암호화된 SealedSecret 리소스를 Git에 저장, 클러스터 내 컨트롤러가 복호화
    • External Secrets Operator: AWS Secrets Manager, HashiCorp Vault 등 외부 시크릿 저장소와 연동

    4. ArgoCD 자체도 GitOps로 관리하기 — App of Apps 패턴

    ArgoCD Application 리소스가 많아지면 관리가 힘들어져요. 이럴 때 App of Apps 패턴을 씁니다. 루트 Application 하나가 다른 Application들을 관리하는 계층 구조예요.

    # root-application.yaml — 다른 Application들을 관리하는 루트
    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: root-app
      namespace: argocd
    spec:
      project: default
      source:
        repoURL: https://github.com/your-username/my-gitops-repo.git
        targetRevision: HEAD
        path: argocd-apps  # 이 폴더 안에 다른 Application YAML들이 있음
      destination:
        server: https://kubernetes.default.svc
        namespace: argocd
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

    ✅ 배포 결과 확인 및 검증

    모든 설정이 끝났으면 이렇게 확인하시면 됩니다.

    # ArgoCD CLI로 앱 상태 확인
    argocd app list
    
    # 상세 상태 확인
    argocd app get sample-app-dev
    
    # 동기화 이력 확인
    argocd app history sample-app-dev
    
    # kubectl로 직접 확인
    kubectl get pods -n default
    kubectl get svc -n default

    ArgoCD UI에서 애플리케이션 상태가 Synced / Healthy로 표시되면 성공입니다. 🎉

    이제 Git 저장소에서 deployment.yaml의 이미지 태그만 바꿔서 커밋하면, 몇 분 안에 (기본 polling 주기는 3분) 클러스터에 자동으로 반영되는 걸 볼 수 있어요. 처음에 이게 자동으로 되는 걸 보고 “드디어 됐다!” 하고 혼자 좋아했던 기억이 납니다 ㅎㅎ.

    # 롤백도 이렇게 간단합니다
    argocd app rollback sample-app-dev 
    
    # 또는 Git에서 revert 후 push하면 ArgoCD가 자동으로 처리

    ArgoCD 애플리케이션 상세 화면 — Synced/Healthy 상태와 쿠버네티스 리소스 트리 시각화

    자주 묻는 질문 (FAQ)

    Q. ArgoCD는 무료인가요?

    네, ArgoCD는 오픈소스(Apache 2.0 라이선스)로 완전 무료입니다. CNCF(Cloud Native Computing Foundation) 졸업 프로젝트이기도 하고요.

    Q. Flux와 ArgoCD 중 어떤 걸 써야 하나요?

    둘 다 GitOps 도구이지만, ArgoCD는 UI가 풍부하고 직관적이라 팀에서 처음 GitOps를 도입할 때 진입 장벽이 낮습니다. Flux는 더 경량이고 CLI 친화적이에요. 저는 팀 협업 환경에서는 ArgoCD를, 단독 운영이나 자동화 중심이면 Flux를 추천합니다.

    Q. 여러 클러스터를 관리할 수 있나요?

    가능합니다. ArgoCD 하나로 여러 쿠버네티스 클러스터를 등록하고 관리할 수 있어요. argocd cluster add 명령어로 추가하면 됩니다.

    마무리 — GitOps, 한 번 맛보면 못 돌아갑니다

    ArgoCD와 GitOps를 도입하고 나서 제 일상이 꽤 달라졌어요. 배포가 무서운 이벤트에서 그냥 평범한 Git 커밋 하나로 바뀌었달까요. 팀원들도 “내가 뭘 배포했는지” Git 로그만 보면 바로 알 수 있으니 커뮤니케이션 비용도 줄었고요.

    물론 처음 셋업할 때 시크릿 관리나 멀티 클러스터 권한 설정 같은 부분에서 삽질이 좀 있긴 합니다. 근데 그 초기 투자를 하고 나면 이후에는 정말 편해요.

    오늘 다룬 내용을 정리하면 이렇습니다.

    • ✅ GitOps 개념과 기존 CI/CD 방식의 차이 이해
    • ✅ ArgoCD 설치 및 초기 설정
    • ✅ Application 리소스로 Git 저장소와 클러스터 연결
    • ✅ GitHub Actions와 연동한 완전 자동화 파이프라인 구축
    • ✅ 자주 겪는 문제와 해결법

    다음 글에서는 ArgoCD ApplicationSet을 활용해서 여러 환경(dev/staging/prod)을 템플릿 하나로 관리하는 방법을 다룰 예정입니다. App of Apps 패턴도 더 깊이 파볼 거고요. 이 글이 도움이 됐다면 댓글로 알려주세요! 궁금한 점도 편하게 물어봐 주시고요. 😊

  • [k8s] ArgoCD 프로덕션 환경 GitOps 베스트 프랙티스: 안정적인 배포와 보안 강화

    [k8s] ArgoCD 프로덕션 환경 GitOps 베스트 프랙티스: 안정적인 배포와 보안 강화

    ArgoCD 프로덕션 환경 GitOps 베스트 프랙티스: 안정적인 배포와 보안 강화

    안녕하세요, 13년차 인프라 엔지니어입니다. 오늘은 쿠버네티스(Kubernetes) 배포의 핵심 툴 중 하나인 ArgoCD와 GitOps에 대해 이야기해보려고 해요. 사실 제가 처음 인프라 엔지니어를 시작했을 때는 배포라고 하면 SSH로 서버에 접속해서 스크립트 돌리고, 수동으로 설정을 변경하고, 문제가 터지면 눈으로 찾아 헤매는 게 일상이었거든요. 그러다 쿠버네티스 세상이 열리고 CI/CD 파이프라인이 중요해지면서, 더 안정적이고 효율적인 배포 방식에 대한 갈증이 커졌습니다.

    수많은 삽질 끝에 제가 정착한 방법이 바로 GitOps였습니다. 그리고 그 중심에는 ArgoCD가 있었죠. 처음엔 이게 뭔가 싶었는데, 막상 써보니까 ‘아, 이거 진짜 편하고 안전하네!’ 싶더라고요. 프로덕션 환경에서 ArgoCD를 안정적으로 운영하고 GitOps 보안을 강화하기 위한 저만의 경험과 베스트 프랙티스를 공유해볼까 합니다. 혹시 쿠버네티스 배포 때문에 밤잠 설치고 계신 분들이 있다면, 이 글이 조금이나마 도움이 되었으면 좋겠네요. 💡

    ArgoCD와 GitOps의 전체 아키텍처는 위 그림처럼 구성됩니다. Git을 중심으로 모든 것이 돌아가는 모습을 보실 수 있어요.

    왜 ArgoCD와 GitOps인가요? – 삽질 끝에 찾은 안정성

    저도 처음에는 Jenkins 같은 전통적인 CI/CD 툴로 쿠버네티스 배포를 시도했어요. 하지만 배포 스크립트 관리도 어렵고, 배포 이력 추적도 쉽지 않더라고요. 특히 긴급 롤백(Rollback) 상황에서는 정말 아찔한 경험도 많았습니다. 😱

    GitOps는 쉽게 말해, Git을 인프라의 ‘단 하나의 진실된 소스(Single Source of Truth)’로 삼는 운영 방식입니다. 모든 인프라와 애플리케이션의 상태를 Git 리포지토리(Repository)에 코드(Code)로 저장하고, Git에 변경사항이 푸시(Push)되면 자동으로 인프라에 반영하는 방식이죠. ArgoCD는 이 GitOps 철학을 쿠버네티스 환경에서 구현해주는 강력한 선언적(Declarative) GitOps 지속적 배포(Continuous Delivery) 툴입니다.

    ArgoCD는 쿠버네티스 클러스터(Cluster) 내부에서 동작하면서, Git 리포지토리의 상태와 실제 클러스터의 상태를 계속 비교합니다. 만약 두 상태가 다르면, Git 리포지토리의 상태(원하는 상태)로 클러스터의 상태를 동기화(Sync)하려고 시도하죠. 이걸 풀 기반(Pull-based) 배포라고 하는데, 기존의 푸시 기반(Push-based) CI/CD 방식보다 훨씬 안정적이고 보안에도 유리합니다. 직접 써보니, 이 방식이 정말 믿음직하더라고요. ✅

    ArgoCD와 GitOps, 쉽게 이해하기

    복잡하게 생각할 것 없이, GitOps는 우리가 늘 쓰던 Git으로 인프라도 관리하자는 이야기입니다. 애플리케이션 코드를 Git으로 관리하듯이, 쿠버네티스 매니페스트(Manifest) 파일들도 Git에 넣고 관리하는 거죠. 이렇게 하면 다음과 같은 장점들이 생깁니다.

    • 버전 관리(Version Control): 모든 변경 이력이 Git에 남으니, 누가 언제 무엇을 바꿨는지 명확하게 알 수 있습니다.
    • 롤백(Rollback) 용이: 문제가 생기면 Git 커밋(Commit)을 되돌리는 것만으로 이전 상태로 쉽게 돌아갈 수 있습니다.
    • 감사(Auditing) 및 보안 강화: 모든 변경이 Git을 통해 이루어지므로, 승인된 변경만 반영될 수 있도록 워크플로우(Workflow)를 구축하기 좋습니다.
    • 단일 진실 공급원(Single Source of Truth): 개발, 운영팀 모두 Git만 보면 현재 인프라 상태를 파악할 수 있습니다.

    ArgoCD는 이 GitOps를 쿠버네티스에서 실현시켜주는 컨트롤러(Controller)입니다. 주요 특징은 다음과 같아요.

    • 선언적(Declarative) 관리: 원하는 상태를 YAML 파일로 선언해두면, ArgoCD가 알아서 그 상태를 유지합니다.
    • 자동 동기화(Automatic Synchronization): Git 리포지토리의 변경을 감지하고 자동으로 클러스터에 반영할 수 있습니다.
    • 시각적인 UI: 웹 UI를 통해 애플리케이션의 배포 상태, 리소스(Resource) 현황, 동기화 이력 등을 한눈에 확인할 수 있습니다. 저처럼 눈으로 확인해야 직성이 풀리는 사람에겐 정말 최고더라고요.
    • 다양한 배포 전략 지원: 롤링 업데이트(Rolling Update), 카나리 배포(Canary Deployment), 블루/그린 배포(Blue/Green Deployment) 등 다양한 배포 전략을 연동하여 구현할 수 있습니다.

    프로덕션 환경을 위한 ArgoCD 설정 팁

    이제 본격적으로 프로덕션 환경에서 ArgoCD를 효과적으로 사용하는 베스트 프랙티스를 공유해볼게요. 제가 직접 겪으면서 터득한 노하우들이니, 꼭 참고하시면 좋겠습니다.

    1. Git Repository 구조화: Monorepo vs. Multirepo

    Git 리포지토리를 어떻게 구성할지는 GitOps 전략의 첫 단추입니다. 크게 모노레포(Monorepo)와 멀티레포(Multirepo) 두 가지 방식이 있어요.

    • 모노레포(Monorepo): 모든 애플리케이션과 인프라 설정 파일을 하나의 Git 리포지토리에 저장하는 방식입니다. 초기 설정이 간단하고, 모든 것을 한곳에서 관리할 수 있다는 장점이 있습니다.
    • 멀티레포(Multirepo): 각 애플리케이션이나 환경별로 별도의 Git 리포지토리를 사용하는 방식입니다. 팀별 권한 분리나 대규모 서비스 운영에 유리할 수 있습니다.

    저 같은 경우, 초기에는 모노레포로 시작했다가 규모가 커지면서 멀티레포 형태로 전환했어요. 하지만 ArgoCD를 통해 여러 애플리케이션을 관리할 때는 애플리케이션별 Git 리포지토리 + 인프라 설정용 Git 리포지토리를 분리하는 방식이 가장 효율적이라고 느꼈습니다. 프로덕션 환경에서는 GitOps 보안과 관리의 용이성을 위해 인프라 설정과 애플리케이션 코드를 분리하는 것을 추천합니다.

    예시: 인프라 설정 Git 리포지토리 구조

    ├── applications # ArgoCD Application 정의
    │   ├── app1.yaml
    │   ├── app2.yaml
    │   └── ...
    ├── environments
    │   ├── dev
    │   │   ├── kustomization.yaml
    │   │   ├── namespace.yaml
    │   │   └── ...
    │   ├── stage
    │   │   ├── kustomization.yaml
    │   │   └── ...
    │   └── prod
    │       ├── kustomization.yaml
    │       └── ...
    └── base # 공통 설정
        ├── deployment.yaml
        ├── service.yaml
        └── ...
    

    위 다이어그램은 제가 주로 사용하는 Git Repository 구조를 시각적으로 보여줍니다. 환경별로 설정을 분리하고, 공통 설정은 base에 두는 방식이에요.

    2. 환경별 분리 및 Kustomize/Helm 활용

    개발(dev), 스테이징(stage), 프로덕션(prod) 환경은 각각 다른 설정(리소스 요구 사항, 환경 변수 등)을 가집니다. 이를 효과적으로 관리하려면 Kustomize나 Helm을 적극적으로 활용해야 합니다.

    • Kustomize: 기존 YAML 파일을 수정하지 않고 덮어쓰기(Overlay) 방식으로 환경별 설정을 관리하는 데 매우 유용합니다. base 디렉터리에 공통 설정 파일을 두고, 각 환경별 overlays 디렉터리에서 필요한 부분만 변경하는 방식은 정말 깔끔하죠.
    • Helm: 재사용 가능한 쿠버네티스 애플리케이션 패키징(Packaging) 도구입니다. 데이터베이스(Database)나 메시지 큐(Message Queue)처럼 공통적으로 사용되는 미들웨어(Middleware)를 배포할 때 매우 편리합니다. 저도 처음엔 Helm이 좀 어렵게 느껴졌는데, 익숙해지니 없으면 안 되는 존재가 되더라고요.

    ArgoCD 애플리케이션 정의에서 Kustomize나 Helm을 소스(Source)로 지정하면, ArgoCD가 알아서 해당 툴을 사용해서 매니페스트를 렌더링(Rendering)하고 배포해줍니다. 🚀

    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: my-app-prod
      namespace: argocd
    spec:
      project: default
      source:
        repoURL: https://github.com/my-org/my-infra-gitops.git
        targetRevision: HEAD
        path: environments/prod/my-app # Kustomize overlay 경로
      destination:
        server: https://kubernetes.default.svc
        namespace: my-app-prod
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
          - CreateNamespace=true
    

    3. Sync Options와 Health Checks

    ArgoCD의 syncPolicy는 배포의 안정성을 결정하는 중요한 부분입니다. 프로덕션 환경에서는 다음 옵션들을 신중하게 설정해야 합니다.

    • automated.prune: true: Git 리포지토리에서 삭제된 리소스를 클러스터에서도 자동으로 삭제합니다. 클러스터의 불필요한 리소스 잔여물을 방지해줍니다.
    • automated.selfHeal: true: 클러스터의 상태가 Git 리포지토리의 상태와 다를 경우, ArgoCD가 자동으로 Git의 상태로 되돌립니다. 누군가 수동으로 클러스터 설정을 변경했을 때 원래대로 복구해주는 강력한 기능이죠. GitOps의 핵심 정신과 일치하는 부분입니다.
    • syncOptions: - CreateNamespace=true: 해당 네임스페이스(Namespace)가 없으면 ArgoCD가 자동으로 생성하도록 합니다.
    • 커스텀 헬스 체크(Custom Health Checks): 애플리케이션이 단순히 배포되었다고 끝이 아닙니다. 실제로 정상 작동하는지 확인하는 헬스 체크가 중요하죠. ArgoCD는 기본적으로 Pod의 Readiness/Liveness Probe를 활용하지만, 경우에 따라 ConfigMap에 커스텀 헬스 체크를 정의하여 더 정교한 상태 감지를 할 수 있습니다.

    4. Rollback 전략

    아무리 잘 준비해도 문제는 발생하기 마련이죠. 이때 빠르고 안전하게 롤백하는 것이 중요합니다. ArgoCD 환경에서의 롤백은 크게 두 가지 방식이 있어요.

    1. Git Revert: 가장 권장되는 방식입니다. 문제가 발생한 커밋을 Git에서 되돌리면(Revert) ArgoCD가 이를 감지하고 자동으로 이전 상태로 클러스터를 동기화합니다. 이 방식은 Git의 변경 이력이 그대로 남으므로 감사 추적에도 유리합니다.
    2. ArgoCD UI 롤백: ArgoCD 웹 UI에서 특정 애플리케이션의 History and Rollback 탭을 통해 이전 동기화 지점(Sync Point)으로 롤백할 수 있습니다. 긴급 상황에서 빠르게 대처할 수 있는 방법이지만, Git의 변경 이력에는 남지 않으므로 나중에 Git Revert로 맞춰주는 게 좋습니다.

    저도 예전에 새벽에 긴급 롤백을 해야 했던 적이 있었는데, Git Revert 하나로 모든 상황이 깔끔하게 정리되었을 때의 안도감이란… 정말 겪어봐야 알 수 있습니다. 👍

    GitOps 보안 강화: ArgoCD 프로덕션 환경 보안 설정

    프로덕션 환경에서는 GitOps 보안이 최우선 고려사항입니다. ArgoCD를 통해 모든 것이 배포되므로, ArgoCD 자체의 보안 설정은 물론 주변 환경과의 연동도 중요합니다.

    1. RBAC (Role-Based Access Control)

    ArgoCD는 자체적인 RBAC(Role-Based Access Control)를 지원합니다. 이를 통해 누가 어떤 애플리케이션을 조회, 동기화, 삭제할 수 있는지 세밀하게 권한을 제어할 수 있어요. argocd-cm ConfigMap이나 argocd-rbac-cm ConfigMap을 수정하여 정책을 정의합니다.

    또한, ArgoCD 프로젝트(Project)를 활용하여 애플리케이션들을 논리적으로 묶고, 프로젝트별로 RBAC 정책을 적용하면 관리 효율성과 보안을 동시에 잡을 수 있습니다. 예를 들어, 개발팀은 dev-project에만 접근 가능하고, 운영팀은 prod-project에만 접근 가능하도록 설정하는 식이죠.

    # argocd-rbac-cm ConfigMap 예시
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: argocd-rbac-cm
      namespace: argocd
    data:
      policy.csv: |
        p, role:admin, applications, *, */*, allow
        p, role:dev, applications, get, dev-project/*, allow
        g, myuser, role:dev
      policy.default: role:readonly
    

    2. Secret Management (외부 Secret 연동)

    민감한 정보인 시크릿(Secret)을 Git 리포지토리에 평문으로 저장하는 것은 절대 금물입니다. 🙅‍♂️ GitOps 보안을 위해 외부 시크릿 관리 솔루션과 연동하는 것이 필수입니다.

    • Sealed Secrets: 클러스터에 배포된 컨트롤러가 시크릿을 암호화하고, Git에 암호화된 시크릿을 저장합니다. 암호화된 시크릿은 해당 클러스터에서만 복호화(Decrypt)될 수 있어 안전합니다. 제가 홈랩에서도 가장 즐겨 쓰는 방식이에요.
    • External Secrets Operator: AWS Secrets Manager, Azure Key Vault, Google Secret Manager, HashiCorp Vault 등 클라우드(Cloud) 기반 시크릿 관리 서비스와 연동하여 시크릿을 쿠버네티스 시크릿으로 동기화합니다. 프로덕션 환경에서는 이 방식이 가장 일반적입니다.

    어떤 방법을 선택하든, 절대 시크릿을 Git에 직접 올리는 일은 없어야 합니다! 이건 제가 정말 피땀 흘려 배운 교훈입니다. ⚠️

    3. Private Repository 접근

    대부분의 프로덕션 환경에서는 프라이빗 Git 리포지토리(Private Git Repository)를 사용합니다. ArgoCD가 이 리포지토리에 접근하려면 인증 정보가 필요하겠죠. 다음 방법들을 사용할 수 있습니다.

    • SSH 키(SSH Key): 가장 일반적이고 강력한 방법입니다. ArgoCD에 SSH 키를 등록하고, 해당 키를 사용하여 리포지토리에 접근합니다.
    • HTTPS with Username/Password 또는 Personal Access Token (PAT): Git 서비스에서 발급받은 PAT를 ArgoCD에 등록하여 사용할 수 있습니다. 보안상 일반적인 비밀번호보다는 PAT를 사용하는 게 좋습니다.

    인증 정보를 ArgoCD에 등록할 때는 쿠버네티스 시크릿으로 안전하게 관리해야 합니다. 당연한 이야기지만, 이걸 놓쳐서 문제가 되는 경우를 꽤 많이 봤거든요. 😅

    ArgoCD 트러블슈팅: 제가 겪었던 문제들 (그리고 해결책)

    13년차 엔지니어라고 해도 삽질은 피할 수 없는 운명이죠. ArgoCD를 쓰면서도 여러 번 머리를 쥐어뜯었습니다. 몇 가지 흔한 문제와 해결책을 공유해볼게요.

    • 문제: ImagePullBackOff 에러 (프라이빗 레지스트리)
      상황: 배포된 Pod에서 프라이빗 컨테이너 이미지 레지스트리(Private Container Image Registry)의 이미지를 당겨오지 못하고 ImagePullBackOff 에러가 발생하는 경우.
      해결: 해당 네임스페이스에 ImagePullSecrets를 제대로 설정했는지 확인해야 합니다. ArgoCD 애플리케이션이 배포될 때 이 시크릿이 같이 생성되도록 매니페스트에 포함하거나, 수동으로 시크릿을 생성하고 Pod Spec에 추가해야 합니다. 저는 주로 ArgoCD가 CreateNamespace=true와 함께 시크릿도 함께 배포하도록 설정합니다.

    • 문제: Resource is not available 또는 Failed to install CRD
      상황: 애플리케이션 배포 시 커스텀 리소스 정의(CRD: Custom Resource Definition)가 먼저 설치되어야 하는데, 순서가 맞지 않아 발생하는 에러.
      해결: ArgoCD의 Sync Waves 기능을 활용하면 배포 순서를 제어할 수 있습니다. CRD를 먼저 배포하고, 그 이후에 CRD를 사용하는 애플리케이션 리소스를 배포하도록 설정하는 거죠. 예를 들어, CRD는 sync-wave: "-1", 일반 리소스는 sync-wave: "0"으로 설정하면 됩니다. 이 기능을 알게 된 후로 정말 속이 시원했습니다. 🎉

    • 문제: 롤백 후에도 문제가 지속됨
      상황: Git Revert나 ArgoCD UI 롤백을 했는데도 애플리케이션이 정상 상태로 돌아오지 않는 경우.
      해결: 롤백 대상이 되는 커밋이 정말 이전의 ‘정상’ 상태를 가리키는지 확인해야 합니다. 때로는 환경 변수나 외부 의존성(예: 데이터베이스 스키마 변경) 때문에 롤백만으로는 해결되지 않을 수 있거든요. 이럴 때는 문제 발생 시점을 정확히 파악하고, 관련된 모든 변경사항(Git, DB 스키마, 외부 서비스 설정 등)을 함께 되돌려야 합니다. 그리고 롤백 후 ArgoCD UI에서 애플리케이션의 Health 상태와 Events 탭을 꼼꼼히 확인하는 습관을 들이는 게 좋습니다.

    결과 및 검증: 안정적인 배포, 이제 Git만 바라봅니다.

    ArgoCD와 GitOps 베스트 프랙티스를 적용하고 나니, 정말 배포 과정이 안정적이고 예측 가능해졌습니다. 더 이상 불안에 떨며 배포 버튼을 누를 필요가 없어졌죠. ✅

    배포가 완료되면 ArgoCD 웹 UI에서 각 애플리케이션의 상태를 한눈에 확인할 수 있습니다. 모든 리소스가 Healthy 상태이고, Synced 상태인지 확인하는 것이 중요해요. 혹시 OutOfSync 상태라면, 어떤 리소스가 Git과 다른지 명확하게 보여주므로 문제 파악이 매우 쉽습니다. 이 시각적인 피드백(Feedback) 덕분에 트러블슈팅 시간도 대폭 줄었습니다.

    ArgoCD UI에서 모든 애플리케이션이 건강하고(Healthy) 동기화(Synced)된 상태를 보여주는 화면입니다. 이 화면을 볼 때마다 뿌듯하더라고요!

    실제로 저는 홈랩에서 여러 서비스를 ArgoCD로 관리하고 있는데, Git에 커밋만 하면 알아서 배포가 되고, 문제가 생겨도 Git Revert 한 번으로 해결되는 경험은 정말 혁신적이었습니다. CI/CD 파이프라인의 완성도를 높이는 데 ArgoCD가 결정적인 역할을 했다고 생각합니다.

    ArgoCD GitOps를 프로덕션 환경에 적용하기 위한 핵심 베스트 프랙티스를 요약한 인포그래픽입니다.

    마무리: GitOps 여정, 계속됩니다

    오늘은 ArgoCD 프로덕션 환경 GitOps 베스트 프랙티스에 대해 저의 경험을 바탕으로 이야기해봤습니다. 안정적인 배포와 GitOps 보안 강화를 위해 Git 리포지토리 구조화, 환경별 설정 관리, Sync Policy, 롤백 전략, RBAC, 시크릿 관리 등 다양한 측면을 다루었네요.

    처음에는 복잡하게 느껴질 수도 있지만, 한 번 제대로 구축해두면 개발팀과 운영팀 모두에게 엄청난 효율성과 안정성을 가져다줄 겁니다. 저도 아직 배워야 할 것이 많고, 계속해서 새로운 기술을 실험하고 있습니다. 이 글이 여러분의 쿠버네티스 배포 여정에 작은 등불이 되기를 바랍니다. 궁금한 점이나 공유하고 싶은 삽질 경험이 있다면 언제든지 댓글로 남겨주세요! 다음에는 ArgoCD와 함께 CI/CD 파이프라인을 더욱 자동화하는 방법에 대해 다뤄보겠습니다. 그때까지 모두 즐거운 서버실 라이프 즐기시길 바랍니다! 😊