Migrate Monolith to Microservices dengan Docker, Kubernetes, dan CI/CD

Migrate Monolith to Microservices dengan Docker, Kubernetes, dan CI/CD


Migrasi dari monolith ke microservices sering terasa menakutkan, tetapi dengan strategi bertahap, containerization, dan pipeline CI/CD yang baik Anda bisa meminimalkan risiko. Artikel ini menyediakan langkah praktis, contoh Dockerfile, manifest Kubernetes, Helm chart, dan workflow GitHub Actions.


Mengapa migrasi bertahap penting?

Memecah monolith secara langsung ke ratusan layanan adalah resep untuk kegagalan. Strategi yang disarankan:

  • Strangler Pattern: ekstrak fitur satu per satu.
  • Database ownership: pastikan ownership data jelas sebelum split.
  • Contract-first: definisikan API/kontrak agar backward compatibility terjaga.

Versi dan tooling yang digunakan dalam contoh:

  • Docker Engine 24.x
  • Kubernetes 1.27 (minikube atau managed cluster seperti EKS/GKE/AKS)
  • Helm 3.12
  • GitHub Actions runners (ubuntu-latest)

Persiapan: analisis dan decomposition

  1. Inventory: identifikasi bounded contexts, dependency graph, dan titik bottleneck.
  2. Metrics: catat latency, CPU, memori untuk baseline.
  3. Define APIs: gunakan OpenAPI/Swagger untuk kontrak service.
  4. Data strategy: shared DB vs database-per-service (disarankan database-per-service untuk isolation).

Contoh decomposition

  • Monolith awal: auth, catalog, order, billing.
  • Langkah 1: ekstrak auth menjadi Service Auth (stateless + token)
  • Langkah 2: ekstrak catalog (read-heavy) -> caching & scaling terpisah

Containerize: contoh Dockerfile dan build

Buat Dockerfile sederhana untuk service Node.js/Express:

# Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
RUN npm run build

FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app ./
ENV NODE_ENV=production
EXPOSE 3000
CMD ["node", "dist/index.js"]

Build & tag:

docker build -t registry.example.com/myapp/auth:1.0.0 .
docker push registry.example.com/myapp/auth:1.0.0

Untuk development lokal, gunakan docker-compose sebelum beralih ke Kubernetes:

# docker-compose.yml
version: "3.8"
services:
  auth:
    image: registry.example.com/myapp/auth:1.0.0
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
  catalog:
    image: registry.example.com/myapp/catalog:1.0.0
    ports:
      - "4000:4000"

Deploy ke Kubernetes: manifest dasar

Contoh Deployment + Service untuk auth service:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: auth-deployment
  labels:
    app: auth
spec:
  replicas: 2
  selector:
    matchLabels:
      app: auth
  template:
    metadata:
      labels:
        app: auth
    spec:
      containers:
        - name: auth
          image: registry.example.com/myapp/auth:1.0.0
          ports:
            - containerPort: 3000
          env:
            - name: NODE_ENV
              value: "production"

Service:

apiVersion: v1
kind: Service
metadata:
  name: auth-service
spec:
  selector:
    app: auth
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000
  type: ClusterIP

Ingress (contoh menggunakan NGINX Ingress):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
    - host: myapp.example.com
      http:
        paths:
          - path: /auth
            pathType: Prefix
            backend:
              service:
                name: auth-service
                port:
                  number: 80

Helm: manage konfigurasi dan release

Struktur chart minimal:

  • charts/
  • templates/deployment.yaml
  • templates/service.yaml
  • values.yaml (default values)

Contoh values.yaml:

replicaCount: 2
image:
  repository: registry.example.com/myapp/auth
  tag: "1.0.0"
service:
  port: 80
ingress:
  enabled: true
  host: myapp.example.com

Install/upgrade:

helm upgrade --install auth ./charts/auth -f values.yaml --namespace myapp --create-namespace

Helm memudahkan rollout, rollback, dan konfigurasi multi-env (staging/production).

CI/CD: contoh GitHub Actions workflow

Contoh .github/workflows/ci-cd.yml:

name: CI/CD

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
      - name: Log in to registry
        uses: docker/login-action@v2
        with:
          registry: registry.example.com
          username: ${{ secrets.REGISTRY_USER }}
          password: ${{ secrets.REGISTRY_PASS }}
      - name: Build and push
        uses: docker/build-push-action@v4
        with:
          context: .
          push: true
          tags: registry.example.com/myapp/auth:${{ github.sha }}
      - name: Deploy to Kubernetes via kubectl
        uses: manusa/actions-setup-kubectl@v3
        with:
          version: '1.27.0'
      - name: Set KUBECONFIG
        run: echo "${{ secrets.KUBECONFIG }}" > $HOME/.kube/config
      - name: Update image in deployment
        run: |
          kubectl set image deployment/auth-deployment auth=registry.example.com/myapp/auth:${{ github.sha }} -n myapp

Poin penting:

  • Gunakan image tag berbasis git sha untuk immutability.
  • Simpan KUBECONFIG, registry creds di GitHub Secrets.
  • Untuk rollback, gunakan kubectl rollout undo atau Helm rollback.

Observability: logging, metrics, tracing

  • Logging: gunakan centralized logging (ELK/EFK, Loki).
  • Metrics: Prometheus + Grafana untuk CPU, latency, error rate.
  • Tracing: OpenTelemetry + Jaeger untuk distributed tracing.

Contoh sederhana: expose /metrics endpoint dan gunakan ServiceMonitor (Prometheus Operator) untuk scrape.

Data migration dan konsistensi

  • Mulai dengan read replica: tulis tetap ke monolith, baca dari new service (dual-write konsiderasi).
  • Event-driven migration: gunakan change data capture (Debezium) untuk publish events ke Kafka/RabbitMQ.
  • Schema evolution: gunakan versioning dan backward-compatible changes.

Praktik rollback dan canary

  • Canary deployment: mulai deploy ke 5-10% traffic (Ingress, Istio or Flagger).
  • Automatic rollback: pantau error rate, jika meningkat > threshold, rollback otomatis.
  • Backup DB: snapshot sebelum migrasi kritikal.

Troubleshooting Umum

  • Image tidak di-pull pada pod:
    • Cek imagePullSecrets, nama registry, dan tag.
    • Perintah: kubectl describe pod -n dan kubectl get events.
  • Service tidak accessible:
    • Pastikan Service selector sesuai labels pada Pod.
    • Gunakan kubectl port-forward atau curl dari inside cluster untuk debug.
  • Error 500 setelah split:
    • Periksa kontrak API (OpenAPI), versi field berubah.
    • Cek tracing untuk cari span yang lambat/error.
  • GitHub Actions gagal karena permissions:
    • Pastikan secrets benar.
    • Debug dengan menambahkan step run: env untuk print minimal (jangan cetak secrets).
  • Database race condition:
    • Gunakan distributed locks (Redis/DB advisory locks) atau design idempotent operations.

Troubleshooting: commands cepat

  • Cek pod & logs:
    • kubectl get pods -n myapp
    • kubectl logs -f deployment/auth-deployment -n myapp
  • Check rollout:
    • kubectl rollout status deployment/auth-deployment -n myapp
  • Rollback:
    • kubectl rollout undo deployment/auth-deployment -n myapp
  • Inspect events:
    • kubectl get events -n myapp β€”sort-by=.metadata.creationTimestamp

Ringkasan

Migrasi monolith ke microservices harus direncanakan: decomposition domain, containerization, deployment ke Kubernetes, dan pipeline CI/CD otomatis. Mulai bertahap dengan Strangler Pattern, gunakan Helm untuk manajemen release, implement observability, dan siapkan strategi rollback dan data migration. Dengan langkah-langkah praktis, contoh Dockerfile, manifest Kubernetes, dan workflow GitHub Actions di atas, Anda bisa meminimalkan risiko dan meningkatkan agility tim tanpa mengorbankan stability sistem. Selamat mencoba β€” lakukan setiap langkah pada environment staging sebelum production.

πŸ’¬ Komentar

Real-time

⏳ Memuat komentar...

Tulis Komentar

Email tidak akan ditampilkan

0/2000 karakter

⚠️ Catatan: Komentar akan dimoderasi sebelum ditampilkan. Mohon bersikap sopan dan konstruktif.