# 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 설정

```bash
# 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 설치 (없으면)

```bash
brew install helm
```

---

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

### 2.1 Nginx Ingress Controller

```bash
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 확인:
```bash
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

```bash
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 생성

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

---

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

### 3.1 네임스페이스

```bash
kubectl apply -f k8s/namespace.yaml
```

### 3.2 OCIR 이미지 Pull Secret

```bash
# 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 앱 시크릿

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

### 3.4 Oracle Wallet Secret

```bash
# 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

```bash
# 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` 경로를 컨테이너 내부 마운트 경로로 수정:
```ini
[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 적용

```bash
kubectl apply -f k8s/configmap.yaml
```

---

## 4단계: 앱 배포

### 4.1 기본 리소스 배포

```bash
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 로그인 (이미지 푸시용)

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

### 4.3 이미지 빌드 & 배포

```bash
# 전체 배포
./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 인증서를 발급합니다.

---

## 운영 명령어

### 상태 확인

```bash
# 파드 상태
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
```

### 롤백

```bash
# 이전 버전으로 롤백
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
```

### 시크릿 업데이트

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

### 스케일링

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

---

## 배포 태그 규칙

- 형식: `v0.1.X` (patch 버전 자동 증가)
- `deploy.sh`가 빌드 → 푸시 → K8s 업데이트 → git tag 생성 → 태그 푸시까지 자동 처리
- 태그 메시지에 배포 대상(backend/frontend)과 이미지 태그 포함

```bash
# 태그 목록 확인
git tag -l 'v*' --sort=-v:refname

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

---

## 트러블슈팅

### 이미지 Pull 실패
```bash
kubectl describe pod <pod-name> -n tasteby
# Events에서 ImagePullBackOff 확인 → ocir-secret 점검
```

### DB 연결 실패
```bash
kubectl exec -it deployment/backend -n tasteby -- env | grep ORACLE
# Oracle Wallet 마운트 확인
kubectl exec -it deployment/backend -n tasteby -- ls /etc/oracle/wallet/
```

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

### OCI GenAI 연결 실패
```bash
kubectl exec -it deployment/backend -n tasteby -- cat /root/.oci/config
# key_file 경로가 /root/.oci/oci_api_key.pem 인지 확인
```
