목차
1. 개요
•
프로젝트명: COME2US (Sprint #3)
•
목표:
◦
ECS 기반 2차 아키텍처를 Kubernetes(EKS) 기반으로 확장
◦
GitOps 기반 선언적 배포 구조 정립 (GitHub Actions + ArgoCD)
◦
서비스 메시에 Istio 도입하여 보안(mTLS)·트래픽 제어·관찰성 확립
◦
Helm 기반 Kubernetes Manifest 템플릿화
◦
Kafka(MSK) 기반 이벤트 시스템을 결제(Payment) 서비스 중심으로 부분 도입
◦
인프라 자동화는 Terraform 중심으로 유지
◦
Istio를 활용한 Canary 배포 전략 도입
◦
Karpenter 기반 자동 노드 프로비저닝 도입
•
핵심 구성 계층
계층 | 주요 구성 요소 |
Network Layer | VPC, Subnet(Public/App/Data), NAT, LB, Route53 |
Compute Layer | EKS, NodeGroup, Karpenter |
Service Layer | Spring Boot Microservices, Istio, Envoy Sidecar, Helm |
Data Layer | RDS(PostgreSQL), Redis, MSK(Kafka), S3 |
DevOps Layer | GitHub Actions(CI), ArgoCD(CD), Terraform, Helm |
Observability Layer | CloudWatch, Prometheus, Grafana, Loki, Tempo(Tracing) |
2. 시스템 아키텍처 요약
아키텍처 다이어그램
주요 변경점 요약 (ECS → EKS 전환)
영역 | 2차 프로젝트 (기존) | 3차 프로젝트 (변경 버전) |
컨테이너 오케스트레이션 | ECS Fargate | EKS + Karpenter |
배포 체계 | Jenkins + Terraform | GitHub Actions(CI) + ArgoCD(CD) |
서비스 디스커버리 | Eureka | K8s Service + Istio Mesh |
트래픽 라우팅 | Spring Cloud Gateway | Istio Ingress Gateway + Envoy |
App 설정 관리 | Config Server | Helm Values + ConfigMap/Secret |
이벤트 시스템 | - | Kafka(MSK) 도입 (결제 서비스, 로그 파이프라인) |
관찰성 | CloudWatch 중심 | Prometheus + Grafana + Loki + Tempo |
배포 전략 | Blue/Green | Canary Deployment (Istio 기반) |
3. 네트워크 구조
•
2차 프로젝트와 동일한 2-AZ 구성
•
Public, Private(Application), Private(Database) Subnet을 분리하여 트래픽 및 보안 계층화
◦
기존과 동일
•
Istio Ingress Gateway는 LoadBalancer Service이며, AWS NLB 생성
•
모든 서비스 간 통신은 Envoy Sidecar를 통해 처리
구분 | 역할 | 구성 계획 |
Public Subnet | 외부 노출용 리소스 | - ALB(Grafana, ArgoCD)
- NLB(Istio Ingress Gateway)
- NAT |
Private Subnet(Application) | 내부 서비스 | EKS Worker Node |
Private Subnet(Database) | 데이터 리소스 | RDS, Redis, MSK |
Routing | IGW / NAT | Outbound → NAT |
DNS | Route53 + ACM | HTTPS 통신 기반 인증서 관리 |
4. 애플리케이션 계층
구성 요소
요소 | 설명 |
EKS Cluster | 모든 MSA 서비스의 런타임 환경 |
NodeGroup + Karpenter Autoscaling | On-demand 최소 구성 + Karpenter 통한 Autoscaling |
Pod / Deployment / Service | 내부 서비스들은 ClusterIP를 통해 노출 |
Istio (Service Mesh) | mTLS, Traffic Splitting, Routing, Circuit Breaker |
Envoy Sidecar | Pod 간 통신 프록시 |
Helm Charts | Microservice 템플릿 관리 |
ArgoCD | GitOps 기반 지속적 배포(CD) |
서비스 흐름
Client → Route53 → Istio Ingress Gateway → Envoy Sidecar
→ K8s Service → Microservice Pod
→ RDS / Redis / MSK(Kafka)
→ Envoy Sidecar → Istio Ingress Gateway → Client 응답
Plain Text
복사
5. 데이터 계층
•
기존과 동일한 데이터베이스를 유지하며, MSK(Kafka)를 도입하여 이벤트 기반 메시징 처리
구성요소 | 설계 의도 |
RDS (PostgreSQL) | Multi-AZ 구성 (Writer: AZ-a, Standby: AZ-b, Reader 다중 구성) |
Redis (ElastiCache) | - Session Redis (세션 + 비영속 데이터 저장소)
- Cache Redis (캐시 저장소) |
MSK (Kafka) | - 결제(Payment) 서비스 적용
- 로그 파이프라인 적용 |
S3 | - 이미지 저장소 및 정적 오브젝트 저장
- VPC Endpoint 통한 사설 연결 구성 |
6. 이벤트 기반 아키텍처 - MSK
MSK(Kafka)는 결제 승인 결과를 비롯한 주문·상품·쿠폰 서비스 간 SAGA 보상 트랜잭션을 구현하기 위한 핵심 메시징 플랫폼으로 사용한다.
본 프로젝트에서는 결제 서비스 중심의 부분 도입을 시작으로, 점진적으로 EDA를 확장한다.
6.1 도입 배경
목적 | 설명 |
SAGA 보상 트랜잭션 처리 | 결제 승인 실패 시 주문/재고/쿠폰 원복 처리 |
서비스 간 강결합 제거 | 동기 HTTP 호출 제거 → 비동기 메시지 기반 통신 |
장애 전파 차단 | 외부 서비스 실패가 주문 서비스까지 전파되지 않도록 격리 |
6.2 이벤트 흐름
결제 승인 성공 흐름
1.
payment-service → payments-paid 발행
2.
order-service consume → 주문 상태 PREPARING 로 변경
결제 승인 실패(보상 흐름)
1.
payment-service → payments-failed 발행
2.
order-service consume → 주문·쿠폰 원복 (idempotent)
3.
order-service → orders-failed 발행
4.
product-service consume → 재고 롤백
6.3 Topic 설계
이벤트 | Topic 명 | 발행 주체 | 소비 주체 |
결제 승인 성공 | payments-paid | payment-service | order-service |
결제 승인 실패 | payments-failed | payment-service | order-service |
주문 보상 실패 | orders-failed | order-service | product-service |
6.4 Kafka 클러스터 구성
항목 | 값 | 이유 |
Broker 개수 | 3개 | Quorum(2) 확보, 고가용성 |
Partition 수 | 3개 | Broker 수의 배수 → Leader 분산 |
Replica 수 | 3개 | 장애 시에도 메시지 유실 방지 |
보관 기간 | 7일 | 비정상 이벤트 재처리 대비 |
6.5 Consumer Group 전략
•
서비스별 1 Consumer Group
◦
주문(Rebalancing) 문제를 줄이고 안정적인 메시지 처리를 위해
order-service-group, product-service-group 형태로 구성
•
같은 그룹 내에서는 메시지 병렬성 = Partition 수
◦
현재 Partition=3 → 3개 인스턴스까지 병렬 처리 가능
•
Exactly Once 보장
◦
Consumer는 메시지를 처리 성공 시 명시적으로 Commit
◦
실패 시 Commit하지 않고 DLQ로 이동 → 재처리 가능
6.6 DLT (Dead Letter Topic)
Kafka에서 Consumer가 메시지 처리에 실패할 경우, 해당 메시지는 DLT(Dead Letter Topic)
으로 이동하며 재처리 또는 수동 복구를 위한 근거 데이터로 사용된다.
DLT 적용 포인트
실패 위치 | DLT 활용 이유 |
order-service (payments-failed 처리 실패) | 주문/쿠폰 원복 실패 시 반드시 재처리 필요 |
product-service (orders-failed 처리 실패) | 재고 원복 실패 시 비즈니스 장애 유발 |
DLT 메시지 스키마
1) payments.failed 처리 실패 이벤트
필드 | 내용 |
orderId | 주문 ID |
paymentKey | PG 결제 키 |
errorSource | order-service or product-service |
errorCode | 내부 에러 코드 |
errorMessage | 오류 메시지2) orders-failed 처리 실패 |
timestamp | 실패 발생 시각 |
2) orders.failed 처리 실패 이벤트
필드 | 내용 |
orderDetailId | 주문 상세 ID |
optionValueId | 옵션 ID |
quantity | 원복해야 하는 수량 |
paymentKey | PG 결제 키 |
errorSource | order-service or product-service |
errorCode | 내부 에러 코드 |
errorMessage | 오류 메시지 |
DLT 활용 전략
1.
DLT Consumer를 통한 자동 재처리
•
일시적 장애(잠깐의 DB 락, 네트워크 지연 등)는 재처리 시 성공 가능
•
주문/재고 시스템 데이터 정합성을 위해 반드시 필요
2.
운영자 수동 재처리
•
구조적 장애(논리적 오류, 스키마 문제 등)는 수동 조치 필요
3.
DLT 모니터링
•
Grafana / CloudWatch에서 DLT 적재량을 모니터링해 운영 장애 조기 감지
•
특정 Topic의 DLT 증가 = 특정 서비스 장애로 볼 수 있음
6.7 멱등성(Idempotency) 전략
중복 메시지 처리 및 중복 결제 실행 방지를 위한 멱등성 처리 전략.
1) 결제하기 API 멱등성 – Toss Idempotency-Key
•
클라이언트에서 UUIDv4 기반 명등키 Idempotency-Key 생성 및 전달
•
토스페이먼츠가 서버 내부적으로 멱등 처리
•
ALREADY_PROCESSED_PAYMENT 응답 시 → 보상 트랜잭션 실행 금지
2) Consumer 멱등성
•
Kafka 메시지는 At-Least-Once가 기본이므로 동일 메시지가 중복 전달될 가능성 존재
•
Consumer는 DB 상태 기반 멱등성 체크 필요
예시 (order-service):
if (order.status == FAILED) return
if (order.status == PREPARING) return
Java
복사
6.8 Producer 발행 실패 처리
방안 1) Transactional Outbox Pattern
DB 업데이트 + Event 저장을 하나의 트랜잭션으로 묶어 원자성 보장
장점:
•
Kafka 장애에도 데이터 유실 없음
•
재처리 가능
방안 2) 발행 실패 재시도 테이블 + 스케줄러
•
publishStatus = FAILED 마킹
•
스케줄러가 1분 간격 재시도
•
Exponential Backoff 적용 가능
6.9 PENDING 장기 체류 주문 스케줄러
결제 지연·외부 서비스 오류로 인해 5분 이상 PENDING 상태로 남아있는 주문 정리 로직
실행 전략
•
스케줄 주기: 1분
•
타임아웃 기준: 5분
처리 방식
1.
5분 이상 PENDING 주문 조회
2.
주문 상태 FAILED로 변경
3.
쿠폰 / 재고 롤백 요청 발행
4.
DB 업데이트 후 Kafka에 보상 이벤트 발행
개선 방안
1.
외부 시스템 호출을 비동기 이벤트 기반으로 전환 (최적 방식)
•
주문 서비스는 DB 업데이트 + Kafka 이벤트 발행으로 작업 종료
•
product/payment 서비스가 토픽을 구독하여 자체적으로 롤백 실행
•
응답 대기 시간이 없으므로 안정성 + 성능 개선
2.
청크 처리 (대량 주문 대비)
•
PENDING 주문을 전체 조회하지 않고 chunk 단위로 처리
•
시스템 부하 감소
•
실패 시 특정 chunk만 재처리 가능
7. CI/CD 파이프라인
GitOps 파이프라인 다이어그램
GitHub Actions (CI)
•
Lint → Build → Test → Docker Build → ECR Push
•
Helm values 업데이트
ArgoCD (CD)
•
GitOps Repo 상태를 기준으로 EKS 상태 자동 동기화
•
Health/Sync 자동 관리
•
Helm-Based Release 관리
•
데이터 보존을 위한 EBS Volume 또는 EFS Volume 마운트 고려
◦
ArgoCD는 GitOps 기반의 stateless 운영 모델을 사용하므로 별도의 EBS/EFS 마운트 불필요
◦
ArgoCD는 Kubernetes 리소스를 Git 저장소를 통해 재생성할 수 있으므로,
EKS 클러스터 재생성 시에도 Git 상태를 기준으로 전체 상태 복구 가능
8. 배포 전략 - Canary
우선적으로는 Istio VirtualService 기반의 수동 Canary 방식으로 운영
도입 배경
•
Blue/Green 대비 더 안전한 점진적 배포 제공
•
Istio VirtualService 기반 트래픽 분할 가능
•
서비스 안정성 확보를 위한 점진적 검증
•
GitOps 기반 배포 이력 보존
8.1 배포 흐름
1.
신규 버전 배포
2.
DestinationRule을 통한 v1/v2 Subset 정의
3.
VirtualService 기반 Canary 트래픽 설정
•
v1: 90%, v2: 10%
4.
Grafana + Tempo + Loki 기반 모니터링
•
Latency/Error, Log, Trace
5.
오류 시 Rollback
•
v1 = 100%
6.
정상 동작 시 트래픽 확대
•
10 → 30 → 50 → 100
8.2 Canary 배포 단계
단계 | 트래픽 비율 | 수행 항목 | 성공 기준 |
Phase 0 | 0% → 10% | 신규 버전(v2) 배포, VirtualService weight 10% 적용 | Pod Ready 100%, 오류 없음 |
Phase 1 | 10% → 30% | 주요 API 응답 검증 | Latency 증가 < 200ms, Error Rate < 1% |
Phase 2 | 30% → 50% | 실제 사용자 트래픽 점진적 반영 | 5xx < 0.3%, Business Error < 1% |
Phase 3 | 50% → 100% | 전체 트래픽 전환 | Pod 안정화, 로그 이상 없음 |
8.3 Canary 실패 기준 (Rollback 조건)
Rollback은 즉시 VirtualService를 Stable(v1)로 전환하여 처리한다.
분류 | 조건 |
HTTP 오류율 | 5xx 비율 3% 이상 (1분 평균) |
Latency 증가 | 평균 응답속도 200ms 이상 증가 |
애플리케이션 오류율 | Business Error 1% 이상 |
Readiness 실패 | 신규 Pod Ready 실패 |
리소스 임계치 | CPU > 80%, Memory > 85% |
8.4 구성 요소
요소 | 역할 |
Deployment (v1/v2) | 버전별 Pod |
DestinationRule | Subset 정의 (labels 기반) |
VirtualService | 트래픽 비율 조정 |
Envoy Sidecar | 실제 트래픽 분배 수행 |
ArgoCD Sync | GitOps 기반 자동 배포 |
8.5 고려사항 (Manual Canary 운영 관점)
항목 | 설명 |
Observability | Grafana / Loki / Tempo 통합 필요 |
Sticky Session | 세션 일관성 확보가 필요한 API에 대한 Session Redis 호환성 검증 필요 |
테스트 자동화 필요성 | Canary 단계별 검증을 위한 k6/JMeter 등의 API Test 구성 고려 |
Resource Impact | v1/v2 동시 운영으로 인한 Pod 수 증가 → HPA/Karpenter |
향후 확장성 | 현재는 프로젝트 기간 고려하여 수동 Canary 운영 방식 적용
향수 Auto Rollback을 도입할 경우 Argo Rollouts + AnalysisTemplate 기반 확장 |
9. 오토스케일링 전략
9.1 Pod Autoscaling (HPA)
9.1.1 HPA 정책 기준
•
CPU 사용률 > 70%
•
Memory 사용률 > 75%
•
Target Metric 기반 자동 확장
•
Canary 배포시 v1 + v2 Pod 동시 존재 고려
•
Karpenter Node 생성 시간을 고려한 최소 Replica 버퍼 전략 적용
9.1.2 서비스별 HPA minReplicas 버퍼 전략
Karpenter의 Node Provisioning 시간동안 기존 Pod가 과부하되지 않도록 최소 Replica를 여유있게 유지한다.
서비스 유형 | 트래픽 특성 | 초기 구성 minReplica 버퍼 |
Gateway (Ingress) | 외부 요청 집중, Latency 민감 | 평시 Pod의 150% |
Order / Payment | Latency 민감, 장애 영향 큼 | 130~150% |
Product | 높은 조회 빈도 | 120~130% |
User | 일반 API | 120% |
AI | 중요도 낮음, 사용량 적음 | 100~110% |
9.1.3 서비스별 HPA 설정
서비스 | Min~Max | 특징 |
Gateway (Ingress) | 3~6 | 요청 집중 구간, 안정성 중요 |
User/Product | 2~10 | 조회 중심, 트래픽 변동폭 큼 |
Order/Payment | 2~5 | 주문/결제 중심, 안정성 중요 |
AI | 1~2 | 최소 유지 |
9.1.4 Requests / Limits
•
임시 - GPT 추천값 / 추후 모니터링 반영 조정
서비스 | CPU Request | CPU Limit | Memory Request | Memory Limit |
Gateway | 250m | 500m | 512Mi | 1Gi |
User/Product | 200m | 400m | 256Mi | 512Mi |
Order | 200m | 500m | 512Mi | 1Gi |
Payment | 300m | 600m | 512Mi | 1Gi |
AI | 100m | 300m | 256Mi | 512Mi |
9.2 NodeAutoscaling (Karpenter)
•
Karpenter를 도입하여 자동 Node Provisioning을 목표로 함
9.2.1 Karpenter 도입 배경
문제 | 설명 |
ECS / 기존 EKS의 한계 | Pod 증가 시 NodeGroup의 scale-out 속도가 느림 |
고정 노드 비용 발생 | 항상 Node를 유지해야 해서 비용 증가 |
Canary 배포 시 Pod 일시 증가 | Canary 실행 시 v1+v2 Pod 동시 운영 → 노드 부족 발생 |
트래픽 변동성 | Product, Order 서비스의 트래픽 변동 폭이 큼 |
9.2.2 Karpenter 동작 흐름
HPA가 Pod 증가
→ 기존 Node capacity 부족 → Pod Pending 발생
→ Node Provisioning (Karpenter)
→ Pod Scheduling 완료
→ 트래픽 감소 → Idle Node 발생
→ Idle Node 자동 제거 (Consolidation)
Plain Text
복사
9.2.3 Autoscaling 고려사항
•
Karpenter Provisioning 시간동안 기존 Pod의 과부화 방지를 위한 minReplicas 버퍼 적용
•
Canary 배포 시 v1/v2 Replica 동시 증가 → Karpenter 즉각 확장 필수
•
트래픽 감소 시 Consolidation을 통해 비용 최소화
•
Pod 요청(Request)이 낮게 잡히면 과도한 확장 발생하므로 적절한 Request 필요
•
Spot Instance 사용 고려
10. Observability
10.1 구성요소
계층 | 구성 요소 | 역할 |
Metrics | Prometheus | 애플리케이션·Istio·Node 메트릭 수집 |
Logs | Fluentbit → Loki | stdout 로그 수집 및 저장 |
Tracing | Envoy / Spring Boot OTel → OTel Collector → Tempo | 분산 트레이싱 저장 |
Dashboard | Grafana | Metrics / Logs / Tracing 시각화 |
Infra Logs | CloudWatch Logs | Node, Control Plane, EKS Infra 로그 저장 |
10.2 Metrics 수집 흐름
10.2.1 애플리케이션 / 서비스 메트릭
•
Spring Boot Actuator의 /actuator/prometheus 활용
•
Prometheus Operator를 사용하여 메트릭 수집
•
서비스별 ServiceMonitor를 통해 Scrape
데이터 흐름:
Application Pod (/actuator/prometheus)
→ ServiceMonitor
→ Prometheus
→ Grafana
Plain Text
복사
10.2.2 Istio (Envoy) 메트릭
•
Istio Telemetry v2 활성화
•
Prometheus가 Istio의 Envoy Proxy를 Scrape
•
ServiceMonitor 활용
Envoy SideCar
→ Prometheus (ServiceMonitor)
→ Grafana (Istio Dashboard)
Plain Text
복사
10.2.3 Node / 시스템 메트릭
•
구성요소
◦
kube-state-metrics
◦
node-exporter (PodMonitor 활용)
•
수집 지표
◦
CPU / Memory
◦
Pod 상태
◦
Node 상태 / Disk I/O
◦
네트워크 등 인프라 자원 상태 모니터링
10.3 Logs 수집 흐름
구성 요소
•
FluentBit DaemonSet
•
Loki
•
S3
로그 흐름
Container stdout/stderr
→ Fluentbit
→ Loki → S3
→ Grafana
Plain Text
복사
Fluentbit 주요 필터
•
JSON Log Parser
•
Level 필터
10.4 Tracing 수집 흐름
Tracing은 Envoy(네트워크 레벨) + Application(비즈니스 레벨) 모두 수집하며, OTel Collector를 거쳐 Tempo에 저장
10.4.1 Envoy → Tempo(Zipkin)
1.
Envoy가 Zipkin 포맷으로 Trace 생성
•
Istio Proxy(Envoy)는 Zipkin 포맷 Trace를 기본 지원
•
Ingress Gateway, Sidecar 모두 Span 생성
2.
OTel Collector가 Zipkin 포맷 수신
•
Collector의 Zipkin Receiver가 Envoy에서 보낸 데이터를 수신
•
내부적으로 OTLP로 변환 → Tempo로 Export
3.
Collector에서 Tempo로 Export
데이터 흐름
Envoy (Zipkin)
→ OTel Collector (zipkin receiver)
→ OTel Collector (otlp exporter)
→ Tempo
→ Grafana
Plain Text
복사
10.4.2 Application → Tempo (OTLP)
Java 서비스를 OpenTelemetry Java Agent로 구성하여 OTLP/gRPC로 Trace 전송
Application (OTLP → grpc)
→ OTel Collector (otlp receiver)
→ Tempo (otlp exporter)
→ Grafana
Plain Text
복사
10.4.3 End-to-End 트레이싱
Envoy Span과 Application Span은 동일 Trace ID를 공유하여 하나의 전체 트랜잭션 흐름으로 결합된다.
11. 고가용성 & 장애 복구 전략
•
EKS Multi-AZ NodeGroup 운영
•
RDS Multi-AZ Failover
•
Redis Multi-AZ
•
ArgoCD Rollback
•
S3 Versioning
•
Terraform 기반 인프라 re-provision
12. 비용 관리 전략
항목 | 전략 |
EKS | NodeGroup 온디맨드 최소 유지 + Karpenter 자동 확장 |
Node | Consolidation으로 Idle Node 최소화 |
NAT Gateway | Dev/Stage 최소 구성 |
CloudWatch Logs | 15일 보관 |
Redis | ClusterMode Off |
MSK | 결제 서비스 중심 최소 구성 |
ECR | Private ECR 사용 |




