fix: selectCompanyName LIMIT 1 추가 및 K8s 배포 설정 추가
Build & Deploy to K8s / build-and-deploy (push) Failing after 7s
Build & Deploy to K8s / build-and-deploy (push) Failing after 7s
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: backend-node
|
||||
namespace: invyone
|
||||
labels:
|
||||
app: backend-node
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: backend-node
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: backend-node
|
||||
spec:
|
||||
containers:
|
||||
- name: backend-node
|
||||
image: localhost:5000/invyone/backend-node:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
env:
|
||||
- name: NODE_ENV
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: invyone-config
|
||||
key: NODE_ENV
|
||||
- name: PORT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: invyone-config
|
||||
key: NODE_PORT
|
||||
- name: DATABASE_URL
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: invyone-config
|
||||
key: DATABASE_URL
|
||||
- name: JWT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: invyone-secrets
|
||||
key: JWT_SECRET
|
||||
- name: CORS_ORIGIN
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: invyone-config
|
||||
key: CORS_ORIGIN
|
||||
- name: BOK_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: invyone-secrets
|
||||
key: BOK_API_KEY
|
||||
- name: KMA_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: invyone-secrets
|
||||
key: KMA_API_KEY
|
||||
- name: ITS_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: invyone-secrets
|
||||
key: ITS_API_KEY
|
||||
- name: EXWAY_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: invyone-secrets
|
||||
key: EXWAY_API_KEY
|
||||
- name: ENCRYPTION_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: invyone-secrets
|
||||
key: ENCRYPTION_KEY
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: backend-node
|
||||
namespace: invyone
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
app: backend-node
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
nodePort: 30080
|
||||
@@ -0,0 +1,105 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: backend-spring
|
||||
namespace: invyone
|
||||
labels:
|
||||
app: backend-spring
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: backend-spring
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: backend-spring
|
||||
spec:
|
||||
containers:
|
||||
- name: backend-spring
|
||||
image: localhost:5000/invyone/backend-spring:latest
|
||||
ports:
|
||||
- containerPort: 8081
|
||||
env:
|
||||
- name: SPRING_PROFILES_ACTIVE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: invyone-config
|
||||
key: SPRING_PROFILES_ACTIVE
|
||||
- name: SERVER_PORT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: invyone-config
|
||||
key: SERVER_PORT
|
||||
- name: SPRING_DATASOURCE_URL
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: invyone-config
|
||||
key: SPRING_DATASOURCE_URL
|
||||
- name: SPRING_DATASOURCE_USERNAME
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: invyone-config
|
||||
key: SPRING_DATASOURCE_USERNAME
|
||||
- name: SPRING_DATASOURCE_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: invyone-secrets
|
||||
key: SPRING_DATASOURCE_PASSWORD
|
||||
- name: JWT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: invyone-secrets
|
||||
key: JWT_SECRET
|
||||
- name: JWT_EXPIRATION
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: invyone-config
|
||||
key: JWT_EXPIRATION
|
||||
- name: FILE_UPLOAD_DIR
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: invyone-config
|
||||
key: FILE_UPLOAD_DIR
|
||||
resources:
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 1024Mi
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 8081
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 8081
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
volumeMounts:
|
||||
- name: uploads
|
||||
mountPath: /app/uploads
|
||||
volumes:
|
||||
- name: uploads
|
||||
persistentVolumeClaim:
|
||||
claimName: invyone-uploads-pvc
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: backend-spring
|
||||
namespace: invyone
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
app: backend-spring
|
||||
ports:
|
||||
- port: 8081
|
||||
targetPort: 8081
|
||||
nodePort: 30081
|
||||
@@ -0,0 +1,18 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: invyone-config
|
||||
namespace: invyone
|
||||
data:
|
||||
SPRING_PROFILES_ACTIVE: "prod"
|
||||
SERVER_PORT: "8081"
|
||||
SPRING_DATASOURCE_URL: "jdbc:postgresql://211.115.91.141:11134/vexplor"
|
||||
SPRING_DATASOURCE_USERNAME: "postgres"
|
||||
JWT_EXPIRATION: "86400000"
|
||||
FILE_UPLOAD_DIR: "./uploads"
|
||||
NODE_ENV: "production"
|
||||
NODE_PORT: "8080"
|
||||
DATABASE_URL: "postgresql://postgres:vexplor0909!!@211.115.91.141:11134/vexplor"
|
||||
CORS_ORIGIN: "https://solution.invyone.com"
|
||||
NEXT_PUBLIC_API_URL: "https://solution.invyone.com/api"
|
||||
NEXT_TELEMETRY_DISABLED: "1"
|
||||
Executable
+129
@@ -0,0 +1,129 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# ================================================
|
||||
# invyone Kubernetes 배포 스크립트
|
||||
# 사용법: ./k8s/deploy.sh [build|deploy|all]
|
||||
# ================================================
|
||||
|
||||
REGISTRY="localhost:5000"
|
||||
PROJECT="invyone"
|
||||
TAG="${GIT_COMMIT_SHORT:-latest}"
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
log() { echo -e "${GREEN}[DEPLOY]${NC} $1"; }
|
||||
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
|
||||
|
||||
# 프로젝트 루트 디렉토리로 이동
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
build_images() {
|
||||
log "Docker 이미지 빌드 시작..."
|
||||
|
||||
log "1/3 Backend Spring 빌드..."
|
||||
docker build -t "$REGISTRY/$PROJECT/backend-spring:$TAG" \
|
||||
-f docker/deploy/backend-spring.Dockerfile \
|
||||
backend-spring/
|
||||
|
||||
log "2/3 Backend Node 빌드..."
|
||||
docker build -t "$REGISTRY/$PROJECT/backend-node:$TAG" \
|
||||
-f docker/deploy/backend-node.Dockerfile \
|
||||
backend-node/
|
||||
|
||||
log "3/3 Frontend 빌드..."
|
||||
docker build -t "$REGISTRY/$PROJECT/frontend:$TAG" \
|
||||
-f docker/deploy/frontend.Dockerfile \
|
||||
frontend/
|
||||
|
||||
log "Docker 이미지 빌드 완료!"
|
||||
}
|
||||
|
||||
push_images() {
|
||||
log "Docker Registry로 이미지 Push..."
|
||||
|
||||
docker push "$REGISTRY/$PROJECT/backend-spring:$TAG"
|
||||
docker push "$REGISTRY/$PROJECT/backend-node:$TAG"
|
||||
docker push "$REGISTRY/$PROJECT/frontend:$TAG"
|
||||
|
||||
# latest 태그도 push
|
||||
if [ "$TAG" != "latest" ]; then
|
||||
docker tag "$REGISTRY/$PROJECT/backend-spring:$TAG" "$REGISTRY/$PROJECT/backend-spring:latest"
|
||||
docker tag "$REGISTRY/$PROJECT/backend-node:$TAG" "$REGISTRY/$PROJECT/backend-node:latest"
|
||||
docker tag "$REGISTRY/$PROJECT/frontend:$TAG" "$REGISTRY/$PROJECT/frontend:latest"
|
||||
docker push "$REGISTRY/$PROJECT/backend-spring:latest"
|
||||
docker push "$REGISTRY/$PROJECT/backend-node:latest"
|
||||
docker push "$REGISTRY/$PROJECT/frontend:latest"
|
||||
fi
|
||||
|
||||
log "이미지 Push 완료!"
|
||||
}
|
||||
|
||||
deploy_k8s() {
|
||||
log "Kubernetes 배포 시작..."
|
||||
|
||||
# Namespace 생성
|
||||
kubectl apply -f k8s/namespace.yaml
|
||||
|
||||
# Secret & ConfigMap (Secret은 이미 존재하면 skip)
|
||||
kubectl apply -f k8s/secrets.yaml
|
||||
kubectl apply -f k8s/configmap.yaml
|
||||
|
||||
# PVC
|
||||
kubectl apply -f k8s/pvc.yaml
|
||||
|
||||
# Deployments & Services
|
||||
kubectl apply -f k8s/backend-spring.yaml
|
||||
kubectl apply -f k8s/backend-node.yaml
|
||||
kubectl apply -f k8s/frontend.yaml
|
||||
|
||||
# NetworkPolicy
|
||||
kubectl apply -f k8s/networkpolicy.yaml
|
||||
|
||||
# 이미지 태그가 latest가 아니면 이미지 업데이트
|
||||
if [ "$TAG" != "latest" ]; then
|
||||
kubectl set image deployment/backend-spring \
|
||||
backend-spring="$REGISTRY/$PROJECT/backend-spring:$TAG" \
|
||||
-n invyone
|
||||
kubectl set image deployment/backend-node \
|
||||
backend-node="$REGISTRY/$PROJECT/backend-node:$TAG" \
|
||||
-n invyone
|
||||
kubectl set image deployment/frontend \
|
||||
frontend="$REGISTRY/$PROJECT/frontend:$TAG" \
|
||||
-n invyone
|
||||
fi
|
||||
|
||||
# Rollout 대기
|
||||
log "Rollout 대기 중..."
|
||||
kubectl rollout status deployment/backend-spring -n invyone --timeout=180s || warn "backend-spring rollout timeout"
|
||||
kubectl rollout status deployment/backend-node -n invyone --timeout=120s || warn "backend-node rollout timeout"
|
||||
kubectl rollout status deployment/frontend -n invyone --timeout=120s || warn "frontend rollout timeout"
|
||||
|
||||
log "Kubernetes 배포 완료!"
|
||||
kubectl get pods -n invyone
|
||||
}
|
||||
|
||||
case "${1:-all}" in
|
||||
build)
|
||||
build_images
|
||||
push_images
|
||||
;;
|
||||
deploy)
|
||||
deploy_k8s
|
||||
;;
|
||||
all)
|
||||
build_images
|
||||
push_images
|
||||
deploy_k8s
|
||||
;;
|
||||
*)
|
||||
echo "사용법: $0 [build|deploy|all]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,73 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: frontend
|
||||
namespace: invyone
|
||||
labels:
|
||||
app: frontend
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: frontend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: frontend
|
||||
spec:
|
||||
containers:
|
||||
- name: frontend
|
||||
image: localhost:5000/invyone/frontend:latest
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
env:
|
||||
- name: NODE_ENV
|
||||
value: "production"
|
||||
- name: NEXT_PUBLIC_API_URL
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: invyone-config
|
||||
key: NEXT_PUBLIC_API_URL
|
||||
- name: SERVER_API_URL
|
||||
value: "http://backend-spring.invyone.svc.cluster.local:8081"
|
||||
- name: NEXT_TELEMETRY_DISABLED
|
||||
value: "1"
|
||||
- name: PORT
|
||||
value: "3000"
|
||||
- name: HOSTNAME
|
||||
value: "0.0.0.0"
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 3000
|
||||
initialDelaySeconds: 20
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 3000
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: frontend
|
||||
namespace: invyone
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
app: frontend
|
||||
ports:
|
||||
- port: 3000
|
||||
targetPort: 3000
|
||||
nodePort: 30000
|
||||
@@ -0,0 +1,6 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: invyone
|
||||
labels:
|
||||
app.kubernetes.io/part-of: invyone
|
||||
@@ -0,0 +1,58 @@
|
||||
# NetworkPolicy: frontend는 backend에만 접근 가능
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: frontend-policy
|
||||
namespace: invyone
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app: frontend
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
# backend-spring 접근 허용
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app: backend-spring
|
||||
ports:
|
||||
- port: 8081
|
||||
# backend-node 접근 허용
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app: backend-node
|
||||
ports:
|
||||
- port: 8080
|
||||
# DNS 허용
|
||||
- to: []
|
||||
ports:
|
||||
- port: 53
|
||||
protocol: UDP
|
||||
- port: 53
|
||||
protocol: TCP
|
||||
---
|
||||
# NetworkPolicy: backend는 외부 DB 접근만 허용
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: backend-policy
|
||||
namespace: invyone
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels: {}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
# 같은 네임스페이스 내 트래픽 허용
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: invyone
|
||||
# NodePort 외부 트래픽 허용 (Traefik에서 들어오는 트래픽)
|
||||
- from: []
|
||||
ports:
|
||||
- port: 3000
|
||||
- port: 8080
|
||||
- port: 8081
|
||||
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: invyone-uploads-pvc
|
||||
namespace: invyone
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: local-path
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: invyone-secrets
|
||||
namespace: invyone
|
||||
type: Opaque
|
||||
stringData:
|
||||
DB_PASSWORD: "vexplor0909!!"
|
||||
SPRING_DATASOURCE_PASSWORD: "vexplor0909!!"
|
||||
JWT_SECRET: "b354a8587eaded4c9e7fdcaf139a3ab8a23fcdb8a80232587c894b757bf13bf9"
|
||||
BOK_API_KEY: "OXIGPQXH68NUKVKL5KT9"
|
||||
KMA_API_KEY: "ogdXr2e9T4iHV69nvV-IwA"
|
||||
ITS_API_KEY: "d6b9befec3114d648284674b8fddcc32"
|
||||
EXWAY_API_KEY: "7820214492"
|
||||
@@ -0,0 +1,51 @@
|
||||
# Traefik 동적 설정 파일
|
||||
# 기존 Traefik Docker 컨테이너의 dynamic config 디렉토리에 배치
|
||||
# 예: /etc/traefik/dynamic/ 또는 Traefik volume mount 위치
|
||||
|
||||
http:
|
||||
routers:
|
||||
# Frontend (Next.js)
|
||||
invyone-frontend:
|
||||
rule: "Host(`v1.invion.com`)"
|
||||
entryPoints:
|
||||
- web
|
||||
- websecure
|
||||
service: invyone-frontend
|
||||
tls:
|
||||
certResolver: le
|
||||
|
||||
# Backend Spring Boot API
|
||||
invyone-api:
|
||||
rule: "Host(`api.invion.com`)"
|
||||
entryPoints:
|
||||
- web
|
||||
- websecure
|
||||
service: invyone-api
|
||||
tls:
|
||||
certResolver: le
|
||||
|
||||
# Backend Node.js API (필요시)
|
||||
invyone-node-api:
|
||||
rule: "Host(`node-api.invion.com`)"
|
||||
entryPoints:
|
||||
- web
|
||||
- websecure
|
||||
service: invyone-node-api
|
||||
tls:
|
||||
certResolver: le
|
||||
|
||||
services:
|
||||
invyone-frontend:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://127.0.0.1:30000"
|
||||
|
||||
invyone-api:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://127.0.0.1:30081"
|
||||
|
||||
invyone-node-api:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://127.0.0.1:30080"
|
||||
Reference in New Issue
Block a user