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:
@@ -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`
|
||||||
|
|||||||
396
docs/en/guides/kubernetes-local.md
Normal file
396
docs/en/guides/kubernetes-local.md
Normal 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)
|
||||||
@@ -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`
|
||||||
|
|||||||
396
docs/vi/guides/kubernetes-local.md
Normal file
396
docs/vi/guides/kubernetes-local.md
Normal 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)
|
||||||
Reference in New Issue
Block a user