Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

253 Commits

Folders and files

Repository files navigation

☁️ Connected Car Telemetry Platform

Kubernetes 위에서 CQRS 패턴으로 동작하는 커넥티드카 실시간 텔레메트리 플랫폼입니다. 차량에서 발생하는 위치·속도·배터리 데이터를 Kafka로 수집하고, MongoDB(이력)와 Redis(최신 상태)로 나누어 처리·조회합니다.

Kubernetes Kafka FastAPI Helm

진행 기간 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편 참고)


🛠️ Tech Stack

분류 기술
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편 자세히 보기


🚀 CI/CD 파이프라인

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 분리는 팀원들과 함께 진행했습니다.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages