본문 바로가기
IT/k8s

[k8s] ArgoCD 도입 실패 사례 분석: GitOps 전환 시 흔한 실수와 방지 전략

by 수누다 2026. 6. 23.

[DevOps] ArgoCD 도입 실패 사례 분석과 GitOps 실수 방지

ArgoCD 도입 실패 이야기는 생각보다 흔합니다. 저도 처음엔 GitOps(깃옵스, Git을 단일 진실 공급원으로 삼는 운영 방식)만 붙이면 배포가 깔끔해질 줄 알았거든요. 그런데 실제로 해보니, ArgoCD(아르고CD, Kubernetes 선언형 배포 도구)를 넣는 순간 오히려 배포가 더 복잡해지는 팀도 많았습니다. 특히 CI/CD 전환 사례를 보면, 기술 문제가 아니라 역할 분리, 저장소 구조, 승인 흐름 같은 운영 설계에서 먼저 무너지는 경우가 많더라고요. 이번 글은 제가 현업과 홈랩에서 반복해서 본 ArgoCD 도입 실패 패턴을 중심으로, 왜 그런 일이 생기는지와 어떻게 피해야 하는지를 정리해보겠습니다.

혹시 이런 경험 있으신가요? 배포 자동화는 넣었는데 누가 어떤 값을 바꿨는지 더 헷갈리고, 장애가 나면 Git이 문제인지 클러스터가 문제인지부터 추적하게 되는 상황 말입니다. 여기서 중요한 포인트는, ArgoCD 자체가 문제라기보다 GitOps 실수가 누적되면서 운영 복잡도가 폭발한다는 점입니다.

ArgoCD 도입 실패와 GitOps 전환 흐름을 설명하는 아키텍처 이미지

Git 저장소, CI 파이프라인, ArgoCD, Kubernetes 클러스터 사이의 흐름과 실패 포인트를 한눈에 보여주는 개요 이미지입니다.

1. 왜 ArgoCD 도입 실패가 반복될까요?

쉽게 말해 ArgoCD는 배포 버튼을 없애는 도구가 아니라, 변경 관리 방식 자체를 바꾸는 도구입니다. 그래서 예전 CI/CD에서는 잘 통하던 습관이 GitOps로 오면 바로 문제를 만듭니다. 예를 들면 이런 식입니다.

  • 운영값을 Git이 아니라 사람 손으로 클러스터에서 직접 수정함
  • 애플리케이션 코드 저장소와 배포 매니페스트 저장소의 책임이 불명확함
  • 자동 동기화(auto-sync)를 켰는데 승인 절차는 그대로 수동 운영을 기대함
  • Helm(헬름, Kubernetes 패키지 관리 도구) 값 파일이 환경별로 제멋대로 늘어남
  • 장애가 나도 누가 마지막 변경을 만들었는지 추적이 어려움

저도 처음엔 이게 뭔가 싶었는데, 결국 핵심은 하나였습니다. ArgoCD는 배포 도구이면서 동시에 운영 규율을 강제하는 도구라는 점입니다. 팀이 그 규율을 합의하지 않은 상태에서 도입하면, ArgoCD 문제점처럼 보이는 현상이 사실은 프로세스 문제로 터집니다.

2. GitOps와 ArgoCD를 아주 쉽게 설명해보면

GitOps는 “실제 운영 상태는 Git에 적힌 선언대로 맞춘다”는 철학입니다. ArgoCD는 그 선언과 클러스터 상태를 계속 비교해서 drift(드리프트, 선언과 실제 상태가 어긋난 상태)를 감지하고 맞춰주는 역할을 하죠.

예전 방식은 대체로 이랬습니다. CI 서버가 빌드하고, 누군가 kubectl(쿠버네티스 CLI)이나 Helm으로 운영 클러스터에 직접 배포합니다. 반면 GitOps 방식은 배포 변경도 Pull Request(PR, 변경 제안 요청)로 남고, 승인 후 Git이 바뀌면 ArgoCD가 그걸 따라갑니다. 감사 추적(audit trail, 변경 이력 추적)이 되는 대신, 우회 수정이 어려워집니다. 이 점이 장점이자 초반 저항 포인트입니다.

항목 기존 CI/CD GitOps + ArgoCD
배포 트리거 파이프라인 또는 운영자 수동 실행 Git 변경 반영
변경 이력 파이프라인 로그 중심 Git 커밋과 PR 중심
긴급 수정 클러스터에서 직접 수정 가능 직접 수정 시 drift 발생
권한 통제 클러스터 권한 중심 저장소 권한과 승인 흐름 중요
실패 원인 스크립트 불안정, 환경 차이 저장소 구조, 책임 분리 실패

그래서 ArgoCD 도입 실패를 줄이려면 설치보다 운영 모델을 먼저 설계해야 합니다. 이걸 건너뛰면 나중에 진짜 많이 돌아갑니다. 저도 삽질 좀 했습니다 ㅎㅎ

3. 실제로 많이 본 실패 사례 4가지

3-1. 저장소 구조를 너무 늦게 정한 경우

가장 흔한 실수입니다. 앱 소스와 배포 설정이 한 저장소에 섞여 있거나, 반대로 너무 잘게 쪼개져서 어디를 기준으로 봐야 하는지 모호한 경우죠. 처음엔 편해 보였는데, 팀이 커질수록 충돌이 심해집니다. 누가 이미지 태그를 관리하고, 누가 replica 수를 바꾸고, 누가 Ingress(인그레스, 외부 트래픽 진입점)를 수정하는지 경계가 안 잡히거든요.

3-2. 자동 동기화만 켜고 승인 체계를 안 만든 경우

auto-sync는 정말 편합니다. 드디어 됐다! 싶은 순간이 오거든요. 근데 여기서 바로 사고가 납니다. 운영 반영 전 검토가 필요한 팀인데도 자동 배포를 먼저 켜버리면, 잘못된 값 하나가 바로 프로덕션으로 갑니다. 도구는 빨라졌는데 프로세스는 그대로인 상태죠.

3-3. Secret 관리 방식을 정하지 않은 경우

GitOps 실수에서 빠지지 않는 항목입니다. 민감 정보(Secret)를 평문으로 저장하면 안 되고, 그렇다고 운영자가 클러스터에만 몰래 만들어두면 Git과 실제 상태가 분리됩니다. 저는 이 부분에서 팀마다 가장 오래 멈추는 걸 많이 봤습니다. Sealed Secrets(시일드 시크릿)나 External Secrets Operator 같은 접근을 검토하되, 핵심은 “Git에 무엇을 남기고 실제 값은 어디서 주입할지”를 팀 단위로 합의하는 겁니다.

3-4. Drift를 장애로 볼지, 운영 유연성으로 볼지 합의가 없는 경우

운영자가 급한 패치를 직접 넣는 문화가 남아 있으면 ArgoCD는 계속 OutOfSync(아웃오브싱크) 상태를 만들 겁니다. 이걸 경고로 볼지, 바로 되돌릴지, 특정 리소스는 예외로 둘지 정하지 않으면 경보만 쌓이고 신뢰가 깨집니다. 이 지점이 대표적인 ArgoCD 문제점처럼 보이는데, 사실은 정책 부재에 가깝습니다.

4. 실전 구현: 실패 확률을 낮추는 최소 전환 절차

제가 직접 해보니, 처음부터 전 서비스에 GitOps를 거는 것보다 작은 서비스 하나로 운영 규칙을 검증하는 게 훨씬 낫더라고요. 아래는 많이 무리하지 않는 최소 절차입니다.

  1. 배포 대상 네임스페이스(namespace) 하나를 파일럿으로 고릅니다.
  2. 애플리케이션 코드 저장소와 배포 매니페스트 저장소의 책임을 분리합니다.
  3. ArgoCD 프로젝트(AppProject)로 허용 대상 클러스터/네임스페이스를 제한합니다.
  4. 자동 동기화는 바로 켜지 말고, 먼저 수동 sync로 운영 흐름을 익힙니다.
  5. 변경 승인 기준을 PR 템플릿과 리뷰 규칙으로 문서화합니다.
  6. Drift 발생 시 대응 절차를 정합니다.

예시로는 아래처럼 시작하면 무난합니다.

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl get pods -n argocd

설치 자체보다 더 중요한 건 프로젝트 경계를 먼저 두는 일입니다.

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: sample-project
  namespace: argocd
spec:
  description: sample project for controlled GitOps rollout
  sourceRepos:
    - 'https://github.com/example/platform-manifests.git'
  destinations:
    - namespace: sample-app
      server: 'https://kubernetes.default.svc'
  clusterResourceWhitelist:
    - group: '*'
      kind: '*'

그 다음 애플리케이션은 이렇게 붙일 수 있습니다.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: sample-app
  namespace: argocd
spec:
  project: sample-project
  source:
    repoURL: 'https://github.com/example/platform-manifests.git'
    targetRevision: main
    path: apps/sample-app/overlays/prod
  destination:
    server: 'https://kubernetes.default.svc'
    namespace: sample-app
  syncPolicy: {}

여기서 일부러 자동 동기화 설정을 비워둔 것이 포인트입니다. 처음엔 수동 sync로 팀이 변경 흐름을 이해하게 만드는 게 좋습니다. 자동화는 익숙해진 뒤에 켜도 늦지 않습니다.

ArgoCD 도입 실패를 줄이기 위한 AppProject와 저장소 구조 구성 이미지

AppProject 경계, Application 연결, PR 승인 후 반영되는 흐름을 시각적으로 설명하는 이미지입니다.

5. CI/CD 전환 사례에서 특히 조심해야 할 체크포인트

기존 파이프라인에서 이미지 빌드까지는 잘 돌아가는데 GitOps로 넘기면서 꼬이는 경우가 많습니다. 보통 CI는 artifact(아티팩트, 배포 가능한 결과물)를 만들고, CD는 배포를 실행합니다. GitOps에선 이 경계가 바뀝니다. CI가 직접 배포하지 않고, 이미지 태그나 차트 값을 Git에 반영하는 식으로 역할이 이동하죠.

예를 들면 이런 방식입니다.

# CI job example
export IMAGE_TAG=${GIT_COMMIT_SHA}
sed -i "s/tag: .*/tag: ${IMAGE_TAG}/" apps/sample-app/overlays/prod/values.yaml
git add apps/sample-app/overlays/prod/values.yaml
git commit -m "chore: deploy sample-app ${IMAGE_TAG}"
git push origin main

이 방식은 단순하지만, 바로 main 브랜치에 반영하면 위험합니다. 제가 추천하는 건 별도 배포 브랜치나 PR 자동 생성 방식입니다. 사람이 마지막으로 한 번 더 보고 머지하는 흐름이 초반 안정화에 꽤 도움이 됩니다.

  • 프로덕션 반영은 PR 승인 후에만 가능하게 설정
  • 리뷰어를 플랫폼 담당자와 서비스 담당자로 분리
  • 롤백 기준을 Git revert 중심으로 문서화
  • 수동 kubectl 적용은 예외 상황에서만 허용

이런 기본선만 있어도 CI/CD 전환 사례에서 실패 확률이 꽤 내려갑니다.

6. ⚠️ 트러블슈팅: 제가 실제로 많이 본 문제와 해결법

여기서부터는 정말 많이 부딪히는 부분들입니다. 처음엔 저도 “왜 sync는 성공인데 앱은 안 뜨지?” 같은 상황을 자주 만났거든요.

증상 원인 해결 방향
OutOfSync가 계속 발생 운영자가 클러스터에서 직접 수정 직접 수정 금지 원칙 정리, 예외 리소스만 ignore 설정 검토
Sync 성공인데 서비스 장애 매니페스트 문법은 맞지만 런타임 의존성 누락 readinessProbe, Secret 참조, ConfigMap 값 검증 강화
배포가 너무 자주 일어남 이미지 태그나 공통 값 파일이 과도하게 변경됨 환경별 경로 분리, 변경 범위 최소화
리뷰 병목 발생 모든 변경이 한 저장소에 몰림 팀 단위 경계 재설계, CODEOWNERS 활용
롤백이 헷갈림 Git revert와 수동 핫픽스가 섞임 롤백 절차를 Git 기준으로 단일화

6-1. ignoreDifferences 남용

ArgoCD에는 특정 필드 차이를 무시하는 기능이 있습니다. 편하긴 한데, 이걸 남용하면 drift 감지 의미가 사라집니다. 정말 컨트롤러가 자동으로 바꾸는 필드처럼 불가피한 경우에만 제한적으로 쓰는 게 맞습니다.

6-2. Helm 값 파일 난립

환경이 늘수록 values 파일이 너무 많아집니다. dev, stage, prod는 그렇다 쳐도 팀별 패치, 긴급 패치, 지역별 패치가 늘어나면 나중에 아무도 구조를 설명 못 합니다. 저도 홈랩에서 비슷하게 풀었다가, 결국 Kustomize(커스터마이즈, 오버레이 기반 설정 관리)와 역할을 분리하면서 정리했었습니다.

6-3. 알림 없이 운영

Sync 실패나 Health degraded(헬스 저하) 이벤트를 아무도 못 받으면, ArgoCD UI를 매번 열어보기 전까지 장애를 놓치게 됩니다. 알림 체계는 초반부터 붙이는 게 좋습니다. 최소한 운영 채널로 실패 이벤트는 전달되게 구성해두세요.

7. 검증: 전환이 잘 되고 있는지 어떻게 확인할까

성공 기준도 미리 정의해야 합니다. 그냥 “ArgoCD가 떴다”로 끝내면 안 됩니다. 저는 보통 아래 항목으로 봅니다.

  1. 배포 변경이 모두 PR과 커밋으로 추적되는가
  2. 직접 클러스터 수정 비율이 줄고 있는가
  3. 장애 시 마지막 변경점 확인 시간이 짧아졌는가
  4. 롤백 절차가 Git revert 기준으로 일관되게 동작하는가
  5. 서비스별 소유권(owner)이 저장소 구조와 일치하는가

ArgoCD UI에서 Health, Sync 상태를 보는 것도 좋지만, 그것만으론 부족합니다. 진짜 중요한 건 운영팀과 개발팀이 같은 변경 이력을 보고 같은 언어로 이야기하게 됐는지입니다. 이게 되면 도입이 절반은 성공한 겁니다. 실제로 써보니까 배포 속도보다 커뮤니케이션 비용이 더 크게 줄더라고요.

ArgoCD 도입 실패 검증을 위한 Sync와 Health 상태 대시보드 이미지

배포 상태 확인, 이상 징후 탐지, 롤백 판단 포인트를 한눈에 보여주는 결과 검증 이미지입니다.

8. 정리 FAQ: 많이 받는 질문

Q1. ArgoCD는 무조건 자동 동기화로 써야 하나요?

아닙니다. 초반에는 수동 sync가 오히려 안전합니다. 팀이 GitOps 흐름에 익숙해지고 승인 절차가 자리 잡으면 그때 auto-sync를 검토해도 됩니다.

Q2. 기존 CI/CD를 전부 버려야 하나요?

그건 아닙니다. 빌드와 테스트는 CI가 계속 담당하고, 배포 실행만 Git 기반으로 넘기는 식이 일반적입니다.

Q3. ArgoCD 문제점은 결국 도구 한계 아닌가요?

일부는 맞지만, 현장에서 보이는 대부분은 정책과 구조 문제였습니다. 특히 저장소 책임 분리와 승인 체계가 약하면 같은 문제가 반복됩니다.

Q4. 작은 팀도 GitOps가 필요할까요?

작은 팀도 필요할 수 있습니다. 다만 처음부터 무겁게 가지 말고, 단일 서비스와 단순한 저장소 구조로 시작하는 편이 좋습니다.

ArgoCD 도입 실패 방지 전략과 GitOps 실수 비교 요약 이미지

도입 전후 비교, 실패 패턴, 예방 전략을 요약한 인포그래픽 형태의 정리 이미지입니다.

9. 마무리: ArgoCD 도입 실패를 줄이는 진짜 핵심

ArgoCD 도입 실패는 대개 설치 실패가 아니라 운영 모델 설계 실패입니다. GitOps는 도구를 붙이는 프로젝트가 아니라, 변경을 기록하고 승인하고 되돌리는 방식을 다시 정의하는 작업이거든요. 저도 처음엔 UI가 예쁘고 sync가 자동으로 돌아가니까 금방 안정화될 줄 알았는데, 실제론 저장소 구조와 팀 규칙을 먼저 잡아야 효과가 났습니다.

정리하면 이렇습니다. GitOps 실수를 줄이려면 작은 범위로 시작하고, 수동 sync로 흐름을 익히고, 저장소 책임과 승인 규칙을 먼저 고정해야 합니다. 그리고 drift, Secret, 롤백 기준을 문서로 남겨야 합니다. 이 4가지만 해도 현장에서 체감 차이가 큽니다.

다음 글에서는 App of Apps 패턴과 멀티 클러스터 운영에서 어디까지 표준화해야 하는지 다뤄볼 예정입니다. 이전 글에서 다뤘던 Kubernetes 배포 기본기와 함께 보시면 흐름이 더 잘 잡히실 겁니다. 혹시 지금 ArgoCD 도입 실패를 겪고 계시다면, 설치 로그보다 먼저 운영 규칙부터 점검해보세요. 그게 생각보다 훨씬 빠른 지름길입니다. 🎉