GKE-Pod-Snapshots

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

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. KI-Inferenzarbeitslasten, bei denen große Modelle in den CPU- oder GPU-Arbeitsspeicher geladen werden, oder große Anwendungen, bei denen viele Bibliotheken und Abhängigkeiten geladen werden. Arbeitslasten, die bereits schnelle Startzeiten haben, profitieren in der Regel nicht von Pod-Snapshots.

Funktionsweise von Pod-Snapshots

In GKE-Pod-Snapshots wird eine genaue Kopie des Prozessstatus eines Pods zu einem bestimmten Zeitpunkt gespeichert. Wenn neue Replikate erstellt werden, wird der Pod nicht von einem neuen Zustand 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 (CRDs), um das Snapshot-Verhalten deklarativ zu konfigurieren. Ein Agent, der auf jedem GKE-Knoten ausgeführt wird, verwaltet den Snapshot-Lebenszyklus. Anhand der von Ihnen definierten Richtlinien bestimmt der Agent, wann neue Snapshots erstellt und wann vorhandene Snapshots zum Wiederherstellen neuer Pods verwendet werden. Ein Controller, der auf der GKE-Steuerungsebene ausgeführt wird, bereinigt veraltete Snapshots und behebt Probleme. Cloud Storage speichert Ihre Pod-Snapshots.

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 der Arbeitsspeicher.
Dateisysteme Das Container-Root-Dateisystem (rootfs), EmptyDir-Volumes und tmpfs-Bereitstellungen. Alles, was nicht in der vorherigen Spalte enthalten ist. Vor allem nichtflüchtige Volumes werden nicht als Checkpoint gespeichert.
Netzwerk Loopback-Verbindungen, Listening-Sockets und Unix-Domain-Sockets. Externe Verbindungen werden nicht wiederhergestellt, sondern bei der Wiederherstellung beendet. Vom Nutzer 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, welche Pods auf Grundlage von Kubernetes-Label-Selektoren als Snapshot erstellt 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 Arbeitslast-Trigger verwendet wird, wird ein manueller Trigger zum Erstellen eines Snapshots für einen bestimmten Pod definiert.

Snapshot-Trigger

Sie haben folgende Möglichkeiten, einen Pod-Snapshot auszulösen:

  • Arbeitslast-Trigger: Die Anwendung im Pod signalisiert dem GKE-Agent, dass sie für einen Snapshot bereit ist. Dieser Triggertyp wird einmal in einem Arbeitslastzyklus ausgeführt, z. B. wenn eine 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 Ressource vom Typ „PodSnapshotManualTrigger“ erstellen. Dieser Triggertyp kann beliebig oft ausgeführt werden. Diese Vorgehensweise eignet sich am besten, wenn Sie Ihre Anwendung nicht ändern können, um die Bereitschaft zu signalisieren.

Snapshot-Abgleich

Beim Pod-Abgleich wird ermittelt, ob ein Pod-Snapshot mit einem bestimmten Pod kompatibel ist. Diese Übereinstimmung wird erreicht, indem ein eindeutiger Hash aus den wesentlichen Laufzeitspezifikationen des Pods erstellt wird, auch als „destillierte Pod-Spezifikation“ bezeichnet. Dieser Hash wird dann in den Pod-Snapshot eingebettet. Damit ein späterer Pod aus diesem Pod-Snapshot wiederhergestellt werden kann, muss er einen identischen Hash aus seiner eigenen komprimierten Pod-Spezifikation generieren. Dieser Prozess trägt dazu bei, dass die Checkpoint- 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. Die Werte dieser wichtigen Felder müssen zwischen dem Pod, der für die Erstellung von Prüfpunkten verwendet wird, und dem Pod, der für die Wiederherstellung vorgesehen ist, übereinstimmen.

Die folgenden Felder des Pod-Objekts beeinflussen den eindeutigen Hash:

  • 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. Die Maschinenserie und die Architektur müssen identisch sein. Die Anzahl der CPUs und die Speichermenge können sich ändern. E2-Maschinentypen werden aufgrund ihrer dynamischen zugrunde liegenden Architektur nicht unterstützt.
  • Versionsverwaltung: 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.

Tagesform und Hintergrundladen wiederherstellen

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 Arbeitsspeicher der Anwendung vollständig geladen ist. Der Arbeitsspeicher der Anwendung wird durch einen Hintergrundstreaming-Mechanismus wiederhergestellt.

Wenn die Anwendung versucht, auf einen Teil des Speichers zuzugreifen, der noch nicht geladen wurde, tritt ein Seitenfehler auf. gVisor fängt diesen Fehler ab, pausiert den Anwendungs-Thread und ruft die erforderliche Speicherseite sofort aus dem Speicher ab. Dieses On-Demand-Abrufen 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 Speicher benötigt, der noch nicht gestreamt wurde. Diese Latenz verschwindet, wenn der Speicherstatus vollständig synchronisiert ist.

Dieses Verhalten beim Laden im Hintergrund gilt auch für den GPU-Status. Ein Pod für ein Large Language Model (LLM) kann beispielsweise den Status Running haben und auf Netzwerkprüfungen reagieren, obwohl der GPU-Arbeitsspeicher noch belegt wird. Das Modell reagiert erst wieder vollständig auf Anfragen, wenn der GPU-Status vollständig wiederhergestellt ist. Achten Sie daher beim Messen der Wiederherstellungsgeschwindigkeit darauf, dass Sie erfassen, wann der Modellserver gestartet wurde. Sie können anhand von Messwerten wie „Time-to-First-Token“ (TTFT) oder Bereitschaftsprüfungen für Pods prüfen, wann der Modellserver gestartet wird.

GPU-Status

Pod-Snapshots unterstützen das Erfassen des GPU-Status. 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 es wird ein Snapshot erstellt. Bei der Wiederherstellung wird der Vorgang umgekehrt.

Da der GPU-Status in den Prozessspeicher geschrieben wird, steigt die Pod-Arbeitsspeichernutzung während Snapshot- und Wiederherstellungsvorgängen. Sie sollten diesen zusätzlichen Arbeitsspeicherbedarf berücksichtigen, 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 Arbeitsspeichers und Prozessstatus. Einige Aspekte des Pod-Status müssen sich jedoch ändern, damit er als neue, eindeutige Instanz fungieren kann.

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 des Snapshots 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 zur aktuellen Zeit vor.
  • Anwendungsstatus: Der Anwendungsstatus muss für jeden Pod eindeutig sein, z. B. Test-IDs oder Zufallszahl-Seeds, und muss nach einer Wiederherstellung neu initialisiert werden.
  • Secrets: Verschlüsselungsschlüssel und Zertifikate, die vor der Erstellung des Snapshots 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 im Pod manuell aktualisiert werden. Die neuen Umgebungsvariablen sind in der Datei /proc/gvisor/spec_environ verfügbar. Das Dateiformat ist dasselbe wie für /proc/<pid>/environ.

Mehrmandantenfähigkeit und Identität

Für Pod-Snapshots sind manuelle IAM-Bindungen für das Kubernetes-Dienstkonto (KSA) jedes Pods erforderlich, um auf Cloud Storage zuzugreifen. Die manuelle Weitergabe von IAM-Bindungen kann einige Zeit in Anspruch nehmen. Das kann problematisch sein, wenn Sie Snapshots unmittelbar nach dem Erstellen eines Pods erstellen müssen.

Um Verzögerungen zu vermeiden und die Verwaltung von Mandanten zu vereinfachen, können Sie optional ein GKE-Knoten-Dienstkonto verwenden, um kurzlebige Tokens bei Bedarf zu erstellen, anstatt IAM manuell an KSAs zu binden. Wenn Sie Pod-Snapshots mit diesem Ansatz konfigurieren möchten, verwenden Sie das Feld tokenSource im Objekt „PodSnapshotStorageConfig“ mit einem der folgenden Werte:

  • podKSA (Standard): Manuelle IAM-Bindung des KSA des Pods an den Cloud Storage-Bucket.
  • federatedP4SA: Verwenden Sie ein pfadspezifisches Token, das vom Knotendienstkonto erstellt wurde.

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.
  • Für die GPU-Unterstützung für Pod-Snapshots gelten die folgenden Anforderungen und Einschränkungen:
    • Pods mit einer einzelnen GPU werden sowohl auf Knoten mit einer einzelnen GPU als auch auf Knoten mit mehreren GPUs unterstützt.
    • Multi-GPU-Pods werden nur auf L4-GPUs (g2-standard-*-Maschinentypen) unterstützt.
    • Die GPU-Freigabe mit Multi-Instance GPU (MIG) wird nicht unterstützt.
    • In GKE-Versionen bis 1.35.0-gke.1738000 muss ein Pod, der auf einem Knoten mit mehreren GPUs ausgeführt wird, alle auf diesem Knoten verfügbaren GPUs verwenden. In den Versionen 1.35.0-gke.1738000 und höher können Pods eine Teilmenge der GPUs auf einem Knoten verwenden.
    • Pod-Snapshots unterstützen die folgenden Maschinentypen:
      • 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 × L4)
      • g2-standard-96 (8 × L4)
      • a2-highgpu-1g (1 × A100-40 GB)
      • a2-ultragpu-1g (1 × A100-80GB)
      • a3-highgpu-1g (1 × H100-80GB)
  • Die Verwendung des Sidecar-Containers für den Cloud Storage FUSE CSI-Treiber mit Pod-Snapshots wird nicht unterstützt.
  • Pods unterstützen keine TPU-Maschinentypen.

Nächste Schritte