[챌린지 #2] 팀 프로젝트 K8s 마이그레이션 - Part 1: 프로젝트 분석 & 전략
🎯 챌린지 배경
이번 챌린지는 이커머스 프로젝트를 K8s로 마이그레이션하는 과제였습니다. 원래는 내용이 없는 빈 프로젝트로 마이그레이션을 해보는 것이었는데, 저는 팀에서 작업하고 있는 프로젝트를 마이그레이션하며 진행하였습니다.
weAlist 프로젝트:
- 5명 팀 프로젝트 (회원/게시판/프론트)
- 현재 Docker Compose로 개발 중
- 이번 마이그레이션: 게시판(FastAPI) + 프론트(React) + PostgreSQL
회원 서비스는 아직 개발 중이라 이번에는 제외했습니다. 실무에서도 완성된 것부터 단계적으로 전환한다고 하니 따로 먼저 진행해보는 느낌으로 했습니다.
🏗️ 기존 구조 (Docker Compose)
기존에는 docker-compose 로 다음과 같이 구성되어 있습니다.
# docker-compose.yml (일부)
services:
postgres:
image: postgres:16-alpine
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: wealist
POSTGRES_USER: postgres
POSTGRES_PASSWORD: mysupersecret
board-api:
build: ./backend/services/kanban
ports:
- "8000:8000"
environment:
DATABASE_URL: postgresql://postgres:mysupersecret@postgres:5432/wealist
depends_on:
- postgres
frontend:
build: ./frontend
ports:
- "3000:80"
depends_on:
- board-api
실행은 잘 되지만 여기서 추가로 채팅같은 추가 기능들을 구현하기에는 여러모로 복잡성이 높은 프로젝트 입니다.
🤔 왜 K8s로 마이그레이션?
챌린지 요구사항
부트캠프 과제로 “기존 애플리케이션을 K8s로 전환”이라는 미션이 있었습니다. 네임스페이스 분리, 서비스 타입 활용, 스토리지 관리 같은 K8s 핵심 개념을 익히는 게 목표입니다.
실무 학습 목적
기존 과제는 구조만 이럴꺼다 하는 빈 프로젝트를 마이그레이션 해보자 였지만, 실제 프로젝트를 마이그레이션하면서 부딪혀보는 게 나중에 도움이 될 것 같아서 팀에서 진행하던 wealist 프로젝트를 마이그레이션 해보기로 하였습니다.
Docker Compose는 단일 서버에서 돌아가다 보니, 나중에 트랙픽이 늘거나 하면 스케일 아웃을 수동으로 하거나 해야되다보니 불편하지만, k8s 로 구축을 하게되면 자동 스케일 아웃 인을 설정할 수 있기 때문에 더 유연하다고 볼 수 있습니다.
📋 마이그레이션 전략
완성된 것부터 단계적으로
실무에서도 모든 서비스를 한 번에 전환하진 않는다고 합니다. 우리도 마찬가지로 나와있는것 부터 마이그레이션 해보기로 하였습니다.
Phase 1 (이번): 게시판 + 프론트 + PostgreSQL
- ✅ FastAPI 백엔드 (게시판)
- ✅ React 프론트 (nginx)
- ✅ PostgreSQL DB
Phase 2 (나중에): 회원 서비스 추가
- ⏸️ Spring Boot 백엔드 (회원)
- ⏸️ Redis 캐시
완성된 게시판과 프론트만 먼저 전환을 시도하고,나중에 회원 서비스를 추가할 예정입니다.
기술 스택 선택
로컬 클러스터: k3d
Minikube나 k3s도 있지만, k3d를 선택했습니다.
- Docker 컨테이너로 실행 (WSL2에서 안정적)
- 멀티 노드 클러스터 구성 가능
- 로컬 이미지 바로 사용 가능 (
k3d image import
)
네임스페이스 분리
- board-api-prod: 게시판 백엔드
- front-prod: 프론트엔드
- postgresql-prod: 데이터베이스
서비스별로 네임스페이스를 나눠서 리소스를 관리했습니다. 나중에 dev 환경도 추가할 수 있게 -prod
suffix를 붙여서 만들었습니다.
🎯 핵심 과제들
이번 마이그레이션에서 집중적으로 다룰 부분들은 다음과 같습니다.(상세설명은 각 part 에서 하겠습니다)
StatefulSet vs Deployment
PostgreSQL 같은 데이터베이스는 Deployment가 아니라 StatefulSet을 사용합니다.
Secret 관리
DB 비밀번호 같은 민감 정보는 ConfigMap이 아니라 Secret으로 관리합니다. 일단 여기서는 Base64 인코딩만 사용하고(실무에선 더 강력하게), 네임스페이스마다 따로 만들어야 합니다.
크로스 네임스페이스 통신
board-api-prod
네임스페이스의 Pod가 postgresql-prod
네임스페이스의 DB에 접근하려면 어떻게 해야 할까?
# 같은 네임스페이스:
postgres-service
# 다른 네임스페이스:
postgres-service.postgresql-prod.svc.cluster.local
💭 한번 더 생각해볼 질문들
Q1: Docker Compose에서 depends_on
을 썼는데, K8s에서는 서비스 간 시작 순서를 어떻게 보장할까?
Q2: 네임스페이스를 나눴는데, 만약 백엔드가 프론트엔드의 API를 호출해야 한다면? (서로 다른 네임스페이스)
Q3: 로컬에서 k3d로 개발하다가 실제 클라우드(EKS, GKE)로 배포할 때 뭘 바꿔야 할까?
🎯 추가 학습
- Docker Compose와 K8s 리소스 매핑
- 로컬 개발 환경 비교 (Minikube vs k3d vs kind)
- 마이그레이션 체크리스트