13년차의 서버실

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

[태그:] Flux CD

  • [Cloud] Flux CD 마이그레이션 경험기: Argo CD와 비교하며

    [Cloud] Flux CD 마이그레이션 경험기: Argo CD와 비교하며

    13년차 인프라 엔지니어의 GitOps 전환기: Flux CD 마이그레이션과 Argo CD 비교

    안녕하세요! 13년차 인프라 엔지니어입니다. 오늘은 많은 분들이 관심을 갖고 계신 Flux CD 마이그레이션 경험에 대해 얘기해볼까 합니다. 기존에 Argo CD를 쓰다가 Flux CD로 전환을 고민 중이신 분들이나 이제 막 GitOps를 시작하려는 분들께 제 경험이 도움이 되길 바랍니다. 저도 처음에는 두 도구 사이에서 정말 많이 고민했거든요. 😅

    쿠버네티스 환경에서 애플리케이션 배포를 자동화하는 GitOps는 이제 선택이 아닌 필수가 되어가고 있습니다. Git 저장소를 단일 진실 공급원(Single Source of Truth)으로 삼아 인프라와 애플리케이션의 상태를 관리하는 방식인데요. 이 GitOps 워크플로우를 구현하는 데 핵심적인 역할을 하는 도구가 바로 Argo CD와 Flux CD입니다. 오늘은 이 두 도구를 비교하며, 제가 Flux CD v2로 마이그레이션하면서 겪었던 실제 경험과 배운 점들을 솔직하게 공유해볼게요.

    GitOps 아키텍처 개요 다이어그램: Git 저장소, GitOps 컨트롤러, 쿠버네티스 클러스터 간의 동기화 흐름

    GitOps의 기본적인 흐름과 도구의 역할을 보여주는 아키텍처 다이어그램입니다.

    1. GitOps와 CI/CD 도구, 왜 이렇게 중요할까요?

    개발자라면 누구나 ‘배포’라는 단어에 복잡한 감정을 느낄 겁니다. 빠르고 정확하게 배포하고 싶지만, 현실은 늘 예상치 못한 문제들로 가득하죠. 수동 배포는 실수를 유발하기 쉽고, 스크립트 기반 자동화는 관리 포인트가 자꾸 늘어납니다. GitOps는 이런 고민을 해결해주는 강력한 방법론입니다. Git 저장소를 통해 인프라와 애플리케이션의 상태를 선언적으로 관리하기 때문에, 누가 언제 무엇을 바꿨는지 명확하게 추적할 수 있고, 문제가 생기면 이전 상태로 롤백하기도 쉬워요. 롤백? 네, Git 커밋 하나면 끝입니다! 🎉

    이런 GitOps 환경을 구축할 때 Argo CD와 Flux CD는 대표적인 선택지입니다. 두 도구 모두 Git 저장소의 상태와 쿠버네티스 클러스터의 실제 상태를 동기화하는 역할을 하지만, 동작 방식이나 기능, 설정 방법 등에서 확실히 달라요. 제가 Flux CD로 마이그레이션하게 된 배경도 이런 차이점들과 저희 팀의 특정 요구사항 때문이었습니다.

    2. Argo CD vs Flux CD: 핵심 개념 비교

    마이그레이션 얘기를 시작하기 전에, 두 도구의 기본적인 차이를 짚고 넘어가겠습니다. 쉽게 말해, Argo CD는 Pull 방식에 집중하고, Flux CD는 GitOps Toolkit이라는 모듈식 접근 방식을 사용합니다.

    Argo CD는 클러스터 내부에 설치되어 Git 저장소를 주기적으로 폴링(polling)하며 변경 사항을 감지합니다. 사용자는 Argo CD UI나 CLI를 통해 Git 저장소와 클러스터의 동기화 상태를 쉽게 확인하고 관리할 수 있죠. 다양한 Git provider와의 통합이 잘 되어 있고, 사용자 친화적인 웹 UI가 강점입니다.

    반면 Flux CD는 GitOps Toolkit이라는 여러 컴포넌트(Source Controller, Kustomize Controller, Helm Controller, Notification Controller 등)로 구성돼 있어요. 각 컴포넌트가 특정 역할을 수행하며, 필요한 컴포넌트만 선택적으로 구성할 수 있습니다. Flux CD는 Git 저장소를 주기적으로 폴링하기보다는 Git hook이나 내부 Controller를 통해 변경 사항을 감지하는 방식을 선호하며, 좀 더 세밀한 제어가 가능하다는 특징이 있어요. 특히 Flux CD v2부터는 이런 모듈식 아키텍처가 훨씬 강화됐습니다.

    구분 Argo CD Flux CD (v2)
    아키텍처 단일 컨트롤러 기반 모듈식 GitOps Toolkit (Source, Kustomize, Helm Controller 등)
    설정 방식 Application CRD, UI, CLI Kustomization/HelmRelease CRD, CLI
    동기화 방식 주기적 폴링 (기본), Git hook 지원 Git hook (권장), 주기적 폴링
    UI 풍부하고 사용자 친화적인 웹 UI CLI 중심, 웹 UI는 제한적 (지속 개선 중)
    확장성/유연성 높음 매우 높음 (모듈식)
    학습 곡선 비교적 완만함 초기 학습 곡선 있음 (GitOps Toolkit 이해 필요)
    Flux CD v2 GitOps Toolkit 구성 요소 다이어그램: Source, Kustomize, Helm Controller 등 모듈 설명

    Flux CD v2의 핵심 컴포넌트인 GitOps Toolkit의 구조를 나타내는 다이어그램입니다.

    3. Flux CD v2 마이그레이션 여정: 삽질과 깨달음 😅

    저희는 기존에 Argo CD를 잘 사용하고 있었어요. 하지만 몇 가지 이유로 Flux CD v2로의 전환을 결정했습니다. 첫째, 클러스터의 상태를 좀 더 세밀하게 제어하고 싶다는 생각이 들었어요. Flux CD의 모듈식 아키텍처가 이런 요구를 충족해줄 수 있다고 판단했거든요. 둘째, Helm Chart 관리를 더 효율적으로 하고 싶었는데, Flux CD의 Helm Controller가 이를 잘 지원한다는 정보를 얻었습니다.

    마이그레이션 단계는 크게 다음과 같았습니다.

    1. Flux CD 설치 및 기본 설정: 먼저 클러스터에 Flux CD v2를 설치했어요. bootstrapping 과정을 통해 Git 저장소와 연결하고, 초기 동기화 설정을 완료합니다. 이때 Git 저장소의 디렉토리 구조나 접근 권한 등을 꼼꼼히 확인해야 했습니다.
    2. 기존 Argo CD 애플리케이션 전환: Argo CD에서 관리하던 Kubernetes Manifests (YAML 파일)나 Helm Charts를 Flux CD가 인식할 수 있는 형태로 변경했습니다. 저는 주로 Kustomize를 사용하고 있었기 때문에, Flux CD의 Kustomization Controller가 참조할 수 있도록 Git 저장소 구조를 조정하는 작업이 필요했어요.
    3. Helm Chart 관리 전환: Argo CD에서 Helm Release를 사용했다면, Flux CD의 Helm Controller를 사용하도록 설정 파일을 변경합니다. Helm Chart의 `values.yaml` 파일 관리 방식이나 Release 이름, 네임스페이스 등을 Flux CD의 `HelmRelease` CRD(Custom Resource Definition)에 맞게 수정해야 했어요. 이 과정에서 몇 가지 오타와 설정 누락으로 배포가 실패하는 경험도 했습니다. ⚠️
    4. 동기화 방식 검토 및 적용: Git hook을 사용할지, 주기적인 폴링을 사용할지 결정하고 설정했어요. 보안과 효율성을 고려했을 때 Git hook이 낫다고 판단하여, Git Provider (GitHub/GitLab 등)와 Flux CD 간의 Webhook 설정을 진행했습니다.
    5. 검증 및 테스트: 모든 설정이 완료된 후, 실제 애플리케이션 배포 및 업데이트를 반복적으로 테스트했습니다. 변경 사항이 제대로 Git에 반영되고, Flux CD가 이를 감지하여 클러스터에 적용하는지, 롤백은 잘 되는지 등을 꼼꼼히 확인했어요.
    Flux CD CLI를 이용한 Git 저장소 부트스트랩 및 초기 설정 화면

    Flux CD CLI를 사용하여 Git 저장소와 클러스터를 연결하고 초기 설정을 진행하는 과정의 일부입니다.

    4. ⚠️ 주의사항 및 트러블슈팅 경험

    마이그레이션 과정에서 몇 가지 예상 밖의 문제들을 겪었어요. 여러분도 이런 상황에 마주칠 수 있으니 미리 알아두시면 좋을 겁니다.

    • Git 저장소 구조 및 권한 문제: Flux CD는 Git 저장소의 특정 경로를 바라보고 동기화합니다. 처음에는 Git 저장소 구조를 Argo CD 방식 그대로 사용하려다 보니 Flux CD가 파일을 제대로 찾지 못하더라고요. Git 저장소 구조를 Flux CD가 이해하기 쉬운 형태로 재구성하는 게 중요했습니다. 또한 Git 저장소에 대한 클러스터의 접근 권한 (SSH Key 또는 Access Token) 설정이 올바르지 않으면 동기화 자체가 실패합니다.
    • HelmRelease CRD 설정 오류: Helm Chart를 관리할 때 `HelmRelease` CRD의 필드 이름을 잘못 입력하거나, 필수 값을 누락하는 경우가 있었어요. 예를 들어, `chart.spec.version` 대신 `chart.version`으로 잘못 입력한다거나, `releaseName`을 지정하지 않아 예상치 못한 이름으로 Helm Release가 생성되는 등의 문제가 발생했습니다. Flux CD의 공식 문서를 옆에 끼고 설정하는 걸 추천합니다.
    • Controller 간의 의존성 문제: Flux CD v2는 여러 Controller가 협력하여 동작합니다. Source Controller가 Git 저장소에서 소스를 가져오면, Kustomize Controller나 Helm Controller가 이를 받아 실제 리소스를 생성/업데이트하는 식이죠. Source Controller에 문제가 생기면 후속 Controller들도 제대로 동작하지 않아요. Flux CD의 각 Controller 상태를 `flux get kustomization`, `flux get helmrelease` 같은 명령어로 자주 확인하는 습관이 중요합니다.
    • 네임스페이스 (Namespace) 관리: Argo CD에서는 Application CRD에 네임스페이스를 지정하는 방식이 Flux CD의 `HelmRelease`나 `Kustomization` CRD와 조금 달라요. 기존 Argo CD에서 여러 네임스페이스에 걸쳐 리소스를 관리하고 있었다면, Flux CD에서는 각 CRD에 네임스페이스를 명확히 지정해주거나, Git 저장소 구조를 네임스페이스별로 분리하는 전략이 필요했습니다.

    가장 큰 삽질은 아마 Helm Chart의 `values.yaml`을 GitOps 방식으로 관리하면서 발생했던 버전 충돌 문제였어요. Git 저장소에서 Helm Chart를 가져오고, 이를 Kustomize로 패치하는 과정에서 버전 관리가 꼬여버렸거든요. 결국에는 Flux CD의 **`HelmRelease` CRD 내에서 `valuesFrom` 필드를 활용하여 Git 파일 참조 방식을 명확히 지정**해주고, Kustomize를 통한 패치보다는 `HelmRelease` 자체에서 값을 관리하는 방식으로 변경했어요. 이게 가장 큰 깨달음 중 하나였습니다. 💡

    Flux CD CLI를 이용한 동기화 상태 및 리소스 정보 확인 화면

    Flux CD의 CLI 명령어로 확인한 동기화 상태 및 리소스 정보를 보여주는 화면입니다.

    5. Flux CD 마이그레이션 결과: 뭐가 달라졌나? ✅

    Flux CD v2로 성공적으로 마이그레이션한 후, 저희는 몇 가지 긍정적인 변화를 경험했어요.

    • 향상된 모듈성과 유연성: GitOps Toolkit 덕분에 필요한 기능만 선택적으로 활성화하고 설정할 수 있게 됐어요. 이건 클러스터 리소스 사용량을 최적화하는 데도 도움이 되더라고요.
    • 강력해진 Helm Chart 관리: Helm Controller를 통해 Helm Chart 버전을 관리하고, `values.yaml`을 GitOps 방식으로 선언적으로 관리하는 게 훨씬 수월해졌어요.
    • 세밀한 제어 기능: Git hook을 통한 실시간 동기화, Controller별 상태 확인 등 이전보다 클러스터 상태를 더 세밀하게 제어하고 모니터링할 수 있게 됐습니다.
    • 개발팀의 GitOps 경험 개선: Git 저장소에 대한 변경 사항이 자동으로 클러스터에 반영되는 경험은 개발팀의 만족도를 높였어요. Pull Request를 통해 변경 사항을 리뷰하고 머지하는 과정이 자연스럽게 CI/CD 파이프라인으로 통합됐거든요.

    물론, Argo CD의 풍부한 웹 UI가 제공하는 편함은 Flux CD에서는 조금 줄어들었어요. 하지만 CLI의 발전과 커뮤니티의 노력으로 많은 부분이 개선되고 있고, 저희 팀은 CLI 중심의 워크플로우에 금방 익숙해졌습니다. 오히려 **CLI의 강력한 자동화 가능성** 덕분에 더 많은 부분을 스크립트로 관리할 수 있게 된 점을 긍정적으로 보고 있어요.

    Flux CD 마이그레이션 이후 CI/CD 파이프라인의 성공률 및 배포 속도 개선 지표를 시각화한 그래프입니다.

    6. 마무리하며: Flux CD와 함께하는 GitOps 여정

    Flux CD로의 마이그레이션은 분명 쉽지 않은 과정이었어요. Argo CD와는 다른 철학과 구조를 가지고 있었기에, 새로운 학습이 필요했고 예상치 못한 문제들과도 많이 씨름했거든요. 하지만 결과적으로 저희 팀은 GitOps 환경을 더욱 견고하고 효율적으로 구축할 수 있었습니다.

    핵심은 각 도구의 철학을 이해하고, 우리 환경에 맞는 방식을 선택하는 것입니다.

    • 단순하고 직관적인 GitOps 환경을 원하고, 풍부한 웹 UI가 중요하다면 Argo CD가 좋은 선택이 될 거예요.
    • 세밀한 제어, 모듈성, 그리고 강력한 Helm/Kustomize 통합을 원한다면 Flux CD v2가 매력적인 대안이 될 겁니다.

    아직 GitOps를 도입하지 않으셨거나, CI/CD 도구 전환을 고민하고 계신다면, 오늘 제가 나눈 경험이 조금이라도 도움이 되었으면 좋겠어요. 다음 글에서는 Flux CD의 특정 기능 (예: Policy as Code, Observability)에 대해 더 깊이 파고드는 내용을 다룰 예정이니 기대해주세요!

    궁금한 점이 있다면 언제든지 댓글로 남겨주세요. 함께 성장하는 엔지니어들이 되겠습니다! 감사합니다. 😊

  • [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] Flux CD GitOps 파이프라인 구축: 안정적인 쿠버네티스 배포 자동화

    [k8s] Flux CD GitOps 파이프라인 구축: 안정적인 쿠버네티스 배포 자동화

    안녕하세요, 13년차 서버실 지킴이입니다. 오늘은 많은 인프라 엔지니어분들이 한 번쯤은 고민해봤을 주제, 바로 쿠버네티스(Kubernetes) 배포 자동화에 대해 이야기해보려고 합니다. 특히 GitOps(깃옵스) 방법론과 그 구현체 중 하나인 Flux CD(플럭스 CD)를 활용한 파이프라인 구축 경험을 공유해 드릴게요.

    혹시 이런 경험 있으신가요? 개발팀에서 “배포해주세요!” 요청이 들어오면, kubectl apply -f 명령어를 조심스럽게 입력하면서, “혹시나 다른 설정이 덮어씌워지는 건 아닐까?”, “이전 버전으로 되돌리려면 어떻게 해야 하지?” 같은 걱정을 했던 순간 말이죠. 저는 셀 수 없이 많습니다. 수동 배포는 휴먼 에러의 온상이었고, 배포하다 새벽을 맞이하는 일도 비일비재했거든요. 이런 삽질을 거듭하다가 GitOps를 만나고 나서야 비로소 안정적인 배포의 빛을 보게 되었습니다. 제 홈랩에서도 여러 서비스를 GitOps로 관리하고 있는데, 정말 편하더라고요!

    GitOps 파이프라인은 Git 저장소를 ‘진리의 단일 출처(Single Source of Truth)’로 삼아, 쿠버네티스 클러스터의 상태를 Git에 선언된 대로 유지하는 방식입니다. 간단히 말해, Git에 저장된 설정 파일이 곧 클러스터의 현재 상태여야 한다는 거죠.

    GitOps와 Flux CD, 정말 좋은 이유

    처음 GitOps라는 개념을 들었을 때는 “어차피 Git에 YAML 파일 올리는 건 똑같은데, 뭐가 다르지?” 싶었어요. 근데 실제로 써보니 이 방식이 가진 장점이 정말 많더라고요. 제가 느낀 가장 큰 장점들을 꼽아보면 이렇습니다.

    • 일관성(Consistency): 모든 설정이 Git에 있으니, 개발, 스테이징, 운영 환경 간의 차이를 최소화할 수 있어요. “제 환경에서는 잘 되는데요?” 하는 말이 확 줄어듭니다.
    • 감사 및 추적(Auditability & Traceability): Git 커밋(Commit) 기록 자체가 변경 이력이 되니까요. 누가, 언제, 무엇을 변경했는지 명확하게 알 수 있죠. 문제 발생 시 롤백(Rollback)도 Git으로 너무나 쉽습니다.
    • 안정성(Reliability): Git에 선언된 상태와 클러스터의 실제 상태가 다르면, GitOps 에이전트가 자동으로 클러스터를 Git의 상태로 되돌립니다. 마치 자가 치유(Self-healing) 능력 같달까요?
    • 생산성(Productivity): 수동 작업이 줄어들고 자동화되면서, 엔지니어는 더 중요한 일에 집중할 수 있게 됩니다.

    이런 GitOps의 철학을 구현하는 대표적인 도구가 바로 Flux CD입니다. Flux CD는 쿠버네티스 클러스터 내에서 동작하는 컨트롤러(Controller)들의 집합인데요, 주기적으로 Git 저장소를 감시하다가 변경 사항이 감지되면 자동으로 클러스터에 적용해주는 역할을 합니다. 주요 컴포넌트로는 Source Controller(소스 컨트롤러), Kustomize Controller(커스터마이즈 컨트롤러), Helm Controller(헬름 컨트롤러) 등이 있습니다.

    Flux CD GitOps 파이프라인 구축 실전 가이드

    자, 그럼 이제 제 홈랩에서 Flux CD를 어떻게 구축했는지, 단계별로 자세히 알려드릴게요. 저도 처음엔 공식 문서를 보면서 여러 번 헤맸는데, 이 가이드가 여러분의 삽질 시간을 줄여주길 바랍니다!

    1단계: 사전 준비 및 Flux CLI 설치

    먼저, 쿠버네티스 클러스터에 접근 가능한 환경과 kubectl, git이 설치되어 있어야 합니다. 저는 로컬 PC에 flux CLI(Command Line Interface)를 설치하는 것부터 시작했어요.

    # Flux CLI 설치 (macOS 기준)
    brew install fluxcd/flux/flux
    
    # 설치 확인
    flux --version
    # flux version 2.x.x (최신 버전으로 설치됩니다)
    
    # 클러스터에 Flux CD가 설치될 네임스페이스 생성 (선택 사항)
    kubectl create namespace flux-system
    

    flux-system 네임스페이스는 Flux CD 컨트롤러들이 배포될 기본 공간입니다. 따로 지정하지 않으면 기본으로 이 네임스페이스에 설치되죠.

    2단계: Git 저장소 준비

    Flux CD는 Git 저장소를 바라보며 작동하기 때문에, 쿠버네티스 설정 파일(YAML)들을 저장할 Git 저장소가 필요합니다. 저는 GitHub에 gitops-k8s-homelab이라는 프라이빗(Private) 저장소를 만들었어요. 저장소 안에는 다음과 같은 구조로 파일을 구성할 예정입니다.

    gitops-k8s-homelab/
    ├── clusters/
    │   └── my-cluster/
    │       ├── flux-system/
    │       │   └── gotk-components.yaml
    │       │   └── gotk-sync.yaml
    │       └── apps/
    │           └── my-app/
    │               └── kustomization.yaml
    ├── apps/
    │   └── my-app/
    │       ├── deployment.yaml
    │       ├── service.yaml
    │       └── ingress.yaml
    └── README.md
    

    clusters/my-cluster/flux-system 경로에는 Flux CD 자체의 설정 파일들이, clusters/my-cluster/apps 경로에는 클러스터에 배포할 애플리케이션들을 정의하는 Kustomization 파일들이 들어갈 겁니다. 실제 애플리케이션 YAML 파일들은 apps/my-app 경로에 두고요.

    3단계: Flux CD 부트스트랩 (Bootstrap)

    이제 가장 중요한 단계입니다. flux bootstrap github 명령어를 사용해서 Flux CD를 쿠버네티스 클러스터에 설치하고, Git 저장소와 연결하는 작업을 수행합니다. 이 명령 한 방으로 Flux CD가 클러스터에 필요한 모든 컴포넌트를 배포하고, 지정된 Git 저장소를 바라보도록 설정해줍니다. 저는 GitHub를 사용했으니 github 옵션을 사용했어요.

    # 환경 변수 설정 (개인 GitHub 토큰과 사용자명으로 대체하세요!)
    export GITHUB_TOKEN="YOUR_GITHUB_TOKEN" # Personal Access Token
    export GITHUB_USER="YOUR_GITHUB_USERNAME"
    
    # Flux CD 부트스트랩 실행
    flux bootstrap github \
      --owner=${GITHUB_USER} \
      --repository=gitops-k8s-homelab \
      --branch=main \
      --path=clusters/my-cluster \
      --personal
    

    이 명령을 실행하면 Flux CD가 클러스터에 설치되고, clusters/my-cluster 경로를 기준으로 Git 저장소의 내용을 동기화하기 시작합니다. --personal 옵션은 개인 저장소에 주로 사용하고, 조직(Organization) 저장소의 경우 --owner를 조직명으로 지정하고 SSH 키 방식으로 인증하는 것이 일반적입니다. 저는 홈랩이라 개인 토큰으로 편하게 작업했어요.

    부트스트랩이 완료되면, Git 저장소의 clusters/my-cluster/flux-system 경로에 Flux CD 자체의 Kustomization 파일들이 자동으로 생성되어 커밋되는 것을 볼 수 있습니다. 이게 바로 Flux CD가 스스로를 GitOps 방식으로 관리하는 모습이죠. 신기하더라고요!

    4단계: 애플리케이션 배포를 위한 Kustomization 정의

    이제 클러스터에 배포할 애플리케이션을 정의하고 Flux CD가 이를 인식하도록 설정할 차례입니다. 먼저, apps/my-app 경로에 간단한 NGINX 애플리케이션을 정의하는 YAML 파일들을 만듭니다.

    # apps/my-app/deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-nginx-app
      labels:
        app: my-nginx-app
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: my-nginx-app
      template:
        metadata:
          labels:
            app: my-nginx-app
        spec:
          containers:
          - name: nginx
            image: nginx:latest
            ports:
            - containerPort: 80
    ---
    # apps/my-app/service.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: my-nginx-app-service
    spec:
      selector:
        app: my-nginx-app
      ports:
      - protocol: TCP
        port: 80
        targetPort: 80
      type: ClusterIP
    

    그리고 이 애플리케이션을 클러스터에 배포하도록 지시하는 Kustomization 파일을 clusters/my-cluster/apps/my-app/kustomization.yaml 경로에 생성합니다.

    # clusters/my-cluster/apps/my-app/kustomization.yaml
    apiVersion: kustomize.toolkit.fluxcd.io/v1
    kind: Kustomization
    metadata:
      name: my-nginx-app
      namespace: flux-system
    spec:
      interval: 1m0s
      sourceRef:
        kind: GitRepository
        name: flux-system
      path: ./apps/my-app
      prune: true
      validation: client
    

    이 파일들을 Git 저장소에 커밋(Commit)하고 푸시(Push)합니다.

    git add .
    git commit -m "Add my-nginx-app and kustomization"
    git push origin main
    

    Flux CD는 clusters/my-cluster/flux-system/gotk-sync.yaml 파일에 정의된 Kustomization에 의해 clusters/my-cluster 경로를 1분마다 동기화합니다. 그러면 방금 추가한 clusters/my-cluster/apps/my-app/kustomization.yaml 파일이 클러스터에 적용되고, 이 Kustomization이 다시 apps/my-app 경로의 NGINX 애플리케이션을 클러스터에 배포하게 됩니다. 이 모든 과정이 자동으로 이뤄지는 거죠!

    ⚠️ 삽질 경험 & 트러블슈팅 팁

    제가 Flux CD를 사용하면서 겪었던 몇 가지 삽질과 해결 팁을 공유해 드릴게요. 여러분은 저처럼 헤매지 마시라고요! ㅎㅎ

    • 동기화 지연 문제: Git에 변경사항을 푸시했는데, 클러스터에 바로 적용이 안 되는 경우가 있습니다. Kustomization 리소스의 interval 값이 기본 10분으로 설정되어 있거나, 네트워크 문제 등으로 Git 저장소에 접근이 안 되는 경우가 많았어요. 급할 때는 다음 명령어로 강제 동기화를 시도합니다.
      flux reconcile kustomization my-nginx-app --with-source
      

      이 명령은 해당 Kustomization과 그 소스 GitRepository를 즉시 동기화하도록 Flux CD에 지시합니다.

    • Git Repository 구조 설계: 처음에는 모든 YAML 파일을 한 폴더에 때려 넣었는데, 나중에 애플리케이션이 많아지고 환경이 복잡해지면서 관리가 힘들어지더라고요. clusters/[클러스터이름]/[환경]/apps/[앱이름] 같은 계층적인 구조나, clusters와 apps를 분리하는 구조로 가져가는 것이 훨씬 효율적입니다. 저는 지금 clusters와 apps를 분리해서 관리하고 있어요.
    • 시크릿(Secret) 관리: 데이터베이스 비밀번호 같은 민감한 정보는 Git에 평문으로 올릴 수 없죠. 저는 SOPS(Secrets OPerationS)를 사용해서 Git 저장소에 암호화된 시크릿을 저장하고, Flux CD가 배포 시 자동으로 복호화하도록 설정했습니다. EKS(Elastic Kubernetes Service) 같은 클라우드 환경에서는 KMS(Key Management Service)를 연동해서 SOPS를 사용하는 것이 일반적입니다.
    • CRD(Custom Resource Definition) 적용 순서: 때로는 특정 컨트롤러나 미들웨어의 CRD가 먼저 클러스터에 적용되어야만 해당 리소스를 배포할 수 있습니다. 예를 들어, Istio(이스티오)나 Cert-Manager(서트 매니저) 같은 도구들이 그렇죠. 이런 경우, Kustomization의 dependsOn 필드를 사용하거나, healthChecks를 설정하여 의존성을 명확히 해주는 것이 중요합니다.

    ✅ 배포 결과 확인 및 검증

    이제 모든 설정이 잘 적용되었는지 확인해볼 시간입니다. flux get kustomizations 명령어로 Flux CD가 관리하는 Kustomization 리소스들의 상태를 확인할 수 있습니다.

    flux get kustomizations
    NAME            REVISION        SUSPENDED   READY   MESSAGE                                         LAST ACTIVITY
    flux-system     main/a1b2c3d4   False       True    Kustomization reconciled successfully           2026-05-15T10:00:00Z
    my-nginx-app    main/e5f6g7h8   False       True    Kustomization reconciled successfully           2026-05-15T10:01:00Z
    

    READY 상태가 True이고 MESSAGE에 성공 메시지가 보인다면, Flux CD가 정상적으로 작동하고 있다는 뜻입니다. 이제 쿠버네티스 클러스터에 NGINX 애플리케이션이 잘 배포되었는지 확인해볼까요?

    kubectl get deployment my-nginx-app
    NAME           READY   UP-TO-DATE   AVAILABLE   AGE
    my-nginx-app   2/2     2            2           5m
    
    kubectl get service my-nginx-app-service
    NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
    my-nginx-app-service     ClusterIP   10.96.100.123   <none>        80/TCP    5m
    

    🎉 드디어 성공입니다! my-nginx-app 배포가 정상적으로 2개의 레플리카(Replica)로 동작하고 있는 것을 확인할 수 있네요. 이제 Git 저장소의 apps/my-app/deployment.yaml 파일에서 replicas 수를 3으로 변경하고 푸시해보세요. 잠시 후 Flux CD가 이를 감지하고 자동으로 클러스터의 레플리카 수를 3으로 업데이트할 겁니다. 이 경험을 하고 나면 GitOps의 매력에서 헤어 나올 수 없을 거예요!

    GitOps는 이렇게 Git에 대한 변경만으로 클러스터의 상태를 관리할 수 있게 해줍니다. 저는 이 편리함 덕분에 홈랩에서 새로운 서비스를 배포할 때마다 kubectl 명령어를 직접 입력할 일이 거의 없어졌어요. 모든 변경사항은 Git에 기록되니, 누가 어떤 변경을 했는지도 명확하게 알 수 있고요. 정말 안정적이고 편리한 배포 파이프라인이 구축된 거죠.

    마무리하며: GitOps와 Flux CD, 현대 인프라의 필수 도구

    오늘은 13년차 인프라 엔지니어의 경험을 바탕으로 Flux CD GitOps 파이프라인 구축에 대해 상세히 이야기해봤습니다. 쿠버네티스 배포 자동화는 현대 인프라에서 선택이 아닌 필수가 되어가고 있습니다. 특히 GitOps는 그 중심에서 안정성, 일관성, 생산성이라는 세 마리 토끼를 동시에 잡을 수 있게 해주는 강력한 방법론이라고 생각합니다.

    물론 처음에는 GitOps 개념이나 Flux CD 사용법이 낯설고 어렵게 느껴질 수 있습니다. 저도 그랬거든요. 하지만 한 번 제대로 구축하고 나면, 인프라 관리의 패러다임이 확 바뀌는 것을 경험하실 수 있을 겁니다. 마치 수동으로 서버를 한 대 한 대 설치하다가 프로비저닝(Provisioning) 자동화를 접했을 때의 충격과 비슷하다고 할까요?

    다음 글에서는 오늘 다루지 못한 Helm Chart(헬름 차트)를 Flux CD로 관리하는 방법이나, 멀티 클러스터(Multi-cluster) 환경에서의 GitOps 전략, 그리고 SOPS를 이용한 시크릿 관리 등 좀 더 심화된 주제들을 다뤄볼 예정입니다. 이 글이 여러분의 쿠버네티스 여정에 작은 도움이 되었기를 바랍니다!

    궁금한 점이나 저의 삽질 경험에 대한 질문이 있으시면 언제든지 댓글 남겨주세요! 저도 계속 배우고 성장하는 중이거든요. 😊