# Hướng Dẫn Deploy Kubernetes Local

> Hướng dẫn triển khai Kubernetes cục bộ với Docker Desktop trên macOS

## Quy Trình Deploy

```mermaid
graph TD
 Start([ Bắt đầu]) --> EnvPrep[1. Chuẩn bị Môi trường]
 EnvPrep --> BuildImg[2. Build Docker Image]
 BuildImg --> LoadImg[3. Load Image vào Cluster]
 LoadImg --> Secrets[4. Cấu hình Secrets & Environment]
 Secrets --> Deploy[5. Deploy Service]
 Deploy --> Verify[6. Kiểm tra & Verify]
 Verify --> Test[7. Test Service]
 Test --> End([ Hoàn tất])

 subgraph "Chi tiết Deploy"
 Deploy --> |Apply| ConfigMap[ConfigMap]
 Deploy --> |Apply| Deployment[Deployment]
 Deploy --> |Apply| Service[Service]
 end

 style Start fill:#1a1a2e,color:#fff
 style End fill:#0f3460,color:#fff
 style EnvPrep fill:#16213e,color:#fff
 style BuildImg fill:#1a1a40,color:#fff
 style LoadImg fill:#1a1a40,color:#fff
 style Secrets fill:#0f4c75,color:#fff
 style Deploy fill:#3282b8,color:#fff
 style Verify fill:#3282b8,color:#fff
 style Test fill:#3282b8,color:#fff
 style ConfigMap fill:#16213e,color:#fff
 style Deployment fill:#16213e,color:#fff
 style Service fill:#16213e,color:#fff
```

## Tổng Quan

Hướng dẫn này mô tả chi tiết cách deploy IAM Service (hoặc bất kỳ microservice nào trong hệ sinh thái GoodGo) lên local Kubernetes cluster sử dụng Docker Desktop trên macOS.

> **Lưu ý**: Hướng dẫn này giả định bạn đang sử dụng **Docker Desktop** với **Kubernetes enabled**. Nếu bạn sử dụng Minikube hoặc Kind thuần, các bước có thể hơi khác một chút (đặc biệt là phần load image).

## 1. Yêu Cầu

### Phần Mềm
- **Docker Desktop 4.0+**: [Download Link](https://www.docker.com/products/docker-desktop/)
 - Kubernetes phải được enable trong settings.
- **kubectl CLI**: Công cụ dòng lệnh để tương tác với K8s.
 ```bash
 brew install kubectl
 ```
- **kind CLI**: Cần thiết để load images vào cluster nếu dùng Kind backend (mặc định cho dev).
 ```bash
 brew install kind
 ```
- **pnpm 8+**: Package manager của dự án.
 ```bash
 npm install -g pnpm
 ```

### Kiến Thức
- Hiểu cơ bản về các khái niệm Kubernetes: **Pod**, **Deployment**, **Service**, **Secret**, **ConfigMap**.
- Quen thuộc với các lệnh Docker cơ bản (`docker build`, `docker images`).
- Biết cách điều hướng và chạy lệnh trong Terminal.

## 2. Chuẩn Bị Môi Trường

### 2.1 Enable Kubernetes trong Docker Desktop

1. Mở **Docker Desktop**.
2. Nhấn vào biểu tượng **Settings ()**.
3. Chọn tab **Kubernetes**.
4. Check vào ô **Enable Kubernetes**.
5. Chọn **Show system containers (advanced)** để dễ debug (tùy chọn).
6. Nhấn **Apply & Restart**.
7. Đợi 2-3 phút cho đến khi icon Kubernetes ở góc dưới chuyển sang màu xanh lá.

### 2.2 Verify Kubernetes Connection

Kiểm tra xem `kubectl` đã kết nối đúng context chưa:

```bash
# Kiểm tra context hiện tại
kubectl config current-context
# Output mong đợi: docker-desktop

# Liệt kê các node trong cluster
kubectl get nodes
# Output mong đợi:
# NAME STATUS ROLES AGE VERSION
# docker-desktop Ready control-plane 10m v1.29.1
```

## 3. Build Docker Image

Chúng ta cần build image của service trước khi deploy. Ở đây lấy ví dụ là `iam-service`.

```bash
# Di chuyển đến thư mục deployments/local/kubernetes
cd deployments/local/kubernetes

# Build Docker image từ root context
# Lưu ý: -f trỏ đến Dockerfile của service, context là root (../../..)
docker build -t iam-service:local -f ../../../services/iam-service/Dockerfile ../../..

# Kiểm tra image đã build thành công chưa
docker images | grep iam-service
# Output mong đợi:
# iam-service local [IMAGE_ID] [SIZE] [CREATED]
```

## 4. Load Image vào Cluster

** QUAN TRỌNG**: Docker Desktop có thể sử dụng các backend khác nhau. Nếu bạn đang chạy Kubernetes trong Docker Desktop, đôi khi nó không nhìn thấy image local ngay lập tức nếu sử dụng `kind` node dưới nền.

Nếu bạn dùng **Kind** (Kubernetes in Docker) riêng biệt hoặc cấu hình Docker Desktop đặc biệt, bạn cần load image:

```bash
# Load image vào kind cluster (nếu dùng kind rõ ràng)
kind load docker-image iam-service:local --name desktop

# Kiểm tra sự tồn tại của image (tùy chọn)
```

> **Mẹo**: Với Docker Desktop mặc định, việc build image local (`docker build ...`) thường tự động khả dụng cho K8s cluster của Docker Desktop. Bước load này chủ yếu dành cho ai dùng `kind` CLI để tạo cluster riêng.

## 5. Cấu Hình Secrets & ConfigMap

Môi trường Kubernetes cần các biến môi trường nhạy cảm (Secrets) và cấu hình chung (ConfigMap).

### 5.1 Tạo Secrets (Thủ công)

Bạn có thể chạy script hoặc lệnh sau để tạo secrets an toàn.

```bash
# Tạo namespace riêng cho local testing
kubectl create namespace iam-local

# Tạo secrets ngẫu nhiên và lưu vào Kubernetes
kubectl create secret generic iam-service-secrets \
 --from-literal=DATABASE_URL="postgresql://user:password@host.docker.internal:5432/iam_db?schema=public" \
 --from-literal=JWT_SECRET="$(openssl rand -base64 32)" \
 --from-literal=JWT_REFRESH_SECRET="$(openssl rand -base64 32)" \
 --from-literal=ENCRYPTION_KEY="$(openssl rand -base64 32)" \
 -n iam-local

# Kiểm tra secrets đã tạo
kubectl get secrets -n iam-local
```

> **Lưu ý về `host.docker.internal`**: Trên macOS, để pod trong K8s kết nối được với PostgreSQL chạy trên máy host (hoặc container khác qua port mapping), ta dùng `host.docker.internal`.

### 5.2 ConfigMap

File `iam-service-configmap.yaml` thường chứa các biến không nhạy cảm như `NODE_ENV`, `LOG_LEVEL`.

```bash
# Apply ConfigMap
kubectl apply -f iam-service-configmap.yaml -n iam-local
```

## 6. Deploy Service

Bây giờ chúng ta sẽ deploy các resource chính.

```bash
# Apply file Deployment manifest
kubectl apply -f iam-service-deployment.yaml -n iam-local

# Apply file Service manifest
kubectl apply -f iam-service-service.yaml -n iam-local
```

## 7. Verify & Debug

Sau khi deploy, cần đảm bảo Pod đang chạy ổn định (Running).

### 7.1 Kiểm tra Pods

```bash
# Lấy danh sách pod trong namespace
kubectl get pods -n iam-local

# Output mong đợi:
# NAME READY STATUS RESTARTS AGE
# iam-service-68994fdc79-gh2mj 1/1 Running 0 30s
```

### 7.2 Xem Logs Chi Tiết

Nếu Status không phải `Running` (ví dụ `CrashLoopBackOff` hoặc `ImagePullBackOff`), hãy xem logs:

```bash
# Xem logs thời gian thực từ pod
kubectl logs -f -n iam-local -l app=iam-service

# Xem chi tiết pod để check events (lỗi pull, mount, scheduling)
kubectl describe pod -n iam-local -l app=iam-service
```

### 7.3 Lỗi Thường Gặp

1. **ImagePullBackOff**:
 - **Lý do**: K8s không tìm thấy image `iam-service:local`.
 - **Fix**: Đảm bảo `imagePullPolicy: IfNotPresent` hoặc `Never` trong file yaml deployment local. Nếu dùng Kind, nhớ chạy lệnh `kind load`.

2. **CrashLoopBackOff**:
 - **Lý do**: Lỗi runtime, thường là không kết nối được Database.
 - **Fix**: Check biến `DATABASE_URL` trong Secret. Đảm bảo Postgres đang chạy và accessible từ K8s (dùng `host.docker.internal`).

3. **Pending Service**:
 - **Lý do**: Type `LoadBalancer` trên local đôi khi mãi pending IP.
 - **Fix**: Không sao cả, chúng ta có thể dùng `port-forward` hoặc truy cập qua `localhost`.

## 8. Test Service Access

Để truy cập service từ máy local, cách an toàn nhất là dùng `port-forward`.

```bash
# Port forward từ cổng local 5002 tới cổng 80 của service
kubectl port-forward svc/iam-service 5002:80 -n iam-local

# Terminal sẽ treo và hiện: Forwarding from 127.0.0.1:5002 -> 8000
```

Mở terminal khác và test:

```bash
# Test Health Check
curl http://localhost:5002/health/live
# Response: {"status":"ok", ...}

# Xem tài liệu Swagger/OpenAPI (nếu bật)
open http://localhost:5002/api-docs
```

## 9. Cleanup

Khi hoàn tất, hãy xóa resources để giải phóng tài nguyên.

```bash
# Xóa namespace (xóa tất cả resource bên trong)
kubectl delete namespace iam-local
```

---

## Quick Tips


### Các Vấn Đề Thường Gặp & Giải Pháp

| Vấn đề | Triệu chứng | Giải pháp |
|--------|-------------|-----------|
| **ImagePullBackOff** | Pod bị kẹt ở trạng thái `ImagePullBackOff` | Đặt `imagePullPolicy: Never` trong deployment YAML<br/>Chạy `kind load docker-image` nếu dùng Kind |
| **CrashLoopBackOff** | Pod liên tục restart | Kiểm tra logs với `kubectl logs`<br/>Verify `DATABASE_URL` trong secrets<br/>Đảm bảo DB accessible qua `host.docker.internal` |
| **Pending LoadBalancer** | Service External-IP hiển thị `<pending>` | Bình thường trên local—dùng `kubectl port-forward` thay thế |
| **Connection Refused** | Không kết nối được sau port-forward | Kiểm tra pod đang `Running` (không phải `CrashLoopBackOff`)<br/>Verify port mapping chính xác |

### Tham Chiếu Lệnh Thiết Yếu

```bash
# Debugging
kubectl get pods -n iam-local -w # Theo dõi pods real-time
kubectl describe pod <POD_NAME> -n iam-local # Thông tin chi tiết pod + events
kubectl logs -f <POD_NAME> -n iam-local # Stream logs
kubectl exec -it <POD_NAME> -n iam-local -- /bin/sh # Shell vào container

# Quản Lý Image
docker build -t service:local -f Dockerfile . # Build image
kind load docker-image service:local --name desktop # Load vào Kind cluster
docker images | grep service # Liệt kê local images

# Deploy Nhanh
kubectl apply -f deployment.yaml -n iam-local # Deploy single manifest
kubectl apply -f . -n iam-local # Deploy tất cả files trong thư mục
kubectl rollout restart deployment/iam-service -n iam-local # Force restart pods

# Cleanup
kubectl delete pod <POD_NAME> -n iam-local --force # Force delete pod bị kẹt
kubectl delete namespace iam-local --force --grace-period=0 # Force delete namespace
```

### Deployment Checklist

- [ ] Docker Desktop Kubernetes enabled
- [ ] kubectl context = `docker-desktop`
- [ ] Image built locally: `docker images | grep iam-service`
- [ ] Namespace created: `kubectl get ns iam-local`
- [ ] Secrets created: `kubectl get secrets -n iam-local`
- [ ] ConfigMap applied: `kubectl get cm -n iam-local`
- [ ] Deployment applied: `kubectl get deploy -n iam-local`
- [ ] Service created: `kubectl get svc -n iam-local`
- [ ] Pods running: `kubectl get pods -n iam-local`
- [ ] Port-forward works: `kubectl port-forward ...`
- [ ] Health check passes: `curl http://localhost:5002/health/live`

### Resource Management

**Recommended Resources per Pod:**
```yaml
resources:
 requests:
 memory: "256Mi"
 cpu: "250m"
 limits:
 memory: "512Mi"
 cpu: "500m"
```

**Check Resource Usage:**
```bash
# Overall cluster resources
kubectl top nodes

# Pod resource usage
kubectl top pods -n iam-local

# Detailed pod metrics
kubectl describe node docker-desktop
```

### Best Practices

1. **Sử dụng namespaces** để tách biệt môi trường
2. **Set resource limits** cho mọi pod
3. **Use health checks** (liveness & readiness probes)
4. **Tag images** với version cụ thể, không dùng `:latest`
5. **Store secrets** trong Kubernetes Secrets, không hardcode
6. **Use ConfigMaps** cho configuration
7. **Enable logging** để dễ debug
8. **Regular cleanup** các resources không dùng

### Trạng Thái Visual

- **Running** - Service hoạt động bình thường
- **Pending** - Đang chờ resources
- **CrashLoopBackOff** - Service liên tục fail (kiểm tra logs!)
- **ContainerCreating** - Pod đang khởi động
- **Terminating** - Pod đang tắt

### Pro Tips

1. ** Fast Rebuild**: Để iterate nhanh, dùng `kubectl rollout restart deployment/iam-service -n iam-local` sau khi rebuild image
2. ** Watch Mode**: Dùng flag `-w` để theo dõi resources update real-time
3. ** YAML Validation**: Chạy `kubectl apply --dry-run=client -f file.yaml` để validate trước khi apply
4. ** Label Filtering**: Dùng `-l app=iam-service` để filter resources theo label thay vì gõ pod names

### Tài Liệu Tham Khảo

- [Kubernetes Documentation](https://kubernetes.io/docs/)
- [Docker Desktop for Mac](https://docs.docker.com/desktop/mac/networking/)
- [Prisma Deployment Guide](https://www.prisma.io/docs/guides/deployment/deployment-guides/deploying-to-kubernetes)
- [kubectl Cheat Sheet](https://kubernetes.io/docs/reference/kubectl/cheatsheet/)
- [Kubernetes Best Practices](https://kubernetes.io/docs/concepts/configuration/overview/)
