# Tasteby CI/CD 파이프라인 & 전체 아키텍처 ## 전체 시스템 아키텍처 ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ Internet │ │ www.tasteby.net │ └──────────────────────────────┬──────────────────────────────────────────┘ │ ┌─────────▼──────────┐ │ Namecheap DNS │ │ A → LB External IP │ └─────────┬──────────┘ │ ┌──────────────────────────────▼──────────────────────────────────────────┐ │ OCI Load Balancer (NLB) │ │ (Nginx Ingress Controller가 자동 생성) │ └──────────────────────────────┬──────────────────────────────────────────┘ │ ┌──────────────────────────────▼──────────────────────────────────────────┐ │ OKE Cluster (tasteby-cluster) │ │ ap-seoul-1 │ ARM64 × 2 노드 (2CPU/8GB 각) │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ Nginx Ingress Controller (ingress-nginx) │ │ │ │ │ │ │ │ TLS termination (Let's Encrypt via cert-manager) │ │ │ │ tasteby.net → www.tasteby.net 리다이렉트 │ │ │ │ │ │ │ │ /api/* ──→ backend Service :8000 │ │ │ │ /* ──→ frontend Service :3001 │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─── namespace: tasteby ─────────────────────────────────────────────┐ │ │ │ │ │ │ │ ┌──────────────────┐ ┌──────────────────┐ ┌────────────────┐ │ │ │ │ │ backend (×1) │ │ frontend (×1) │ │ redis (×1) │ │ │ │ │ │ Spring Boot 3 │ │ Next.js 15 │ │ Redis 7 │ │ │ │ │ │ Java 21 │ │ standalone mode │ │ alpine │ │ │ │ │ │ :8000 │ │ :3001 │ │ :6379 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ┌─ Volumes ─────┐│ └──────────────────┘ └────────────────┘ │ │ │ │ │ │ oracle-wallet ││ │ │ │ │ │ │ oci-config ││ │ │ │ │ │ └───────────────┘│ │ │ │ │ └──────────────────┘ │ │ │ │ │ │ │ │ ┌─── ConfigMap / Secrets ──────────────────────────────────────┐ │ │ │ │ │ tasteby-config : REDIS_HOST, OCI endpoints, 등 │ │ │ │ │ │ tasteby-secrets : DB credentials, API keys, JWT │ │ │ │ │ │ oracle-wallet : cwallet.sso, tnsnames.ora, keystore.jks │ │ │ │ │ │ oci-config : OCI API config + PEM key │ │ │ │ │ │ ocir-secret : OCIR 이미지 Pull 인증 │ │ │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─── namespace: cert-manager ──┐ ┌─── namespace: ingress-nginx ──┐ │ │ │ cert-manager (×3 pods) │ │ ingress-nginx-controller │ │ │ │ ClusterIssuer: letsencrypt │ │ (NLB 자동 생성) │ │ │ └──────────────────────────────┘ └────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ │ ┌─────────▼──────────┐ │ Oracle ADB 23ai │ │ (mTLS via Wallet) │ └────────────────────┘ ``` ## 외부 서비스 연동 ``` backend (Spring Boot) ├─→ Oracle ADB 23ai : JDBC + mTLS (Wallet) ├─→ OCI GenAI (Chat) : 식당 정보 추출, 음식 태그, 평가 생성 ├─→ OCI GenAI (Embed) : 벡터 임베딩 (Cohere embed-v4) ├─→ Google Maps Places API : 식당 검색, 좌표 조회 ├─→ YouTube Data API v3 : 채널/영상 정보 조회 └─→ Redis : 캐시 (API 응답, 검색 결과) frontend (Next.js) ├─→ Google Maps JavaScript API : 지도 렌더링 └─→ Google OAuth 2.0 : 사용자 인증 ``` --- ## CI/CD 파이프라인 ### 파이프라인 개요 ``` ┌──────────┐ ┌──────────────────┐ ┌──────────────────────┐ ┌─────────┐ │ 개발자 │────→│ OCI Code Repo │────→│ OCI DevOps Build │────→│ OKE │ │ git push │ │ (tasteby) │ │ Pipeline │ │ 배포 │ └──────────┘ └──────────────────┘ └──────────────────────┘ └─────────┘ ``` ### 상세 흐름 ``` 1. 코드 푸시 ┌──────────────┐ │ git push oci │ ← OCI Code Repository remote └──────┬───────┘ │ ▼ 2. 빌드 파이프라인 (OCI DevOps Build Pipeline) ┌───────────────────────────────────────────────────────────┐ │ │ │ Stage 1: Managed Build │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ build_spec.yaml 실행 │ │ │ │ │ │ │ │ 1) IMAGE_TAG 생성 (BuildRunID + timestamp) │ │ │ │ 2) docker build --platform linux/arm64 │ │ │ │ - backend-java/Dockerfile → backend image │ │ │ │ - frontend/Dockerfile → frontend image │ │ │ │ 3) Output: BACKEND_IMAGE, FRONTEND_IMAGE │ │ │ └──────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ Stage 2: Deliver Artifacts │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ Docker images → OCIR 푸시 │ │ │ │ │ │ │ │ icn.ocir.io/idyhsdamac8c/tasteby/backend:TAG │ │ │ │ icn.ocir.io/idyhsdamac8c/tasteby/frontend:TAG │ │ │ └──────────────────────────────────────────────────────┘ │ └───────────────────────────────────────────────────────────┘ │ ▼ 3. 배포 (수동 또는 deploy.sh) ┌───────────────────────────────────────────────────────────┐ │ kubectl set image deployment/backend backend=IMAGE:TAG │ │ kubectl set image deployment/frontend frontend=IMAGE:TAG │ │ kubectl rollout status ... │ │ │ │ git tag -a "vX.Y.Z" -m "Deploy: ..." │ │ git push origin "vX.Y.Z" │ └───────────────────────────────────────────────────────────┘ ``` ### Git Remote 구성 ``` origin → Gitea (gittea.cloud-handson.com) ← 소스 코드 관리 oci → OCI Code Repository ← CI/CD 트리거용 ``` 두 리모트에 모두 push하여 소스와 빌드를 동기화합니다. ### OCI IAM 권한 설정 (빌드/배포용) OCI DevOps Build Pipeline이 코드 레포, OCIR, 시크릿 등에 접근하려면 **Dynamic Group**과 **IAM Policy**가 필요합니다. #### Dynamic Group | 이름 | 설명 | |------|------| | `tasteby-build-pipeline` | DevOps 빌드/배포 파이프라인 리소스 | **Matching Rule:** ``` ANY { resource.type = 'devopsbuildpipeline', resource.type = 'devopsrepository', resource.type = 'devopsdeploypipeline', resource.type = 'devopsconnection' } ``` #### IAM Policy | 이름 | 설명 | |------|------| | `tasteby-devops-policy` | DevOps 파이프라인 리소스 접근 권한 | **Policy Statements:** ``` Allow dynamic-group tasteby-build-pipeline to manage devops-family in tenancy Allow dynamic-group tasteby-build-pipeline to manage repos in tenancy Allow dynamic-group tasteby-build-pipeline to read secret-family in tenancy Allow dynamic-group tasteby-build-pipeline to manage generic-artifacts in tenancy Allow dynamic-group tasteby-build-pipeline to use ons-topics in tenancy ``` > **참고**: IAM 정책은 적용 후 전파에 최대 수 분이 걸릴 수 있습니다. > 빌드 실행 시 `RelatedResourceNotAuthorizedOrNotFound` 오류가 나면 정책 전파를 기다린 후 재시도하세요. #### OCI Code Repository 인증 (HTTPS) ``` Username: /oracleidentitycloudservice/ Password: OCI Auth Token (User Settings에서 생성) ``` ```bash # Git remote 추가 예시 git remote add oci https://devops.scmservice.ap-seoul-1.oci.oraclecloud.com/namespaces//projects/tasteby/repositories/tasteby ``` ### build_spec.yaml 구조 ```yaml # OCI DevOps Build Pipeline 설정 version: 0.1 component: build shell: bash env: variables: REGISTRY: "icn.ocir.io/idyhsdamac8c/tasteby" exportedVariables: - IMAGE_TAG # 다음 stage에서 사용 - BACKEND_IMAGE - FRONTEND_IMAGE steps: - Set image tag # BuildRunID + timestamp 조합 - Build backend image # backend-java/Dockerfile, ARM64 - Build frontend image # frontend/Dockerfile, ARM64 outputArtifacts: - backend-image (DOCKER_IMAGE) - frontend-image (DOCKER_IMAGE) ``` --- ## 로컬 배포 (deploy.sh) OCI DevOps 없이 로컬에서 직접 배포할 때 사용합니다. ```bash # 전체 배포 ./deploy.sh "초기 배포" # 백엔드만 ./deploy.sh --backend-only "API 버그 수정" # 프론트엔드만 ./deploy.sh --frontend-only "UI 개선" # 드라이런 ./deploy.sh --dry-run "테스트" ``` **deploy.sh 동작:** 1. 최신 git tag에서 다음 버전 계산 (v0.1.X → v0.1.X+1) 2. Docker build (ARM64) + OCIR push 3. `kubectl set image` → rollout 대기 4. git tag 생성 + push --- ## Docker 이미지 빌드 ### Backend (Spring Boot) ``` eclipse-temurin:21-jdk (build) └─ gradlew bootJar └─ app.jar eclipse-temurin:21-jre (runtime) └─ java -XX:MaxRAMPercentage=75.0 -jar app.jar └─ EXPOSE 8000 ``` ### Frontend (Next.js) ``` node:22-alpine (build) └─ npm ci + npm run build └─ NEXT_PUBLIC_* 빌드 시 주입 (build args) node:22-alpine (runtime) └─ .next/standalone + .next/static + public/ └─ node server.js └─ EXPOSE 3001 ``` --- ## K8s 리소스 구성 ### 파일 구조 ``` k8s/ ├── namespace.yaml # tasteby namespace ├── configmap.yaml # 비밀이 아닌 설정 ├── secrets.yaml.template # 시크릿 템플릿 (실제 파일은 .gitignore) ├── redis-deployment.yaml # Redis 7 + Service ├── backend-deployment.yaml # Spring Boot + Service ├── frontend-deployment.yaml # Next.js + Service ├── ingress.yaml # Nginx Ingress + TLS └── cert-manager/ └── cluster-issuer.yaml # Let's Encrypt ClusterIssuer ``` ### 리소스 할당 | Pod | replicas | CPU req/lim | Memory req/lim | |-----|----------|-------------|----------------| | backend | 1 | 500m / 1 | 768Mi / 1536Mi | | frontend | 1 | 200m / 500m | 256Mi / 512Mi | | redis | 1 | 100m / 200m | 128Mi / 256Mi | | ingress-controller | 1 | 100m / 200m | 128Mi / 256Mi | | cert-manager (×3) | 1 each | 50m / 100m | 64Mi / 128Mi | | **합계** | | **~1.2 CPU** | **~1.6GB** | 클러스터: ARM64 × 2 노드 (4 CPU / 16GB 총) → 여유 충분 ### 네트워크 흐름 ``` Client → NLB:443 → Ingress Controller → /api/* → backend:8000 → /* → frontend:3001 backend → redis:6379 (K8s Service DNS, 클러스터 내부) backend → Oracle ADB (mTLS, Wallet Volume Mount) backend → OCI GenAI (OCI SDK, oci-config Volume Mount) backend → Google APIs (API Key, 환경변수) ``` ### Volume Mounts (backend) ``` /etc/oracle/wallet/ ← Secret: oracle-wallet ├── cwallet.sso ├── tnsnames.ora ├── sqlnet.ora ├── keystore.jks ├── truststore.jks └── ojdbc.properties /root/.oci/ ← Secret: oci-config ├── config └── oci_api_key.pem ``` --- ## 환경 분리 ``` ┌────────────────────────────┬──────────────────────────────────────┐ │ 개발 (Local) │ 운영 (OKE) │ ├────────────────────────────┼──────────────────────────────────────┤ │ backend/.env │ ConfigMap + Secret │ │ frontend/.env.local │ Dockerfile build args │ │ ~/.oci/config │ Secret: oci-config → /root/.oci/ │ │ 로컬 Wallet 디렉토리 │ Secret: oracle-wallet → /etc/oracle/ │ │ Redis: 192.168.0.147:6379 │ Redis: redis:6379 (K8s DNS) │ │ PM2로 프로세스 관리 │ K8s Deployment로 관리 │ │ nginx + certbot (SSL) │ Ingress + cert-manager (SSL) │ └────────────────────────────┴──────────────────────────────────────┘ ``` **변수명이 동일**하므로 코드 변경 없이 환경만 교체 가능합니다. 자세한 환경변수 목록은 [environment-guide.md](./environment-guide.md) 참고. --- ## OCI 리소스 정보 | 항목 | 값 | |------|-----| | 리전 | ap-seoul-1 (Seoul) | | OCI 프로필 | JOUNGMINKOAWS | | OKE 클러스터 | tasteby-cluster | | OCIR Registry | icn.ocir.io/idyhsdamac8c/tasteby | | DevOps 프로젝트 | tasteby | | Code Repository | tasteby (OCI DevOps SCM) | | 도메인 | www.tasteby.net (Namecheap) | | SSL | Let's Encrypt (cert-manager HTTP-01) | | 노드 | ARM64 × 2대 (2 CPU / 8GB 각) | --- ## 배포 버전 관리 - 태그 형식: `v0.1.X` (patch 자동 증가) - deploy.sh가 자동으로 git tag 생성 + push - 태그 메시지에 배포 대상(backend/frontend)과 이미지 태그 포함 ```bash # 태그 목록 확인 git tag -l 'v*' --sort=-v:refname # 특정 태그 상세 확인 git tag -n20 v0.1.5 # 롤백 kubectl rollout undo deployment/backend -n tasteby ``` --- ## 관련 문서 - [OKE 배포 가이드](./oke-deployment-guide.md) — 인프라 설치 및 배포 절차 - [환경 관리 가이드](./environment-guide.md) — 환경변수 및 시크릿 관리