- Authors

- Name
- Phillip Pham
- @ddppham
Kubernetes Hands-On Tutorial: Vom ersten Pod zum laufenden Service
TL;DR
- In 30 Minuten deployen Sie einen Pod, ein Deployment mit drei Replicas und einen Service mit Load Balancing.
- Pods sind die kleinste Einheit. Deployments sorgen fuer Selbstheilung und Rolling Updates. Services geben eine stabile Adresse.
- Alle YAML-Beispiele sind vollstaendig und koennen direkt per
kubectl apply -fangewendet werden. - Am Ende steht ein komplettes Beispiel mit Liveness- und Readiness-Probes zum Kopieren.
Voraussetzungen
Sie brauchen einen laufenden Kubernetes-Cluster und kubectl auf Ihrem Rechner. Fuer dieses Tutorial reicht ein lokaler Cluster voellig aus.
Option A: Docker Desktop -- Kubernetes in den Einstellungen aktivieren. Funktioniert auf macOS und Windows.
Option B: minikube -- Laeuft ueberall, braucht nur Docker oder eine VM.
# minikube installieren und starten
minikube start --cpus=2 --memory=2048
# Cluster pruefen
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# minikube Ready control-plane 30s v1.29.0
Option C: Online Playground -- Killercoda oder Play with Kubernetes im Browser. Keine Installation noetig, aber zeitlich begrenzt.
Sobald kubectl get nodes einen Node im Status Ready zeigt, kann es losgehen.
Teil 1: Der erste Pod
Ein Pod ist die kleinste deploybare Einheit in Kubernetes. Er enthaelt einen oder mehrere Container, die sich einen Netzwerk-Namespace teilen. In der Praxis laeuft fast immer genau ein Container pro Pod.
# Pod mit einem nginx-Container starten
kubectl run mein-erster-pod --image=nginx:alpine
# Status pruefen
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# mein-erster-pod 1/1 Running 0 5s
Der Pod laeuft. Jetzt die wichtigsten Befehle zum Untersuchen:
# Details und Events anzeigen
kubectl describe pod mein-erster-pod
# Shell im Container oeffnen
kubectl exec -it mein-erster-pod -- /bin/sh
# hostname, cat /etc/nginx/nginx.conf, exit
# Logs anschauen (live mit -f)
kubectl logs mein-erster-pod
kubectl logs -f mein-erster-pod
# Pod loeschen
kubectl delete pod mein-erster-pod
Wichtig zu verstehen: Ein einzelner Pod hat keine Selbstheilung. Wenn der Prozess im Container abstuerzt, startet Kubernetes den Container zwar neu (je nach restartPolicy). Aber wenn der Node ausfaellt oder jemand den Pod loescht, ist er weg. Fuer Produktions-Workloads braucht man Deployments.
Teil 2: Deployments fuer Hochverfuegbarkeit
Ein Deployment verwaltet eine Menge identischer Pods (Replicas). Es sorgt dafuer, dass immer die gewuenschte Anzahl laeuft, und ermoeglicht Rolling Updates ohne Downtime.
Erstellen Sie eine Datei meine-app.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: meine-app
labels:
app: meine-app
spec:
replicas: 3
selector:
matchLabels:
app: meine-app
template:
metadata:
labels:
app: meine-app
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
Drei Dinge sind hier zentral:
replicas: 3sagt Kubernetes, dass immer drei Pods laufen sollen.selector.matchLabelsdefiniert, welche Pods zu diesem Deployment gehoeren.resourcessetzt CPU- und Memory-Limits. Ohne Limits riskiert man, dass ein Pod den ganzen Node leer frisst. Mehr dazu unter OOMKilled Troubleshooting.
# Deployment anwenden
kubectl apply -f meine-app.yaml
# Status pruefen
kubectl get deployment meine-app
# NAME READY UP-TO-DATE AVAILABLE AGE
# meine-app 3/3 3 3 10s
# Alle Pods des Deployments anzeigen
kubectl get pods -l app=meine-app
Selbstheilung testen
Das ist die Eigenschaft, die Kubernetes auszeichnet:
# Einen Pod manuell loeschen
kubectl delete pod $(kubectl get pods -l app=meine-app -o name | head -1)
# Sofort danach pruefen
kubectl get pods -l app=meine-app
# -> Kubernetes startet automatisch einen neuen Pod
Der Deployment Controller bemerkt, dass nur noch zwei statt drei Pods laufen, und erstellt sofort einen neuen. Das dauert typischerweise wenige Sekunden.
Skalieren
# Hoch auf 5 Replicas
kubectl scale deployment meine-app --replicas=5
# Runter auf 2 Replicas
kubectl scale deployment meine-app --replicas=2
# Aktuellen Stand pruefen
kubectl get deployment meine-app
Teil 3: Services fuer stabilen Netzwerk-Zugriff
Pods bekommen bei jedem Neustart eine neue IP-Adresse. Das macht es unmoeglich, sie direkt anzusprechen. Ein Service loest dieses Problem: Er hat eine stabile IP, einen DNS-Namen und verteilt Traffic per Load Balancing auf die dahinter liegenden Pods.
Fuegen Sie am Ende Ihrer meine-app.yaml hinzu (mit --- als Trenner):
---
apiVersion: v1
kind: Service
metadata:
name: meine-app-service
spec:
selector:
app: meine-app
ports:
- port: 80
targetPort: 80
type: ClusterIP
selector: app: meine-app verbindet den Service mit allen Pods, die dieses Label tragen. ClusterIP bedeutet, der Service ist nur innerhalb des Clusters erreichbar.
# Anwenden
kubectl apply -f meine-app.yaml
# Service pruefen
kubectl get service meine-app-service
# NAME TYPE CLUSTER-IP PORT(S) AGE
# meine-app-service ClusterIP 10.96.45.123 80/TCP 5s
Service testen
# Temporaeren Test-Pod starten
kubectl run test-client --rm -it --image=busybox -- /bin/sh
# Im Test-Pod: Service per DNS-Name ansprechen
wget -qO- http://meine-app-service
# -> nginx-Startseite
# Voller DNS-Name funktioniert auch
wget -qO- http://meine-app-service.default.svc.cluster.local
exit
Extern erreichbar machen
Fuer lokale Tests kann man den Service-Typ auf NodePort aendern:
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30080
kubectl apply -f meine-app.yaml
curl http://localhost:30080
# -> nginx-Startseite
In Produktions-Umgebungen nutzt man stattdessen einen Ingress Controller oder einen LoadBalancer-Service. Fuer den Einstieg reicht NodePort aber voellig.
Teil 4: Rolling Updates und Rollbacks
Eine der staerksten Funktionen von Deployments: Man kann das Container-Image aendern, und Kubernetes aktualisiert die Pods nacheinander ohne Downtime.
# Image aktualisieren
kubectl set image deployment/meine-app nginx=nginx:1.25-alpine
# Update live beobachten
kubectl rollout status deployment/meine-app
# Waiting for deployment "meine-app" rollout to finish...
# deployment "meine-app" successfully rolled out
Kubernetes startet neue Pods mit dem neuen Image, wartet bis sie ready sind, und terminiert dann die alten. Zu keinem Zeitpunkt sind null Pods verfuegbar.
Wenn etwas schiefgeht:
# Update-Historie anzeigen
kubectl rollout history deployment/meine-app
# Zur vorherigen Version zurueck
kubectl rollout undo deployment/meine-app
# Oder zu einer bestimmten Revision
kubectl rollout undo deployment/meine-app --to-revision=1
Teil 5: Troubleshooting-Grundlagen
Pod bleibt im Status Pending
kubectl describe pod <pod-name>
# Events pruefen. Haeufige Ursachen:
# - Insufficient cpu/memory -> Node hat nicht genug Ressourcen
# - No nodes match selector -> nodeSelector oder Taints falsch
Mehr dazu unter Pod Pending Troubleshooting.
CrashLoopBackOff
# Logs des letzten Crash anzeigen
kubectl logs <pod-name> --previous
# Exit-Code pruefen
kubectl describe pod <pod-name> | grep -A2 "Last State"
Exit Code 137 bedeutet OOMKilled (zu wenig Memory). Exit Code 1 ist ein Anwendungsfehler. Ausfuehrlich erklaert unter CrashLoopBackOff Troubleshooting.
Service hat keine Endpoints
# Endpoints pruefen -- wenn leer, stimmen die Labels nicht
kubectl get endpoints meine-app-service
kubectl get pods --show-labels
Zusammenfassung
| Konzept | Befehl | Zweck |
|---|---|---|
| Pod | kubectl run | Einzelnen Container ausfuehren |
| Deployment | kubectl apply -f | Replicas, Selbstheilung, Updates |
| Service | kubectl apply -f | Stabile IP und DNS, Load Balancing |
| Skalierung | kubectl scale | Replica-Anzahl aendern |
| Update | kubectl set image | Rolling Update ohne Downtime |
| Rollback | kubectl rollout undo | Zur vorherigen Version zurueck |
| Debug | kubectl logs/describe | Fehlersuche |
Komplettes Beispiel zum Kopieren
Deployment mit Liveness- und Readiness-Probes plus Service in einer Datei:
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 3
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 3
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
selector:
app: webapp
ports:
- port: 80
targetPort: 80
type: NodePort
kubectl apply -f webapp.yaml && kubectl get deployment webapp
kubectl delete -f webapp.yaml
Die livenessProbe startet den Container bei Nicht-Antwort neu. Die readinessProbe steuert, ob der Pod Traffic empfangen soll.
Naechste Schritte
Dieses Tutorial deckt die Grundlagen ab. Fuer den naechsten Schritt empfehle ich:
- Helm Charts Einfuehrung -- Anwendungen als Pakete verwalten
- Kubernetes Rollback-Strategien -- Deployment-Strategien fuer Produktion
- CKA Zertifizierung Guide -- Wenn Sie sich zertifizieren lassen wollen
Wenn Sie Unterstuetzung bei Ihren Kubernetes-Projekten brauchen, schauen Sie gerne auf /kontakt vorbei.
Kubernetes-Beratung gesucht?
Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.
📖 Verwandte Artikel
Weitere interessante Beiträge zu ähnlichen Themen
ArgoCD installieren und erstes Projekt deployen
ArgoCD auf Kubernetes installieren und das erste Projekt Schritt für Schritt deployen, von der CLI-Einrichtung bis zur automatischen Synchronisation.
Helm Charts Tutorial: Eigene Charts erstellen und nutzen
Helm Charts für Kubernetes verstehen und selbst erstellen. Von der Installation über Templates bis zum eigenen Production-ready Chart mit Best Practices.
Helm Charts für Anfänger: Eigenes Chart erstellen
Helm von Grund auf lernen: Charts verstehen, die wichtigsten CLI-Befehle nutzen und Schritt für Schritt ein eigenes Helm Chart erstellen.
ArgoCD ApplicationSets: Multi-App Deployment Patterns
ArgoCD ApplicationSets automatisieren Multi-App und Multi-Cluster Deployments mit Generatoren. Praxis-Patterns für Git, Cluster und Matrix.
Java Spring Boot auf Kubernetes containerisieren
Spring Boot Anwendungen für Kubernetes containerisieren: Multi-Stage Dockerfile, JVM-Tuning, Health Checks mit Actuator und fertige Deployment-YAMLs.