Zum Hauptinhalt springen
  1. Blog/

Kubernetes 1.37: Was vor dem Upgrade geprüft werden muss

·8 min
Marius Reinhardt
Autor
Marius Reinhardt
Allgemeine und technische Deep-Dives in cloud native (Sicherheits-) Themen, hoffentlich allverständlich geschrieben.

Was vor dem Upgrade geprüft werden muss
#

Kubernetes 1.37 (Codename „Garhwal") ist seit dem 26. August 2026 released. Der Sneak Peek aus dem Juli listet die Punkte, die aus einem Routine-Upgrade einen Incident machen können — am häufigsten sind das genau vier:

  1. cgroup-Version auf jedem Node — der Kubelet startet sonst nicht mehr.
  2. containerd-Version — 1.37 ist die letzte Version, die containerd 1.x unterstützt.
  3. kube-proxy-Modus — ipvs ist deprecated, die Warning kommt ab 1.37.
  4. Static-Pod-Manifeste — Secrets/ConfigMap-Referenzen sind ab sofort verboten.

Dazu kommt eine Breaking Change, die man schnell übersieht: SELinuxMount geht auf GA und kann auf Enforcing-Clustern Pods am Start hindern.

Check 1: cgroup v1 – der Kubelet startet nicht mehr
#

Seit Kubernetes 1.35 ist failCgroupV1 standardmäßig true. Heißt: Auf einem Node mit cgroup v1 verweigert der Kubelet den Start. In 1.37 gibt es noch einen Override — aber der ist ein Countdown, kein Dauerzustand:

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
failCgroupV1: false

Das ist keine nachhaltige Lösung. Die Entfernung von cgroup v1 ist angekündigt, und die guten neuen Features (In-Place Pod Resizing, Tiered Memory Protection, Memory QoS) funktionieren nur mit v2.

So prüfst du es — auf jedem Node:

stat -fc %T /sys/fs/cgroup/
  • cgroup2fs → v2, alles in Ordnung
  • tmpfs → v1, dieser Node blockiert das Upgrade

Wer ist betroffen? Ältere LTS-Installationen, Custom-Kernel und Hosts, die die Migration auf v2 nie gemacht haben. Moderne Distros (Ubuntu 22.04+, RHEL 9+, Flatcar) booten standardmäßig mit v2.

Check 2: containerd 1.x – die letzte Runde
#

Dieser Punkt steht im Sneak Peek nicht prominent, ist aber mindestens so wichtig: Kubernetes 1.37 ist die letzte Version, die containerd 1.x unterstützt. Das ist in der Container-Runtimes-Doku explizit: Der Kubelet erfragt den cgroup-Treiber seit Neuerem direkt vom Runtime (RuntimeConfig-RPC). containerd 1.y beherrscht das nicht und der Kubelet fällt auf den eigenen konfigurierten Wert zurück — in 1.38 fällt dieser Fallback weg, dann scheitert der Kubelet mit containerd 1.y (kubeadm Issue #3229).

Der Zeitplan aus der kubeadm-Tracking-Issue:

  • 1.35: kubeadm gibt eine Warnung aus, wenn containerd 1.y erkannt wird
  • 1.36: containerd 1.7 taucht nicht mehr in der Kubernetes-Support-Matrix auf
  • 1.37: letzte unterstützende Version
  • 1.38: Error statt Fallback (geplant)

Zum Status von containerd 1.7: Die Version war offiziell LTS bis März 2026, verlängert bis September 2026 — allerdings nur im erweiterten Support mit Fokus auf Kubernetes 1.30–1.32. Wer jetzt auf einem aktuellen Cluster noch 1.7 fährt, steht mit 1.37 vor dem letzten Zug.

So prüfst du es:

kubectl get nodes -o wide

Die Spalte CONTAINER-RUNTIME zeigt die Version, z.B. containerd://1.7.20. Alles mit 1.x gehört auf 2.x, bevor 1.38 kommt — je nach Kubernetes-Version sind 2.2 oder neuer die unterstützten Ziele.

Check 3: kube-proxy im ipvs-Modus – die Warning ist da
#

Der ipvs-Modus von kube-proxy war schon länger für die Abschaffung vorgesehen: Die Kernel-ipvs-API kann Kubernetes Services nie vollständig abbilden und greift deshalb weiterhin auf iptables zurück — technische Schuld ohne echten Payoff (KEP-5495). Ab 1.37 gibt es dafür eine Deprecation-Warning beim Start. Der Zeitplan:

  • 1.37: Warning-Log beim Start
  • ~1.40: disabled by default, noch per Feature Gate aktivierbar
  • ~1.43: komplett entfernt

So prüfst du es:

kubectl -n kube-system get configmap kube-proxy -o jsonpath='{.data.config\.conf}' | grep 'mode:'

Steht dort mode: ipvs, ist noch Zeit — aber die Migration ist nur eine Config-Änderung samt Rollout. Das empfohlene Backend ist nftables; kube-proxy nutzt dafür inzwischen die Kernel-netlink-Schnittstelle statt der nft-CLI (deutlich effizienteres Regel-Management, Release-Notes).

Check 4: Static Pods dürfen keine Secrets mehr referenzieren
#

Static Pods laufen aus Manifest-Dateien auf dem Node, nicht über den API-Server — genau für den Bootstrap-Fall, in dem der API-Server noch gar nicht läuft. Dass sie trotzdem configMapRef/secretRef referenzieren konnten, war ein Bug, der in 1.37 behoben wurde: Diese Referenzen sind jetzt strikt verboten, das PreventStaticPodAPIReferences-Feature-Gate wurde entfernt (Sneak Peek).

So prüfst du es:

grep -rlE 'configMapRef|secretRef|configMapKeyRef|secretKeyRef' /etc/kubernetes/manifests/ 2>/dev/null

Jeder Treffer ist ein Manifest, das überarbeitet werden muss: Werte direkt einbetten oder den Workload zu einem regulären API-managed Pod machen.


Breaking: SELinuxMount geht auf GA
#

SELinuxMount und SELinuxChangePolicy erreichen in 1.37 Stable und sind standardmäßig aktiv — das kann Pods betreffen, auch wenn es keine Deprecation ist.

Was sich ändert: Bisher wurden Volumes rekursiv relabeled. Ab 1.37 mountet die CSI-Integration mit -o context=<label>, sobald ein CSIDriver-Objekt .spec.seLinuxMount: true setzt. Das Problem: Ein Mount kann nur einen SELinux-Context halten. Teilen sich zwei Pods mit unterschiedlichen Labels dasselbe Volume auf demselben Node (bisher dank rekursivem Relabeling kein Problem), startet der zweite Pod nicht mehr (KEP-1710).

Workaround für betroffene Workloads:

spec:
  securityContext:
    seLinuxChangePolicy: Recursive

Das Verhalten ist erst ab 1.38 gelockt — clusterweites Deaktivieren bleibt also noch einen Release lang möglich.

So prüfst du es: Kein SELinux im Cluster → kein Effekt. Sonst:

getenforce
# Enforcing → prüfen, ob Workloads Volumes über Pods mit unterschiedlichen Labels teilen
# Disabled/Permissive → kein Problem

Die Deprecation, die nicht im Sneak Peek stand: kube-dns
#

Erst im finalen Release-Post ist sie aufgetaucht: kube-dns wird eingestellt. CoreDNS ist seit Kubernetes 1.13 der Default, kube-dns hat EndpointSlices und Dual-Stack-Services nie unterstützt. Das Subprojekt ist bereits retired, node-local-dns wurde in ein eigenes Repository ausgelagert und funktioniert mit CoreDNS weiter.

Die Timeline: Nach v1.40 werden keine neuen kube-dns-Packages mehr gebaut (Release-Post). Wer noch kube-dns betreibt, sollte jetzt die Migration zu CoreDNS planen — die Doku beschreibt die Schritte.

So prüfst du es:

kubectl -n kube-system get pods | grep -E 'kube-dns|coredns'

kube-dns statt coredns → Migrationsplan erstellen.


Jetzt die guten Nachrichten
#

Kubelet in User Namespace (Rootless Mode) → Beta
#

Der Kubelet läuft traditionell mit Root-Rechten auf dem Host — ein Kubelet-Exploit bedeutet damit Host-Kompromittierung. In 1.37 geht der Rootless Mode in die Beta: Die Node-Komponenten laufen auf dem Host als unprivilegierter User und verhalten sich nur innerhalb ihres Namespaces wie Root (KEP-2033). Das ist der größte Blast-Radius-Reducer dieses Releases: Ein Kubelet-Exploit landet auf einem Rootless-Node als normaler User — nicht als Root.

Metrics API → GA
#

Nach fast neun Jahren Beta ist metrics.k8s.io Stable — die API hinter kubectl top und dem Horizontal Pod Autoscaler. Keine Funktionsänderung, v1 und v1beta1 bleiben beide nutzbar, die Migration ist reine Formsache (Release-Post).

Volume Health Monitor → Alpha (Reset)
#

KEP-1432 startet nach einem ersten Anlauf in 1.21 nochmal neu auf Alpha — mit vier neuen CSI-RPCs. CSI-Treiber können Storage-Ausfälle (Inaccessible, Degraded) jetzt maschinenlesbar in PersistentVolumeClaim.status.healthStatus und Pod.status.volumeHealth melden. Noch Alpha, aber die richtige Richtung für Storage-Überwachung.

Gateway API v1.6 – TCPRoute und UDPRoute sind GA
#

Nicht direkt Kubernetes-Core, aber zeitgleich: Die Gateway API v1.6.0 holt TCPRoute und UDPRoute aus dem Experimental-Kanal ins v1-API-Release. Datenbanken, DNS, Gaming-Server und IoT-Protokolle routen damit über die Gateway API, ohne Workarounds über normale Services. Gleichzeitig wandern neue experimentelle Ressourcen in eine eigene API-Gruppe (gateway.networking.x-k8s.io) mit X-Prefix — die Grenze zwischen experimenteller und stabiler API ist damit auf Gruppenebene sichtbar.

KYAML – das striktere YAML, jetzt Stable
#

SIG CLI hat mit KYAML (KEP-5295) ein striktes YAML-Subset definiert, das die bekannten Fallstricke entschärft:

  • Keine stille Typ-Koersion: Strings werden gequotet — der klassische „Norway Bug", bei dem country: NO als boolean false geparst wird, ist damit ausgeschlossen.
  • Struktur statt Einrückung: Maps und Listen werden explizit mit {} und [] geschrieben, keine Whitespace-Fallen mehr.
  • Besser als JSON: Kommentare und Trailing Commas sind erlaubt — genau das, was JSON nervig macht.

Und das Beste: Alles gültige KYAML ist gültiges YAML. Kein Migrationsaufwand, nur weniger Footguns. kubectl get -o kyaml ist mit den abgeschlossenen Conformance Tests in 1.37 stabil nutzbar (KYAML-Blog).

HPA Scale to Zero – Beta, standardmäßig aktiv
#

Der Horizontal Pod Autoscaler kann Workloads auf null Replicas herunterfahren, wenn nichts zu tun ist, und bei Bedarf wieder hochfahren (spec.minReplicas: 0). Klar: Das funktioniert nur mit Object- oder External-Metrics — CPU- und Memory-Werte setzen laufende Pods voraus, die es bei null nicht gibt. Use Cases sind Queue-Consumer, Batch-Jobs und GPU-Workloads. Wer teure GPU-Kapazität für intermittierende Arbeit vorhält, spart hier real Geld.


Die Checks – Zusammenfassung
#

Vor dem Upgrade auf 1.37:

# 1. cgroup v2 prüfen – auf JEDEM Node
stat -fc %T /sys/fs/cgroup/
# Erwartet: cgroup2fs

# 2. containerd-Version clusterweit
kubectl get nodes -o wide
# CONTAINER-RUNTIME: containerd://2.x als Ziel, 1.x läuft in 1.37 nur noch mit Warnung

# 3. kube-proxy-Modus
kubectl -n kube-system get configmap kube-proxy -o jsonpath='{.data.config\.conf}' | grep 'mode:'
# ipvs → Migrationsplan erstellen (Entfernung ~1.43, nftables ist das empfohlene Backend)

# 4. Static-Pod-Manifeste auf Secret/ConfigMap-Referenzen
grep -rlE 'configMapRef|secretRef|configMapKeyRef|secretKeyRef' /etc/kubernetes/manifests/ 2>/dev/null
# Keine Treffer erwartet

Und je nach Umgebung:

# 5. SELinux-Status (nur relevant bei Enforcing)
getenforce
# Enforcing → prüfen, ob Pods Volumes über unterschiedliche Labels teilen

# 6. kube-dns im Einsatz?
kubectl -n kube-system get pods | grep -E 'kube-dns|coredns'
# kube-dns statt coredns → ab 1.40 keine Packages mehr, Migration planen

Fazit
#

Kubernetes 1.37 bringt echte Verbesserungen — Rootless Kubelet als Beta, Metrics API GA, KYAML Stable, HPA Scale to Zero. Aber die Deprecations sind das, was ohne vorherige Prüfung zum Incident führt.

Die vier harten Wahrheiten:

  1. cgroup v1 ist am Ende. Der Override in 1.37 ist ein Countdown, kein Dauerzustand.
  2. containerd 1.x läuft zum letzten Mal. 1.37 ist die letzte unterstützende Version, ab 1.38 fällt der Fallback weg.
  3. ipvs ist auf der Abschussliste. Nicht brennend, aber nftables ist besser und die Migration ist nur eine Config-Änderung.
  4. kube-dns wird eingestellt. Nach 1.40 keine neuen Packages — CoreDNS-Migration jetzt einplanen.

Und die Breaking Change, die keiner erwartet: SELinuxMount GA kann auf Enforcing-Clustern Pods am Start hindern, wenn sie Volumes über unterschiedliche Labels teilen. Erst ab 1.38 ist das Verhalten gelockt.

Erst prüfen, dann upgraden.


Quellen
#

Verwandte Artikel

Wieso deine Container Images noch nicht sicher sind

·9 min
Eine Beschreibung der aktuellen Container Security Lage in Bezug auf CVE Management in Deutschland. Tiefer: Wieso es nicht einfach ist sichere Container Images in die Produktivumgebung zu bekommen.