DevOps 2026.11.06 7 min read

기존 Helm 리소스 여덟 개를 삭제 없이 Argo CD에 연결하기

10월 18일 배포 작업에서는 GitOps 후보 파일만 준비했다. 이어진 작업에서 Argo CD를 실제 설치하고 격리 시험을 거친 뒤 기존 Platform 리소스 여덟 개를 제한된 권한으로 채택했다. 설치 완료와 운영 변경 권한의 범위를 나누어 진행했다.

RCA Platform이 클러스터에서 동작하고 나니 Git에서 검토한 변경을 운영에 적용할 경로가 필요했다. 이미 Helm으로 설치된 앱과 DB, PVC가 있었기 때문에 Argo CD를 추가하면서 기존 리소스의 소유권과 데이터 경계를 먼저 정리해야 했다.

10월 18일 배포 작업에서는 GitOps 후보 파일만 준비했다. 이어진 작업에서 Argo CD를 실제 설치하고 격리 시험을 거친 뒤 기존 Platform 리소스 여덟 개를 제한된 권한으로 채택했다. 설치 완료와 운영 변경 권한의 범위를 나누어 진행했다.

작은 설치와 격리된 수동 Sync부터 확인했다

Argo CD는 전용 namespace에 chart 10.10.5와 app v3.5.5를 고정해 설치했다. 활성 구성은 controller, repository server, API server, Redis 네 Pod였다. ApplicationSet은 replica 0으로 두고 Dex, notifications, HA 구성은 비활성화했다.

API server는 ClusterIP와 TLS로만 접근했다. 외부 LoadBalancer나 Ingress를 만들지 않고 SSH 터널과 port-forward를 사용했다. 관리 접속에서도 명시적으로 인증서를 검증했다. 기본 Project는 거부 상태로 두고 사용할 저장소와 namespace, 리소스 종류를 좁혔다.

처음에는 운영 앱과 분리한 시험 namespace를 사용했다. Git 연결 후 OutOfSync와 diff를 확인하고 Manual Sync를 실행해 Healthy/Synced가 되는지 살폈다. 이어 설정을 v2에서 v1으로, 다시 v2로 돌렸다. 이 과정에서는 같은 Pod UID와 restart 0, HTTP 200을 유지했다고 확인했다.

이 시험으로 Git 변경을 읽고 수동 적용하는 기본 흐름을 확인했다. 운영 이미지나 DB를 이전 상태로 돌린 검증까지 여기서 끝났다고 계산하지는 않았다. 이후 운영 채택과 이미지 전환은 별도의 범위로 진행했다.

Argo CD Applications의 Healthy·Synced 상태
rca-platform-onprem Healthy·Synced, Argo CD v3.5.5.

저장소 보호 설정에서 403을 만났다

GitOps 저장소에는 환경별 values와 vendored chart, Application 설정, 운영 문서를 두었다. Kubernetes Secret은 이름으로 참조하고 실제 비밀번호와 토큰, 개인키는 저장하지 않는 구성으로 정리했다. Argo CD의 Git 접속에는 읽기 전용 deploy key를 사용했다.

저장소 보호 규칙을 적용하는 과정에서는 private 저장소의 branch protection 요청이 403으로 거부됐다. 이 제약을 확인한 뒤 공개 전환의 영향을 검토하고 승인받아 진행했다. 공개 전후에는 알려진 secret과 private-key 패턴을 검사했으며, 각각 57개와 후속 68개 history blob 범위에서 일치 항목이 없었다. 이 검사를 저장소에 비밀이 전혀 없다는 보증으로 확대하지 않았다.

main에는 PR 필수, 관리자 적용, force push와 삭제 금지 규칙을 두고 auto-merge는 사용하지 않았다. 단독 소유자 환경이라 review count는 0이었다. 별도 독립 승인자가 검토하는 조직형 절차가 있다고 설명하지 않고, PR diff를 남기고 소유자가 검토·병합하는 실제 흐름으로 기록했다.

Helm을 지우지 않고 기존 리소스만 채택했다

운영 연결의 핵심은 새 앱을 만드는 것이 아니라 기존 리소스를 식별한 상태로 관리 주체를 연결하는 일이었다. Argo CD에 맡긴 대상은 Platform 관련 다음 여덟 종류의 기존 리소스였다.

관리 대상 관리 범위
ServiceAccount, Service, Deployment, Ingress 기존 이름의 리소스
NetworkPolicy, PodDisruptionBudget 기존 이름의 리소스
ServiceMonitor, AlertmanagerConfig 기존 이름의 리소스

controller 권한은 정확한 대상 이름에 대한 get, update, patch로 제한했다. create와 delete는 허용하지 않았다. Secret, PVC, DB StatefulSet, Agent RBAC, namespace와 노드는 관리 대상으로 넣지 않았다. 이 권한으로 클러스터 전체를 자동 재구성할 수 있다고 기대하지 않았다.

초기 채택은 기존 여덟 개의 metadata를 동기화하는 범위로 진행했다. Pod와 이미지, DB와 PVC를 유지하면서 Synced/Healthy를 확인했다. Helm release의 revision 4 이력도 보존했다. 소유권을 넘긴다는 이유로 helm uninstall을 실행하지 않았다.

기존 rca revision 4와 Argo CD Helm 설치 이력
기존 rca revision 4와 Argo CD Helm 설치 이력.

채택 후에는 같은 리소스에 Helm upgrade나 rollback을 섞지 않도록 기존 이력을 동결했다. Agent의 별도 Helm release는 그대로 관리했고 Argo CD에 넘기지 않았다. 앱에 대한 GitOps 도입이 곧 모든 주변 리소스의 관리 전환을 의미하지는 않았다.

Argo CD가 관리하는 기존 리소스 여덟 개와 Sync 이력
Argo CD가 관리하는 기존 리소스 여덟 개와 Sync 이력.

main 추적과 실제 적용 revision을 나누었다

Application은 GitOps main을 추적하게 했지만 실제 Manual Sync에는 승인한 immutable SHA를 지정했다. 추적 브랜치의 최신 상태를 보여주는 것과 특정 변경을 지금 운영에 적용하는 판단을 분리했다.

Argo CD Healthy·Synced와 추적 revision·적용 revision
Argo CD Healthy·Synced와 추적 revision·적용 revision.

검토 branch와 merge commit의 SHA가 달라지는 경우에는 문자열이 같다고 설명하지 않았다. 실제 검토 내용과 merge tree가 일치하는지 확인한 뒤 적용 대상으로 연결했다. Platform digest 한 줄을 바꾼 PR과 이후 topology 보정 PR도 각각 변경 범위가 달랐다.

Auto Sync, Prune, Self-Heal은 비활성화했다. CreateNamespace, force와 replace, 삭제 finalizer도 사용하지 않았다. Git 변경이 들어오면 OutOfSync를 통해 차이를 확인하고, 검토와 승인 뒤 수동으로 적용하는 방식이었다.

Argo CD의 Synced 리소스 수와 애플리케이션 트리 일부
Argo CD 관리 리소스 Synced 8개와 연결 관계.
AppProject의 허용 저장소와 배포 namespace
AppProject의 허용 GitOps repository와 rca-system 배포 목적지.
AppProject의 허용 Kubernetes 리소스 종류
AppProject의 namespace 허용 리소스 8종.

Argo CD 설치 자체보다 오래 고민한 부분은 기존 서비스의 어느 지점까지 관리하게 할지였다. 격리 시험, 저장소 보호, 이름 단위 권한, metadata 채택, 승인 revision 지정으로 단계를 나눴다. 그 결과 이미 실행 중이던 서비스와 데이터를 보존하면서 Git에서 검토한 Platform 변경을 수동으로 적용할 기반을 만들었다.

SEARCH JOURNAL

기록 검색

글 제목, 요약, 태그에서 찾습니다.

검색을 준비하고 있어요.

검색어를 입력해 주세요.

    Ctrl/⌘ K 검색 Esc 닫기 ↑ ↓ 결과 이동