Kubernetes Compose App Uebersetzen

Aus Xinux Wiki
Version vom 9. August 2026, 08:11 Uhr von Thomas.will (Diskussion | Beiträge) (Die Seite wurde neu angelegt: „Dieser Artikel übersetzt eine bekannte Docker-Compose-Anwendung Schritt für Schritt nach Kubernetes. Als Beispiel dient eine einfache Web-Anwendung mit Daten…“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

Dieser Artikel übersetzt eine bekannte Docker-Compose-Anwendung Schritt für Schritt nach Kubernetes. Als Beispiel dient eine einfache Web-Anwendung mit Datenbank – die gleiche Art von Setup, die in Compose aus einem web- und einem db-Service besteht.

Ausgangspunkt: die Compose-Datei

Als Referenz die Compose-Anwendung, die übersetzt wird:

services:
  web:
    image: nginx:1.25
    ports:
      - "8080:80"
    environment:
      - APP_MODE=production
    depends_on:
      - db

  db:
    image: postgres:16
    environment:
      - POSTGRES_PASSWORD=geheim
      - POSTGRES_DB=appdb
    volumes:
      - db_data:/var/lib/postgresql/data

volumes:
  db_data:

Diese Datei wird in den folgenden Abschnitten Stück für Stück in Kubernetes-Objekte übersetzt.

Von Container zu Pod und Deployment

Der Pod
  • Die kleinste ausführbare Einheit in Kubernetes ist der Pod, kein einzelner Container. Ein Pod kann einen oder mehrere Container enthalten, die sich Netzwerk und Storage teilen. In den meisten Fällen – wie hier – enthält ein Pod genau einen Container.
Warum nicht direkt Pods erstellen
  • Ein einzeln erstellter Pod wird bei einem Absturz nicht automatisch neu gestartet. Dafür braucht es eine übergeordnete Instanz.
Das Deployment
  • Ein Deployment beschreibt den Zielzustand ("es sollen N Instanzen dieses Pods laufen") und sorgt dafür, dass er eingehalten wird – inklusive Neustart bei Absturz und kontrollierten Updates. Das Deployment entspricht am ehesten dem web:-Service aus der Compose-Datei, nur mit eingebauter Selbstheilung.

Das web-Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:1.25
          ports:
            - containerPort: 80
          env:
            - name: APP_MODE
              value: "production"
Anwenden
  • kubectl apply -f web-deployment.yaml
Status prüfen
  • kubectl get deployments
  • kubectl get pods -o wide

Von ports zu Service

Das ports: "8080:80" aus Compose hat in Kubernetes kein direktes Gegenstück auf Container-Ebene. Stattdessen übernimmt ein eigenes Objekt die Netzwerk-Erreichbarkeit.

Der Service
  • Ein Service gibt einer Gruppe von Pods (ausgewählt über Labels) eine stabile, gleichbleibende Adresse. Das ist notwendig, weil Pods jederzeit neu erstellt werden und dabei eine neue IP-Adresse bekommen – ein Service bleibt davon unberührt erreichbar.
ClusterIP als Standard
  • Ohne weitere Angabe ist ein Service nur innerhalb des Clusters erreichbar. Das entspricht noch nicht dem externen Zugriff aus der Compose-Datei, ist aber der erste, notwendige Schritt.
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 80
Anwenden
  • kubectl apply -f web-service.yaml
Erreichbarkeit von innerhalb des Clusters testen
  • kubectl run test-curl --rm -it --image=curlimages/curl -- curl -s http://web
Erreichbarkeit von außen testen (ohne Ingress)
  • Solange noch kein Ingress existiert, kann mit Port-Forwarding von außen zugegriffen werden – vergleichbar mit dem 8080:80 aus Compose, nur manuell für die Dauer der Sitzung.
  • kubectl port-forward service/web 8080:80
  • Anschließend ist die Anwendung unter http://localhost:8080 erreichbar, solange der Befehl im Vordergrund läuft.

Von environment zu ConfigMap und Secret

In der Compose-Datei stehen APP_MODE=production (unkritisch) und POSTGRES_PASSWORD=geheim (sensibel) beide gleich als environment:. Kubernetes trennt das bewusst.

ConfigMap für unkritische Werte
  • Für Konfiguration ohne Geheimhaltungsbedarf.
apiVersion: v1
kind: ConfigMap
metadata:
  name: web-config
data:
  APP_MODE: "production"
Secret für sensible Werte
  • Inhalt wird base64-kodiert gespeichert – das ist keine Verschlüsselung, nur Verschleierung. Für echte Vertraulichkeit braucht ein Cluster zusätzliche Maßnahmen (Encryption at Rest, externe Secret-Stores), was über diesen Kurs hinausgeht.
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
stringData:
  POSTGRES_PASSWORD: geheim
Beide anwenden
  • kubectl apply -f web-config.yaml
  • kubectl apply -f db-secret.yaml
Im Deployment referenzieren
  • Der env:-Abschnitt im Deployment wird angepasst, um aus ConfigMap und Secret zu lesen statt den Wert direkt einzutragen.
env:
  - name: APP_MODE
    valueFrom:
      configMapKeyRef:
        name: web-config
        key: APP_MODE
  - name: POSTGRES_PASSWORD
    valueFrom:
      secretKeyRef:
        name: db-secret
        key: POSTGRES_PASSWORD

Das db-Deployment und der Datenbank-Service

Die Datenbank wird nach demselben Muster übersetzt wie web.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: db
spec:
  replicas: 1
  selector:
    matchLabels:
      app: db
  template:
    metadata:
      labels:
        app: db
    spec:
      containers:
        - name: db
          image: postgres:16
          ports:
            - containerPort: 5432
          env:
            - name: POSTGRES_DB
              value: "appdb"
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-secret
                  key: POSTGRES_PASSWORD
---
apiVersion: v1
kind: Service
metadata:
  name: db
spec:
  selector:
    app: db
  ports:
    - port: 5432
      targetPort: 5432
Wichtig zum Namen des Service
  • Der Service heißt db. Innerhalb des Clusters ist die Datenbank damit unter genau diesem Namen erreichbar – das entspricht exakt dem Verhalten von depends_on: db in Compose, wo der Service-Name ebenfalls als Hostname funktioniert. Der web-Container kann sich also mit db:5432 verbinden, ohne dass eine IP-Adresse bekannt sein muss.
Anwenden
  • kubectl apply -f db-deployment.yaml

depends_on gibt es nicht – was das bedeutet

Kein eingebautes Warten
  • Kubernetes startet web und db unabhängig voneinander. Es gibt kein automatisches "warte, bis die Datenbank bereit ist" wie es depends_on in Compose suggeriert (selbst dort wartet es ohne Healthcheck-Angabe nur auf den Containerstart, nicht auf Bereitschaft).
Die Kubernetes-Lösung
Probes
  • Statt einer Startreihenfolge prüft Kubernetes fortlaufend, ob ein Container tatsächlich bereit ist, Traffic zu empfangen. Das wird im nächsten Artikel beim Thema Health-Checks und Rolling Updates vertieft.

Alltagswerkzeuge zum Debuggen

Diese Befehle ersetzen im Kubernetes-Alltag das, was docker logs und docker exec bei Compose waren.

Logs eines Pods ansehen
  • kubectl logs <pod-name>
Logs fortlaufend verfolgen
  • kubectl logs -f <pod-name>
In einen laufenden Container wechseln
  • kubectl exec -it <pod-name> -- /bin/bash
Detaillierten Zustand und Ereignisse eines Pods ansehen
  • Der wichtigste Befehl bei Problemen – zeigt unter anderem, warum ein Pod nicht startet.
  • kubectl describe pod <pod-name>
Alle Ressourcen eines Namespace auf einen Blick
  • kubectl get all

Übung: Vollständige Übersetzung selbst durchführen

  1. Legt für jedes der oben gezeigten Manifeste eine eigene YAML-Datei an und wendet sie in dieser Reihenfolge an: ConfigMap, Secret, db-Deployment inkl. Service, web-Deployment inkl. Service.
  2. Prüft mit kubectl get pods, dass beide Pods im Status Running sind.
  3. Wechselt mit kubectl exec -it in den web-Pod und prüft von dort mit curl db:5432 (oder nc -zv db 5432), ob die Datenbank über den Service-Namen erreichbar ist.
  4. Löscht den db-Pod gezielt mit kubectl delete pod und beobachtet, ob der web-Pod danach noch funktioniert – vergleicht das Verhalten mit dem, was ihr in Compose erwarten würdet.
  5. Öffnet mit kubectl port-forward service/web 8080:80 die Anwendung im Browser und bestätigt den Zugriff.

Übung: Fehler bewusst provozieren

  1. Ändert im web-Deployment den Image-Namen versehentlich auf nginx:1.25.9999 (nicht existierendes Tag) und wendet es erneut an.
  2. Beobachtet mit kubectl get pods, welcher Status auftritt.
  3. Findet mit kubectl describe pod <pod-name> im Abschnitt Events die genaue Fehlerursache.
  4. Korrigiert das Image wieder auf nginx:1.25 und bestätigt, dass der Pod danach wieder normal startet.