티스토리 뷰
project/맥미니로 시작하는 쿠버네티스
쿠버네티스 실습: Helm Chart로 NestJS + NextJS + PostgreSQL + Redis 통합 배포하기
octo54 2025. 9. 15. 14:02반응형
쿠버네티스 실습: Helm Chart로 NestJS + NextJS + PostgreSQL + Redis 통합 배포하기
앞선 글에서는 Helm Chart에 ConfigMap, Secret, PVC, Ingress, HPA를 통합해 실제 서비스 수준의 배포 패키지를 구성했습니다.
이번 글에서는 우리가 목표로 하는 프로젝트, 즉 NestJS + NextJS + PostgreSQL + Redis 기반의 위치 기반 주유소 정보 시스템을 Helm Chart 하나로 배포하는 과정을 실습합니다.
1) 전체 아키텍처
구성 요소:
- NestJS: 백엔드 API 서버
- NextJS: 프론트엔드 웹 애플리케이션
- PostgreSQL: 주유소 데이터 저장소
- Redis: 캐싱/세션 관리
- Ingress: 외부 트래픽 라우팅
- PVC: PostgreSQL 데이터 영속성
- ConfigMap/Secret: 환경 변수 및 민감 정보 관리
- HPA: 트래픽에 따른 Pod 오토스케일링
구조 다이어그램:
[사용자] → [Ingress] → [NextJS Service]
→ [NestJS Service] → [PostgreSQL PVC]
→ [Redis Service]
2) Chart 구조
fuelstation-app/
Chart.yaml
values.yaml
templates/
deployment-backend.yaml
deployment-frontend.yaml
service-backend.yaml
service-frontend.yaml
postgres-statefulset.yaml
postgres-service.yaml
redis-deployment.yaml
redis-service.yaml
configmap.yaml
secret.yaml
pvc.yaml
ingress.yaml
hpa.yaml
3) values.yaml
반응형
image:
backend: <DOCKER_USERNAME>/nestjs-app:latest
frontend: <DOCKER_USERNAME>/nextjs-app:latest
postgres: postgres:15
redis: redis:7
service:
backendPort: 3000
frontendPort: 3000
dbPort: 5432
redisPort: 6379
ingress:
hostBackend: api.fuel.local
hostFrontend: www.fuel.local
persistence:
dbSize: 1Gi
secrets:
dbPassword: supersecret
hpa:
backendTargetCPU: 60
frontendTargetCPU: 50
4) Deployment 예시 (NestJS 백엔드)
templates/deployment-backend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-backend
spec:
replicas: 2
selector:
matchLabels:
app: {{ .Release.Name }}-backend
template:
metadata:
labels:
app: {{ .Release.Name }}-backend
spec:
containers:
- name: nestjs
image: {{ .Values.image.backend }}
ports:
- containerPort: {{ .Values.service.backendPort }}
env:
- name: DATABASE_URL
value: "postgres://postgres:{{ .Values.secrets.dbPassword }}@{{ .Release.Name }}-postgres:{{ .Values.service.dbPort }}/fuel"
- name: REDIS_URL
value: "redis://{{ .Release.Name }}-redis:{{ .Values.service.redisPort }}"
5) PostgreSQL StatefulSet
templates/postgres-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ .Release.Name }}-postgres
spec:
serviceName: {{ .Release.Name }}-postgres
replicas: 1
selector:
matchLabels:
app: {{ .Release.Name }}-postgres
template:
metadata:
labels:
app: {{ .Release.Name }}-postgres
spec:
containers:
- name: postgres
image: {{ .Values.image.postgres }}
ports:
- containerPort: {{ .Values.service.dbPort }}
env:
- name: POSTGRES_PASSWORD
value: {{ .Values.secrets.dbPassword | quote }}
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: postgres-storage
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: {{ .Values.persistence.dbSize }}
6) Redis Deployment
templates/redis-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-redis
spec:
replicas: 1
selector:
matchLabels:
app: {{ .Release.Name }}-redis
template:
metadata:
labels:
app: {{ .Release.Name }}-redis
spec:
containers:
- name: redis
image: {{ .Values.image.redis }}
ports:
- containerPort: {{ .Values.service.redisPort }}
7) Ingress 예시
templates/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ .Release.Name }}-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: {{ .Values.ingress.hostBackend }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ .Release.Name }}-backend
port:
number: {{ .Values.service.backendPort }}
- host: {{ .Values.ingress.hostFrontend }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ .Release.Name }}-frontend
port:
number: {{ .Values.service.frontendPort }}
8) 배포 및 검증
8-1. Chart 배포
helm install fuelstation ./fuelstation-app
8-2. 리소스 확인
kubectl get all
kubectl get ingress
8-3. 도메인 매핑
/etc/hosts에 추가:
192.168.49.2 api.fuel.local www.fuel.local
브라우저 확인:
- http://api.fuel.local → NestJS API
- http://www.fuel.local → NextJS 프론트엔드
9) 정리
- Helm Chart를 활용해 **백엔드(NestJS) + 프론트엔드(NextJS) + DB(PostgreSQL) + 캐시(Redis)**까지 통합 배포 완료.
- ConfigMap/Secret/PVC/Ingress/HPA 등 운영 필수 리소스를 포함해 실제 서비스 운영 가능한 구조 확보.
- 이제부터는 클라우드(Kubernetes on GCP, AWS, Azure) 환경으로 옮겨도 큰 변경 없이 배포 가능.
다음 글에서는 **운영 환경에서 발생할 수 있는 트러블슈팅 사례 (CrashLoopBackOff, PVC 바인딩 실패, Ingress 문제 등)**를 실제 시나리오로 정리해보겠습니다.
쿠버네티스,Helm,통합배포,NestJS,NextJS,PostgreSQL,Redis,DevOps,Minikube,K8s실습
✅ 좋았던 부분
먼저 장점부터요:
- ConfigMap, Secret, PVC, Ingress, HPA가 한 차트에 포함되어 있어 “풀스택 배포” 느낌이 강해짐
- NestJS + NextJS + PostgreSQL + Redis 조합은 실제 프로젝트 환경에서 자주 쓰이는 조합임
- values.yaml 통해 이미지, 포트, 크기, 호스트, 비밀값 등이 명확히 분리되어 있어 환경 간 설정 차별 가능
⚠️ 보완/주의할 점 & 웹 자료 참고
아래 항목들은 실습 중 흔히 발생하는 오류나 혼란을 줄이기 위해 보강되면 좋습니다.
항목 설명 & 개선 제안 관련 웹 자료
| Ingress rewrite-target & pathType 사용 주의 | Ingress에서 nginx.ingress.kubernetes.io/rewrite-target을 사용할 땐 path 패턴을 적절히 설정해야 하고, use-regex: "true" 등의 설정이 필요할 수 있음. 기본 / path 사용 시 rewrite가 불필요하거나 오히려 잘못된 라우팅을 유발할 수 있음. 예: pathPrefix 사용하는 방식이나 regex 캡처 그룹을 쓰는 방식. 또한, Ingress 클래스(ingressClassName 또는 annotation) 명시하는 것이 안정적임. | NGINX Ingress 공식 문서: rewrite-target 예시들 (kubernetes.github.io) “Nginx Ingress & rewrite-target” 스택오버플로우 Q&A에서 capture group 사용 예 (Stack Overflow) |
| Helm 차트 구조와 Best Practices | 차트 버전 관리, Chart.yaml 내 version vs appVersion 구분, dependency 사용 여부 등의 기본 원칙을 지키면 좋음. 예: PostgreSQL, Redis 같은 부품을 umbrella chart 또는 subcharts로 분리하면 유지보수가 쉬워짐. 또한, values.yaml 안에 기본값과 optional 설정(예: Ingress enabled 여부, HPA enabled 여부)을 넣고, templates 안에 if 분기 처리 추가하여 유연성 확보. | Helm 공식 “Chart Best Practices Guide” 문서 (helm.sh) Plural.sh의 “Kubernetes Helm Charts: A Practical Guide” 에서도 구조화/버전 관리 중요성 강조됨 (plural.sh) |
| Secret / DB 접속 정보 보안 | Secret 값이 values.yaml에 노출되는 형태이면 실습엔 괜찮지만, 운영 환경에선 암호화 또는 외부 Secret Manager 연동 방식 고려해야 함. Helm 차트에서는 secrets 블록을 optional로, 또는 stringData vs data 방식 명확히 구분되도록 하면 좋음. | |
| PVC + StatefulSet 주의 | PostgreSQL StatefulSet 사용 시, VolumeClaimTemplates 이름/스토리지 클래스 지정 등이 필요함. 또한, 리소스 제한(Requests/Limits)도 설정하면 안정성 증가. 또한, StorageClass 기본 설정 여부(동적 프로비저닝) 확인 필요. | |
| HPA 설정 시 조건 명확화 | HPA를 enabled 옵션으로 감출 수 있게 하고, resources.requests 및 limits 설정이 반드시 포함된 Deployment 템플릿이어야 HPA가 정상 작동. 또한, Backend/Frontend 각각 따로 HPA 붙이는 경우 트래픽 패턴 차이를 고려해서 타겟 CPU %, 최소/최대 replica 수 조정 필요. | |
| Helm values override 및 여러 환경 지원 | 예: values-staging.yaml, values-prod.yaml 같이 환경별 값 파일 두고, helm install/upgrade --values 또는 --set 활용하는 패턴을 문서로 포함하면 좋음. 운영 환경에서는 롤백/upgrade 테스트 포함하는 것이 베스트 프랙티스. |
🔄 수정/보강 예시 제안
아래는 제안하신 배포 예시에 위 사항을 반영한 수정안 일부입니다.
# templates/ingress.yaml 일부 예
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ .Release.Name }}-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
{{- if .Values.ingress.forceSSLRedirect }} nginx.ingress.kubernetes.io/force-ssl-redirect: "true" {{- end }}
{{- if .Values.ingress.rewriteTarget }} nginx.ingress.kubernetes.io/rewrite-target: {{ .Values.ingress.rewriteTarget }} {{- end }}
spec:
ingressClassName: nginx
rules:
- host: {{ .Values.ingress.hostBackend }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ .Release.Name }}-backend
port:
number: {{ .Values.service.backendPort }}
- host: {{ .Values.ingress.hostFrontend }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ .Release.Name }}-frontend
port:
number: {{ .Values.service.frontendPort }}
# values.yaml 일부 예시 보강
ingress:
enabled: true
hostBackend: api.fuel.local
hostFrontend: www.fuel.local
forceSSLRedirect: false
rewriteTarget: "/$1" # 필요 시만 사용하는 옵션
hpa:
enabled: true
backendTargetCPU: 60
backendMinReplicas: 1
backendMaxReplicas: 5
frontendTargetCPU: 50
frontendMinReplicas: 1
frontendMaxReplicas: 3
'project > 맥미니로 시작하는 쿠버네티스' 카테고리의 다른 글
| 쿠버네티스 실습: 운영 환경 트러블슈팅 사례 정리 (0) | 2025.09.18 |
|---|---|
| 쿠버네티스 실습: 운영 환경 트러블슈팅 사례 정리 (0) | 2025.09.17 |
| 쿠버네티스 실습: Helm Chart에 ConfigMap · Secret · PVC · Ingress · HPA 통합하기 (0) | 2025.09.10 |
| 쿠버네티스 실습: Helm Chart로 애플리케이션 배포 자동화하기 (0) | 2025.09.09 |
| 쿠버네티스 실습: 네임스페이스와 RBAC 기초 (0) | 2025.09.08 |
※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 쿠버네티스
- kotlin
- Prisma
- JWT
- nextJS
- LangChain
- seo 최적화 10개
- Next.js
- Redis
- 개발블로그
- ai철학
- node.js
- DevOps
- Docker
- Python
- JAX
- fastapi
- SEO최적화
- REACT
- 생성형AI
- 딥러닝
- rag
- NestJS
- CI/CD
- PostgreSQL
- flax
- 웹개발
- Express
- 백엔드개발
- llm
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
글 보관함
반응형

