Kubernetes od Docker Compose — moja migracja krok po kroku

Miałem działający Docker Compose. Migracja do Kubernetes wymagała napisania manifestów dla każdego serwisu, rozwiązania problemu z sekretami i skonfigurowania health checks.

Punkt startowy — Docker Compose

Docker Compose działał świetnie w developmencie. Jeden plik, docker compose up i wszystko chodzi. Ale Compose nie daje:

  • automatycznego restartu po awarii noda
  • rolling updates bez downtime
  • horizontal scaling
  • deklaratywnego zarządzania konfiguracją

Kubernetes rozwiązuje wszystkie te problemy.

Mapowanie pojęć

Docker Compose Kubernetes
service Deployment + Service
volumes PersistentVolumeClaim
environment ConfigMap + Secret
networks NetworkPolicy
depends_on initContainer
healthcheck livenessProbe + readinessProbe

Deployment manifest

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 2
  selector:
    matchLabels:
      app: frontend
  template:
    spec:
      containers:
        - name: frontend
          image: ghcr.io/szymonborowski/portfolio-frontend:v0.0.4
          ports:
            - containerPort: 80
          envFrom:
            - configMapRef:
                name: frontend-config
            - secretRef:
                name: frontend-secrets
          livenessProbe:
            httpGet:
              path: /health
              port: 80
            initialDelaySeconds: 30
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /ready
              port: 80
            initialDelaySeconds: 10
            periodSeconds: 5

InitContainers — migracje bazy

Największy problem: jak upewnić się, że migracje DB wykonają się przed startem aplikacji? W Compose używałem depends_on z condition: service_healthy. W K8s używam initContainer:

initContainers:
  - name: migrate
    image: ghcr.io/szymonborowski/portfolio-blog:v0.0.4
    command: ["php", "artisan", "migrate", "--force"]
    envFrom:
      - secretRef:
          name: blog-secrets

initContainer musi zakończyć się sukcesem zanim główny kontener wystartuje.

StatefulSets dla baz danych

MySQL i Redis działają jako StatefulSet, nie Deployment — bo potrzebują stabilnej tożsamości sieciowej i trwałego storage:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: blog-db
spec:
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 10Gi

Co poszło nie tak

Największa pułapka: obrazy ARM vs AMD64. Budowałem obrazy na MacBooku (ARM) bez --platform linux/amd64. Na klastrze (AMD64) kontenery crashowały z błędem "exec format error". Rozwiązanie: multi-arch build z docker buildx:

docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/... --push .

Comments

No comments yet