Kubernetes 위에서 CQRS 패턴으로 동작하는 커넥티드카 실시간 텔레메트리 플랫폼입니다. 차량에서 발생하는 위치·속도·배터리 데이터를 Kafka로 수집하고, MongoDB(이력)와 Redis(최신 상태)로 나누어 처리·조회합니다.
진행 기간 2026.02.24 ~ 2026.03.13 (3주) · 팀 구성 4인 (현대오토에버 모빌리티 SW스쿨 클라우드트랙 3기)
이 프로젝트를 만들며 겪은 설계 고민과 트러블슈팅을 5편의 시리즈로 정리했습니다. README에는 핵심만 요약했고, 각 단계의 자세한 원인 분석·해결 과정은 아래 링크에 담았습니다.
| 편 | 제목 | 링크 |
|---|---|---|
| 1편 | 프로젝트 개요 및 CQRS 패턴 이해 | 바로가기 |
| 2편 | Kubernetes 배포 (Deployment/StatefulSet/Ingress/HPA/CronJob) | 바로가기 |
| 3편 | Helm Chart 도입 및 서비스별 분리 | 바로가기 |
| 4편 | 모니터링 (kube-prometheus-stack, Alerting) | 바로가기 |
| 5편 | Jenkins CI/CD + Harbor Registry | 바로가기 |
전체 시리즈: velog.io/@june21dev/series
Dummy Car Server (FastAPI)
│ POST /api/telemetry/batch
▼
[Command] Ingest API ──Kafka Produce(aiokafka)──▶ car.telemetry.events
│
┌─────────────────────────┴─────────────────────────┐
▼ ▼
[Command] MongoDB Consumer [Query] Redis Consumer
│ │
▼ ▼
MongoDB (이력 영구저장, TTL 7일) Redis (최신상태 캐시, TTL 60s)
│
[Query] Query API (FastAPI)
│ GET /api/vehicles
▼
Frontend (React + Leaflet)
왜 CQRS인가: 하나의 Consumer가 MongoDB·Redis를 동시에 처리하는 구조를 초기에 검토했지만, 책임 분리 실패·장애 격리 실패·독립 스케일링 불가라는 4가지 문제를 발견하고 Command/Query Consumer를 완전히 분리했습니다. (1편 참고)
| 분류 | 기술 |
|---|---|
| Backend | Python, FastAPI, kafka-python, pymongo, redis-py |
| Frontend | React 19, TypeScript, Vite, Leaflet |
| Messaging | Apache Kafka (KRaft 모드) |
| Database | MongoDB 7, Redis 7 |
| Infra | Kubernetes, Helm, Harbor Registry, NFS |
| CI/CD | Jenkins |
| Monitoring | Prometheus, Grafana, Alertmanager (kube-prometheus-stack) |
실제로 부딪히고 해결한 문제들입니다. 전체 과정은 각 편 링크에 있습니다.
1. PV/PVC 충돌 → StatefulSet 전환
Deployment + 고정 PVC 구조로 MongoDB를 운영하다 롤링 배포 시 DBPathInUse 오류로 CrashLoopBackOff 발생. 새 Pod가 기존 Pod 종료 전에 같은 데이터 디렉토리를 사용해 락 충돌이 원인이었습니다. MongoDB/Redis/Kafka 모두 StatefulSet + volumeClaimTemplates + Headless Service 구조로 전환해 구조적으로 해결했습니다.
→ 2편 자세히 보기
2. Kafka Consumer Group 분리로 메시지 유실 방지
Command/Query Consumer가 동일한 group_id를 사용하면서 메시지가 양쪽에 분산 소비되어 유실되는 문제 발견. KAFKA_GROUP_ID_COMMAND / KAFKA_GROUP_ID_QUERY로 그룹을 분리하고 ConfigMap으로 중앙화했습니다.
→ 1편 자세히 보기
3. Helm Chart 분리 시 Secret 중복 선언 문제
단일 Chart를 4개(infra/command/query/frontend)로 쪼개는 작업을 팀원 주도로 진행하면서, 각 Chart의 values.yaml에 동일한 Secret이 중복 선언되는 문제가 발생했습니다. _helpers.tpl의 sha256sum 체크섬 패턴으로 Secret 변경 시 자동 롤링 업데이트가 트리거되도록 구조화해 해결했습니다.
→ 3편 자세히 보기
4. Alertmanager 알림 폭탄 방지
일시적 CPU 스파이크(HPA 스케일링 순간 등)에도 알림이 계속 발생하는 노이즈 문제. 모니터링을 맡은 팀원이 PrometheusRule에 for 조건(2~5분)을 추가해 지속되는 이상 상태만 알림 대상으로 걸러내고, Alertmanager group_by로 관련 알림을 하나로 묶어 Discord로 전송하도록 구성했습니다.
→ 4편 자세히 보기
5. GitHub App 인증 도입 중 Private Key 포맷 불일치
Jenkins-GitHub 연동에 개인 액세스 토큰 대신 GitHub App 방식(Contents/Metadata Read-only, Webhooks Read/Write 권한)을 채택했는데, GitHub이 발급하는 Private Key 포맷(PKCS#1)이 Jenkins가 요구하는 포맷(PKCS#8)과 달라 그대로는 Credentials 등록이 되지 않았습니다. 키 포맷을 변환해 Jenkins에 GitHub App 타입으로 정상 등록해 해결했습니다. → 5편 자세히 보기
Checkout → Set image tag(BUILD_NUMBER-shortSHA) → Docker Build & Push (5개 서비스)
→ Prepare Registry Auth → Deploy to Kubernetes (StorageClass 자동감지 + 4개 Chart 순차 배포)
→ Apply Monitoring Resources → Verify Workload Readiness
- StorageClass 3단계 자동 감지:
nfs-storage→ 클러스터 기본 StorageClass → 임의 StorageClass 순으로 fallback, NFS 없는 환경에서도 파이프라인이 죽지 않도록 설계 - RESET_MINIPROJECT 파라미터: 문제 발생 시 네임스페이스를 깨끗하게 초기화하고 재배포하는 옵션 제공
- Harbor 프라이빗 레지스트리를 별도 VM으로 분리해, 클러스터 장애 시에도 이미지 자산을 안전하게 보존
kube-prometheus-stack(Prometheus + Grafana + Alertmanager)을 도입해 5가지 알림 규칙(Pod NotReady/NotRunning/High CPU/High Memory/재시작 과다)을 정의하고, Discord Webhook으로 실시간 알림을 받도록 구성했습니다.
k8s-manifests/
┣ mobility-infra/ # DB, 메시지 브로커, Secret/ConfigMap
┣ mobility-command/ # Ingest API, MongoDB Consumer
┣ mobility-query/ # Query API, Redis Consumer
┣ mobility-frontend/ # React 대시보드
┗ monitoring/ # ServiceMonitor, PodMonitor, PrometheusRule
src-command/ # Command 서비스 소스
src-query/ # Query 서비스 소스
frontend/ # React 앱
dummy-data/ # 가상 차량 데이터 생성기
docs/ # 배포/Secret 가이드
Jenkinsfile # CI/CD 파이프라인 정의
docker compose up -d| 서비스 | 주소 |
|---|---|
| Ingest API | http://localhost:8080 |
| Query API | http://localhost:8000 |
| Frontend | http://localhost:3000 |
K8s 배포 방법은 docs/secret-setup.md 참고.
4인 팀 프로젝트로 진행했습니다. CQRS 아키텍처 설계·Command/Query 핵심 서비스 구현·StatefulSet 장애 대응·CI/CD 파이프라인 구축을 맡았고, Harbor 인프라 구축·모니터링 알림 체계·Helm Chart 분리는 팀원들과 함께 진행했습니다.