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

9.2 KiB

Local Kubernetes Deployment Guide

EN: Local Kubernetes Deployment Guide

VI: Hướng dẫn triển khai Kubernetes cục bộ

Last Updated: 2026-01-05 Difficulty: Intermediate Duration: 30-45 minutes

Workflow

graph TD
    Start([Start]) --> EnvPrep[1. Environment Prep]
    EnvPrep --> BuildImg[2. Build Docker Image]
    BuildImg --> LoadImg[3. Load Image to Cluster<br/>(Kind/Docker Desktop)]
    LoadImg --> Secrets[4. Configure Secrets<br/>& Environment]
    Secrets --> Deploy[5. Deploy Service<br/>(K8s Manifests)]
    Deploy --> Verify[6. Verify Deployment]
    Verify --> Test[7. Test Service<br/>(Port Forward & Curl)]
    Test --> End([Complete])

    subgraph "Deployment Details"
        Deploy --> |Apply| ConfigMap
        Deploy --> |Apply| Deployment
        Deploy --> |Apply| Service
    end
    
    style Start fill:#d4edda,stroke:#28a745,stroke-width:2px
    style End fill:#d4edda,stroke:#28a745,stroke-width:2px
    style EnvPrep fill:#e2e3e5,stroke:#6c757d
    style BuildImg fill:#fff3cd,stroke:#ffc107
    style LoadImg fill:#fff3cd,stroke:#ffc107
    style Secrets fill:#f8d7da,stroke:#dc3545
    style Deploy fill:#cce5ff,stroke:#007bff
    style Verify fill:#cce5ff,stroke:#007bff

Overview

This guide details how to deploy the IAM Service (or any microservice in the GoodGo ecosystem) to a local Kubernetes cluster using Docker Desktop on macOS.

Important Note: This guide assumes you are using Docker Desktop with Kubernetes enabled. If you are using Minikube or plain Kind, the steps might differ slightly (especially the image loading part).

1. Prerequisites

Software

  • Docker Desktop 4.0+: Download Link
    • Kubernetes must be enabled in settings.
  • kubectl CLI: Command-line tool for interacting with K8s.
    brew install kubectl
    
  • kind CLI: Required to load images into the cluster if using Kind backend explicitely.
    brew install kind
    
  • pnpm 8+: Project package manager.
    npm install -g pnpm
    

Knowledge

  • Basic understanding of Kubernetes concepts: Pod, Deployment, Service, Secret, ConfigMap.
  • Familiarity with basic Docker commands (docker build, docker images).
  • Ability to navigate and run commands in the Terminal.

2. Environment Preparation

2.1 Enable Kubernetes in Docker Desktop

  1. Open Docker Desktop.
  2. Click the Settings (⚙️) icon.
  3. Select the Kubernetes tab.
  4. Check Enable Kubernetes.
  5. Select Show system containers (advanced) for easier debugging (optional).
  6. Click Apply & Restart.
  7. Wait 2-3 minutes until the Kubernetes icon in the bottom corner turns green.

2.2 Verify Kubernetes Connection

Check if kubectl is connected to the correct context:

# EN: Check current context
# VI: Kiểm tra context hiện tại
kubectl config current-context
# Expected Output: docker-desktop

# EN: List all nodes in the cluster
# VI: Liệt kê các node trong cluster
kubectl get nodes
# Expected Output:
# NAME             STATUS   ROLES           AGE   VERSION
# docker-desktop   Ready    control-plane   10m   v1.29.1

3. Build Docker Image

We need to build the service image before deploying. Taking iam-service as an example.

# EN: Navigate to the kubernetes deployment directory
# VI: Di chuyển đến thư mục deployments/local/kubernetes
cd deployments/local/kubernetes

# EN: Build the Docker image from the root context
# VI: Build Docker image từ root context
# Note: -f points to service Dockerfile, context is root (../../..)
docker build -t iam-service:local -f ../../../services/iam-service/Dockerfile ../../..

# EN: Verify the image was built successfully
# VI: Kiểm tra image đã build thành công chưa
docker images | grep iam-service
# Expected Output:
# iam-service   local     [IMAGE_ID]   [SIZE]   [CREATED]

4. Load Image into Cluster

⚠️ IMPORTANT: Docker Desktop can use different backends. If you are running Kubernetes inside Docker Desktop, sometimes it doesn't immediately see local images if using a kind node underneath.

If you are using Kind (Kubernetes in Docker) separately or a specific Docker Desktop config, you need to load the image:

# EN: Load image into kind cluster (if using kind explicitly)
# VI: Load image vào kind cluster (nếu dùng kind rõ ràng)
kind load docker-image iam-service:local --name desktop

# EN: Validating image presence (optional, hard with Docker Desktop K8s directly)
# VI: Kiểm tra sự tồn tại của image (tùy chọn)

Tip

: With default Docker Desktop, building the local image (docker build ...) is usually automatically available to Docker Desktop's K8s cluster. This loading step is mainly for those using kind CLI to create separate clusters.

5. Configure Secrets & ConfigMap

Kubernetes environments need sensitive environment variables (Secrets) and general configuration (ConfigMap).

5.1 Create Secrets (Manually)

You can run a script or the following commands to create secrets securely.

# EN: Create a dedicated namespace for local testing
# VI: Tạo namespace riêng cho local testing
kubectl create namespace iam-local

# EN: Generate random secrets and store in Kubernetes
# VI: 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

# EN: Verify secrets creation
# VI: Kiểm tra secrets đã tạo
kubectl get secrets -n iam-local

Note on host.docker.internal: On macOS, for a K8s pod to connect to PostgreSQL running on the host machine (or another container via port mapping), we use host.docker.internal.

5.2 ConfigMap

The iam-service-configmap.yaml file typically contains non-sensitive variables like NODE_ENV, LOG_LEVEL.

# EN: Apply ConfigMap
# VI: Apply ConfigMap
kubectl apply -f iam-service-configmap.yaml -n iam-local

6. Deploy Service

Now we will deploy the main resources.

# EN: Apply Deployment manifest
# VI: Apply file Deployment manifest
kubectl apply -f iam-service-deployment.yaml -n iam-local

# EN: Apply Service manifest (LoadBalancer/NodePort)
# VI: Apply file Service manifest
kubectl apply -f iam-service-service.yaml -n iam-local

7. Verify & Debug

After deployment, ensure the Pod is stable (Running).

7.1 Check Pods

# EN: Get all pods in the namespace
# VI: Lấy danh sách pod trong namespace
kubectl get pods -n iam-local

# Expected Output:
# NAME                           READY   STATUS    RESTARTS   AGE
# iam-service-68994fdc79-gh2mj   1/1     Running   0          30s

7.2 View Detailed Logs

If Status is not Running (e.g., CrashLoopBackOff or ImagePullBackOff), check logs:

# EN: Stream logs from the pod
# VI: Xem logs thời gian thực từ pod
kubectl logs -f -n iam-local -l app=iam-service

# EN: Describe pod to see events (pull error, mounts, scheduling)
# VI: Xem chi tiết pod để check events (lỗi pull, mount, scheduling)
kubectl describe pod -n iam-local -l app=iam-service

7.3 Common Errors

  1. ImagePullBackOff:

    • Reason: K8s cannot find iam-service:local image.
    • Fix: Ensure imagePullPolicy: IfNotPresent or Never in local deployment yaml. If using Kind, remember to run kind load.
  2. CrashLoopBackOff:

    • Reason: Runtime error, usually unable to connect to Database.
    • Fix: Check DATABASE_URL in Secret. Ensure Postgres is running and accessible from K8s (use host.docker.internal).
  3. Pending Service:

    • Reason: LoadBalancer type on local sometimes hangs pending IP.
    • Fix: Not a problem, we can use port-forward or access via localhost.

8. Test Service Access

To access the service from your local machine, the safest way is port-forward.

# EN: Port forward from local port 5002 to service port 80
# VI: 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 will hang and show: Forwarding from 127.0.0.1:5002 -> 8000

Open another terminal and test:

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

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

9. Cleanup

When done, delete resources to free up capacity.

# EN: Delete the namespace (removes all resources within)
# VI: Xóa namespace (xóa tất cả resource bên trong)
kubectl delete namespace iam-local

References