GKE-Pod-Snapshots

GKE-Pod-Snapshots (Google Kubernetes Engine) können die Startlatenz von Arbeitslasten verbessern, indem sie Snapshots von ausgeführten Pods wiederherstellen. In einem Pod-Snapshot wird der gesamte Pod-Status gespeichert, einschließlich Änderungen am Arbeitsspeicher und Dateisystem. Wenn Sie neue Replikate erstellen, werden sie aus dem Snapshot wiederhergestellt. So kann die Arbeitslast fortgesetzt werden, anstatt von einem neuen Status aus zu starten.

Dieses Dokument bietet eine konzeptionelle Übersicht über GKE-Pod-Snapshots. Informationen zum Aktivieren und Verwenden dieser Funktion finden Sie unter Aus einem Pod-Snapshot wiederherstellen.

Wann sollten Pod-Snapshots verwendet werden?

Verwenden Sie Pod-Snapshots für Arbeitslasten mit langen Initialisierungszeiten, z. B. für KI-Inferenzarbeitslasten, bei denen große Modelle in den CPU- oder GPU-Arbeitsspeicher geladen werden, oder für große Anwendungen, bei denen viele Bibliotheken und Abhängigkeiten geladen werden. Arbeitslasten mit bereits kurzen Startzeiten profitieren in der Regel nicht von Pod-Snapshots.

Funktionsweise von Pod-Snapshots

In GKE-Pod-Snapshots wird eine exakte Kopie des Prozessstatus eines Pods zu einem bestimmten Zeitpunkt gespeichert. Wenn neue Replikate erstellt werden, wird der Pod nicht von einem neuen Status aus initialisiert, sondern aus einem Snapshot wiederhergestellt. Die Ausführung wird an dem Punkt fortgesetzt, an dem der Snapshot erstellt wurde.

Wenn Sie Pod-Snapshots verwenden möchten, erstellen Sie benutzerdefinierte Kubernetes-Ressourcendefinitionen (Custom Resource Definitions, CRDs), um das Snapshot-Verhalten deklarativ zu konfigurieren. Ein Agent, der auf jedem GKE-Knoten ausgeführt wird, verwaltet den Snapshot-Lebenszyklus. Basierend auf den von Ihnen definierten Richtlinien bestimmt der Agent, wann neue Snapshots erstellt und wann vorhandene Snapshots verwendet werden sollen, um neue Pods wiederherzustellen. Ein Controller, der auf der GKE-Steuerungsebene ausgeführt wird, bereinigt veraltete Snapshots und behebt Probleme. In Cloud Storage werden Ihre Pod-Snapshots gespeichert.

Snapshot-Inhalte

In der folgenden Tabelle wird beschrieben, was in einem Pod-Snapshot enthalten ist und was nicht:

Kategorie In einem Snapshot enthalten Nicht in einem Snapshot enthalten
Anwendungsstatus Der gesamte Anwendungsstatus: alle offenen Dateideskriptoren, Threads, CPU-Register und Arbeitsspeicher.
Dateisysteme Das Stammdateisystem des Containers (rootfs), EmptyDir-Volumes und tmpfs-Mounts. Alles, was nicht in der vorherigen Spalte aufgeführt ist. Insbesondere werden nichtflüchtige Volumes nicht als Prüfpunkt gespeichert.
Netzwerk Loopback-Verbindungen, Listening-Sockets und Unix-Domain-Sockets. Externe Verbindungen werden nicht wiederhergestellt (sie werden bei der Wiederherstellung beendet). Von Nutzern hinzugefügte Regeln wie iptables oder nftables und Routen werden nicht wiederhergestellt.

Benutzerdefinierte Ressourcendefinitionen

Pod-Snapshots werden deklarativ mit den folgenden CRDs konfiguriert:

  • PodSnapshotStorageConfig: gibt den Speicherort für Snapshots an. Es werden nur Cloud Storage-Buckets unterstützt.
  • PodSnapshotPolicy: definiert anhand von Kubernetes-Labelselektoren, welche Pods als Snapshot gespeichert werden sollen. Diese Ressource enthält die meisten Konfigurationsoptionen für die Funktion, einschließlich der Auslösung von Snapshots und Aufbewahrungsrichtlinien.
  • PodSnapshotManualTrigger: (optional) Wenn kein Arbeitslasttrigger verwendet wird, wird ein manueller Trigger definiert, um einen Snapshot für einen bestimmten Pod zu erstellen.

Snapshot-Trigger

Sie können einen Pod-Snapshot auf folgende Arten auslösen:

  • Arbeitslasttrigger: Die Anwendung im Pod signalisiert dem GKE-Agent, dass sie bereit für einen Snapshot ist. Diese Art von Trigger wird einmal in einem Arbeitslastzyklus ausgeführt, z. B. wenn die Arbeitslast bereit ist. Dieser Ansatz eignet sich am besten, um die Startlatenz von horizontal skalierten Arbeitslasten zu verbessern.
  • Manueller Trigger: Sie können einen Snapshot bei Bedarf für einen bestimmten Pod auslösen, indem Sie eine benutzerdefinierte RessourcePodSnapshotManualTrigger erstellen. Diese Art von Trigger kann beliebig oft ausgeführt werden. Dieser Ansatz eignet sich am besten für Situationen, in denen Sie Ihre Anwendung nicht so ändern können, dass sie die Bereitschaft signalisiert.

Snapshot-Abgleich

Beim Pod-Abgleich wird ermittelt, ob ein Pod-Snapshot mit einem bestimmten Pod kompatibel ist. Dieser Abgleich erfolgt durch Erstellen eines eindeutigen Hashwerts aus den wesentlichen Laufzeitspezifikationen des Pods, auch destillierte Pod-Spezifikation genannt. Dieser Hashwert wird dann in den Pod-Snapshot eingebettet. Damit ein späterer Pod aus diesem Pod-Snapshot wiederhergestellt werden kann, muss er aus seiner eigenen destillierten Pod-Spezifikation einen identischen Hashwert generieren. So wird sichergestellt, dass die als Prüfpunkt gespeicherten und wiederhergestellten Pods in ihren Laufzeitkonfigurationen identisch sind.

Durch die Destillation wird die Pod-Spezifikation vereinfacht, indem nur die kritischen Laufzeitfelder wie image beibehalten und nicht benötigte Felder wie nodeName oder nodeSelector entfernt werden. Sie müssen darauf achten, dass die Werte dieser wesentlichen Felder zwischen dem Pod, der als Prüfpunkt gespeichert wird, und dem Pod, der wiederhergestellt werden soll, übereinstimmen.

Die folgenden Felder aus dem Pod-Objekt beeinflussen den eindeutigen Hashwert:

  • metadata:
    • annotations: nur Anmerkungen, die für die gVisor-Laufzeit relevant sind, z. B. Anmerkungen, die mit dem Präfix dev.gvisor.* beginnen.
    • labels: batch.kubernetes.io/job-completion-index
  • spec:
    • volumes: name, volumeSource, hostPath, persistentVolumeClaim, configMap
    • containers:
      • name
      • image
      • command
      • args
      • workingDir
      • ports: name, containerPort, protocol
      • volumeMounts: name, readOnly, recursiveReadOnly, mountPath, subPath, mountPropagation, subPathExpr
      • volumeDevices: name
      • lifecycle: postStart, preStop
      • terminationMessagePath
      • terminationMessagePolicy
      • securityContext (und alle Unterfelder)
      • stdin
      • stdinOnce
      • tty
    • initContainers: dieselben Unterfelder wie containers.
    • dnsPolicy
    • automountServiceAccountToken
    • hostNetwork
    • hostPID
    • hostIPC
    • shareProcessNamespace
    • securityContext
    • dnsConfig
    • runtimeClassName
    • os
    • hostUsers

Die folgenden zusätzlichen Kriterien müssen übereinstimmen, damit ein Snapshot als kompatibel gilt:

  • Hardware: Der neue Pod muss auf einem Knoten mit derselben Maschinenserie und Architektur wie der ursprüngliche Pod ausgeführt werden. Maschinenserie und Architektur müssen identisch sein. Die Anzahl der CPUs und die Menge des Arbeitsspeichers können sich ändern. E2-Maschinentypen werden aufgrund ihrer dynamischen zugrunde liegenden Architektur nicht unterstützt.
  • Versionierung: Die gVisor-Kernel-Version und die GPU-Treiberversion müssen übereinstimmen.

GKE verwaltet die Snapshot-Kompatibilität. Wenn GKE einen kompatiblen Snapshot findet, wird der neue Pod aus dem Snapshot wiederhergestellt. Wenn kein kompatibler Snapshot vorhanden ist, wird der Pod normal gestartet.

Wiederherstellungsbereitschaft und Hintergrundladen

Wenn ein Pod aus einem Snapshot wiederhergestellt wird, wird zuerst der gVisor-Kernel wiederhergestellt. Das dauert in der Regel einige Sekunden. Um die Startlatenz zu minimieren, wird die Anwendung sofort nach der Wiederherstellung des Kernels fortgesetzt. Es wird nicht gewartet, bis der Anwendungsspeicher vollständig geladen ist. Der Anwendungsspeicher wird mit einem Hintergrund-Streamingmechanismus wiederhergestellt.

Wenn die Anwendung versucht, auf einen Teil des Arbeitsspeichers zuzugreifen, der noch nicht geladen wurde, tritt ein Seitenfehler auf. gVisor fängt diesen Fehler ab, pausiert den Anwendungsthread und ruft die erforderliche Speicherseite sofort aus dem Speicher ab. Dieser On-Demand-Abruf hat Vorrang vor dem Hintergrundstream.

Aufgrund dieses Hintergrundladens kann der Speicherzugriff in den ersten Sekunden nach der Wiederherstellung eine geringe Latenz aufweisen, wenn die Anwendung Arbeitsspeicher benötigt, der noch nicht gestreamt wurde. Diese Latenz verschwindet, wenn der Speicherstatus vollständig synchronisiert ist.

Dieses Verhalten beim Hintergrundladen gilt auch für den GPU-Status. Beispielsweise kann ein Pod mit einem großen Sprachmodell (Large Language Model, LLM) den Status Running haben und auf Netzwerkprüfungen reagieren, obwohl der GPU-Arbeitsspeicher noch gefüllt wird. Das Modell ist erst dann vollständig für die Inferenz verfügbar, wenn der GPU-Status vollständig wiederhergestellt wurde. Achten Sie daher beim Messen der Wiederherstellungsgeschwindigkeit darauf, dass Sie erfassen, wann der Modellserver gestartet wurde. Sie können mit Messwerten wie der Zeit bis zum ersten Token (Time-to-First-Token, TTFT) oder Pod-Bereitschaftstests prüfen, wann der Modell server gestartet wird.

GPU-Status

Pod-Snapshots unterstützen das Erfassen des Status von GPUs. Wenn Sie einen Snapshot für einen Pod auslösen, der GPUs verwendet, speichert das NVIDIA-Tool cuda-checkpoint den GPU-Status im Prozessspeicher. Das bedeutet, dass alle auf der GPU gespeicherten Daten, z. B. Modellgewichte, im Snapshot enthalten sind. Der Pod wird dann pausiert und als Snapshot gespeichert. Bei der Wiederherstellung wird der Vorgang umgekehrt.

Da der GPU-Status in den Prozessspeicher geschrieben wird, steigt die Pod-Arbeitsspeichernutzung während der Snapshot- und Wiederherstellungsvorgänge. Berücksichtigen Sie diesen zusätzlichen Arbeitsspeicherbedarf, wenn Sie Arbeitsspeicherlimits für Ihre Pods festlegen.

Hinweise zu wiederhergestellten Pods

Aus Sicht der Kubernetes API wird ein neuer Pod erstellt. Wenn der Pod gestartet wird und ein entsprechender Snapshot für den Pod vorhanden ist, wird der Pod aus diesem Snapshot wiederhergestellt, einschließlich des ursprünglichen Arbeitsspeicher- und Prozessstatus. Einige Aspekte des Pod-Status müssen sich jedoch ändern, damit er als neue, eindeutige Instanz funktioniert.

Beachten Sie die folgenden Statusänderungen nach einer Wiederherstellung:

  • Netzwerkschnittstellen: Der wiederhergestellte Pod erhält eine neue IP-Adresse. Alle Schnittstellen und Routen werden neu konfiguriert. Aktive Netzwerkverbindungen, die zum Zeitpunkt der Snapshot-Erstellung bestanden, werden bei der Wiederherstellung geschlossen. Listening-Sockets, Loopback-Verbindungen und Unix-Domain-Socket-Verbindungen funktionieren weiterhin.
  • Hostname: Der wiederhergestellte Pod erhält eine neue Identität und einen neuen Hostnamen.
  • Echtzeit: Die Echtzeit springt auf die aktuelle Zeit.
  • Anwendungsstatus: Der Anwendungsstatus muss für jeden Pod eindeutig sein, z. B. Experiment-IDs oder Zufallszahlengeneratoren, und muss nach einer Wiederherstellung neu initialisiert werden.
  • Secrets: Verschlüsselungsschlüssel und Zertifikate, die vor der Snapshot-Erstellung erstellt wurden, müssen neu erstellt werden.
  • Umgebungsvariablen: Sie können Umgebungsvariablen zwischen einem Snapshot und einer Wiederherstellung ändern. Da Umgebungsvariablen jedoch im Anwendungsspeicher gespeichert werden, kann GKE Sandbox sie nicht zuverlässig finden und ersetzen. Wenn Ihre Arbeitslast nach einer Wiederherstellung auf neue Umgebungsvariablen angewiesen ist, müssen diese manuell vom Pod aktualisiert werden. Die neuen Umgebungsvariablen sind in der Datei /proc/gvisor/spec_environ verfügbar. Das Dateiformat ist dasselbe wie /proc/<pid>/environ.

Beschränkungen und Anforderungen

Für GKE-Pod-Snapshots gelten die folgenden Einschränkungen:

  • Pods müssen in GKE Sandbox ausgeführt werden, da Pod-Snapshots von der gVisor-Containerlaufzeit abhängen, die von GKE Sandbox bereitgestellt wird.
  • Pod-Snapshots unterstützen keine E2-Maschinentypen.
  • Pod-Snapshots funktionieren mit Pods mit einer einzelnen GPU. Nur die folgenden Konfigurationen mit mehreren GPUs werden unterstützt:
    • g2-standard-4 (1 x L4)
    • g2-standard-8 (1 x L4)
    • g2-standard-12 (1 x L4)
    • g2-standard-16 (1 x L4)
    • g2-standard-32 (1 x L4)
    • g2-standard-48 (4 x L4)
    • g2-standard-96 (8 x L4)
    • a2-highgpu-1g (1 x A100-40GB)
    • a2-ultragpu-1g (1 x A100-80GB)
    • a3-highgpu-1g (1 x H100-80GB)
  • Die teilweise GPU-Nutzung wird nicht unterstützt. Wenn ein Knoten mehrere GPUs hat, muss ein Pod alle verwenden. Sie können Pod-Snapshots beispielsweise nicht mit vier Pods verwenden, die jeweils eine GPU auf einer Maschine mit vier GPUs nutzen.
  • Die Verwendung des Cloud Storage FUSE CSI-Treiber-Sidecar-Containers mit Pod-Snapshots wird nicht unterstützt.

Nächste Schritte