Files
tasteby/docs/oke-deployment-guide.md
joungmin ff4e8d742d Add cuisine subcategory filter, fix remap logic, and add OKE deployment manifests
- Add 파인다이닝/코스 cuisine type to 한식/일식/중식/양식 categories
- Change cuisine filter from flat list to grouped optgroup with subcategories
- Fix remap-foods/remap-cuisine: add jdbcType=CLOB, fix CLOB LISTAGG,
  improve retry logic (3 attempts, batch size 5), add error logging
- Add OKE deployment: Dockerfiles, K8s manifests, deploy.sh, deployment guide
- Add Next.js standalone output for Docker builds

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 22:58:09 +09:00

8.0 KiB
Raw Blame History

Tasteby OKE 배포 가이드

아키텍처

Internet
  │
  ▼
OCI Load Balancer (Nginx Ingress가 자동 생성)
  │
  ├─ /        → frontend Service (Next.js :3001)
  ├─ /api/    → backend Service (Spring Boot :8000)
  │
  ├─ cert-manager (Let's Encrypt 인증서 자동 발급/갱신)
  └─ Redis (in-cluster 캐시 :6379)

인프라 정보

항목
클러스터 tasteby-cluster
리전 ap-seoul-1 (Seoul)
노드 ARM64 × 2대 (2 CPU / 8GB 각)
K8s 버전 v1.34.2
OCI 프로필 JOUNGMINKOAWS
OCIR icn.ocir.io/idyhsdamac8c/tasteby
도메인 www.tasteby.net (Namecheap DNS)
SSL Let's Encrypt (cert-manager + HTTP-01)

파일 구조

tasteby/
├── backend-java/Dockerfile
├── frontend/Dockerfile
├── k8s/
│   ├── namespace.yaml
│   ├── configmap.yaml
│   ├── secrets.yaml.template      ← 실제 secrets.yaml은 .gitignore
│   ├── redis-deployment.yaml
│   ├── backend-deployment.yaml
│   ├── frontend-deployment.yaml
│   ├── ingress.yaml
│   └── cert-manager/
│       └── cluster-issuer.yaml
└── deploy.sh

리소스 배분

파드 replicas CPU req/lim 메모리 req/lim
backend (Java) 1 500m / 1 768Mi / 1536Mi
frontend (Next.js) 1 200m / 500m 256Mi / 512Mi
redis 1 100m / 200m 128Mi / 256Mi
ingress-controller 1 100m / 200m 128Mi / 256Mi
cert-manager (×3) 1씩 50m / 100m 64Mi / 128Mi
합계 ~1.2 CPU ~1.6GB

전체 클러스터: 4 CPU / 16GB → 여유 충분


1단계: 사전 준비

1.1 kubectl 설정

# OKE kubeconfig 가져오기
oci ce cluster create-kubeconfig \
  --cluster-id ocid1.cluster.oc1.ap-seoul-1.aaaaaaaaoqgd2sh6754m5zrwfqaxwrtlqon3dxtdwbbc2dvzbcbou3pf75rq \
  --profile JOUNGMINKOAWS \
  --region ap-seoul-1 \
  --token-version 2.0.0 \
  --kube-endpoint PUBLIC_ENDPOINT

# ~/.kube/config의 user args에 --profile JOUNGMINKOAWS 추가 필요
# 확인
kubectl get nodes

1.2 Helm 설치 (없으면)

brew install helm

2단계: 인프라 설치 (1회성)

2.1 Nginx Ingress Controller

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

helm install ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx --create-namespace \
  --set controller.service.type=LoadBalancer \
  --set controller.service.annotations."oci\.oraclecloud\.com/load-balancer-type"=nlb

설치 후 External IP 확인:

kubectl get svc -n ingress-nginx ingress-nginx-controller -w
# EXTERNAL-IP가 나오면 Namecheap에서 A 레코드 업데이트
#   www.tasteby.net  → <EXTERNAL-IP>
#   tasteby.net      → <EXTERNAL-IP>

2.2 cert-manager

helm repo add jetstack https://charts.jetstack.io
helm repo update

helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager --create-namespace \
  --set crds.enabled=true

2.3 ClusterIssuer 생성

kubectl apply -f k8s/cert-manager/cluster-issuer.yaml

3단계: 네임스페이스 및 시크릿 생성 (1회성)

3.1 네임스페이스

kubectl apply -f k8s/namespace.yaml

3.2 OCIR 이미지 Pull Secret

# OCI Auth Token 필요 (콘솔 > User Settings > Auth Tokens에서 생성)
kubectl create secret docker-registry ocir-secret \
  --docker-server=icn.ocir.io \
  --docker-username="idyhsdamac8c/<oci-username>" \
  --docker-password="<auth-token>" \
  --docker-email="<email>" \
  -n tasteby

3.3 앱 시크릿

# secrets.yaml.template을 복사하여 실제 값 입력
cp k8s/secrets.yaml.template k8s/secrets.yaml
# 편집 후
kubectl apply -f k8s/secrets.yaml

3.4 Oracle Wallet Secret

# Wallet 디렉토리의 파일들을 Secret으로 생성
kubectl create secret generic oracle-wallet \
  --from-file=cwallet.sso=<wallet-dir>/cwallet.sso \
  --from-file=tnsnames.ora=<wallet-dir>/tnsnames.ora \
  --from-file=sqlnet.ora=<wallet-dir>/sqlnet.ora \
  --from-file=keystore.jks=<wallet-dir>/keystore.jks \
  --from-file=truststore.jks=<wallet-dir>/truststore.jks \
  --from-file=ojdbc.properties=<wallet-dir>/ojdbc.properties \
  -n tasteby

3.5 OCI Config Secret

# OCI API key config 파일과 PEM 키를 Secret으로 생성
# config 파일은 K8s용으로 수정 필요 (key_file 경로를 /root/.oci/oci_api_key.pem으로)
kubectl create secret generic oci-config \
  --from-file=config=<oci-config-for-k8s> \
  --from-file=oci_api_key.pem=<pem-key-file> \
  -n tasteby

참고: OCI config 파일에서 key_file 경로를 컨테이너 내부 마운트 경로로 수정:

[DEFAULT]
user=ocid1.user.oc1..xxx
fingerprint=xx:xx:xx
key_file=/root/.oci/oci_api_key.pem
tenancy=ocid1.tenancy.oc1..xxx
region=ap-seoul-1

3.6 ConfigMap 적용

kubectl apply -f k8s/configmap.yaml

4단계: 앱 배포

4.1 기본 리소스 배포

kubectl apply -f k8s/redis-deployment.yaml
kubectl apply -f k8s/backend-deployment.yaml
kubectl apply -f k8s/frontend-deployment.yaml
kubectl apply -f k8s/ingress.yaml

4.2 OCIR 로그인 (이미지 푸시용)

docker login icn.ocir.io \
  -u "idyhsdamac8c/<oci-username>" \
  -p "<auth-token>"

4.3 이미지 빌드 & 배포

# 전체 배포
./deploy.sh "초기 배포"

# 백엔드만 배포
./deploy.sh --backend-only "API 버그 수정"

# 프론트엔드만 배포
./deploy.sh --frontend-only "UI 개선"

# 드라이런 (실제 실행 안 함)
./deploy.sh --dry-run "테스트"

5단계: DNS 설정

Namecheap에서 A 레코드 변경:

Type Host Value TTL
A @ <LB External IP> Automatic
A www <LB External IP> Automatic

DNS 전파 후 cert-manager가 자동으로 Let's Encrypt 인증서를 발급합니다.


운영 명령어

상태 확인

# 파드 상태
kubectl get pods -n tasteby

# 로그 확인
kubectl logs -f deployment/backend -n tasteby
kubectl logs -f deployment/frontend -n tasteby

# 인증서 상태
kubectl get certificate -n tasteby
kubectl describe certificate tasteby-tls -n tasteby

롤백

# 이전 버전으로 롤백
kubectl rollout undo deployment/backend -n tasteby
kubectl rollout undo deployment/frontend -n tasteby

# 특정 리비전으로 롤백
kubectl rollout history deployment/backend -n tasteby
kubectl rollout undo deployment/backend --to-revision=2 -n tasteby

시크릿 업데이트

# secrets.yaml 수정 후
kubectl apply -f k8s/secrets.yaml
# 파드 재시작 (시크릿 변경 반영)
kubectl rollout restart deployment/backend -n tasteby

스케일링

# 백엔드 2개로 확장
kubectl scale deployment/backend --replicas=2 -n tasteby

배포 태그 규칙

  • 형식: v0.1.X (patch 버전 자동 증가)
  • deploy.sh가 빌드 → 푸시 → K8s 업데이트 → git tag 생성 → 태그 푸시까지 자동 처리
  • 태그 메시지에 배포 대상(backend/frontend)과 이미지 태그 포함
# 태그 목록 확인
git tag -l 'v*' --sort=-v:refname

# 특정 태그의 배포 내역 확인
git tag -n20 v0.1.5

트러블슈팅

이미지 Pull 실패

kubectl describe pod <pod-name> -n tasteby
# Events에서 ImagePullBackOff 확인 → ocir-secret 점검

DB 연결 실패

kubectl exec -it deployment/backend -n tasteby -- env | grep ORACLE
# Oracle Wallet 마운트 확인
kubectl exec -it deployment/backend -n tasteby -- ls /etc/oracle/wallet/

인증서 발급 안 됨

kubectl get challenges -n tasteby
kubectl describe challenge -n tasteby
# DNS A 레코드가 LB IP로 설정되었는지, 80 포트가 열려있는지 확인

OCI GenAI 연결 실패

kubectl exec -it deployment/backend -n tasteby -- cat /root/.oci/config
# key_file 경로가 /root/.oci/oci_api_key.pem 인지 확인