Best Practices: Kubernetes
Workshop-Unterlage für Kubernetes-Reviews, Übungen und Abschlussprojekte Stand: 13. Juni 2026
1. Ziel
Dieses Dokument sammelt bewertete Praxisregeln für Kubernetes. Es ist für Workshops, Reviews und Abschlussprojekte gedacht. Du sollst damit nicht nur YAML schreiben, sondern Entscheidungen nachvollziehbar treffen, Risiken erkennen und Änderungen sicher betreiben.
Die Regeln sind bewusst praxisnah formuliert. Jede Best Practice beantwortet mindestens eine dieser Fragen:
- Warum ist die Regel wichtig?
- Wie setzt du sie konkret um?
- Wie prüfst du, ob sie eingehalten wird?
- Welche typischen Fehlerbilder entstehen, wenn du sie ignorierst?
Was du nach dem Workshop können solltest
Nach der Arbeit mit diesem Dokument solltest du in der Lage sein,
- Kubernetes-Manifeste strukturiert zu schreiben,
- Deployments sicher auszurollen und zurückzurollen,
- Services, Ingress, Gateway API und NetworkPolicies einzuordnen,
- Ressourcenbedarf und Skalierung nachvollziehbar zu definieren,
- RBAC, ServiceAccounts, Secrets und Pod Security Standards fachlich sauber zu verwenden,
- typische Fehlerbilder mit
kubectlsystematisch zu analysieren, - Review-Checklisten für reale Projekte anzuwenden.
Gültigkeitsbereich
Diese Best Practices gelten unabhängig davon, ob du Kubernetes lokal, im eigenen Rechenzentrum oder bei einem Cloud-Anbieter betreibst. Anbieterabhängige Details wie LoadBalancer-Implementierung, CSI-Treiber, CNI-Plugin, IAM-Integration, Managed-Control-Plane oder Registry-Anbindung musst du je Umgebung ergänzen.
2. Leitprinzipien
Kubernetes wird zuverlässiger, wenn du dich an wenige Grundprinzipien hältst.
| Prinzip | Bedeutung | Typische Umsetzung |
|---|---|---|
| Deklarativer Zielzustand | Du beschreibst, was laufen soll, nicht jeden manuellen Schritt. | YAML, Kustomize, Helm, GitOps, kubectl apply |
| Reproduzierbarkeit | Eine Umgebung lässt sich aus Quellen erneut aufbauen. | Versionierte Manifeste, gepinnte Images, dokumentierte Abhängigkeiten |
| Least Privilege | Workloads und Personen erhalten nur die Rechte, die sie wirklich brauchen. | RBAC, eigene ServiceAccounts, keine pauschalen ClusterRoleBindings |
| Defense in Depth | Sicherheit entsteht durch mehrere Schichten. | NetworkPolicies, Pod Security, Image-Scanning, Admission Control, Secrets-Management |
| Beobachtbarkeit | Du kannst Zustand, Fehler und Verhalten prüfen. | Logs, Events, Metriken, Traces, Health-Endpunkte, Alerts |
| Rückbaubarkeit | Änderungen sind korrigierbar. | Rollout-Strategie, Rollback-Pfad, Backup, Migrationsplan |
| Kleine blast radius | Fehler wirken sich möglichst begrenzt aus. | Namespaces, Quotas, getrennte ServiceAccounts, getrennte Deployments |
| Automatisierte Validierung | Fehler werden vor dem Cluster erkannt. | CI-Linting, Schema-Validierung, Policy Checks, Tests |
Merksatz
Eine Kubernetes-Lösung ist nicht gut, weil ein Pod läuft. Gut ist sie, wenn du erklären, reproduzieren, absichern, beobachten und zurückrollen kannst, warum er läuft.
3. Manifest- und Repository-Standards
3.1. Arbeite deklarativ
Schreibe Ressourcen als Manifeste und verwalte sie versioniert. Vermeide manuelle Änderungen im Cluster, die nicht im Repository nachvollziehbar sind.
Best Practice
- Lege alle produktionsrelevanten Ressourcen als YAML, Helm Chart, Kustomize Overlay oder GitOps-Konfiguration ab.
- Verwende
kubectl applyoder ein GitOps-Werkzeug, nicht dauerhaftkubectl edit. - Prüfe Änderungen vorab mit
kubectl diffund--dry-run=server. - Dokumentiere, welche Quelle autoritativ ist: Git, Helm Release, GitOps Controller oder ein anderes Deployment-System.
Gute Prüfung
kubectl diff -f k8s/
kubectl apply --dry-run=server -f k8s/
kubectl apply -f k8s/
Schlechtes Muster
kubectl edit deployment web
kubectl set image deployment/web web=registry.example.com/web:latest
Das kann für Notfälle legitim sein. Danach musst du die Änderung aber zurück in die deklarative Quelle übernehmen. Sonst entsteht Configuration Drift.
3.2. Benenne Ressourcen nachvollziehbar
Namen sollten kurz, eindeutig und sprechend sein. Vermeide Projekt-internen Slang, zufällige Kürzel und Namen, die die Umgebung nicht erkennen lassen.
Empfohlenes Schema
<app>-<komponente>
<app>-<komponente>-<zweck>
Beispiele
| Ressource | Guter Name | Schlechter Name |
|---|---|---|
| Deployment | shop-api |
api2 |
| Service | shop-api |
svc-main |
| ConfigMap | shop-api-config |
config |
| Secret | shop-api-db-credentials |
secret1 |
| ServiceAccount | shop-api |
default |
| NetworkPolicy | shop-api-allow-ingress |
netpol |
Regel
- Der Name beschreibt fachlichen Zweck und technische Funktion.
- Umgebungsspezifische Informationen gehören meistens in Namespace, Overlay oder Labels, nicht zwingend in jeden Ressourcennamen.
- Ein Name sollte auch in Logs, Events und Monitoring verständlich sein.
3.3. Nutze Labels und Annotationen konsequent
Labels sind für Selektion, Gruppierung und Automatisierung. Annotationen sind für zusätzliche Metadaten, die nicht primär selektiert werden.
Empfohlene Standardlabels
metadata:
labels:
app.kubernetes.io/name: shop-api
app.kubernetes.io/component: api
app.kubernetes.io/part-of: shop
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/version: "1.4.2"
environment: dev
team: platform
Wichtig
- Service-Selectoren müssen zu Pod-Labels passen.
- Labels, die Selektoren steuern, dürfen nicht leichtfertig geändert werden.
- Verwende Labels für Monitoring, Kostenstellen, Ownership und Policy-Ausnahmen.
- Verwende Annotationen für Build-Informationen, Git-Revisionen, Dokumentationslinks oder Tool-spezifische Hinweise.
Prüfung
kubectl get pods --show-labels
kubectl get svc shop-api -o yaml
kubectl get endpointslice -l kubernetes.io/service-name=shop-api
3.4. Trenne Basis, Umgebung und Secrets
Eine saubere Struktur verhindert, dass du Umgebungsdetails vermischst oder Secrets versehentlich versionierst.
Beispielstruktur
k8s/
base/
deployment.yaml
service.yaml
serviceaccount.yaml
networkpolicy.yaml
overlays/
dev/
kustomization.yaml
patch-resources.yaml
patch-ingress.yaml
test/
kustomization.yaml
patch-resources.yaml
prod/
kustomization.yaml
patch-resources.yaml
patch-pdb.yaml
Best Practice
- Gemeinsame Ressourcen liegen in
base. - Umgebungsspezifische Unterschiede liegen in Overlays.
- Secrets liegen nicht im Klartext im Repository.
- Provider-spezifische Ressourcen werden getrennt dokumentiert.
- Beispielwerte sind als solche erkennbar.
Review-Frage
Kannst du aus dem Repository ableiten, was in
dev,testundprodunterschiedlich ist, ohne den Cluster abzufragen?
3.5. Validiere Änderungen vor dem Apply
Kubernetes akzeptiert syntaktisch gültige YAML-Dateien, die fachlich trotzdem falsch sein können. Deshalb brauchst du mehrere Validierungsschichten.
Validierungsebenen
| Ebene | Zweck | Beispiel |
|---|---|---|
| YAML-Linting | Einrückung, Struktur, Format | yamllint |
| Schema-Validierung | Existieren API-Version und Felder? | kubeconform, kubectl apply --dry-run=server |
| Policy-Validierung | Entspricht das Manifest internen Regeln? | Kyverno, OPA Gatekeeper, Conftest |
| Security-Scan | Erkennt riskante Einstellungen? | Trivy, Checkov, Kubescape |
| Diff | Was ändert sich am Cluster? | kubectl diff |
Mindeststandard im Workshop
kubectl apply --dry-run=server -f manifest.yaml
kubectl diff -f manifest.yaml
kubectl apply -f manifest.yaml
kubectl rollout status deployment/<name>
4. Workload Best Practices
4.1. Nutze den passenden Workload-Typ
Nicht jeder Workload gehört in ein Deployment.
| Workload-Typ | Geeignet für | Nicht geeignet für |
|---|---|---|
| Deployment | zustandslose Anwendungen, APIs, Webserver, Worker | stabile Netzwerkidentitäten oder geordnete Storage-Semantik |
| StatefulSet | Datenbanken, Broker, zustandsbehaftete Systeme mit stabiler Identität | einfache stateless Web-Anwendungen |
| DaemonSet | Agenten pro Node, Log-Collector, CNI-Komponenten, Monitoring-Agenten | normale Applikationsreplikas |
| Job | einmalige Aufgaben, Migrationen, Batch-Verarbeitung | dauerhaft laufende Dienste |
| CronJob | geplante wiederkehrende Aufgaben | hochfrequente Echtzeitverarbeitung |
Regel
- Nutze Deployments für stateless Standard-Workloads.
- Nutze StatefulSets nur, wenn du stabile Identität, geordnete Starts oder persistente Volumes pro Replica brauchst.
- Nutze Jobs/CronJobs für endliche Aufgaben.
- Nutze DaemonSets nur, wenn wirklich auf jedem oder auf bestimmten Nodes eine Instanz laufen muss.
4.2. Schreibe Deployments rollbackfähig
Ein Deployment ist erst dann sauber, wenn Rollout und Rollback kontrollierbar sind.
Empfohlenes Deployment-Beispiel
apiVersion: apps/v1
kind: Deployment
metadata:
name: shop-api
labels:
app.kubernetes.io/name: shop-api
app.kubernetes.io/component: api
spec:
replicas: 3
revisionHistoryLimit: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app.kubernetes.io/name: shop-api
template:
metadata:
labels:
app.kubernetes.io/name: shop-api
app.kubernetes.io/component: api
spec:
serviceAccountName: shop-api
automountServiceAccountToken: false
containers:
- name: shop-api
image: registry.example.com/shop-api:1.4.2
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 256Mi
readinessProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 20
periodSeconds: 20
timeoutSeconds: 2
failureThreshold: 3
startupProbe:
httpGet:
path: /startup
port: http
periodSeconds: 5
failureThreshold: 30
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 10001
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
Erläuterung
replicas: 3schützt gegen den Ausfall einzelner Pods.maxUnavailable: 0verhindert, dass während des Rollouts absichtlich weniger Pods verfügbar sind.maxSurge: 1erlaubt eine zusätzliche Instanz während des Rollouts.revisionHistoryLimithält alte ReplicaSets für Rollbacks bereit.readinessProbeentscheidet, ob Traffic an den Pod geleitet wird.livenessProbeentscheidet, ob Kubernetes einen Container neu startet.startupProbeschützt langsam startende Anwendungen vor zu früher Liveness-Prüfung.securityContextreduziert Containerprivilegien.
Prüfung
kubectl rollout status deployment/shop-api
kubectl rollout history deployment/shop-api
kubectl describe deployment shop-api
kubectl get rs -l app.kubernetes.io/name=shop-api
4.3. Plane Graceful Shutdown ein
Kubernetes beendet Pods nicht sofort. Es sendet ein Termination-Signal und wartet für die konfigurierte Grace Period. Deine Anwendung muss diese Zeit nutzen, um Requests zu beenden, Verbindungen zu schließen und keine neuen Aufträge mehr anzunehmen.
Best Practice
- Implementiere Signalhandling für
SIGTERM. - Setze
readinessProbeso, dass der Pod vor dem Beenden aus dem Traffic genommen wird. - Wähle
terminationGracePeriodSecondspassend zur Anwendung. - Verwende
preStopnur, wenn du wirklich eine explizite Verzögerung oder Abmeldeaktion brauchst. - Prüfe, ob dein Load Balancer oder Ingress Controller eigene Drain-Zeiten hat.
Beispiel
spec:
terminationGracePeriodSeconds: 30
containers:
- name: shop-api
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 5"]
Risiko
Ein zu kurzer Shutdown führt zu abgebrochenen Requests. Ein zu langer Shutdown verzögert Rollouts, Node Drains und Skalierung.
4.4. Nutze Probes gezielt
Probes ersetzen kein gutes Anwendungsdesign. Die Checks liefern die Signale, mit denen Kubernetes Entscheidungen trifft.
| Probe | Frage | Wirkung |
|---|---|---|
startupProbe |
Ist die Anwendung initial gestartet? | Solange sie fehlschlägt, werden Liveness-Checks zurückgestellt. |
readinessProbe |
Darf der Pod Traffic erhalten? | Fehlschlag entfernt den Pod aus Service-Endpunkten. |
livenessProbe |
Muss der Container neu gestartet werden? | Fehlschlag startet den Container neu. |
Best Practice
- Verwende
readinessProbefür fast alle Services. - Verwende
livenessProbenur, wenn ein Neustart einen echten Hänger beheben kann. - Verwende
startupProbefür langsame Starts. - Prüfe bei Readiness auch Abhängigkeiten, aber nicht zu aggressiv.
- Liveness sollte keine externen Abhängigkeiten hart voraussetzen. Sonst kann ein Datenbankproblem zu einer Neustartlawine führen.
Anti-Pattern
livenessProbe:
httpGet:
path: /deep-check-with-database-and-third-party-api
port: 8080
Wenn die Datenbank kurz nicht erreichbar ist, startet Kubernetes alle Pods neu. Das verschärft die Störung.
4.5. Verteile Pods bewusst
Mehrere Replicas helfen nur, wenn sie nicht alle auf demselben Node oder in derselben Ausfallzone landen.
Optionen
| Mechanismus | Zweck |
|---|---|
topologySpreadConstraints |
gleichmäßige Verteilung über Nodes, Zonen oder andere Topologien |
| Pod Anti-Affinity | vermeidet, dass gleiche Pods zusammen platziert werden |
| Node Affinity | platziert Pods auf geeigneten Node-Gruppen |
| Taints und Tolerations | reserviert Nodes für bestimmte Workloads |
Beispiel: Topology Spread
spec:
template:
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: shop-api
Regel
- Für produktive Services mit mehreren Replicas solltest du Verteilung aktiv prüfen.
- Für kritische Workloads solltest du auch Zonenverteilung betrachten.
- Verwende harte Regeln nur, wenn du genug Kapazität hast. Sonst bleiben Pods Pending.
4.6. Schütze Verfügbarkeit mit PodDisruptionBudgets
Ein PodDisruptionBudget begrenzt freiwillige Unterbrechungen, etwa bei Node Drain, Cluster-Wartung oder kontrollierter Eviction.
Beispiel
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: shop-api
spec:
minAvailable: 2
selector:
matchLabels:
app.kubernetes.io/name: shop-api
Best Practice
- Setze PDBs für produktive Workloads mit mehreren Replicas.
- Verwende PDBs nicht als Ersatz für ausreichende Replica-Zahl.
- Prüfe, ob PDBs Wartungsarbeiten blockieren können.
- Verwende bei quorum-basierten Systemen besondere Sorgfalt.
Prüfung
kubectl get pdb
kubectl describe pdb shop-api
kubectl drain <node> --ignore-daemonsets --dry-run=server
5. Ressourcenmanagement und Skalierung
5.1. Setze Resource Requests
Requests sind Planungsinformationen für den Scheduler. Ohne Requests kann Kubernetes Workloads schlechter platzieren, Quotas greifen unklarer, Autoscaling wird unzuverlässiger und Nodes können überbucht werden.
Best Practice
- Setze für jeden Container
resources.requests.cpuundresources.requests.memory. - Starte mit gemessenen Werten, nicht mit Wunschwerten.
- Nutze Monitoringdaten, Lasttests und Erfahrungswerte.
- Dokumentiere Annahmen: erwartete Requests pro Sekunde, Speicherprofil, Startverhalten, Spitzenlast.
Beispiel
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 256Mi
Hinweis zu CPU
CPU-Requests beeinflussen Scheduling und CPU-Zuteilung. CPU-Limits können zu Throttling führen. Setze CPU-Limits deshalb bewusst und beobachte tatsächliches Verhalten.
Hinweis zu Memory
Memory-Limits sind harte Grenzen. Überschreitet ein Container sein Limit, kann er mit OOMKilled beendet werden. Deshalb brauchst du realistische Werte und Alarme.
5.2. Setze Limits bewusst
Limits schützen Nodes und Nachbar-Workloads, können aber auch Fehler erzeugen.
| Ressource | Empfehlung | Risiko |
|---|---|---|
| Memory | In der Regel setzen. | Zu niedrig: OOMKilled. Zu hoch: ineffiziente Auslastung. |
| CPU | Situationsabhängig setzen. | Zu niedrig: Throttling, Latenzspitzen. Zu hoch: schwache Begrenzung. |
| Ephemeral Storage | Für schreibende Workloads prüfen. | NodePressure durch Logs, Caches oder temporäre Dateien. |
Best Practice
- Setze mindestens Requests für CPU und Memory.
- Setze Memory-Limits für fast alle Anwendungscontainer.
- Prüfe CPU-Limits mit Latenz- und Durchsatztests.
- Begrenze temporären Speicher, wenn Anwendungen viel schreiben.
- Verwende Dashboards für CPU-Throttling, Working Set Memory und OOM-Ereignisse.
5.3. Nutze Namespaces, ResourceQuota und LimitRange
Namespaces sind keine vollständige Sicherheitsgrenze, aber eine wichtige Organisations- und Steuerungsebene.
Namespace-Beispiel
apiVersion: v1
kind: Namespace
metadata:
name: shop-dev
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
ResourceQuota-Beispiel
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: shop-dev
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.memory: 16Gi
pods: "30"
LimitRange-Beispiel
apiVersion: v1
kind: LimitRange
metadata:
name: default-container-limits
namespace: shop-dev
spec:
limits:
- type: Container
defaultRequest:
cpu: 100m
memory: 128Mi
default:
memory: 256Mi
Best Practice
- Verwende Namespaces pro Team, Anwendung, Umgebung oder Mandant.
- Setze ResourceQuotas für geteilte Cluster.
- Setze LimitRanges, damit fehlende Requests nicht unbemerkt bleiben.
- Dokumentiere, welche Ressourcen ein Team erwarten darf.
5.4. Skaliere über Metriken
Skalierung ohne Metriken ist Raten. Kubernetes kann horizontal skalieren, wenn passende Metriken verfügbar sind.
HorizontalPodAutoscaler-Beispiel
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: shop-api
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: shop-api
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Best Practice
- Verwende HPA für zustandslose Workloads mit schwankender Last.
- Stelle sicher, dass Metrics Server oder passende Custom Metrics verfügbar sind.
- Setze Requests korrekt, sonst sind CPU-Auslastungsziele unbrauchbar.
- Definiere
minReplicasundmaxReplicasfachlich. - Prüfe Skalierungsverhalten mit Lasttests.
- Kombiniere Workload-Autoscaling bei Bedarf mit Node-Autoscaling.
Prüfung
kubectl get hpa
kubectl describe hpa shop-api
kubectl top pods
kubectl top nodes
6. Netzwerk und Service Discovery
6.1. Verwende Services als stabile Zugriffsschicht
Pods sind kurzlebig. Services sind die stabile Zugriffsschicht innerhalb des Clusters.
Service-Beispiel
apiVersion: v1
kind: Service
metadata:
name: shop-api
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: shop-api
ports:
- name: http
port: 80
targetPort: http
Best Practice
- Nutze
ClusterIPfür interne Kommunikation. - Nutze
LoadBalancernur, wenn ein Dienst direkt extern erreichbar sein soll. - Nutze Ingress oder Gateway API für HTTP/HTTPS-Routing.
- Benenne Ports, damit Probes, Services und Policies stabiler lesbar sind.
- Prüfe immer, ob der Service Endpoints bzw. EndpointSlices hat.
Prüfung
kubectl get svc shop-api
kubectl get endpoints shop-api
kubectl get endpointslice -l kubernetes.io/service-name=shop-api
6.2. Verstehe DNS im Cluster
Kubernetes stellt DNS-Namen für Services bereit. Typischerweise erreichst du einen Service im gleichen Namespace über den Kurznamen und namespaceübergreifend über den vollqualifizierten Namen.
Beispiele
shop-api
shop-api.shop-dev
shop-api.shop-dev.svc.cluster.local
Best Practice
- Verwende Service-Namen statt Pod-IPs.
- Nutze vollständige DNS-Namen, wenn du namespaceübergreifend kommunizierst.
- Prüfe DNS-Probleme von einem Debug-Pod aus.
- Unterscheide DNS-Fehler von NetworkPolicy- oder Service-Selector-Fehlern.
Prüfung
kubectl run dns-debug --rm -it --image=busybox:1.36 --restart=Never -- nslookup shop-api.shop-dev.svc.cluster.local
kubectl get pods -n kube-system -l k8s-app=kube-dns
6.3. Nutze Ingress oder Gateway API bewusst
Ingress und Gateway API machen Services von außerhalb des Clusters erreichbar. Beide beschreiben Routing, aber die konkrete Umsetzung hängt vom installierten Controller ab.
| Option | Geeignet für | Hinweise |
|---|---|---|
| Ingress | verbreitetes HTTP/HTTPS-Routing | stabil, aber je Controller oft annotation-lastig |
| Gateway API | rollenorientiertes, erweiterbares Routing | moderner, ausdrucksstärker, benötigt Gateway-Controller |
Service LoadBalancer |
einfache direkte Exposition eines Service | weniger Routing-Funktionen |
| NodePort | Lernzwecke, Sonderfälle | in Produktion meist nicht erste Wahl |
Ingress-Beispiel
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shop-api
spec:
ingressClassName: nginx
rules:
- host: shop.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: shop-api
port:
number: 80
Best Practice
- Dokumentiere, welcher Ingress- oder Gateway-Controller eingesetzt wird.
- Lege TLS, Hostnamen und Zertifikatsverwaltung explizit fest.
- Vermeide Controller-spezifische Annotationen ohne Kommentar.
- Prüfe Routing, TLS, Backend-Service und Endpoints getrennt.
6.4. Isoliere Traffic mit NetworkPolicies
Ohne NetworkPolicies ist Pod-zu-Pod-Kommunikation in vielen Clustern weitgehend offen. NetworkPolicies definieren erlaubten Traffic auf Ebene von Pods, Namespaces, IP-Blöcken und Ports. Wichtig: Diese Regeln wirken nur, wenn das CNI-Plugin NetworkPolicy Enforcement unterstützt.
Default-Deny für Ingress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: shop-dev
spec:
podSelector: {}
policyTypes:
- Ingress
Erlaube Traffic vom Ingress Controller zur API
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: shop-api-allow-ingress-controller
namespace: shop-dev
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: shop-api
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
ports:
- protocol: TCP
port: 8080
Best Practice
- Beginne mit
default-denypro Namespace. - Erlaube nur notwendige Kommunikationspfade.
- Dokumentiere Abhängigkeiten zwischen Services.
- Teste Policies aktiv mit Debug-Pods.
- Denke auch an DNS-Egress, wenn du Egress einschränkst.
7. Konfiguration, Secrets und Storage
7.1. Trenne Konfiguration vom Image
Container-Images sollten möglichst unverändert durch Umgebungen wandern. Umgebungsspezifische Konfiguration gehört in ConfigMaps, Secrets oder externe Konfigurationssysteme.
ConfigMap-Beispiel
apiVersion: v1
kind: ConfigMap
metadata:
name: shop-api-config
data:
LOG_LEVEL: "info"
FEATURE_CHECKOUT_V2: "true"
Verwendung als Environment-Variablen
containers:
- name: shop-api
envFrom:
- configMapRef:
name: shop-api-config
Best Practice
- Baue ein Image einmal und nutze es in mehreren Umgebungen.
- Lege Konfigurationswerte nicht fest ins Image.
- Unterscheide öffentliche Konfiguration von sensitiven Daten.
- Dokumentiere, ob eine ConfigMap-Änderung einen Rollout erfordert.
7.2. Behandle Secrets als besonders schützenswert
Kubernetes Secrets sind für sensitive Werte gedacht, aber kein vollständiger Ersatz für Secret-Management. Du musst Zugriff, Speicherung, Rotation und Verwendung bewusst planen.
Best Practice
- Speichere echte Secrets nicht im Klartext in Git.
- Verwende externe Secret-Systeme oder verschlüsselte Git-Workflows, wenn Secrets versioniert werden müssen.
- Begrenze RBAC-Zugriff auf Secrets strikt.
- Aktiviere Verschlüsselung at rest für Secrets, wenn du den Cluster selbst betreibst oder die Option im Managed Service konfigurieren kannst.
- Verwende kurze Gültigkeiten und Rotation, wo möglich.
- Montiere Secrets bevorzugt als Dateien, wenn Anwendungen Rotation unterstützen.
- Vermeide Secrets in Logs, Events, Fehlermeldungen und Kommandozeilenargumenten.
Secret-Beispiel nur für Schulungszwecke
apiVersion: v1
kind: Secret
metadata:
name: shop-api-db-credentials
type: Opaque
stringData:
username: example-user
password: example-password
Wichtig
Dieses Beispiel darf nicht als produktives Muster für echte Passwörter verstanden werden. In realen Projekten verwendest du ein Secret-Management-Verfahren, das zu deiner Organisation passt.
7.3. Plane Persistenz explizit
Pods sind vergänglich. Daten, die Neustarts, Rescheduling oder Rollouts überleben müssen, gehören nicht in das beschreibbare Container-Dateisystem.
Best Practice
- Verwende PersistentVolumeClaims für persistente Daten.
- Prüfe Access Mode, StorageClass, Reclaim Policy, Backup und Restore.
- Verwende StatefulSets für zustandsbehaftete Workloads mit stabilen Volumes.
- Definiere, welche Daten verloren gehen dürfen.
- Teste Restore, nicht nur Backup.
PVC-Beispiel
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: shop-api-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: standard
Review-Fragen
- Welche Daten sind persistent?
- Wer erstellt das Volume?
- Was passiert beim Löschen des PVC?
- Wie wird gesichert?
- Wie wird ein Restore getestet?
- Welche Performance-Anforderungen gelten?
8. Security Best Practices
8.1. RBAC: Least Privilege statt Cluster-Admin
RBAC steuert, wer welche API-Ressourcen lesen, erstellen, ändern oder löschen darf. Zu breite Rechte sind eines der häufigsten Sicherheitsprobleme in Kubernetes-Clustern.
Best Practice
- Vergib Rechte rollenbasiert und minimal.
- Verwende
RoleundRoleBindinginnerhalb eines Namespace, wenn möglich. - Nutze
ClusterRolenur für clusterweite Ressourcen oder bewusst wiederverwendbare Rollen. - Vermeide
cluster-adminfür Anwendungen. - Prüfe Rechte mit
kubectl auth can-i. - Überprüfe regelmäßig Bindings an
system:masters,cluster-adminund breite Gruppen.
Beispiel: Namespace-begrenzte Leserechte
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: shop-dev
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-reader-binding
namespace: shop-dev
subjects:
- kind: ServiceAccount
name: diagnostics
namespace: shop-dev
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pod-reader
Prüfung
kubectl auth can-i get pods --as=system:serviceaccount:shop-dev:diagnostics -n shop-dev
kubectl auth can-i delete secrets --as=system:serviceaccount:shop-dev:diagnostics -n shop-dev
8.2. ServiceAccounts begrenzen
Jeder Pod läuft mit einem ServiceAccount. Wenn du keinen angibst, verwendet Kubernetes den default ServiceAccount des Namespace.
Best Practice
- Erstelle pro Anwendung oder Komponente einen eigenen ServiceAccount.
- Binde nur die notwendigen Rechte.
- Setze
automountServiceAccountToken: false, wenn die Anwendung nicht mit der Kubernetes API sprechen muss. - Verwende keine geteilten ServiceAccounts für viele unabhängige Anwendungen.
Beispiel
apiVersion: v1
kind: ServiceAccount
metadata:
name: shop-api
namespace: shop-dev
automountServiceAccountToken: false
Review-Frage
Warum braucht dieser Pod Zugriff auf die Kubernetes API? Wenn du keine konkrete Antwort hast, sollte der Token nicht automatisch gemountet werden.
8.3. Pod Security Standards anwenden
Pod Security Standards beschreiben Sicherheitsniveaus für Pods. Die drei Profile sind privileged, baseline und restricted.
Best Practice
- Nutze
restricted, wo möglich. - Nutze
baseline, wenn Anwendungen noch nicht alle Einschränkungen erfüllen. - Verwende
privilegednur für klar begründete Infrastruktur-Workloads. - Erzwinge Standards über Namespace-Labels oder Admission Policies.
- Prüfe Verstöße zunächst mit
warnundaudit, bevor du in produktiven Namespaces hart blockierst.
Namespace-Labels
apiVersion: v1
kind: Namespace
metadata:
name: shop-prod
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
Migrationsmuster
- Setze
warn=restrictedundaudit=restricted. - Behebe gemeldete Verstöße.
- Setze
enforce=baselineoderenforce=restricted. - Dokumentiere begründete Ausnahmen.
8.4. Container härten
Container sollten mit möglichst wenigen Privilegien laufen.
Empfohlene SecurityContext-Basis
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 10001
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
Best Practice
- Starte nicht als Root, wenn es vermeidbar ist.
- Entferne Linux Capabilities, die du nicht brauchst.
- Vermeide
privileged: true. - Vermeide Host-Namespace-Zugriff wie
hostNetwork,hostPIDundhostIPC, außer bei Infrastrukturkomponenten mit klarer Begründung. - Nutze ein read-only Root Filesystem, wenn die Anwendung damit umgehen kann.
- Schreibe temporäre Dateien in explizite Volumes wie
emptyDir.
Beispiel für temporären Schreibbereich
spec:
containers:
- name: shop-api
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
8.5. Images und Supply Chain absichern
Ein Kubernetes-Cluster ist nur so vertrauenswürdig wie die Artefakte, die du darin ausführst.
Best Practice
- Verwende Images aus vertrauenswürdigen Registries.
- Pinne Images mindestens mit versionierten Tags; für hohe Sicherheitsanforderungen zusätzlich mit Digest.
- Vermeide
latestin produktiven Manifests. - Scanne Images auf bekannte Schwachstellen.
- Nutze kleine, gepflegte Basisimages.
- Signiere Images, wenn deine Organisation eine Signaturkette betreibt.
- Entferne Build-Tools, Paketmanager und unnötige Shells aus Runtime-Images, wenn möglich.
- Verwende private Registries mit kontrolliertem Zugriff.
Gutes Muster
image: registry.example.com/shop-api:1.4.2@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Schlechtes Muster
image: shop-api:latest
imagePullPolicy: Always
imagePullPolicy: Always löst nicht das Grundproblem eines unpräzisen Tags. Ein veränderbarer Tag bleibt veränderbar.
8.6. Admission Control und Policy-as-Code nutzen
Admission Controller prüfen oder verändern API-Anfragen, bevor Ressourcen persistiert werden. Damit kannst du Sicherheits- und Betriebsregeln zentral erzwingen.
Typische Policy-Regeln
- Keine Container mit
privileged: true. - Keine produktiven Images mit
:latest. - Jeder Container braucht Resource Requests.
- Pods müssen als Non-Root laufen.
- Namespaces müssen Pod Security Labels haben.
- Ingress-Ressourcen brauchen TLS.
- Nur erlaubte Registries sind zulässig.
- Bestimmte Annotationen oder Labels sind Pflicht.
Policy-as-Code-Werkzeuge
| Werkzeug | Typische Nutzung |
|---|---|
| Kyverno | Kubernetes-native Policies als YAML |
| OPA Gatekeeper | Rego-basierte Policies und Constraints |
| ValidatingAdmissionPolicy | native Kubernetes-Validierung mit CEL-Ausdrücken |
| Conftest | Policy-Prüfung in CI |
Best Practice
- Prüfe Policies zuerst im Audit- oder Warnmodus.
- Dokumentiere Ausnahmen mit Ablaufdatum und Begründung.
- Halte Policies versioniert.
- Teste Policies in CI, bevor sie im Cluster erzwingen.
9. Beobachtbarkeit und Betrieb
9.1. Logs, Events und Metriken trennen
Diese Datenquellen beantworten unterschiedliche Fragen.
| Quelle | Frage | Beispiele |
|---|---|---|
| Logs | Was meldet die Anwendung? | Fehlerstack, Request-ID, Geschäftsereignis |
| Events | Was meldet Kubernetes? | Scheduling, Image Pull, Probe Failure, Eviction |
| Metriken | Wie verhält sich das System über Zeit? | CPU, Memory, Latenz, Fehlerquote, Throughput |
| Traces | Wo verbringt eine Anfrage Zeit? | Service-zu-Service-Latenz |
| Audit Logs | Wer hat was an der API getan? | Benutzer, ServiceAccount, Verb, Ressource |
Best Practice
- Anwendungen loggen nach
stdoutundstderr. - Logs enthalten Zeitstempel, Level, Service, Umgebung und Korrelations-ID.
- Kubernetes Events werden bei Fehleranalysen immer geprüft.
- Metriken werden nicht aus Logs rekonstruiert, wenn sie direkt messbar sind.
- Kritische Änderungen an der Kubernetes API werden auditiert.
9.2. Schreibe Anwendungen beobachtbar
Kubernetes kann nur sauber steuern, was deine Anwendung als Signal bereitstellt.
Mindestanforderungen an Services
| Fähigkeit | Erwartung |
|---|---|
| Health-Endpunkte | getrennte Endpunkte für Startup, Readiness und Liveness |
| Strukturierte Logs | maschinenlesbare Felder, keine Secrets |
| Metriken | technische und fachliche Metriken |
| Korrelation | Request-ID oder Trace-ID über Servicegrenzen hinweg |
| Fehlerverhalten | sinnvolle HTTP-Statuscodes und klare Fehlermeldungen |
| Shutdown | SIGTERM wird verarbeitet |
Empfohlene Endpunkte
/startup -> Ist die Anwendung initial gestartet?
/ready -> Kann die Anwendung Traffic bedienen?
/healthz -> Ist der Prozess grundsätzlich lebendig?
/metrics -> Metriken für Monitoring, falls vorgesehen
9.3. Standardisiere Troubleshooting
Troubleshooting sollte nicht aus zufälligen Kommandos bestehen. Gehe von außen nach innen und von grob nach fein vor.
Standardablauf
- Scope klären: Welche Anwendung, welcher Namespace, seit wann, welche Änderung?
- Objekte prüfen: Deployment, ReplicaSet, Pod, Service, EndpointSlice, Ingress/Gateway.
- Status prüfen: Conditions, Events, Restarts, Images, Nodes.
- Logs prüfen: aktuelle Logs und
--previousbei Restarts. - Netz prüfen: DNS, Service-Selector, Endpoints, NetworkPolicy.
- Ressourcen prüfen: Requests, Limits, OOM, NodePressure, Quotas.
- RBAC prüfen:
kubectl auth can-iund ServiceAccount. - Änderung bewerten: Rollout History, Git Diff, CI/CD-Läufe.
- Fix validieren: Vorher/Nachher-Kommandos dokumentieren.
- Rückbau dokumentieren: Wie wird der Fix zurückgenommen?
Kernkommandos
kubectl get all -n <namespace>
kubectl describe pod <pod> -n <namespace>
kubectl logs <pod> -n <namespace>
kubectl logs <pod> -n <namespace> --previous
kubectl get events -n <namespace> --sort-by=.lastTimestamp
kubectl rollout status deployment/<deployment> -n <namespace>
kubectl rollout history deployment/<deployment> -n <namespace>
10. Deployment, Release und Rollback
10.1. Nutze reproduzierbare Images
Ein Deployment sollte später nachvollziehbar sein. Du musst wissen, welcher Code, welche Abhängigkeiten und welches Image tatsächlich liefen.
Best Practice
- Baue Images in CI.
- Versioniere Images mit unveränderlichen Versionen.
- Speichere Git-Commit, Build-Zeitpunkt und Build-Pipeline als Metadaten.
- Verwende Digests für besonders kritische Workloads.
- Dokumentiere, wer ein Image promoten darf.
Nützliche Annotationen
metadata:
annotations:
build.example.com/git-sha: "f4c2a7e"
build.example.com/pipeline: "https://ci.example.com/pipelines/12345"
10.2. Teste Rollouts und Rollbacks
Ein Rollback-Pfad ist nur brauchbar, wenn du ihn getestet hast.
Rollout prüfen
kubectl apply -f k8s/
kubectl rollout status deployment/shop-api
kubectl get pods -l app.kubernetes.io/name=shop-api
Rollback prüfen
kubectl rollout history deployment/shop-api
kubectl rollout undo deployment/shop-api
kubectl rollout status deployment/shop-api
Best Practice
- Teste Rollout und Rollback vor produktiven Änderungen.
- Prüfe Datenbankmigrationen separat. Nicht jede Datenänderung ist rollbackfähig.
- Dokumentiere, ob ein Rollback nur Anwendungscode oder auch Daten betrifft.
- Lege klare Abbruchkriterien fest: Fehlerquote, Latenz, CrashLoop, Business-Metriken.
10.3. Nutze CI/CD-Qualitätsgates
Manifeste sollten nicht erst im Cluster scheitern.
Empfohlene Pipeline-Schritte
- YAML-Linting
- Kubernetes-Schema-Validierung
- Policy-Prüfung
- Image-Scan
- Secret-Scan
- Unit- und Integrationstests
- Rendern von Helm/Kustomize
- Diff gegen Zielumgebung
- Deployment in Testumgebung
- Smoke-Test
- Freigabe oder automatisiertes Promotion-Verfahren
Beispielhafte Gates
| Gate | Blockiert bei |
|---|---|
| Secret Scan | Klartext-Passwörter, Tokens, Private Keys |
| Policy Check | privileged: true, fehlende Requests, latest |
| Schema Check | falsche API-Version, unbekannte Felder |
| Image Scan | kritische CVEs ohne Ausnahmeprozess |
| Smoke Test | Anwendung antwortet nicht oder liefert Fehler |
11. Review-Checklisten
11.1. Manifest-Review
| Frage | Erwartung |
|---|---|
| Ist der Scope der Änderung klar? | Namespace, Ressourcen und Zweck sind benannt. |
| Ist die API-Version passend? | Keine veralteten oder unnötigen Beta-APIs. |
| Sind Labels konsistent? | Service-Selectoren passen zu Pod-Labels. |
| Sind Images versioniert? | Kein latest in produktiven Manifests. |
| Sind Requests gesetzt? | CPU und Memory sind pro Container definiert. |
| Sind Limits bewusst gesetzt? | Memory-Limits sind nachvollziehbar; CPU-Limits sind begründet. |
| Gibt es Probes? | Readiness ist vorhanden; Liveness/Startup sind fachlich begründet. |
| Ist Rollback möglich? | Rollout-History, Strategie und Abbruchkriterien sind dokumentiert. |
| Sind Secrets ausgeschlossen? | Keine echten Secrets im Manifest oder Repository. |
| Ist der Betrieb dokumentiert? | Prüfschritte, Logs und Fehlerbilder sind beschrieben. |
11.2. Security-Review
| Frage | Erwartung |
|---|---|
| Läuft der Container als Non-Root? | runAsNonRoot: true oder begründete Ausnahme. |
| Ist Privilege Escalation deaktiviert? | allowPrivilegeEscalation: false. |
| Sind Capabilities reduziert? | drop: [ALL], nur notwendige Additions. |
| Wird ein eigener ServiceAccount verwendet? | Kein unbewusster default ServiceAccount. |
| Ist der ServiceAccount-Token nötig? | Sonst automountServiceAccountToken: false. |
| Sind RBAC-Rechte minimal? | Keine pauschalen Adminrechte. |
| Gibt es Pod Security Labels? | Namespace erzwingt oder warnt gegen definierte Standards. |
| Sind NetworkPolicies vorhanden? | Mindestens für produktive oder geteilte Namespaces. |
| Sind Images vertrauenswürdig? | Erlaubte Registry, Scan, Versionierung. |
| Sind Secrets geschützt? | Externe Verwaltung, Rotation, eingeschränkter Zugriff. |
11.3. Betriebs-Review
| Frage | Erwartung |
|---|---|
| Wie erkennst du einen gesunden Zustand? | Health-Endpunkte, Metriken und erwartete Pod-Anzahl sind definiert. |
| Wie erkennst du einen Fehler? | Logs, Events, Alerts und SLO-Indikatoren sind bekannt. |
| Wie rollst du zurück? | Rollback-Kommando und Datenkompatibilität sind dokumentiert. |
| Wie skalierst du? | Replica-Zahl, HPA oder anderer Mechanismus ist definiert. |
| Wie sicherst du Daten? | Backup- und Restore-Verfahren sind getestet. |
| Wie gehst du mit Wartung um? | PDBs, Drain-Verhalten und Kapazität sind geprüft. |
| Wie begrenzt du Auswirkungen? | Namespace, Quota, NetworkPolicy und RBAC grenzen blast radius ein. |
11.4. Abschlussprojekt-Review
Für ein Abschlussprojekt gilt eine Lösung als vollständig, wenn du folgende Punkte nachweisen kannst:
- Du kannst die Anwendung aus dem Repository deployen.
- Du kannst erklären, welche Ressourcen entstehen.
- Du kannst die Anwendung intern oder extern erreichen.
- Du kannst Logs, Events und Status prüfen.
- Du kannst einen Rollout auslösen und beobachten.
- Du kannst einen Rollback durchführen.
- Du hast Requests, Limits und Probes gesetzt.
- Du hast einen eigenen Namespace verwendet.
- Du hast keine echten Secrets im Repository.
- Du hast mindestens eine Security-Maßnahme umgesetzt: RBAC, Pod Security, SecurityContext oder NetworkPolicy.
- Du hast mindestens ein typisches Fehlerbild absichtlich erzeugt und gelöst.
12. Anti-Patterns und Fehlerbilder
12.1. Pod bleibt Pending
Typische Ursachen
- Nicht genug CPU oder Memory im Cluster.
- Node Selector, Affinity oder Taints verhindern Scheduling.
- PVC ist nicht gebunden.
- ResourceQuota ist ausgeschöpft.
- Image Pull ist noch nicht relevant, weil der Pod noch nicht geplant wurde.
Prüfung
kubectl describe pod <pod> -n <namespace>
kubectl get events -n <namespace> --sort-by=.lastTimestamp
kubectl describe quota -n <namespace>
kubectl get nodes
kubectl describe node <node>
Korrektur
- Requests realistisch anpassen.
- Quotas prüfen oder erweitern.
- Affinity/Tolerations korrigieren.
- PVC/StorageClass prüfen.
- Clusterkapazität erhöhen.
12.2. CrashLoopBackOff
Typische Ursachen
- Anwendung beendet sich direkt.
- Konfiguration fehlt oder ist falsch.
- Secret oder ConfigMap fehlt.
- LivenessProbe ist zu aggressiv.
- Anwendung kann Abhängigkeit nicht erreichen.
- Startbefehl oder Argumente sind falsch.
Prüfung
kubectl logs <pod> -n <namespace>
kubectl logs <pod> -n <namespace> --previous
kubectl describe pod <pod> -n <namespace>
kubectl get events -n <namespace> --sort-by=.lastTimestamp
Korrektur
- Logs lesen, nicht nur Neustarts zählen.
- ConfigMaps, Secrets und Environment-Variablen prüfen.
- Probes entschärfen oder StartupProbe ergänzen.
- Container lokal oder in Debug-Umgebung reproduzieren.
12.3. ImagePullBackOff oder ErrImagePull
Typische Ursachen
- Image-Name oder Tag ist falsch.
- Registry ist nicht erreichbar.
- Authentifizierung fehlt.
imagePullSecretist falsch oder im falschen Namespace.- Rate Limits oder Netzwerkprobleme verhindern Pull.
Prüfung
kubectl describe pod <pod> -n <namespace>
kubectl get secret -n <namespace>
kubectl get serviceaccount <sa> -n <namespace> -o yaml
Korrektur
- Image-Referenz exakt prüfen.
- Registry-Zugriff testen.
imagePullSecretsim richtigen Namespace anlegen.- ServiceAccount korrekt referenzieren.
- Kein
latestverwenden, um Diagnose und Reproduzierbarkeit zu verbessern.
12.4. Service ohne Endpoints
Typische Ursachen
- Service-Selector passt nicht zu Pod-Labels.
- Pods sind nicht Ready.
- Falscher Namespace.
- Falscher
targetPort.
Prüfung
kubectl get svc <service> -n <namespace> -o yaml
kubectl get pods -n <namespace> --show-labels
kubectl get endpoints <service> -n <namespace>
kubectl get endpointslice -n <namespace> -l kubernetes.io/service-name=<service>
Korrektur
- Labels und Selector angleichen.
- ReadinessProbe prüfen.
- Portnamen und
targetPortprüfen. - Namespace korrigieren.
12.5. DNS im Cluster funktioniert nicht
Typische Ursachen
- Falscher Service-Name oder Namespace.
- CoreDNS läuft nicht korrekt.
- NetworkPolicy blockiert DNS.
- Der Service hat keine Endpoints, obwohl DNS auflöst.
Prüfung
kubectl run dns-debug --rm -it --image=busybox:1.36 --restart=Never -- nslookup kubernetes.default
kubectl run dns-debug --rm -it --image=busybox:1.36 --restart=Never -- nslookup <service>.<namespace>.svc.cluster.local
kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl logs -n kube-system -l k8s-app=kube-dns
Korrektur
- DNS-Namen korrigieren.
- CoreDNS prüfen.
- Egress zu DNS erlauben, wenn Egress-Policies aktiv sind.
- Service-Endpoints separat prüfen.
12.6. Ingress oder Gateway routet nicht
Typische Ursachen
- IngressClass oder GatewayClass fehlt.
- Controller läuft nicht.
- Host oder Pfad stimmt nicht.
- Backend-Service hat keine Endpoints.
- TLS Secret fehlt oder ist falsch.
- Controller-spezifische Annotation ist falsch.
Prüfung
kubectl describe ingress <name> -n <namespace>
kubectl get ingressclass
kubectl get svc <backend-service> -n <namespace>
kubectl get endpoints <backend-service> -n <namespace>
kubectl logs -n <controller-namespace> deploy/<controller-deployment>
Korrektur
- Routing-Regeln prüfen.
- Controller-Logs lesen.
- Backend-Service und Endpoints reparieren.
- TLS Secret und Hostnamen validieren.
12.7. RBAC Forbidden
Typische Ursachen
- Benutzer oder ServiceAccount hat kein passendes RoleBinding.
- Rolle ist im falschen Namespace gebunden.
- Ressource gehört zu einer anderen API-Gruppe.
- Verb fehlt:
get,list,watch,create,update,patch,delete.
Prüfung
kubectl auth can-i get pods -n <namespace>
kubectl auth can-i get secrets -n <namespace> --as=system:serviceaccount:<namespace>:<serviceaccount>
kubectl get rolebinding,clusterrolebinding -A | grep <name>
Korrektur
- Benötigte Verben und Ressourcen exakt bestimmen.
- RoleBinding im richtigen Namespace anlegen.
- Keine pauschale ClusterRoleBinding-Lösung verwenden, wenn eine Role reicht.
12.8. NodePressure
Typische Ursachen
- Zu wenig freier Speicherplatz.
- Zu wenig Memory.
- Zu viele Logs oder temporäre Dateien.
- Images belegen zu viel Platz.
- Zu viele Pods auf einem Node.
Prüfung
kubectl describe node <node>
kubectl get events -A --sort-by=.lastTimestamp
kubectl top nodes
kubectl top pods -A
Korrektur
- Requests und Limits prüfen.
- Ephemeral Storage begrenzen.
- Logrotation prüfen.
- Nicht benötigte Images und Pods entfernen.
- Node-Kapazität erhöhen oder Workloads verteilen.
12.9. OOMKilled
Typische Ursachen
- Memory-Limit zu niedrig.
- Anwendung hat Memory Leak.
- Spitzenlast wurde nicht berücksichtigt.
- Cache wächst unbegrenzt.
Prüfung
kubectl describe pod <pod> -n <namespace>
kubectl get pod <pod> -n <namespace> -o jsonpath='{.status.containerStatuses[*].lastState}'
kubectl top pod <pod> -n <namespace>
Korrektur
- Memory-Profil messen.
- Limit realistisch anpassen.
- Speicherleck analysieren.
- Cache begrenzen.
- Alerts auf Memory-Nutzung und Restarts setzen.
12.10. PVC bleibt Pending
Typische Ursachen
- StorageClass existiert nicht.
- Dynamische Provisionierung funktioniert nicht.
- Access Mode wird nicht unterstützt.
- Zone/Node-Affinity passt nicht.
- Quota verhindert Provisionierung.
Prüfung
kubectl get pvc -n <namespace>
kubectl describe pvc <pvc> -n <namespace>
kubectl get storageclass
kubectl get events -n <namespace> --sort-by=.lastTimestamp
Korrektur
- StorageClass prüfen.
- CSI-Treiber prüfen.
- Access Mode anpassen.
- Quotas prüfen.
- Provider-spezifische Fehler im Controller prüfen.
12.11. HPA skaliert nicht
Typische Ursachen
- Metrics Server fehlt oder liefert keine Daten.
- CPU-Requests fehlen.
- Zielmetrik ist falsch definiert.
minReplicasundmaxReplicasverhindern erwartetes Verhalten.- Last erreicht Zielwert nicht.
Prüfung
kubectl get hpa -n <namespace>
kubectl describe hpa <hpa> -n <namespace>
kubectl top pods -n <namespace>
kubectl get --raw /apis/metrics.k8s.io/v1beta1/pods
Korrektur
- Metrics Server bereitstellen oder reparieren.
- Requests setzen.
- Metrik und Zielwert anpassen.
- Lasttest durchführen.
- Skalierungsgrenzen prüfen.
13. Workshop-Übungen
Übung 1: Deployment reviewen
Aufgabe
Du erhältst ein Deployment ohne Requests, Probes und SecurityContext. Überarbeite es so, dass es workshop-tauglich und reviewbar ist.
Akzeptanzkriterien
- Jeder Container hat CPU- und Memory-Requests.
- Memory-Limit ist gesetzt.
- ReadinessProbe ist vorhanden.
- LivenessProbe ist begründet.
- Container läuft als Non-Root.
- Privilege Escalation ist deaktiviert.
- Image ist versioniert.
Übung 2: Service ohne Endpoints debuggen
Ausgangslage
Ein Service existiert, aber die Anwendung ist nicht erreichbar.
Aufgabe
Finde heraus, ob das Problem an DNS, Service-Selector, Readiness oder Pod-Labels liegt.
Pflichtkommandos
kubectl get svc -o yaml
kubectl get pods --show-labels
kubectl get endpoints
kubectl describe pod <pod>
Ergebnis
Dokumentiere Ursache, Fix und Validierung.
Übung 3: RBAC minimal vergeben
Aufgabe
Erstelle einen ServiceAccount, der nur Pods und Pod-Logs in einem Namespace lesen darf.
Akzeptanzkriterien
- Kein ClusterRoleBinding.
- Keine Schreibrechte.
- Prüfung mit
kubectl auth can-i.
Übung 4: NetworkPolicy einführen
Aufgabe
Setze in einem Namespace zunächst default-deny und erlaube danach nur den Traffic vom Ingress Controller zur API.
Akzeptanzkriterien
- Unerlaubter Pod-zu-Pod-Traffic ist blockiert.
- Erlaubter HTTP-Traffic funktioniert.
- DNS funktioniert weiterhin, falls Egress eingeschränkt wurde.
Übung 5: Rollout und Rollback testen
Aufgabe
Rolle eine neue Image-Version aus, beobachte den Rollout und führe anschließend ein Rollback aus.
Pflichtkommandos
kubectl rollout status deployment/<name>
kubectl rollout history deployment/<name>
kubectl rollout undo deployment/<name>
Ergebnis
Dokumentiere, woran du den erfolgreichen Rollout und Rollback erkannt hast.
14. Betriebsreife
Eine Lösung ist betriebsreif, wenn sie reproduzierbar, beobachtbar, rückbaubar, reviewbar und frei von echten Secrets ist. Für Kubernetes reicht diese Kurzdefinition aber nicht aus. Nutze die folgende Reifegradmatrix.
| Bereich | Mindeststandard | Guter Standard | Sehr guter Standard |
|---|---|---|---|
| Reproduzierbarkeit | Manifeste liegen im Repository. | Umgebungen sind über Overlays getrennt. | GitOps oder klarer Release-Prozess mit Audit Trail. |
| Ressourcen | Requests sind gesetzt. | Limits und Quotas sind bewusst definiert. | Kapazitätsplanung basiert auf Metriken und Lasttests. |
| Verfügbarkeit | Replicas und Readiness sind vorhanden. | Rolling Updates und PDBs sind definiert. | Multi-Zone-Verteilung und getestete Störfallszenarien. |
| Sicherheit | Keine echten Secrets im Git. | RBAC, SecurityContext und Pod Security sind umgesetzt. | Admission Policies, Image-Signaturen und Audit-Auswertung. |
| Netzwerk | Services funktionieren. | Ingress/Gateway und NetworkPolicies sind dokumentiert. | Zero-Trust-nahe Segmentierung mit getesteten Kommunikationspfaden. |
| Beobachtbarkeit | Logs und Events sind prüfbar. | Metriken und Alerts sind vorhanden. | SLOs, Tracing und Runbooks sind etabliert. |
| Rückbau | Rollback-Kommando ist bekannt. | Rollback wurde getestet. | Datenmigrationen haben Vorwärts- und Rückwärtsstrategie. |
| Betrieb | Troubleshooting ist möglich. | Runbooks existieren. | Wiederkehrende Reviews und Chaos-/Failure-Tests sind etabliert. |
Mindestdefinition für Workshop-Abgaben
Eine Workshop-Abgabe gilt als betriebsreif, wenn du diese Punkte nachweisen kannst:
- Deployment, Service und Namespace sind deklarativ definiert.
- Ressourcen sind mit Labels nachvollziehbar gruppiert.
- Images sind versioniert.
- Requests und sinnvolle Limits sind gesetzt.
- ReadinessProbe ist vorhanden.
- Logs und Events können geprüft werden.
- Rollout und Rollback sind dokumentiert.
- Keine echten Secrets sind enthalten.
- Ein eigener ServiceAccount wird verwendet oder bewusst nicht benötigt.
- Mindestens eine NetworkPolicy oder SecurityContext-Härtung ist umgesetzt.
- Typische Fehlerbilder sind dokumentiert.
15. Kommandosammlung
Kontext und Namespace
kubectl config current-context
kubectl config get-contexts
kubectl get namespaces
kubectl config set-context --current --namespace=<namespace>
Ressourcen anzeigen
kubectl get all -n <namespace>
kubectl get pods -n <namespace> -o wide
kubectl get deployment,rs,pod,svc,endpointslice -n <namespace>
Details und Events
kubectl describe pod <pod> -n <namespace>
kubectl get events -n <namespace> --sort-by=.lastTimestamp
Logs
kubectl logs <pod> -n <namespace>
kubectl logs <pod> -n <namespace> --previous
kubectl logs deployment/<deployment> -n <namespace>
Rollout
kubectl rollout status deployment/<deployment> -n <namespace>
kubectl rollout history deployment/<deployment> -n <namespace>
kubectl rollout undo deployment/<deployment> -n <namespace>
Manifestprüfung
kubectl apply --dry-run=server -f k8s/
kubectl diff -f k8s/
kubectl apply -f k8s/
RBAC
kubectl auth can-i get pods -n <namespace>
kubectl auth can-i get secrets -n <namespace> --as=system:serviceaccount:<namespace>:<serviceaccount>
Netzwerkdebugging
kubectl run net-debug --rm -it --image=busybox:1.36 --restart=Never -- sh
nslookup <service>.<namespace>.svc.cluster.local
wget -S -O- http://<service>.<namespace>.svc.cluster.local
Ressourcen
kubectl top nodes
kubectl top pods -A
kubectl describe quota -n <namespace>
kubectl describe limitrange -n <namespace>
16. Quellen und weiterführende Links
Diese Unterlage orientiert sich an der offiziellen Kubernetes-Dokumentation und ergänzt sie um Review- und Workshop-Praxis.
- Kubernetes Dokumentation: https://kubernetes.io/docs/home/
- Kubernetes API und deklarative Objektverwaltung: https://kubernetes.io/docs/concepts/overview/kubernetes-api/
kubectl apply: https://kubernetes.io/docs/reference/kubectl/generated/kubectl_apply/kubectl diff: https://kubernetes.io/docs/reference/kubectl/generated/kubectl_diff/- Ressourcenmanagement für Pods und Container: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
- Liveness, Readiness und Startup Probes: https://kubernetes.io/docs/concepts/workloads/pods/probes/
- Services: https://kubernetes.io/docs/concepts/services-networking/service/
- Ingress: https://kubernetes.io/docs/concepts/services-networking/ingress/
- Gateway API: https://kubernetes.io/docs/concepts/services-networking/gateway/
- NetworkPolicies: https://kubernetes.io/docs/concepts/services-networking/network-policies/
- RBAC Good Practices: https://kubernetes.io/docs/concepts/security/rbac-good-practices/
- ServiceAccounts: https://kubernetes.io/docs/concepts/security/service-accounts/
- Pod Security Standards: https://kubernetes.io/docs/concepts/security/pod-security-standards/
- Pod Security Admission: https://kubernetes.io/docs/concepts/security/pod-security-admission/
- Secrets: https://kubernetes.io/docs/concepts/configuration/secret/
- Good Practices for Kubernetes Secrets: https://kubernetes.io/docs/concepts/security/secrets-good-practices/
- Images: https://kubernetes.io/docs/concepts/containers/images/
- Horizontal Pod Autoscaling: https://kubernetes.io/docs/concepts/workloads/autoscaling/horizontal-pod-autoscale/
- PodDisruptionBudgets: https://kubernetes.io/docs/tasks/run-application/configure-pdb/
- Logging Architecture: https://kubernetes.io/docs/concepts/cluster-administration/logging/
- Auditing: https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/