Files
pos-system/docs/vi/guides/kubernetes-local.md

9.0 KiB

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

# 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

# Install kind
brew install kind

# Verify installation
kind version

Bước 2: Build Docker Image

# 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:

# 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:

# 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:

# 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

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

# 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

# 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

# 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

# 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

# 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

# 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:

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:

# 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:

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:

# 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:

# 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):

# 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

# 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

# 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