B2B 알림 SaaS의 쿠버네티스 운영 환경을 빈 클러스터부터 구축했습니다. GitOps 배포 파이프라인 · 3축 관측 가능성 · 무중단 배포 전략 · 이벤트 기반 아키텍처를 하나의 플랫폼으로 통합한 엔드투엔드 인프라 프로젝트입니다.
Notiflex는 B2B 알림 SaaS 플랫폼입니다. 이 프로젝트는 "코드는 돌아가지만 운영은 없는" 상태에서 출발해, 배포 자동화 · 관측 가능성 · 무중단 배포 · 확장성 · 이벤트 처리를 갖춘 프로덕션급 운영 환경으로 끌어올리는 전 과정을 다룹니다.
모든 변경은 Git을 단일 진실 소스로 삼아 선언적으로 관리되며, 클러스터 상태는 ArgoCD가
자동으로 Git과 일치시킵니다. 애플리케이션은 외부 프레임워크 없는 Go 표준 라이브러리로
작성해 scratch 컨테이너로 빌드했고,
인프라는 비용 효율을 위해 Spot VM 2노드라는 극단적 제약 위에서 전체 스택을 운영했습니다 —
이 제약이 곧 리소스 최적화와 장애 대응 역량을 검증하는 무대가 되었습니다.
각 도구는 대안과의 비교(탐색→비교→결정)를 거쳐 선택했고, 그 근거는 16개의 ADR로 저장소에 남겼습니다.
외부 요청은 Gateway API로 진입해 Canary Rollout으로 라우팅되고, 캐시·메시징·시크릿·트레이싱 백엔드와 연결됩니다.
단순 롤링 업데이트에서 시작해, 안전성과 리소스 효율을 저울질하며 두 번의 전략 전환을 거쳤습니다. 모든 전환은 Git 커밋만으로 롤백 가능합니다.
빈 클러스터에서 고도화된 이벤트 기반 플랫폼까지, 7개 단계로 점진적으로 쌓아 올렸습니다.
GKE Standard(Spot) 클러스터를 생성하고 Go API를 scratch 이미지로 빌드해 첫 배포. Gateway API를 사전 활성화하고 kubectl 컨텍스트 안전 규칙을 확립.
ArgoCD로 GitOps를 구축하고 GitHub Actions CI를 연결. 코드 push → 이미지 빌드 → 매니페스트 자동 갱신 → ArgoCD 자동 배포의 엔드투엔드 파이프라인을 완성하고 롤백까지 검증.
kube-prometheus-stack, Loki+Fluent Bit를 설치하고 Notiflex 전용 대시보드를 구성. PrometheusRule 알림을 실제 firing→resolved까지 유발해 검증.
Gateway API로 외부 진입점을 열고, Deployment를 Argo Rollouts로 전환해 Blue/Green 무중단 배포를 도입. 아키텍처 결정을 ADR로 기록하기 시작.
Valkey로 Pod 간 상태를 공유하고, 시크릿을 Secret Manager + Workload Identity + CSI로 전환(SA 키 파일 제거). 배포 전략을 Canary로 진화시킴.
역할별 노드풀로 워크로드를 격리하고, App of Apps로 여러 Application을 선언적으로 통합. Namespace 기반 멀티테넌시로 2번째 테넌트를 추가.
Kafka(Strimzi, KRaft)로 비동기 처리를 도입하고, OpenTelemetry+Tempo로 요청의 전체 여정을 추적. CronJob으로 헬스체크를 자동화해 관측 3축(메트릭·로그·트레이스)을 완성.
Git을 유일한 진실 소스로 삼아, 코드 push 한 번으로 빌드부터 Canary 배포까지 사람 개입 없이 진행됩니다. selfHeal이 클러스터의 수동 변경을 자동으로 되돌립니다.
메트릭·로그·트레이스를 Grafana 하나로 통합했습니다. /id 요청 하나가 Valkey·Kafka 자식 span으로 분해되어 어디서 느린지 눈으로 보입니다.
비밀번호를 Git이나 K8s Secret 평문이 아니라 GCP Secret Manager에 두고, Workload Identity로 SA 키 파일 없이 Pod에 파일로 마운트합니다. 두 테넌트가 동일 GSA를 안전하게 재사용합니다.
동기 처리로 몰리면 느려지던 요청을 Kafka로 분리했습니다. API가 Producer, 별도 Consumer가 메시지를 소비 — Consumer가 죽어도 디스크에 남은 메시지는 유실되지 않습니다.
가장 많이 배운 지점들입니다. 특히 "에러 없이 조용히 실패하는" 유형의 문제를, 종료 코드·재시작 카운트·스키마 검증 같은 근거로 추적해 해결했습니다.
10m으로 축소(helm-values로 재현성 확보), StatefulSet을 scale 0→1로 강제 재기동해 새 리비전 적용.connection refused)했고 사용자 경로엔 노출 안 됨.512Mi로 상향, 종료 코드(137)·재시작 카운트로 원인 확정, 신규 트레이스 저장까지 검증.consumer.Partitions()로 전체 파티션을 조회해 각각 구독하도록 수정.nodeSelector를 지정했는데 적용되지 않고 ArgoCD가 계속 OutOfSync.template.pod에는 nodeSelector 필드가 없음 → API 서버가 조용히 제거. 노드 배치는 affinity만 지원.kubectl explain으로 스키마 확인 후 nodeAffinity로 교체.100m→5m, Loki/Fluent Bit를 10m→1m로 선제 축소."무엇을 왜 선택했고 무엇을 안 썼는가"를 16개의 ADR로 저장소에 누적했습니다 — 다른 사람도, 미래의 나도 같은 근거를 추적할 수 있습니다.
| ID | 결정 | 대신 안 쓴 것 | 영역 |
|---|---|---|---|
| ADR-001 | GitOps 도구로 ArgoCD | Flux · Jenkins X · Spinnaker | GitOps/CI |
| ADR-002 | CI로 GitHub Actions | Cloud Build · GitLab CI · Jenkins | GitOps/CI |
| ADR-003 | 메트릭에 Prometheus + Grafana | Datadog · CloudWatch | 관측 |
| ADR-004 | 로그에 Loki + Fluent Bit | ELK Stack | 관측 |
| ADR-005 | 알림에 PrometheusRule + Alertmanager | Grafana Alerting | 관측 |
| ADR-006 | 외부 트래픽에 Gateway API | Ingress NGINX · Istio | 트래픽 |
| ADR-007 | 무중단 배포에 Argo Rollouts (B/G) | Flagger · Istio 카나리 | 배포 |
| ADR-008 | 캐시에 Valkey | Redis(SSPL) · Memcached | 데이터 |
| ADR-009 | 시크릿에 Secret Manager CSI + WI | Sealed Secrets · SA 키 | 보안 |
| ADR-010 | 배포 전략을 Canary로 전환 | Blue/Green 유지 | 배포 |
| ADR-011 | 워크로드 배치에 nodeSelector + 노드풀 | taint · nodeAffinity 단독 | 확장 |
| ADR-012 | 다중 앱에 App of Apps | ApplicationSet · 수동 | 확장 |
| ADR-013 | 멀티테넌시에 Namespace 분리 | vCluster · 클러스터 분리 | 확장 |
| ADR-014 | 메시징에 Kafka (Strimzi) | RabbitMQ · NATS | 고도화 |
| ADR-015 | 트레이싱에 Grafana Tempo | Jaeger · Zipkin | 고도화 |
| ADR-016 | 배치에 K8s CronJob | 외부 cron · Argo Workflows | 고도화 |
전 과정을 Git 중심 + AI 페어링 + 운영 자동화가 결합된 GitAIOps 워크플로로 수행했습니다. 모든 도구 선택은 "탐색 → 비교 → 결정" 3단계를 거치고, 위험 작업은 가드레일로 통제하며, 결정은 ADR로, 진행은 JOURNEY 기록으로 남겨 재현 가능하고 감사 가능한 방식으로 진행했습니다.
모든 변경은 커밋으로만. 클러스터는 Git을 자동 추종하고, 롤백은 revert 하나로.
반복·위험 작업을 AI와 페어링하되, 실행 전 상태 확인과 승인 규칙으로 통제.
CLAUDE.md(규칙) · claude-context(현재 그림) · ADR(결정 누적)로 컨텍스트 분리.
ArgoCD App of Apps와 Argo Rollouts로 선언적·자가치유 배포를 엔드투엔드로 구축.
메트릭·로그·트레이스 3축을 Grafana로 통합하고, 알림을 실제 상황으로 검증.
연쇄 Pending, OOMKilled, 조용한 데이터 손실을 exit code·스키마·리소스로 추적·해결.
Workload Identity 기반 keyless 인증과 Secret Manager로 SA 키 파일을 제거.
Spot 2노드 제약 위에서 관측·데이터·메시징 전체 스택을 사전 예산 관리로 운영.
역할별 노드풀 분리와 Namespace 테넌시로 워크로드를 격리하고 2번째 테넌트를 추가.