feat: Thêm hướng dẫn triển khai dịch vụ lên Kubernetes cục bộ bằng tiếng Việt và tiếng Anh, đồng thời cập nhật tài liệu phát triển hiện có.

This commit is contained in:
Ho Ngoc Hai
2026-01-04 13:08:40 +07:00
parent 15a77a661b
commit 67fef542bd
4 changed files with 838 additions and 0 deletions

View File

@@ -81,6 +81,29 @@ pnpm format
./scripts/db/migrate.sh iam-service deploy ./scripts/db/migrate.sh iam-service deploy
``` ```
## Kubernetes Deployment
### Local Kubernetes (Docker Desktop)
```bash
# Enable Kubernetes in Docker Desktop
# Settings → Kubernetes → Enable Kubernetes
# Deploy service
cd deployments/local/kubernetes
./deploy.sh
# Verify deployment
kubectl get pods -n iam-local
kubectl logs -f -n iam-local -l app=iam-service
# Port forward for testing
kubectl port-forward svc/iam-service 5002:80 -n iam-local
curl http://localhost:5002/health/live
```
**See detailed guide**: [Kubernetes Local Deployment Guide](./kubernetes-local.md)
## Debugging ## Debugging
- Use logger from `@goodgo/logger` - Use logger from `@goodgo/logger`

View File

@@ -0,0 +1,396 @@
# Local Kubernetes Deployment Guide
**Last Updated**: 2026-01-04
**Difficulty**: Intermediate
**Duration**: 30-45 minutes
## Overview
This guide describes how to deploy the IAM Service to a local Kubernetes cluster using Docker Desktop on macOS.
## Prerequisites
### Software
- Docker Desktop 4.0+ with Kubernetes enabled
- kubectl CLI
- kind CLI (for loading images into cluster)
- pnpm 8+
### Knowledge
- Basic understanding of Kubernetes (Pods, Deployments, Services)
- Familiarity with Docker and containerization
- Command line proficiency
## Step 1: Environment Preparation
### 1.1 Enable Kubernetes in Docker Desktop
1. Open **Docker Desktop**
2. Go to **Settings → Kubernetes**
3. Check **Enable Kubernetes**
4. Select cluster provisioning:
- **kind** (recommended for development)
- or **kubeadm**
5. Click **Apply & Restart**
6. Wait 2-3 minutes for Kubernetes to start
### 1.2 Verify Kubernetes
```bash
# Check kubectl context
kubectl config current-context
# Output: docker-desktop
# Check nodes
kubectl get nodes
# Output: docker-desktop Ready control-plane ...
# Check kind cluster name (if using kind)
kind get clusters
# Output: desktop
```
### 1.3 Install kind CLI
```bash
# Install kind
brew install kind
# Verify installation
kind version
```
## Step 2: Build Docker Image
```bash
# Navigate to deployments directory
cd deployments/local/kubernetes
# Build image (script auto-builds)
docker build -t iam-service:local -f ../../../services/iam-service/Dockerfile ../../..
# Verify image
docker images | grep iam-service
# Output: iam-service:local ... 1.67GB
```
## Step 3: Load Image into Kubernetes Cluster
**⚠️ Important**: Docker Desktop Kubernetes with kind backend **does not automatically share images** with Docker Desktop. You must load the image into the cluster:
```bash
# Load image into kind cluster
kind load docker-image iam-service:local --name desktop
# Wait for completion (may take 1-2 minutes)
```
**Note**: If using kubeadm instead of kind, you can skip this step as kubeadm shares images better.
## Step 4: Configure Secrets
### 4.1 Prepare Environment Variables
Create `.env.k8s` file with the following variables:
```bash
# Database
DATABASE_URL=postgresql://user:password@host:5432/database?sslmode=require
# JWT Secrets (MUST change in production!)
JWT_SECRET=your-strong-jwt-secret-min-32-chars
JWT_REFRESH_SECRET=your-strong-refresh-secret-min-32-chars
JWT_ID_SECRET=your-strong-id-secret-min-32-chars
# Encryption (optional)
ENCRYPTION_KEY=your-32-char-encryption-key-here
```
### 4.2 Create Kubernetes Secrets
The `deploy.sh` script will automatically create secrets, or you can create them manually:
```bash
# Create namespace
kubectl create namespace iam-local
# Create secrets
kubectl create secret generic iam-service-secrets \
--from-literal=DATABASE_URL="postgresql://..." \
--from-literal=JWT_SECRET="$(openssl rand -base64 32)" \
--from-literal=JWT_REFRESH_SECRET="$(openssl rand -base64 32)" \
--from-literal=JWT_ID_SECRET="$(openssl rand -base64 32)" \
--from-literal=ENCRYPTION_KEY="$(openssl rand -base64 32)" \
-n iam-local
# Verify secrets
kubectl get secrets -n iam-local
```
## Step 5: Deploy Service
### 5.1 Using Automated Script
```bash
cd deployments/local/kubernetes
# Run deployment script
./deploy.sh
# Script will:
# 1. Create namespace
# 2. Create secrets
# 3. Apply ConfigMap
# 4. Build Docker image
# 5. Deploy service
```
### 5.2 Manual Deployment
```bash
# Apply ConfigMap
kubectl apply -f iam-service-configmap.yaml
# Apply Deployment
kubectl apply -f iam-service-deployment.yaml
# Apply Service
kubectl apply -f iam-service-service.yaml
```
## Step 6: Verify Deployment
### 6.1 Check Pod Status
```bash
# View pods
kubectl get pods -n iam-local
# Expected output:
# NAME READY STATUS RESTARTS AGE
# iam-service-68994fdc79-gh2mj 1/1 Running 0 2m
```
### 6.2 Check Logs
```bash
# View logs
kubectl logs -f -n iam-local -l app=iam-service
# Successful logs:
# [iam-service] Database connected successfully
# [iam-service] Service started on port 5001
```
### 6.3 Check Service
```bash
# View services
kubectl get svc -n iam-local
# Output:
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
# iam-service LoadBalancer 10.96.187.160 <pending> 80:30577/TCP
```
**Note**: `EXTERNAL-IP` will be `<pending>` because local cluster doesn't have a cloud load balancer.
## Step 7: Test Service
### 7.1 Port Forward
```bash
# Forward port to access service
kubectl port-forward svc/iam-service 5002:80 -n iam-local
# Service will be available at http://localhost:5002
```
### 7.2 Test Health Endpoints
```bash
# Test liveness probe
curl http://localhost:5002/health/live
# Response:
# {
# "success": true,
# "data": {"status": "live"},
# "timestamp": "2026-01-04T06:04:03.425Z"
# }
# Test readiness probe
curl http://localhost:5002/health/ready
# Test API docs
open http://localhost:5002/api-docs
```
## Troubleshooting
### Issue 1: ImagePullBackOff
**Symptoms**:
```bash
kubectl get pods -n iam-local
# NAME READY STATUS RESTARTS AGE
# iam-service-6b8fbb574d-hn27z 0/1 ImagePullBackOff 0 2m
```
**Cause**: kind cluster cannot find image `iam-service:local`
**Solution**:
```bash
# Load image into kind cluster
kind load docker-image iam-service:local --name desktop
# Restart deployment
kubectl rollout restart deployment/iam-service -n iam-local
```
### Issue 2: CrashLoopBackOff
**Symptoms**:
```bash
kubectl get pods -n iam-local
# NAME READY STATUS RESTARTS AGE
# iam-service-xxx 0/1 CrashLoopBackOff 5 5m
```
**Cause**: Service crashes on startup
**Debug**:
```bash
# View logs
kubectl logs -n iam-local -l app=iam-service --tail=50
# Describe pod
kubectl describe pod -n iam-local -l app=iam-service
```
**Common solutions**:
- Check DATABASE_URL in secrets
- Verify Prisma migrations have run
- Check environment variables in ConfigMap
### Issue 3: Database Connection Failed
**Symptoms**: Logs show `Database connection error`
**Solution**:
```bash
# Verify DATABASE_URL
kubectl get secret iam-service-secrets -n iam-local -o jsonpath='{.data.DATABASE_URL}' | base64 -d
# Test connection from pod
kubectl exec -it -n iam-local deployment/iam-service -- sh
# Inside pod:
# npx prisma db push
```
### Issue 4: Redis Connection Errors
**Symptoms**: Logs show `Redis connection error`
**Cause**: Redis not deployed in cluster
**Solution** (optional - only if Redis needed):
```bash
# Deploy Redis
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
namespace: iam-local
spec:
serviceName: redis
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: iam-local
spec:
selector:
app: redis
ports:
- port: 6379
EOF
# Update ConfigMap with REDIS_HOST=redis
kubectl edit configmap iam-service-config -n iam-local
# Restart deployment
kubectl rollout restart deployment/iam-service -n iam-local
```
## Debugging Commands
```bash
# View all resources
kubectl get all -n iam-local
# Describe deployment
kubectl describe deployment iam-service -n iam-local
# Describe pod
kubectl describe pod -n iam-local -l app=iam-service
# View events
kubectl get events -n iam-local --sort-by='.lastTimestamp'
# Exec into pod
kubectl exec -it -n iam-local deployment/iam-service -- sh
# View logs realtime
kubectl logs -f -n iam-local -l app=iam-service
# View logs from previous container (if pod restarted)
kubectl logs -n iam-local -l app=iam-service --previous
```
## Cleanup
```bash
# Delete deployment
kubectl delete -f iam-service-deployment.yaml
kubectl delete -f iam-service-service.yaml
kubectl delete -f iam-service-configmap.yaml
# Delete secrets
kubectl delete secret iam-service-secrets -n iam-local
# Delete namespace (deletes everything)
kubectl delete namespace iam-local
```
## Next Steps
1. **Deploy Redis** (optional): To enable caching and rate limiting
2. **Setup Ingress**: To expose service externally
3. **Configure HPA**: Horizontal Pod Autoscaler for auto-scaling
4. **Add Monitoring**: Prometheus + Grafana
5. **Setup CI/CD**: Automated deployment on code changes
## Resources
- [Kubernetes Documentation](https://kubernetes.io/docs/)
- [Docker Desktop Kubernetes](https://docs.docker.com/desktop/kubernetes/)
- [kind Documentation](https://kind.sigs.k8s.io/)
- [kubectl Cheat Sheet](https://kubernetes.io/docs/reference/kubectl/cheatsheet/)
- [Local Kubernetes README](../../../deployments/local/kubernetes/README.md)

View File

@@ -81,6 +81,29 @@ pnpm format
./scripts/db/migrate.sh iam-service deploy ./scripts/db/migrate.sh iam-service deploy
``` ```
## Kubernetes Deployment
### Local Kubernetes (Docker Desktop)
```bash
# Enable Kubernetes trong Docker Desktop
# Settings → Kubernetes → Enable Kubernetes
# Deploy service
cd deployments/local/kubernetes
./deploy.sh
# Verify deployment
kubectl get pods -n iam-local
kubectl logs -f -n iam-local -l app=iam-service
# Port forward để test
kubectl port-forward svc/iam-service 5002:80 -n iam-local
curl http://localhost:5002/health/live
```
**Xem hướng dẫn chi tiết**: [Kubernetes Local Deployment Guide](./kubernetes-local.md)
## Debugging ## Debugging
- Sử dụng logger từ `@goodgo/logger` - Sử dụng logger từ `@goodgo/logger`

View File

@@ -0,0 +1,396 @@
# Hướng Dẫn Deploy Kubernetes Local
**Cập nhật**: 2026-01-04
**Độ khó**: Intermediate
**Thời gian**: 30-45 phút
## Tổng Quan
Hướng dẫn này mô tả cách deploy IAM Service lên local Kubernetes cluster sử dụng Docker Desktop trên macOS.
## Yêu Cầu
### Phần Mềm
- Docker Desktop 4.0+ với Kubernetes enabled
- kubectl CLI
- kind CLI (để load images vào cluster)
- pnpm 8+
### Kiến Thức
- Hiểu cơ bản về Kubernetes (Pods, Deployments, Services)
- Quen thuộc với Docker và containerization
- Biết cách sử dụng terminal/command line
## Bước 1: Chuẩn Bị Môi Trường
### 1.1 Enable Kubernetes trong Docker Desktop
1. Mở **Docker Desktop**
2. Vào **Settings → Kubernetes**
3. Check **Enable Kubernetes**
4. Chọn cluster provisioning:
- **kind** (recommended cho development)
- hoặc **kubeadm**
5. Click **Apply & Restart**
6. Đợi 2-3 phút để Kubernetes khởi động
### 1.2 Verify Kubernetes
```bash
# Check kubectl context
kubectl config current-context
# Output: docker-desktop
# Check nodes
kubectl get nodes
# Output: docker-desktop Ready control-plane ...
# Check kind cluster name (nếu dùng kind)
kind get clusters
# Output: desktop
```
### 1.3 Install kind CLI
```bash
# Install kind
brew install kind
# Verify installation
kind version
```
## Bước 2: Build Docker Image
```bash
# Di chuyển đến thư mục deployments
cd deployments/local/kubernetes
# Build image (script tự động build)
docker build -t iam-service:local -f ../../../services/iam-service/Dockerfile ../../..
# Verify image
docker images | grep iam-service
# Output: iam-service:local ... 1.67GB
```
## Bước 3: Load Image vào Kubernetes Cluster
**⚠️ Quan Trọng**: Docker Desktop Kubernetes với kind backend **không tự động share images** với Docker Desktop. Bạn phải load image vào cluster:
```bash
# Load image vào kind cluster
kind load docker-image iam-service:local --name desktop
# Đợi quá trình hoàn tất (có thể mất 1-2 phút)
```
**Lưu ý**: Nếu dùng kubeadm thay vì kind, bạn có thể skip bước này vì kubeadm share images tốt hơn.
## Bước 4: Cấu Hình Secrets
### 4.1 Chuẩn Bị Environment Variables
Tạo file `.env.k8s` với các biến sau:
```bash
# Database
DATABASE_URL=postgresql://user:password@host:5432/database?sslmode=require
# JWT Secrets (PHẢI thay đổi trong production!)
JWT_SECRET=your-strong-jwt-secret-min-32-chars
JWT_REFRESH_SECRET=your-strong-refresh-secret-min-32-chars
JWT_ID_SECRET=your-strong-id-secret-min-32-chars
# Encryption (optional)
ENCRYPTION_KEY=your-32-char-encryption-key-here
```
### 4.2 Tạo Kubernetes Secrets
Script `deploy.sh` sẽ tự động tạo secrets, hoặc bạn có thể tạo thủ công:
```bash
# Tạo namespace
kubectl create namespace iam-local
# Tạo secrets
kubectl create secret generic iam-service-secrets \
--from-literal=DATABASE_URL="postgresql://..." \
--from-literal=JWT_SECRET="$(openssl rand -base64 32)" \
--from-literal=JWT_REFRESH_SECRET="$(openssl rand -base64 32)" \
--from-literal=JWT_ID_SECRET="$(openssl rand -base64 32)" \
--from-literal=ENCRYPTION_KEY="$(openssl rand -base64 32)" \
-n iam-local
# Verify secrets
kubectl get secrets -n iam-local
```
## Bước 5: Deploy Service
### 5.1 Sử Dụng Script Tự Động
```bash
cd deployments/local/kubernetes
# Run deployment script
./deploy.sh
# Script sẽ:
# 1. Tạo namespace
# 2. Tạo secrets
# 3. Apply ConfigMap
# 4. Build Docker image
# 5. Deploy service
```
### 5.2 Deploy Thủ Công
```bash
# Apply ConfigMap
kubectl apply -f iam-service-configmap.yaml
# Apply Deployment
kubectl apply -f iam-service-deployment.yaml
# Apply Service
kubectl apply -f iam-service-service.yaml
```
## Bước 6: Verify Deployment
### 6.1 Check Pod Status
```bash
# Xem pods
kubectl get pods -n iam-local
# Output mong đợi:
# NAME READY STATUS RESTARTS AGE
# iam-service-68994fdc79-gh2mj 1/1 Running 0 2m
```
### 6.2 Check Logs
```bash
# Xem logs
kubectl logs -f -n iam-local -l app=iam-service
# Logs thành công:
# [iam-service] Database connected successfully
# [iam-service] Service started on port 5001
```
### 6.3 Check Service
```bash
# Xem services
kubectl get svc -n iam-local
# Output:
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
# iam-service LoadBalancer 10.96.187.160 <pending> 80:30577/TCP
```
**Lưu ý**: `EXTERNAL-IP` sẽ là `<pending>` vì local cluster không có cloud load balancer.
## Bước 7: Test Service
### 7.1 Port Forward
```bash
# Forward port để access service
kubectl port-forward svc/iam-service 5002:80 -n iam-local
# Service sẽ available tại http://localhost:5002
```
### 7.2 Test Health Endpoints
```bash
# Test liveness probe
curl http://localhost:5002/health/live
# Response:
# {
# "success": true,
# "data": {"status": "live"},
# "timestamp": "2026-01-04T06:04:03.425Z"
# }
# Test readiness probe
curl http://localhost:5002/health/ready
# Test API docs
open http://localhost:5002/api-docs
```
## Troubleshooting
### Issue 1: ImagePullBackOff
**Triệu chứng**:
```bash
kubectl get pods -n iam-local
# NAME READY STATUS RESTARTS AGE
# iam-service-6b8fbb574d-hn27z 0/1 ImagePullBackOff 0 2m
```
**Nguyên nhân**: kind cluster không thể tìm thấy image `iam-service:local`
**Giải pháp**:
```bash
# Load image vào kind cluster
kind load docker-image iam-service:local --name desktop
# Restart deployment
kubectl rollout restart deployment/iam-service -n iam-local
```
### Issue 2: CrashLoopBackOff
**Triệu chứng**:
```bash
kubectl get pods -n iam-local
# NAME READY STATUS RESTARTS AGE
# iam-service-xxx 0/1 CrashLoopBackOff 5 5m
```
**Nguyên nhân**: Service crash khi start
**Debug**:
```bash
# Xem logs
kubectl logs -n iam-local -l app=iam-service --tail=50
# Describe pod
kubectl describe pod -n iam-local -l app=iam-service
```
**Giải pháp phổ biến**:
- Check DATABASE_URL trong secrets
- Verify Prisma migrations đã chạy
- Check environment variables trong ConfigMap
### Issue 3: Database Connection Failed
**Triệu chứng**: Logs hiển thị `Database connection error`
**Giải pháp**:
```bash
# Verify DATABASE_URL
kubectl get secret iam-service-secrets -n iam-local -o jsonpath='{.data.DATABASE_URL}' | base64 -d
# Test connection từ pod
kubectl exec -it -n iam-local deployment/iam-service -- sh
# Inside pod:
# npx prisma db push
```
### Issue 4: Redis Connection Errors
**Triệu chứng**: Logs hiển thị `Redis connection error`
**Nguyên nhân**: Redis chưa được deploy trong cluster
**Giải pháp** (optional - chỉ nếu cần Redis):
```bash
# Deploy Redis
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
namespace: iam-local
spec:
serviceName: redis
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: iam-local
spec:
selector:
app: redis
ports:
- port: 6379
EOF
# Update ConfigMap với REDIS_HOST=redis
kubectl edit configmap iam-service-config -n iam-local
# Restart deployment
kubectl rollout restart deployment/iam-service -n iam-local
```
## Debugging Commands
```bash
# Xem tất cả resources
kubectl get all -n iam-local
# Describe deployment
kubectl describe deployment iam-service -n iam-local
# Describe pod
kubectl describe pod -n iam-local -l app=iam-service
# Xem events
kubectl get events -n iam-local --sort-by='.lastTimestamp'
# Exec vào pod
kubectl exec -it -n iam-local deployment/iam-service -- sh
# Xem logs realtime
kubectl logs -f -n iam-local -l app=iam-service
# Xem logs từ container trước (nếu pod restart)
kubectl logs -n iam-local -l app=iam-service --previous
```
## Cleanup
```bash
# Xóa deployment
kubectl delete -f iam-service-deployment.yaml
kubectl delete -f iam-service-service.yaml
kubectl delete -f iam-service-configmap.yaml
# Xóa secrets
kubectl delete secret iam-service-secrets -n iam-local
# Xóa namespace (xóa tất cả)
kubectl delete namespace iam-local
```
## Next Steps
1. **Deploy Redis** (optional): Để enable caching và rate limiting
2. **Setup Ingress**: Để expose service ra ngoài
3. **Configure HPA**: Horizontal Pod Autoscaler cho auto-scaling
4. **Add Monitoring**: Prometheus + Grafana
5. **Setup CI/CD**: Tự động deploy khi có code changes
## Resources
- [Kubernetes Documentation](https://kubernetes.io/docs/)
- [Docker Desktop Kubernetes](https://docs.docker.com/desktop/kubernetes/)
- [kind Documentation](https://kind.sigs.k8s.io/)
- [kubectl Cheat Sheet](https://kubernetes.io/docs/reference/kubectl/cheatsheet/)
- [Local Kubernetes README](../../../deployments/local/kubernetes/README.md)