티스토리 뷰

반응형

ArgoCD 설치 이틀 만에 운영팀에서 긴급 메시지가 왔다. "아무도 시크릿을 어디에 넣어야 하는지 모른다." 배포 자동화는 됐지만, 운영 규칙은 아무것도 정해지지 않은 상태였다. GitOps를 도입하면 배포가 안전해진다는 말은 맞다. 하지만 운영이 저절로 단순해지는 건 전혀 다른 이야기다.

요약

GitOps는 Kubernetes 배포 자동화의 실질적인 표준이 됐다. CNCF 2025 조사에 따르면 전체 Kubernetes 클러스터의 60%가 Argo CD를 사용하며, 그 중 97%는 프로덕션 환경이다. 하지만 도입 팀의 상당수가 첫 몇 달 안에 예상치 못한 운영 이슈를 마주친다. 이 글은 GitOps가 해결하는 것과 해결하지 못하는 것을 명확히 구분하고, 도입 전에 반드시 점검해야 할 5가지 운영 리스크를 정리한다.

이 글이 필요한 사람

  • GitOps 도입을 검토 중이거나 막 시작한 DevOps/플랫폼 엔지니어
  • Argo CD 또는 Flux를 사용 중인데 운영이 예상보다 복잡하다고 느끼는 팀
  • GitOps의 개념은 알지만 실제 운영 리스크를 체계적으로 정리하고 싶은 인프라 담당자

왜 지금 GitOps인가

GitOps의 핵심 아이디어는 단순하다. Git 저장소를 클러스터의 단일 진실 공급원(Single Source of Truth)으로 삼고, 저장소 상태와 실제 클러스터 상태를 자동으로 동기화한다. CI/CD 파이프라인이 클러스터를 직접 밀어 넣는 방식 대신, 클러스터가 Git에서 끌어오는 구조로 전환한다.

이 방식은 감사 추적, 롤백 가능성, 협업 방식의 개선 등 실질적인 장점이 있다. CNCF의 조사 결과처럼 대규모 프로덕션 환경에서도 이미 검증됐다. 문제는 "GitOps를 써야 하는가"가 아니라 "GitOps를 어떻게 운영할 것인가"다.

GitOps가 해결하는 것과 해결하지 못하는 것

GitOps가 해결하는 것은 배포 프로세스의 일관성, 변경 이력 추적, 선언적 인프라 상태 관리다. 클러스터에 직접 kubectl apply를 날리는 대신 Git PR로 변경을 제어하고, 컨트롤러가 실제 상태를 지속적으로 조정한다.

반면 GitOps가 자동으로 해결하지 못하는 것이 있다.

  • 시크릿 관리 정책
  • 다중 팀 간의 저장소 구조 합의
  • 리컨실리에이션 루프가 깨졌을 때의 운영 절차
  • 롤백이 필요한 상황에서의 상태 일관성

이 영역들은 GitOps 도구가 아니라 팀의 운영 규칙과 아키텍처 설계로 해결해야 한다.

운영 리스크 1 — 시크릿을 Git에 올리는 실수

가장 흔하고 가장 위험한 실수다.

GitOps는 모든 상태를 Git에서 관리하는 구조다. 그러다 보면 DB 비밀번호, API 키, 인증서 같은 민감한 값을 YAML에 그대로 넣고 싶은 유혹이 생긴다. 특히 팀이 빠르게 움직이는 초기에는 임시방편으로 Secret을 직접 Git에 커밋하는 경우가 많다.

문제는 한 번 Git에 올라간 시크릿은 삭제해도 이력에 남는다는 것이다. Private 저장소도 내부 계정 탈취나 CI 토큰 유출에 취약하다.

실무에서 사용하는 패턴은 두 가지로 나뉜다.

첫 번째는 Sealed Secrets 방식이다. Bitnami Sealed Secrets 컨트롤러를 사용하면 시크릿을 클러스터 공개키로 암호화한 뒤 Git에 올릴 수 있다. 복호화는 클러스터 내부에서만 가능하기 때문에 Git에 암호문이 노출돼도 실제 값은 보호된다.

두 번째는 External Secrets Operator 방식이다. AWS Secrets Manager, Azure Key Vault, HashiCorp Vault 같은 외부 시크릿 스토어를 참조하고, Kubernetes Secret은 런타임에 동적으로 생성한다. Git에는 시크릿의 "참조 경로"만 남기고, 실제 값은 외부에서 주입하는 구조다.

GitOps 도입 전에 두 방식 중 하나를 팀 표준으로 결정해야 한다. 나중에 바꾸는 것은 훨씬 어렵다.

운영 리스크 2 — 드리프트는 자동으로 해결되지 않는다

GitOps의 핵심 약속 중 하나는 클러스터 드리프트(구성 편차)를 자동으로 감지하고 복구한다는 것이다. 하지만 현실에서는 이 기능이 의도대로 작동하지 않는 경우가 많다.

드리프트는 주로 이런 상황에서 발생한다.

  • 운영 중 긴급하게 kubectl edit 또는 kubectl patch로 설정을 변경했을 때
  • 외부 툴(Helm, 다른 CI 파이프라인)이 클러스터 상태를 직접 건드렸을 때
  • ArgoCD나 Flux의 자동 동기화(Auto-sync)가 꺼져 있을 때

많은 팀이 자동 동기화를 끄고 운영한다. 이유는 이해할 수 있다. 긴급 롤백이나 임시 수정 때 컨트롤러가 되돌려버리면 장애가 길어질 수 있기 때문이다. 하지만 Auto-sync를 끄면 GitOps의 핵심 보장인 "Git이 클러스터의 진실"이라는 전제가 무너진다.

실무적인 접근은 다음과 같다.

Auto-sync는 기본으로 켜두되, 긴급 조치가 필요한 상황에서는 특정 앱에 한해 일시적으로 Sync를 정지할 수 있는 절차를 미리 정해 놓는다. 그리고 드리프트 감지 알림을 설정해 Sync 실패나 Out-of-Sync 상태가 일정 시간 이상 지속되면 슬랙이나 PagerDuty로 알림이 오도록 한다. 드리프트가 발생한 뒤 되돌리는 것보다, 드리프트가 왜 발생했는지를 먼저 파악하는 것이 더 중요하다.

운영 리스크 3 — 롤백이 생각보다 복잡하다

GitOps를 도입하면 롤백이 쉬워진다고 알려져 있다. "Git revert 하나면 끝"이라는 말이다. 그런데 실제로 해보면 생각보다 복잡하다.

ArgoCD의 롤백 명령은 Auto-sync가 켜진 상태에서 작동하지 않는다. 롤백을 실행하면 클러스터 상태가 과거 버전으로 되돌아가지만, Git의 상태는 그대로다. 컨트롤러는 곧 Git에 맞춰 다시 최신 버전으로 덮어쓰려 한다. 즉, 롤백이 유지되지 않는다.

올바른 GitOps 롤백 방법은 Git revert다. git revert <commit-hash>로 해당 커밋을 되돌리는 커밋을 새로 만들고, 이를 푸시하면 컨트롤러가 그 상태를 클러스터에 적용한다. 이 방식은 롤백 이력도 Git에 남기 때문에 감사 추적이 가능하다.

또 다른 복잡성은 컨테이너 이미지 태그다. 이미지를 latest 태그로 참조하거나 Git 브랜치 기반으로 참조하면 특정 커밋을 되돌려도 실제로 어떤 이미지가 배포됐는지 추적하기 어렵다. 반드시 이미지를 내용 기반 다이제스트(SHA256)나 명확한 버전 태그로 고정해야 한다.

롤백 시나리오를 팀이 미리 연습해 놓지 않으면, 장애 상황에서 혼란이 가중된다. 도입 초기에 롤백 훈련(Game Day)을 한 번 해보는 것이 실질적인 도움이 된다.

운영 리스크 4 — 모노레포 혼란과 다중 팀 충돌

GitOps 저장소 구조를 어떻게 설계할지는 단순한 아키텍처 선택이 아니다. 팀 간 경계, 배포 단위, 권한 모델, 리뷰 프로세스까지 전부 영향을 받는다.

흔한 실수는 처음에 모노레포(Monorepo)로 시작해 모든 팀이 하나의 저장소에 매니페스트를 넣는 것이다. 초기에는 편리하지만, 팀 수가 늘면 다음 문제가 생긴다.

  • PR 충돌이 빈번해진다
  • 특정 팀의 배포 실패가 전체 리컨실리에이션에 영향을 준다
  • 권한 분리가 어렵다 (특정 서비스에만 배포 권한을 줄 수 없다)

반대로 폴리레포(Polyrepo)는 팀 자율성이 높지만, 저장소 간 일관성 유지와 공통 컨피그 관리가 복잡해진다. 플랫폼 팀이 없는 조직에서는 폴리레포가 금방 관리 부담이 된다.

현업에서 많이 쓰는 패턴은 앱 코드 저장소와 GitOps 매니페스트 저장소를 분리하는 것이다. 앱 코드는 기존 서비스 저장소에 두고, 배포 매니페스트는 별도의 GitOps 저장소에 관리한다. 그리고 ArgoCD의 AppProject나 Flux의 Kustomization 계층을 활용해 팀별 소유권과 배포 범위를 명확히 경계 짓는다.

이 설계 결정은 도입 초기에 해야 한다. 나중에 저장소 구조를 바꾸는 것은 수십 개의 ArgoCD 앱을 재설정하는 일이기 때문이다.

운영 리스크 5 — 리컨실리에이션 루프 장애

GitOps에서 가장 조용하게 진행되는 장애 중 하나가 리컨실리에이션 루프 오류다. 컨트롤러가 Git과 클러스터 간 상태를 맞추는 작업(Reconciliation)이 반복적으로 실패하면, 클러스터는 원하는 상태로 수렴하지 못한 채 방치된다.

리컨실리에이션 루프가 깨지는 흔한 원인은 다음과 같다.

  • YAML 오류 또는 잘못된 Helm values가 Git에 머지됐을 때
  • 참조하는 CRD나 Namespace가 존재하지 않을 때
  • 클러스터의 리소스 제한에 걸려 리소스가 생성되지 못할 때
  • ArgoCD 컨트롤러 자체가 메모리 부족으로 재시작될 때

이 상태는 배포가 실패하는 것이 아니라 "아무것도 진행되지 않는" 형태로 나타나기 때문에 모니터링이 없으면 발견하기 어렵다.

Flux와 ArgoCD 모두 Prometheus 메트릭을 노출한다. argocd_app_sync_total, argocd_app_health_status, flux_reconcile_condition 같은 메트릭을 수집하고 Grafana 대시보드와 알림을 구성해야 리컨실리에이션 실패를 조기에 발견할 수 있다.

ArgoCD 3.3(2026년 초 릴리스)은 이 영역에서 개선이 있었다. PreDelete Hook 지원이 추가돼 스테이트풀 앱 삭제 시 발생하던 리소스 잔여 문제를 방지할 수 있게 됐고, 저장소 성능과 인증 경험도 개선됐다.

AWS / Azure 관점

AWS EKS에서 GitOps를 구성할 때 자주 선택하는 조합은 Argo CD + AWS Secrets Manager + External Secrets Operator다. EKS Pod Identity 또는 IRSA(IAM Roles for Service Accounts)를 통해 External Secrets Operator에 Secrets Manager 접근 권한을 주고, Kubernetes Secret은 런타임에 동적으로 생성한다. GitOps 레포지토리에는 SecretStore와 ExternalSecret 오브젝트만 남기고, 실제 시크릿 값은 AWS에 두는 구조다.

드리프트 감지를 보강하고 싶다면 AWS Config와 연계할 수 있다. AWS Config는 EKS 리소스 변경을 추적하기 때문에 GitOps 상태와 비교하는 커스텀 룰을 만들 수 있다.

Azure AKS에서는 GitOps가 Azure 기본 기능으로 제공된다. Azure Arc GitOps Configuration과 AKS의 GitOps Extension(Flux v2 기반)을 통해 Flux를 클러스터에 기본으로 활성화할 수 있다. Azure Key Vault는 AKS의 Secret Store CSI Driver와 연동해 시크릿을 Kubernetes Secret으로 마운트 하거나 환경 변수로 주입하는 방식이 일반적이다. Azure Policy와 Defender for DevOps를 활용하면 GitOps 저장소에 시크릿이 포함됐는지를 CI 단계에서 감지하는 정책도 구성할 수 있다.

실무 체크리스트

  • 시크릿을 Git에 직접 올리지 않도록 Sealed Secrets 또는 External Secrets Operator를 도입 전에 결정한다
  • Auto-sync 정책과 긴급 정지 절차를 운영 문서로 남긴다
  • 롤백은 git revert 기반으로 수행하고, 이미지 태그는 SHA256 다이제스트 또는 명확한 버전으로 고정한다
  • GitOps 저장소 구조(모노레포 vs 폴리레포, 앱 코드와 매니페스트 분리)를 도입 초기에 팀 합의로 결정한다
  • ArgoCD 또는 Flux의 리컨실리에이션 메트릭을 Prometheus로 수집하고 Sync 실패 알림을 설정한다
  • 장애 발생 시 드리프트를 되돌리는 것보다 왜 발생했는지 먼저 파악하는 문화를 만든다
  • 도입 초기에 롤백 훈련을 한 번 수행해 팀 전체가 절차를 숙지한다

흔한 실수

시크릿을 임시로 Git에 올리고 나중에 정리하겠다고 생각하는 것: 임시가 영구가 되는 경우가 많고, Git 이력은 삭제해도 남는다.

Auto-sync를 끄고 운영하다 드리프트를 방치하는 것: Auto-sync를 끄면 GitOps의 핵심 보장이 사라진다. 끄는 것이 아니라 예외 절차를 설계해야 한다.

이미지를 latest 태그로 참조하는 것: 어떤 이미지가 실제로 배포됐는지 알 수 없게 되고 롤백이 의미를 잃는다.

저장소 구조를 팀 합의 없이 단독으로 설계하는 것: GitOps 저장소는 팀 전체의 배포 생명주기에 영향을 미친다. 초기 설계가 나중의 마찰을 줄인다.

리컨실리에이션 실패 알림을 설정하지 않는 것: 조용히 실패하는 루프는 발견하지 못하면 며칠씩 지속될 수 있다.

마무리

GitOps는 배포 자동화와 변경 이력 관리에서 실질적인 가치를 제공한다. 하지만 도구를 설치하는 것만으로 운영이 안전해지지는 않는다. 시크릿 관리, 드리프트 정책, 롤백 절차, 저장소 설계, 모니터링 구성은 팀이 직접 결정하고 운영 문서로 남겨야 한다.

GitOps를 도입하기 전에 위의 5가지 리스크를 팀과 한 번 점검해 보자. 설치 이틀 만에 긴급 메시지를 받는 상황을 미리 막을 수 있다.


이 글이 유용했다면 다음 편도 확인해보세요.
다음 글: 클라우드 주요 업데이트를 운영자 관점에서 읽는 방법

References


 

반응형
댓글
반응형
최근에 올라온 글
Total
Today
Yesterday