Workshop wiki · German

Best Practices: Kubernetes

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 Än…

Workshop examples as ZIP files
Learning progress in the web app

Mark chapters as read, view reading progress and check off practice modules after enabling the optional web app. Workshop progress is calculated from chapters across all document pages. Your choices stay on this device; there is no account or server sync. Installation is not required. Withdrawing your choice in Privacy settings deletes the progress.

Reading progress0%
0%
0 / 16 chapters read
Other language versionEnglish ↗Greek ↗

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 kubectl systematisch 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.


01 / 16

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.


02 / 16

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 apply oder ein GitOps-Werkzeug, nicht dauerhaft kubectl edit.
  • Prüfe Änderungen vorab mit kubectl diff und --dry-run=server.
  • Dokumentiere, welche Quelle autoritativ ist: Git, Helm Release, GitOps Controller oder ein anderes Deployment-System.

Gute Prüfung

bash
kubectl diff -f k8s/
kubectl apply --dry-run=server -f k8s/
kubectl apply -f k8s/

Schlechtes Muster

bash
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

text
<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

yaml
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

bash
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

text
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, test und prod unterschiedlich 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

bash
kubectl apply --dry-run=server -f manifest.yaml
kubectl diff -f manifest.yaml
kubectl apply -f manifest.yaml
kubectl rollout status deployment/<name>

03 / 16

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

yaml
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: 3 schützt gegen den Ausfall einzelner Pods.
  • maxUnavailable: 0 verhindert, dass während des Rollouts absichtlich weniger Pods verfügbar sind.
  • maxSurge: 1 erlaubt eine zusätzliche Instanz während des Rollouts.
  • revisionHistoryLimit hält alte ReplicaSets für Rollbacks bereit.
  • readinessProbe entscheidet, ob Traffic an den Pod geleitet wird.
  • livenessProbe entscheidet, ob Kubernetes einen Container neu startet.
  • startupProbe schützt langsam startende Anwendungen vor zu früher Liveness-Prüfung.
  • securityContext reduziert Containerprivilegien.

Prüfung

bash
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 readinessProbe so, dass der Pod vor dem Beenden aus dem Traffic genommen wird.
  • Wähle terminationGracePeriodSeconds passend zur Anwendung.
  • Verwende preStop nur, wenn du wirklich eine explizite Verzögerung oder Abmeldeaktion brauchst.
  • Prüfe, ob dein Load Balancer oder Ingress Controller eigene Drain-Zeiten hat.

Beispiel

yaml
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 readinessProbe für fast alle Services.
  • Verwende livenessProbe nur, wenn ein Neustart einen echten Hänger beheben kann.
  • Verwende startupProbe fü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

yaml
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

yaml
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

yaml
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

bash
kubectl get pdb
kubectl describe pdb shop-api
kubectl drain <node> --ignore-daemonsets --dry-run=server

04 / 16

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.cpu und resources.requests.memory.
  • Starte mit gemessenen Werten, nicht mit Wunschwerten.
  • Nutze Monitoringdaten, Lasttests und Erfahrungswerte.
  • Dokumentiere Annahmen: erwartete Requests pro Sekunde, Speicherprofil, Startverhalten, Spitzenlast.

Beispiel

yaml
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

yaml
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

yaml
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

yaml
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

yaml
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 minReplicas und maxReplicas fachlich.
  • Prüfe Skalierungsverhalten mit Lasttests.
  • Kombiniere Workload-Autoscaling bei Bedarf mit Node-Autoscaling.

Prüfung

bash
kubectl get hpa
kubectl describe hpa shop-api
kubectl top pods
kubectl top nodes

05 / 16

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

yaml
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 ClusterIP für interne Kommunikation.
  • Nutze LoadBalancer nur, 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

bash
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

text
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

bash
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

yaml
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

yaml
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

yaml
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-deny pro 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.

06 / 16

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

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: shop-api-config
data:
  LOG_LEVEL: "info"
  FEATURE_CHECKOUT_V2: "true"

Verwendung als Environment-Variablen

yaml
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

yaml
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

yaml
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?

07 / 16

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 Role und RoleBinding innerhalb eines Namespace, wenn möglich.
  • Nutze ClusterRole nur für clusterweite Ressourcen oder bewusst wiederverwendbare Rollen.
  • Vermeide cluster-admin für Anwendungen.
  • Prüfe Rechte mit kubectl auth can-i.
  • Überprüfe regelmäßig Bindings an system:masters, cluster-admin und breite Gruppen.

Beispiel: Namespace-begrenzte Leserechte

yaml
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

bash
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

yaml
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 privileged nur für klar begründete Infrastruktur-Workloads.
  • Erzwinge Standards über Namespace-Labels oder Admission Policies.
  • Prüfe Verstöße zunächst mit warn und audit, bevor du in produktiven Namespaces hart blockierst.

Namespace-Labels

yaml
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

  1. Setze warn=restricted und audit=restricted.
  2. Behebe gemeldete Verstöße.
  3. Setze enforce=baseline oder enforce=restricted.
  4. Dokumentiere begründete Ausnahmen.

8.4. Container härten

Container sollten mit möglichst wenigen Privilegien laufen.

Empfohlene SecurityContext-Basis

yaml
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, hostPID und hostIPC, 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

yaml
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 latest in 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

yaml
image: registry.example.com/shop-api:1.4.2@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Schlechtes Muster

yaml
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.

08 / 16

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 stdout und stderr.
  • 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

text
/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

  1. Scope klären: Welche Anwendung, welcher Namespace, seit wann, welche Änderung?
  2. Objekte prüfen: Deployment, ReplicaSet, Pod, Service, EndpointSlice, Ingress/Gateway.
  3. Status prüfen: Conditions, Events, Restarts, Images, Nodes.
  4. Logs prüfen: aktuelle Logs und --previous bei Restarts.
  5. Netz prüfen: DNS, Service-Selector, Endpoints, NetworkPolicy.
  6. Ressourcen prüfen: Requests, Limits, OOM, NodePressure, Quotas.
  7. RBAC prüfen: kubectl auth can-i und ServiceAccount.
  8. Änderung bewerten: Rollout History, Git Diff, CI/CD-Läufe.
  9. Fix validieren: Vorher/Nachher-Kommandos dokumentieren.
  10. Rückbau dokumentieren: Wie wird der Fix zurückgenommen?

Kernkommandos

bash
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>

09 / 16

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

yaml
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

bash
kubectl apply -f k8s/
kubectl rollout status deployment/shop-api
kubectl get pods -l app.kubernetes.io/name=shop-api

Rollback prüfen

bash
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

  1. YAML-Linting
  2. Kubernetes-Schema-Validierung
  3. Policy-Prüfung
  4. Image-Scan
  5. Secret-Scan
  6. Unit- und Integrationstests
  7. Rendern von Helm/Kustomize
  8. Diff gegen Zielumgebung
  9. Deployment in Testumgebung
  10. Smoke-Test
  11. 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

10 / 16

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.

11 / 16

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

bash
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

bash
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.
  • imagePullSecret ist falsch oder im falschen Namespace.
  • Rate Limits oder Netzwerkprobleme verhindern Pull.

Prüfung

bash
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.
  • imagePullSecrets im richtigen Namespace anlegen.
  • ServiceAccount korrekt referenzieren.
  • Kein latest verwenden, 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

bash
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 targetPort prü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

bash
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

bash
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

bash
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

bash
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

bash
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

bash
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.
  • minReplicas und maxReplicas verhindern erwartetes Verhalten.
  • Last erreicht Zielwert nicht.

Prüfung

bash
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.

12 / 16

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

bash
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

bash
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.


13 / 16

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.

14 / 16

15. Kommandosammlung

Kontext und Namespace

bash
kubectl config current-context
kubectl config get-contexts
kubectl get namespaces
kubectl config set-context --current --namespace=<namespace>

Ressourcen anzeigen

bash
kubectl get all -n <namespace>
kubectl get pods -n <namespace> -o wide
kubectl get deployment,rs,pod,svc,endpointslice -n <namespace>

Details und Events

bash
kubectl describe pod <pod> -n <namespace>
kubectl get events -n <namespace> --sort-by=.lastTimestamp

Logs

bash
kubectl logs <pod> -n <namespace>
kubectl logs <pod> -n <namespace> --previous
kubectl logs deployment/<deployment> -n <namespace>

Rollout

bash
kubectl rollout status deployment/<deployment> -n <namespace>
kubectl rollout history deployment/<deployment> -n <namespace>
kubectl rollout undo deployment/<deployment> -n <namespace>

Manifestprüfung

bash
kubectl apply --dry-run=server -f k8s/
kubectl diff -f k8s/
kubectl apply -f k8s/

RBAC

bash
kubectl auth can-i get pods -n <namespace>
kubectl auth can-i get secrets -n <namespace> --as=system:serviceaccount:<namespace>:<serviceaccount>

Netzwerkdebugging

bash
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

bash
kubectl top nodes
kubectl top pods -A
kubectl describe quota -n <namespace>
kubectl describe limitrange -n <namespace>

15 / 16

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/
16 / 16

K8S · Orthevs Academy

31 modules as one continuous learning path.

The sequence remains unchanged: from the lab skeleton through technical foundations and operating models to final troubleshooting. The technical directory names are deliberately preserved.

Orthevs – Engineering the foundation for what comes next.

Orthevs as an app

Install Orthevs

The Orthevs web app can be installed on supported mobile devices and desktop browsers.

iPhone and iPad

Open Orthevs in Safari. Tap Share, then Add to Home Screen. Enable Open as Web App if offered, then tap Add.

Android

For the web app, open the browser menu and choose Install app or Add to Home screen. Confirm the installation.

Desktop browser

Open the browser menu or the install icon in the address bar, then choose Install app or Add to Dock.

Web app installation depends on your browser. If no install prompt appears, follow the browser steps shown above.