Dennis Hemeier

Kubernetes 1.25 - Combiner

Kubernetes
Mit Kubernetes 1.25 erhalten wir eine neue Kubernetes Version, die insgesamt mehr als 40 Verbesserungen mit sich bringt. Darunter die neuen Pod Security Standards, CSI-Migration, Retrieable Job Failures, cgroups v2, Container Checkpointing und mehr. Was sich genau ändert, erfahrt ihr in diesem Beitrag!
Kubernetes 1.25 Release

PodSecurityPolicies entfernt - Pod Security Admission ist nun Stable

Stage: Stable
Feature group: auth
Feature gatePodSecurity

Bereits seit der Kubernetes Version 1.21 sind die PodSecurityPolicies deprecated und sollten nicht mehr verwendet werden. Spätesten mit dieser Version müsst ihr also auf die neuen Pod Security Standards migriert haben. Die erforderliche Funktion dahinter - Pod Security Admission - liegt nun in der Stable Version vor. Eine Anleitung für die Migration findet ihr in der offiziellen Kubernetes Dokumentation.

Mit den neuen Pod Security Standards wird ein neuer Weg eingeführt, gewisse Sicherheitsrichtlinien innerhalb seines Clusters zu überwachen oder zu enforcen. Dazu stehen drei vordefinierte Profile zur Verfügung:

Privileged (Keine Richtlinien) über
Baseline (Minimale Richtlinien zur Vermeidung von "Privilege Escalations") zu
Restricted (Sehr restriktive Richtlinien und Pod Hardening Best Practices)

Implementiert werden kann das ganze z.B. mit Kubewarden, Kyverno oder dem OPA Gatekeeper.

CSI Migration, Deprecated Provider und mehr

Im Bereich des Container Storage Interface haben sich mit der Kubernetes Version 1.25 viele Änderungen ergeben. Bereits bekannt ist euch sicherlich, dass fast alle internen Provider jetzt deprecated sind und nach und nach in das neue Interface übertragen werden müssen. Lediglich die folgenden Provider sind aktuell noch nicht deprecated:

cephfs, csi, fc, hostPath, iscsi, local, nfs und rbd

Auch wurden mit Kubernetes 1.25 folgende Provider komplett entfernt und müssen vor dem Update migriert sein:

GlusterFS, flocker, quobyte, storageos

Gerne möchte ich euch aber noch mal kurz das grundsätzliche Thema erklären:

Bisher wurden Volumes in vielen Clustern direkt über einen internen Storage Provider (in-tree-Provider) gemanaged. Diese internen Provider werden nun ausgelagert und gegen externe CSI-Provider ersetzt. Ob ihr noch einen alten Provider verwendet, könnt ihr ganz einfach über den Befehl kubectl get storageclass überprüfen:

$ kubectl get storageclass
NAME                      PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
default                   kubernetes.io/aws-ebs   Delete          Immediate              false                  5y94d

In diesem Beispiel sehen wir, dass es in diesem Cluster eine Storageclass mit dem Provisioner kubernetes.io/aws-ebs gibt. Dieser ist veraltet und muss ersetzt werden. Grundsätzlich lauten alle alten Provisioner kubernetes.io/xxxxxx

Schauen wir uns daher einmal ein Cluster mit bereits migrierten Storageclasses an:

kubectl get storageclass
NAME                    PROVISIONER          RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
azurefile               file.csi.azure.com   Delete          Immediate              true                   159d

In diesem Cluster sehen wir eine Storageclass, welche bereits CSI-Volumes verwendet. Diese Information findet ihr meist anhand des Namens des Provisioners.

Doch wie werden Volumes nun migriert? Dazu gibt es eine Funktionalität direkt im Kubernetes Core mit dem Namen CSI Migration, welche mit Kubernetes 1.25 nun in der Stable Version vorliegt. Der exakte Migrationsweg ist je nach Provider etwas unterschiedlich. Daher schaut hierzu am besten in die jeweiligen Dokumentationen eures Storageanbieters / Cloud Providers.

Auch erhalten wir durch den Einsatz der neuen CSI-Volumes weitere Vorteile, welche wir euch in einem weiteren Blogbeitrag im Detail vorstellen werden. Daher an dieser Stelle nur kurz ein paar Schlagworte: Volume Resizing, Volume Migration, Volume Cloning, Snapshots, Restores und mehr.

NetworkPolicy endPort - Stable

Stage: Stable
Feature group: networking
Feature gateNetworkPolicyEndPort

Mit der endPort Konfiguration könnt ihr eure NetworkPolicies nicht nur für einen einzelnen Port, sondern für eine komplette Port Range freigeben. Somit entfällt etwa die mehrfache Deklaration von Policies, sofern mehrere Ports auf einmal freigegeben werden müssen.

Um das ganze zu verdeutlichen, findet ihr hier einmal eine Beispiel NetworkPolicy, welche die Ports 32000 bis 32768 freigibt:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: multi-port-egress
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 32000
      endPort: 32768

Retrieable and non-retriable Job failures - Alpha

Stage: Alpha
Feature group: apps
Feature gateJobBackoffPolicy

Aktuell können fehlgeschlagene Jobs nur durch die Verwendung der Einstellung spec.backoffLimit neu gestartet werden. Diese Einstellung gilt allerdings immer. Egal, ob ein Neustart des Jobs etwas bringen würde oder nicht. Mit der neuen Einstellung spec.backoffPolicy könnt ihr genau definieren, wann ein Job neu starten soll – und wann eben nicht.

apiVersion: batch/v1
kind: Job
metadata:
  name: job-pod-failure-policy-example
spec:
  completions: 12
  parallelism: 3
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: main
        image: docker.io/library/bash:5
        command: ["bash"]        # example command simulating a bug which triggers the FailJob action
        args:
        - -c
        - echo "Hello world!" && sleep 5 && exit 42
  backoffLimit: 6
  podFailurePolicy:
    rules:
    - action: FailJob
      onExitCodes:
        containerName: main      # optional
        operator: In             # one of: In, NotIn
        values: [42]
    - action: Ignore             # one of: Ignore, FailJob, Count
      onPodConditions:
      - type: DisruptionTarget   # indicates Pod disruption

Bei dieser Spezifikation wird der Job direkt als Fehlschlag gewertet, sofern der Exit Code des main Containers 42 ist. Alle anderen Fehlercodes laufen auf die bereits bekannte backoffLimit, welche insgesamt 6 Restarts erlaubt. Zusätzlich erlauben wir bei diesem Job keine Disruption, sodass der Job vollständig durchlaufen kann.

Ephermal Containers - Stable

Stage: Stable
Feature group: node
Feature gateEphermalContainers

Mit der Kubernetes Version 1.16 wurden Ephermal Containers als Alpha Feature zu Kubernetes hinzugefügt. Seit K8S 1.23 sind diese Beta und nun in der Stable Version vorhanden.

Mit diesem Feature könnt ihr zu einem laufenden Pod temporär einen weiteren Container hinzufügen. Dieses Feature ist besonders im Bereich der Fehleranalyse sinnvoll, da ihr so benötigte Funktionen zur Laufzeit eines Containers oder während die eigentliche Applikation sich im CrashloopBackoff befindet hinzufügen könnt.

Um das Feature zu testen, könnt ihr den Befehl kubectl debug verwenden.

cgroup v2 - Stable

Stage: Stable
Feature group: node

Bereits seit zwei Jahren ist die Linux Kernel cgroups v2 API Stable. Einige Kubernetes Installationen verwenden diese bereits als Standard.

cgroups v2 hat einige Vorteile im Vergleich zu cgroups v1. Weitere Informationen dazu findet ihr in der cgroups v2 Dokumentation. Wichtig: Zum aktuellen Stand ist v1 weiterhin unterstützt. In späteren Kubernetes Releases kann es allerdings sein, dass Version 1 deprecated wird.

terminationGracePeriod für LivenessProbes - Beta

Stage: Beta
Feature group: node
Feature gateProbeTerminationGracePeriod

Mit dieser Änderung wird die terminationGracePeriod, die steuert, wie viel Zeit ein Container in Sekunden bekommt, sich sauber zu beenden um eine weitere Einstellung innerhalb der LivenessProbe ergänzt.

Somit könnt ihr nicht nur eine allgemeingültige terminationGracePeriod setzen, sondern dieses getrennt für eine potenziell fehlgeschlagene LivenessProbe setzen.

Container Checkpointing - Alpha

Stage: Alpha
Feature group: node
Feature gateContainerCheckpointRestore

Mit dieser Funktion bekommen wir die Möglichkeit, einen Snapshot von einem laufenden Container zu erstellen, diesen zu exportieren und ihn auf einem anderen System (oder auf einer anderen Node innerhalb des Clusters) wieder zu starten.

Dieses Feature verwendet eine neu eingeführte CRI API, sodass der entsprechende Kubelet einen Request an die verwendete Container Runtime zur Erstellung des Snapshots senden kann.

Zum aktuellen Stand werden Snapshot als .tar unter checkpoint-[POD-NAME]-[CONTAINER-NAME]-[TIMESTAMP].tar auf der Node unter /var/lib/kubelet/checkpoints (Einstellung --root-dir) abgelegt.

Local Ephermal Storage Capacity - Stable

Stage: Stable
Feature group: storage
Feature gateLocalStorageCapacityIsolation

Über Pod Resource Requests und Limits setzen wir ja bereits seit einiger Zeit Ressourcen für Memory und CPU. Details dazu findet ihr in unserer 101-Series zu dem Thema Resource Management. Ein weniger bekanntes Feature seit Kubernetes 1.8 ist es, den Ephermal Storage eines Containers (z. B. ein emptyDir Volume) zu beschränken.

Die Einstellungen dazu setzt ihr unter spec.containers.resources.requests.ephermal-storage sowie unter spec.containers.resources.limits.ephermal-storage. Sollte ein Pod sein Limit überschreiten, so wird dieser evicted.

Retroactive Default StorageClass - Alpha

Stage: Alpha
Feature group: storage
Feature gateRetroactiveDefaultStorageClass

Mit dem neuen Feature erhält Kubernetes die Möglichkeit, automatisch eine neu angelegte Default StorageClass für alle PVCs zu übernehmen, die zuvor keine StorageClass gesetzt hatten.

Um das Feature an einem Beispiel zu erklären: Stellt euch vor, ihr habt ein neues Cluster, in dem bereits einige PersistentVolumeClaims ohne StorageClass angelegt wurden. Sofern dieses Feature aktiviert wurde, kann ich nun als Administrator eine neue StorageClass als Default definieren und Kubernetes kümmert sich darum, dass alle bereits vorhandenen PVCs diese StorageClass bekommen.

Efficient SELinux volume relabeling - Alpha

Stage: Alpha
Feature group: storage
Feature gateSELinuxMountReadWriteOncePod

Wer innerhalb seines Kubernetes Clusters große Volumes mit vielen (kleinen) Dateien verwendet, der kennt eventuell auch das Problem, dass das Einhängen des Volumes in den Pod unter Umständen mehrere Minuten dauern kann. Grund hierfür ist, dass Kubernetes intern für jede Datei den SELinux Context ändern muss.

Diese Option sorgt dafür, dass das Volume direkt mit dem korrekten Context eingehängt wird und somit die rekursiven Änderungen entfallen. Aktuell hat dieses Feature allerdings einen kleinen Nachteil: Es ist nur für Volumes vom Typ ReadWriteOncePod nutzbar, welche nach unserer Erfahrung zurzeit noch wenig eingesetzt werden.

Entfernte APIs / Versionen

Die folgenden API Versionen sind deprecated und werden mit Kubernetes 1.25 nicht mehr unterstützt:

CronJob batch/v1beta1
EndpointSlice discovery.k8s.io/v1beta1
Event events.k8s.io/v1beta1
HorizontalPodAutoscaler autoscaling/v2beta1
PodDisruptionBudget policy/v1beta1
PodSecurityPolicy policy/v1beta1
RuntimeClass node.k8s.io/v1beta1

Release Notes & Changelog

Hier findet ihr die offiziellen Release Notes und das Changelog zu Kubernetes 1.25

Release Notes

kubernetes.io

Changelog

GitHub

Habt ihr noch Fragen oder Feedback zum neuen Kubernetes Release? Weitere Informationen findet ihr in unserer Kubernetes Einführungsschulung! Oder ihr wollt jetzt auch Kubernetes einsetzen? Dann wendet euch gerne an uns und schreibt uns eine kurze Nachricht oder nutzt den Chat auf unserer Website. Wir freuen uns auf eure Nachrichten!