← Projects
Resume

KT CLOUD TECH UP · 실무 프로젝트

Hotel Booking · GitOps & Observability

특가 오픈 순간 트래픽이 몰리는 호텔 예약 MSA를 Terraform으로 만든 EKS에 올리고, push 한 번으로 dev/prod까지 이어지는 배포 흐름을 만들었습니다.

PERIOD2026.07
TEAM3인
ROLE팀장 · 인프라 & CI/CD
STACKEKS · Terraform · GitHub Actions · ArgoCD
SYSTEM ARCHITECTURE
Hotel Booking Observability 통합 구성도: ALB Ingress 뒤의 hotel-frontend와 user · search · event · notice 서비스, PostgreSQL · Redis, Prometheus · Loki · Tempo · Grafana 관찰성 3축, GitHub Actions → ECR → Argo CD → Kubernetes → Slack으로 이어지는 CI/CD

특가 오픈처럼 짧은 시간에 요청이 몰리는 상황에서도, 배포는 사람 손을 타지 않고 장애는 한 화면에서 찾을 수 있는 운영 환경을 목표로 했습니다.

Next.js 프론트엔드와 Spring Boot 4개 서비스(회원 · 검색 · 예약 · 알림)로 구성된 호텔 예약 MSA를 AWS EKS에 올렸습니다. 팀장이자 인프라 · CI/CD 담당으로 Terraform 기반 EKS 구성, GitHub Actions CI, Helm Chart, ArgoCD GitOps 배포와 dev/prod 환경 분리를 맡았습니다. 팀원은 대기열 · 재고 로직과 분산 추적(MSA 개발), 메트릭 · 로그 · 알림(Observability 스택)을 담당했습니다.

PROJECT GOAL배포 자동화 + 3축 관찰성

Build → Scan → Deploy → Observe → Alert를 하나의 운영 흐름으로 연결했습니다.

MY ROLE팀장 · Infra & CI/CD

클러스터부터 배포 파이프라인, 환경 분리까지 서비스가 올라가는 경로 전체를 담당했습니다.

ENVIRONMENTdev / prod 분리

브랜치(joon / main), Namespace, Helm values 파일로 환경을 나눴습니다.

VERIFYK6 1,000명 버스트 · 장애 주입

특가 트래픽과 서비스 중단 상황에서 정합성, 알림, 복구 흐름을 확인했습니다.

GitHub Push변경 서비스 감지
→
GitHub ActionsTest · Build · Trivy
→
Amazon ECR7자리 SHA Tag
→
Helm valuesyq로 Tag 갱신 · 커밋
→
ArgoCDAuto Sync · selfHeal
→
EKSdev / prod Namespace
TERRAFORMEKS 클러스터 코드화

terraform-aws-modules/eks로 t3.medium 노드 그룹(3대, 1~4대)과 IRSA를 구성하고, Access Entry로 팀원 권한을 부여했습니다. ArgoCD도 Terraform Helm Release로 함께 설치했습니다.

CI변경된 서비스만 빌드하는 Matrix

paths-filter로 바뀐 서비스만 골라 Matrix를 만들고, 백엔드는 Postgres · Redis 서비스 컨테이너를 띄워 Gradle 테스트, 프론트엔드는 npm 빌드를 실행했습니다.

SECURITYTrivy 스캔으로 Push 차단

이미지를 로컬에 먼저 빌드하고 HIGH · CRITICAL 취약점이 있으면 실패시켜, 검사를 통과한 이미지만 ECR에 올라가도록 했습니다.

GITOPSSHA Tag → values 갱신 → 자동 Sync

CI가 이미지 Tag를 Helm values에 커밋하면 ArgoCD가 감지해 배포합니다. App of Apps(root-dev / root-prod)와 prune · selfHeal로 클러스터를 Git 상태에 맞췄습니다.

PROD GUARDprod 배포 전 매니페스트 검증

prod 파이프라인은 helm lint와 렌더링 후 namespace: dev, targetRevision: joon, 빈 값이 섞여 있으면 실패하도록 해 dev 설정 유입을 막았습니다.

HELM공통 기본값 + 서비스별 Override

단일 hotel Chart에서 serviceDefaults를 서비스별 값과 병합했습니다. HPA(2~5, CPU 70%), 무중단 Rolling Update(maxUnavailable: 0), ALB Ingress 경로 라우팅을 공통으로 적용했습니다.

ALB에서 로그인 후 401 반복

증상EKS에 배포한 뒤 로그인 API는 성공하지만, 이후 인증이 필요한 요청에서 401이 반복됐습니다.
원인JWT 쿠키에 Secure 속성이 붙어 있었는데 ALB가 HTTP로만 열려 있어, 브라우저가 쿠키를 저장하지 않았습니다.
해결Secure 적용 여부를 환경 변수(COOKIE_SECURE)로 분리하고, 환경별 Helm values에서 값을 주입하도록 변경했습니다.
결과ALB를 통한 로그인 후 쿠키가 정상 저장되고, 마이페이지 · 예약 API가 401 없이 동작

배포 직후 Pod 반복 재시작

증상배포 직후 Spring Boot Pod가 준비되기 전에 재시작을 반복했습니다.
원인애플리케이션 초기화가 끝나기 전에 Liveness Probe가 실패로 판정했습니다.
해결Chart 공통값에서 initialDelaySeconds를 45초, failureThreshold를 6으로 올려 초기화 시간을 확보했습니다.
결과시작 중 불필요한 재시작이 줄고, 배포 후 Pod가 안정적으로 Ready 상태에 도달

클러스터에서만 API 호출 실패

증상로컬에서는 동작하던 프론트엔드 API 호출이 EKS 환경에서는 실패했습니다.
원인서비스마다 CORS 설정이 흩어져 있었고, 프론트엔드가 로컬 서비스 주소를 직접 호출하고 있었습니다.
해결CORS 설정을 공통화하고 API 호출을 상대경로로 바꾼 뒤, ALB Ingress에서 /api/v1/* 경로별로 서비스에 라우팅했습니다.
결과대기열(/api/v1/queue)을 포함한 API가 Ingress를 통해 정상 전달되어, 로컬과 클러스터 양쪽에서 동작

배포한 환경 위에서 특가 트래픽과 장애 상황을 실제로 재현해 확인했습니다.

재고 30개 특가에 1,000명이 동시에 구매하는 상황을 K6로 재현했습니다. 대기열 슬롯 미반납, 토큰 발급 경쟁 상태 같은 병목은 팀원이 수정했고, 최종 테스트에서 정합성 목표는 충족했습니다. 다만 전체 요청 p95는 239ms로 목표(200ms)에 닿지 못했습니다. 장애 주입은 event-service Replica를 0으로 줄여 Slack ServiceDown 알림과 복구 후 RESOLVED 알림을 확인했고, ArgoCD에서 hotel-prod가 Synced · Healthy로 유지되는 것을 확인했습니다.

LOAD TEST오버셀 0건

K6 1,000명 · 재고 30

ERROR시스템 오류 0%

매진(409)은 정상 응답으로 분리

DEPLOY5개 서비스 · 2개 환경

push 한 번으로 자동 배포

아쉬운 점클러스터에서만 생기는 로그 · 트레이스 유실을 끝까지 좁히지 못함

로컬에서는 메트릭 · 로그 · 트레이스가 모두 연결됐지만, EKS에서는 일부 서비스 로그가 Loki로 전송되지 않고 일부 POST 요청의 Span이 Tempo에 남지 않은 채로 마무리했습니다.

다시 한다면

배포 후 검증 단계에 로그 · 트레이스 수집 여부 확인을 넣어, 환경 차이를 배포 시점에 바로 잡겠습니다.

아쉬운 점버스트 트래픽의 응답시간 목표 미달

정합성은 지켰지만 1,000명이 동시에 몰리는 순간의 p95는 239ms로 목표를 넘었습니다. HPA는 CPU 기준이라 짧은 버스트에 대응하는 확장 전략은 검증하지 못했습니다.

다시 한다면

대기열 길이나 요청량 같은 지표 기반 스케일링과 특가 오픈 전 사전 확장을 함께 검토하겠습니다.

Tech Stack: AWS EKS · Terraform · GitHub Actions · Amazon ECR · Trivy · Helm · ArgoCD · ALB Ingress · Prometheus · Loki · Tempo · Grafana · Alertmanager · Slack · K6