Merge pull request #45 from ktds-dg0501/feature/gappa

add build,deploy prototype
This commit is contained in:
hyeda2020 2025-10-31 13:28:30 +09:00 committed by GitHub
commit 61bb391568
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 842 additions and 0 deletions

View File

@ -0,0 +1,108 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kt-event-marketing-ceo
namespace: kt-event-marketing
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
ingressClassName: nginx
rules:
- host: ceo-api.kubepia.com
http:
paths:
# User Service
- path: /api/v1/users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 80
# Content Service
- path: /api/v1/content
pathType: Prefix
backend:
service:
name: content-service
port:
number: 80
# Event Service
- path: /api/v1/events
pathType: Prefix
backend:
service:
name: event-service
port:
number: 80
- path: /api/v1/jobs
pathType: Prefix
backend:
service:
name: event-service
port:
number: 80
- path: /api/v1/redis-test
pathType: Prefix
backend:
service:
name: event-service
port:
number: 80
# AI Service
- path: /api/v1/ai-service
pathType: Prefix
backend:
service:
name: ai-service
port:
number: 80
# Participation Service
- path: /api/v1/participations
pathType: Prefix
backend:
service:
name: participation-service
port:
number: 80
- path: /api/v1/winners
pathType: Prefix
backend:
service:
name: participation-service
port:
number: 80
- path: /debug
pathType: Prefix
backend:
service:
name: participation-service
port:
number: 80
# Analytics Service
- path: /api/v1/analytics
pathType: Prefix
backend:
service:
name: analytics-service
port:
number: 80
# Distribution Service
- path: /api/v1/distribution
pathType: Prefix
backend:
service:
name: distribution-service
port:
number: 80

View File

@ -0,0 +1,56 @@
# Git
.git
.gitignore
# IDE
.idea
.vscode
*.iml
# Build artifacts
target/
build/
*.class
*.jar
*.war
# Logs
logs/
*.log
# Temporary files
*.tmp
*.temp
*.swp
*~
# OS files
.DS_Store
Thumbs.db
# Documentation (except prototype files)
docs/
*.md
!README.md
# Test files
test/
tests/
*.test.js
# CI/CD
.github/
.gitlab-ci.yml
Jenkinsfile
# Dependencies (will be installed in container)
node_modules/
vendor/
# Deployment files (except what we need)
deployment/*
!deployment/uiux/nginx.conf
# Keep only prototype HTML files
design/*
!design/uiux/prototype/*.html

View File

@ -0,0 +1,21 @@
# Nginx 기반 프로토타입 배포 이미지
FROM nginx:1.25-alpine
# 메타데이터
LABEL maintainer="KT Event Marketing Team"
LABEL description="UI/UX Prototype for KT Event Marketing Service"
# 프로토타입 HTML 파일들을 nginx의 웹 루트로 복사
COPY design/uiux/prototype/* /usr/share/nginx/html/
# nginx 설정 파일 복사 (커스텀 설정이 필요한 경우)
COPY deployment/uiux/nginx.conf /etc/nginx/conf.d/default.conf
# 헬스체크 엔드포인트 추가
RUN echo '<!DOCTYPE html><html><body>OK</body></html>' > /usr/share/nginx/html/health
# 포트 노출
EXPOSE 80
# nginx 실행
CMD ["nginx", "-g", "daemon off;"]

339
deployment/uiux/README.md Normal file
View File

@ -0,0 +1,339 @@
# KT 이벤트 마케팅 프로토타입 배포 가이드
UI/UX 프로토타입을 Docker 컨테이너로 빌드하고 Kubernetes 클러스터에 배포하는 가이드입니다.
## 📋 목차
1. [사전 요구사항](#사전-요구사항)
2. [이미지 빌드](#이미지-빌드)
3. [로컬 테스트](#로컬-테스트)
4. [Kubernetes 배포](#kubernetes-배포)
5. [접속 및 확인](#접속-및-확인)
6. [문제 해결](#문제-해결)
---
## 🔧 사전 요구사항
### 필수 도구
- Docker (버전 20.10 이상)
- kubectl (버전 1.24 이상)
- Kubernetes 클러스터 (접근 권한 필요)
### 환경 변수 설정 (선택사항)
```bash
# Docker 레지스트리 설정
export DOCKER_REGISTRY=acrdigitalgarage01.azurecr.io # Azure Container Registry
export IMAGE_TAG=v1.0.0 # 기본값: latest
# Kubernetes 네임스페이스 설정
export KUBE_NAMESPACE=kt-event-marketing # 기본값: kt-event-marketing
```
---
## 🔨 이미지 빌드
### 1. 빌드 스크립트 실행
프로젝트 루트에서 다음 명령어를 실행합니다:
```bash
./deployment/uiux/build.sh
```
### 2. 빌드 프로세스
스크립트는 다음 단계를 수행합니다:
1. Docker 이미지 빌드
2. 레지스트리 푸시 여부 확인
3. (선택시) 이미지를 레지스트리에 푸시
### 3. 수동 빌드 (선택사항)
스크립트를 사용하지 않고 수동으로 빌드할 수도 있습니다:
```bash
# 이미지 빌드
docker build -f deployment/uiux/Dockerfile \
-t acrdigitalgarage01.azurecr.io/kt-event-prototype:latest .
# 레지스트리에 푸시
docker push acrdigitalgarage01.azurecr.io/kt-event-prototype:latest
```
---
## 🧪 로컬 테스트
Kubernetes에 배포하기 전에 로컬에서 테스트할 수 있습니다:
```bash
# 컨테이너 실행
docker run -d -p 8080:80 --name prototype \
acrdigitalgarage01.azurecr.io/kt-event-prototype:latest
# 브라우저에서 접속
# http://localhost:8080
# 컨테이너 중지 및 제거
docker stop prototype
docker rm prototype
```
### 헬스체크 확인
```bash
curl http://localhost:8080/health
# 출력: OK
```
---
## ☸️ Kubernetes 배포
### 1. 배포 스크립트 실행
```bash
./deployment/uiux/deploy.sh
```
### 2. 배포 옵션 선택
스크립트 실행 시 다음 옵션을 선택할 수 있습니다:
- **1) 전체 배포**: Deployment + Service + Ingress 모두 배포
- **2) 업데이트**: Deployment 업데이트 (이미지 변경 시)
- **3) 삭제**: 모든 리소스 삭제
### 3. 수동 배포 (선택사항)
```bash
# 모든 리소스 배포
kubectl apply -f deployment/uiux/k8s/deployment.yaml
kubectl apply -f deployment/uiux/k8s/service.yaml
kubectl apply -f deployment/uiux/k8s/ingress.yaml
# 배포 상태 확인
kubectl rollout status deployment/kt-event-prototype
```
### 4. 이미지 업데이트
새 이미지로 업데이트하려면:
```bash
# 새 이미지로 태그 변경
kubectl set image deployment/kt-event-prototype \
nginx=acrdigitalgarage01.azurecr.io/kt-event-prototype:v1.0.1 \
-n kt-event-marketing
# 롤아웃 상태 확인
kubectl rollout status deployment/kt-event-prototype -n kt-event-marketing
# 롤백 (필요시)
kubectl rollout undo deployment/kt-event-prototype -n kt-event-marketing
```
---
## 🌐 접속 및 확인
### 1. Pod 상태 확인
```bash
kubectl get pods -l app=kt-event-prototype -n kt-event-marketing
```
정상 상태:
```
NAME READY STATUS RESTARTS AGE
kt-event-prototype-xxxxxxxxxx-xxxxx 1/1 Running 0 1m
```
### 2. Service 확인
```bash
kubectl get svc kt-event-prototype -n kt-event-marketing
```
### 3. Ingress 확인
```bash
kubectl get ingress kt-event-prototype -n kt-event-marketing
```
Ingress 호스트 주소: `prototype.kt-event.kubepia.com`
### 4. 브라우저에서 접속
```
http://prototype.kt-event.kubepia.com
```
> **참고**: 도메인이 외부 DNS에 등록되어 있지 않은 경우, `/etc/hosts` (또는 Windows: `C:\Windows\System32\drivers\etc\hosts`) 파일에 다음을 추가하여 로컬 테스트 가능:
> ```
> <INGRESS_CONTROLLER_IP> prototype.kt-event.kubepia.com
> ```
>
> Ingress Controller IP 확인:
> ```bash
> kubectl get svc -n ingress-nginx
> ```
### 6. 프로토타입 화면 목록
접속 후 다음 화면들을 확인할 수 있습니다:
- 01-로그인.html
- 02-회원가입.html
- 03-프로필.html
- 04-로그아웃확인.html
- 05-대시보드.html
- 06-이벤트목록.html
- 07-이벤트목적선택.html
- 08-AI이벤트추천.html
- 09-콘텐츠미리보기.html
- 10-콘텐츠편집.html
- 11-이벤트게시.html
- 12-내이벤트.html
- 13-이벤트상세.html
- 14-이벤트수정.html
- 15-이벤트삭제확인.html
- 16-통계대시보드.html
- 17-예산관리.html
- 18-공유하기.html
- 19-알림센터.html
- 20-도움말.html
---
## 🔍 문제 해결
### Pod가 시작하지 않을 때
```bash
# Pod 상세 정보 확인
kubectl describe pod -l app=kt-event-prototype -n kt-event-marketing
# Pod 로그 확인
kubectl logs -l app=kt-event-prototype -n kt-event-marketing
# 이벤트 확인
kubectl get events -n kt-event-marketing --sort-by='.lastTimestamp'
```
### 일반적인 문제
#### 1. ImagePullBackOff 에러
- **원인**: 이미지를 레지스트리에서 가져올 수 없음
- **해결**:
```bash
# 이미지 이름 확인
kubectl get deployment kt-event-prototype -n kt-event-marketing \
-o jsonpath='{.spec.template.spec.containers[0].image}'
# 수동으로 이미지 pull 테스트
docker pull acrdigitalgarage01.azurecr.io/kt-event-prototype:latest
```
#### 2. CrashLoopBackOff 에러
- **원인**: 컨테이너가 시작 후 계속 종료됨
- **해결**:
```bash
# 로그 확인
kubectl logs -l app=kt-event-prototype -n kt-event-marketing --previous
# 컨테이너 내부 확인
kubectl exec -it <pod-name> -n kt-event-marketing -- sh
```
#### 3. Ingress 접속 안됨
- **원인**: Ingress Controller 미설치 또는 DNS 미설정
- **해결**:
```bash
# Ingress Controller 확인
kubectl get pods -n ingress-nginx
# Ingress 상세 확인
kubectl describe ingress kt-event-prototype -n kt-event-marketing
```
### 로그 확인 명령어
```bash
# 실시간 로그 확인
kubectl logs -f -l app=kt-event-prototype -n kt-event-marketing
# 최근 100줄 로그
kubectl logs --tail=100 -l app=kt-event-prototype -n kt-event-marketing
# 모든 Pod의 로그
kubectl logs -l app=kt-event-prototype -n kt-event-marketing --all-containers=true
# 이전 컨테이너 로그 (CrashLoopBackOff 시)
kubectl logs -l app=kt-event-prototype -n kt-event-marketing --previous
```
### 리소스 정리
```bash
# 모든 리소스 삭제
kubectl delete -f deployment/uiux/k8s/ -n kt-event-marketing
# 또는 개별 삭제
kubectl delete ingress kt-event-prototype -n kt-event-marketing
kubectl delete service kt-event-prototype -n kt-event-marketing
kubectl delete deployment kt-event-prototype -n kt-event-marketing
```
---
## 📊 리소스 사양
### Deployment
- **Replicas**: 2개 (고가용성)
- **Container Port**: 80
- **Resources**:
- CPU: 100m (request), 200m (limit)
- Memory: 128Mi (request), 256Mi (limit)
### Service
- **Type**: ClusterIP
- **Port**: 80
### Ingress
- **Host**: `prototype.kt-event.local` (변경 필요)
- **Path**: `/` (모든 경로)
- **Backend**: kt-event-prototype:80
---
## 🔐 보안 설정
- **runAsNonRoot**: true (root 사용자로 실행 안함)
- **readOnlyRootFilesystem**: false (nginx 로그 작성 허용)
- **allowPrivilegeEscalation**: false
- **Capabilities**: NET_BIND_SERVICE만 허용
---
## 📝 참고 사항
1. **도메인**: 현재 `prototype.kt-event.kubepia.com`으로 설정되어 있습니다. 변경이 필요한 경우 `k8s/ingress.yaml`에서 수정하세요.
2. **네임스페이스**: `kt-event-marketing` 네임스페이스를 사용합니다. 환경변수 `KUBE_NAMESPACE`로 변경 가능합니다.
3. **레지스트리**: Azure Container Registry(`acrdigitalgarage01.azurecr.io`)를 사용합니다.
4. **리소스 제한**: 프로덕션 환경에서는 리소스 요청/제한을 조정하세요.
5. **TLS**: HTTPS 사용 시 `ingress.yaml`에서 TLS 섹션을 활성화하세요.
6. **모니터링**: Prometheus/Grafana를 통한 모니터링 권장합니다.
7. **nginx 설정**: nginx 설정은 Docker 이미지에 포함되어 있습니다. 변경이 필요한 경우 `nginx.conf`를 수정하고 이미지를 재빌드하세요.
---
## 🤝 지원
문제가 발생하면 다음을 확인하세요:
1. Pod 로그
2. Ingress Controller 로그
3. Kubernetes 이벤트
추가 지원이 필요하면 개발팀에 문의하세요.

48
deployment/uiux/build.sh Normal file
View File

@ -0,0 +1,48 @@
#!/bin/bash
# 빌드 스크립트
# 프로토타입 이미지를 빌드하고 레지스트리에 푸시합니다.
set -e
# 변수 설정
IMAGE_NAME="kt-event-prototype"
REGISTRY="${DOCKER_REGISTRY:-acrdigitalgarage01.azurecr.io}"
TAG="${IMAGE_TAG:-latest}"
FULL_IMAGE="${REGISTRY}/${IMAGE_NAME}:${TAG}"
echo "================================="
echo "프로토타입 이미지 빌드"
echo "================================="
echo "이미지: ${FULL_IMAGE}"
echo ""
# 프로젝트 루트로 이동
cd "$(dirname "$0")/../.."
# Docker 이미지 빌드
echo "🔨 이미지 빌드 중..."
docker build -f deployment/uiux/Dockerfile -t ${FULL_IMAGE} .
echo ""
echo "✅ 이미지 빌드 완료: ${FULL_IMAGE}"
echo ""
# 레지스트리 푸시 여부 확인
read -p "레지스트리에 푸시하시겠습니까? (y/N): " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "📤 이미지 푸시 중..."
docker push ${FULL_IMAGE}
echo "✅ 이미지 푸시 완료"
else
echo "⏭️ 푸시 생략"
fi
echo ""
echo "================================="
echo "빌드 완료"
echo "================================="
echo ""

116
deployment/uiux/deploy.sh Normal file
View File

@ -0,0 +1,116 @@
#!/bin/bash
# Kubernetes 배포 스크립트
# 프로토타입을 Kubernetes 클러스터에 배포합니다.
set -e
# 변수 설정
NAMESPACE="${KUBE_NAMESPACE:-kt-event-marketing}"
MANIFEST_DIR="$(dirname "$0")/k8s"
echo "================================="
echo "프로토타입 Kubernetes 배포"
echo "================================="
echo "네임스페이스: ${NAMESPACE}"
echo "매니페스트 위치: ${MANIFEST_DIR}"
echo ""
# kubectl 확인
if ! command -v kubectl &> /dev/null; then
echo "❌ kubectl이 설치되어 있지 않습니다."
exit 1
fi
# 클러스터 연결 확인
if ! kubectl cluster-info &> /dev/null; then
echo "❌ Kubernetes 클러스터에 연결할 수 없습니다."
echo " kubectl 설정을 확인해주세요."
exit 1
fi
echo "✅ Kubernetes 클러스터 연결 확인"
echo ""
# 배포 옵션 선택
echo "배포 옵션을 선택하세요:"
echo "1) 전체 배포 (deployment + service + ingress)"
echo "2) 업데이트 (deployment만)"
echo "3) 삭제"
read -p "선택 (1-3): " -n 1 -r
echo ""
echo ""
case $REPLY in
1)
echo "🚀 전체 리소스 배포 중..."
kubectl apply -f ${MANIFEST_DIR}/deployment.yaml -n ${NAMESPACE}
kubectl apply -f ${MANIFEST_DIR}/service.yaml -n ${NAMESPACE}
kubectl apply -f ${MANIFEST_DIR}/ingress.yaml -n ${NAMESPACE}
echo "✅ 배포 완료"
;;
2)
echo "🔄 Deployment 업데이트 중..."
kubectl apply -f ${MANIFEST_DIR}/deployment.yaml -n ${NAMESPACE}
kubectl rollout status deployment/kt-event-prototype -n ${NAMESPACE}
echo "✅ 업데이트 완료"
;;
3)
echo "🗑️ 리소스 삭제 중..."
kubectl delete -f ${MANIFEST_DIR}/ingress.yaml -n ${NAMESPACE} --ignore-not-found
kubectl delete -f ${MANIFEST_DIR}/service.yaml -n ${NAMESPACE} --ignore-not-found
kubectl delete -f ${MANIFEST_DIR}/deployment.yaml -n ${NAMESPACE} --ignore-not-found
echo "✅ 삭제 완료"
exit 0
;;
*)
echo "❌ 잘못된 선택입니다."
exit 1
;;
esac
echo ""
echo "================================="
echo "배포 상태 확인"
echo "================================="
# Pod 상태 확인
echo ""
echo "📦 Pod 상태:"
kubectl get pods -n ${NAMESPACE} -l app=kt-event-prototype
# Service 상태 확인
echo ""
echo "🌐 Service 상태:"
kubectl get svc -n ${NAMESPACE} -l app=kt-event-prototype
# Ingress 상태 확인
echo ""
echo "🚪 Ingress 상태:"
kubectl get ingress -n ${NAMESPACE} -l app=kt-event-prototype
echo ""
echo "================================="
echo "배포 완료"
echo "================================="
echo ""
echo "유용한 명령어:"
echo " # Pod 로그 확인"
echo " kubectl logs -n ${NAMESPACE} -l app=kt-event-prototype -f"
echo ""
echo " # Pod 상세 정보"
echo " kubectl describe pods -n ${NAMESPACE} -l app=kt-event-prototype"
echo ""
echo " # 서비스 상태 확인"
echo " kubectl get all -n ${NAMESPACE} -l app=kt-event-prototype"
echo ""
# Ingress 호스트 정보 표시
INGRESS_HOST=$(kubectl get ingress kt-event-prototype -n ${NAMESPACE} -o jsonpath='{.spec.rules[0].host}' 2>/dev/null)
if [ -n "$INGRESS_HOST" ]; then
echo "🌍 접속 URL: http://${INGRESS_HOST}"
echo ""
echo "⚠️ /etc/hosts 파일에 다음 내용 추가 필요 (로컬 테스트):"
echo " <INGRESS_IP> ${INGRESS_HOST}"
echo ""
fi

View File

@ -0,0 +1,41 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: kt-event-prototype
namespace: kt-event-marketing
labels:
app: kt-event-prototype
tier: frontend
component: prototype
spec:
replicas: 1
selector:
matchLabels:
app: kt-event-prototype
template:
metadata:
labels:
app: kt-event-prototype
tier: frontend
component: prototype
spec:
containers:
- name: nginx
image: acrdigitalgarage01.azurecr.io/kt-event-prototype:latest
imagePullPolicy: Always
ports:
- name: http
containerPort: 80
protocol: TCP
# 리소스 제한
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
# 재시작 정책
restartPolicy: Always

View File

@ -0,0 +1,42 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kt-event-prototype
namespace: kt-event-marketing
labels:
app: kt-event-prototype
tier: frontend
component: prototype
annotations:
# Nginx Ingress Controller 설정
# rewrite-target 제거: Pod 내부 nginx가 직접 처리하도록
nginx.ingress.kubernetes.io/ssl-redirect: "false"
# CORS 설정 (필요시 활성화)
# nginx.ingress.kubernetes.io/enable-cors: "true"
# nginx.ingress.kubernetes.io/cors-allow-methods: "GET, OPTIONS"
# nginx.ingress.kubernetes.io/cors-allow-origin: "*"
# 타임아웃 설정
nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
nginx.ingress.kubernetes.io/proxy-send-timeout: "30"
nginx.ingress.kubernetes.io/proxy-read-timeout: "30"
# 버퍼 크기 설정
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
# Rate limiting (필요시 활성화)
# nginx.ingress.kubernetes.io/limit-rps: "10"
spec:
ingressClassName: nginx
rules:
- host: prototype.kt-event.kubepia.com # 실제 도메인으로 변경 필요
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kt-event-prototype
port:
number: 80

View File

@ -0,0 +1,19 @@
apiVersion: v1
kind: Service
metadata:
name: kt-event-prototype
namespace: kt-event-marketing
labels:
app: kt-event-prototype
tier: frontend
component: prototype
spec:
type: ClusterIP
selector:
app: kt-event-prototype
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
sessionAffinity: None

View File

@ -0,0 +1,52 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index 01-로그인.html;
# 한글 파일명 지원
charset utf-8;
# 로그 설정
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# 루트 경로를 명시적으로 로그인 페이지로 처리
# 디렉토리처럼 처리하여 index 지시어가 작동하도록
location = / {
try_files $uri/ /01-로그인.html;
}
# 모든 다른 요청에 대해 기본 처리
location / {
try_files $uri $uri/ /01-로그인.html;
}
# index.html 요청도 로그인 페이지로
location = /index.html {
return 301 /01-로그인.html;
}
# 정적 파일 캐싱
location ~* \.(html|css|js|png|jpg|jpeg|gif|ico|svg)$ {
expires 1d;
add_header Cache-Control "public, immutable";
}
# 헬스체크 엔드포인트
location /health {
access_log off;
return 200 "OK\n";
add_header Content-Type text/plain;
}
# 404 처리
error_page 404 /01-로그인.html;
# gzip 압축
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss;
}