Kapazitätsreserven konfigurieren

Kapazitätspuffer verbessern die Reaktionsfähigkeit und Zuverlässigkeit kritischer Arbeitslasten, indem sie die freie Clusterkapazität und den angehaltenen Status von vorab bereitgestellter, vorkonfigurierter Kapazität proaktiv mithilfe einer Kubernetes-CapacityBuffer-CustomResourceDefinition (CRD) verwalten. Mit Kapazitätspuffern können Sie explizit eine bestimmte Menge an ungenutzter Knotenkapazität in Ihrem Cluster definieren. Diese reservierte Kapazität trägt dazu bei, die Pod-Planungszeit zu verkürzen.

Wenn eine Arbeitslast mit hoher Priorität schnell skaliert werden muss, kann die neue Arbeitslast die leere Kapazität sofort nutzen, ohne auf die Knotenbereitstellung warten zu müssen. Dieser Ansatz minimiert die Latenz und vermeidet Ressourcenkonflikte bei plötzlichen Nachfragespitzen.

Auf dieser Seite finden Sie Methoden zum Konfigurieren von Kapazitätspuffern: einen Puffer mit fester Anzahl von Replikaten, einen Puffer mit Ressourcenlimits und einen prozentualen Puffer.

Hinweis

Führen Sie die folgenden Aufgaben aus, bevor Sie beginnen:

  • Aktivieren Sie die Google Kubernetes Engine API.
  • Google Kubernetes Engine API aktivieren
  • Wenn Sie die Google Cloud CLI für diese Aufgabe verwenden möchten, müssen Sie die gcloud CLI installieren und dann initialisieren. Wenn Sie die gcloud CLI bereits installiert haben, rufen Sie die neueste Version mit dem Befehl gcloud components update ab. Ältere gcloud CLI-Versionen unterstützen möglicherweise nicht die Ausführung der Befehle in diesem Dokument.
  • Erstellen Sie einen GKE-Cluster, der die folgenden Versionsanforderungen erfüllt, oder sorgen Sie dafür, dass Sie auf einen solchen Cluster zugreifen können:
    • Verwenden Sie für aktive Puffer die Version 1.35.2-gke.1842000 oder höher auf Standard- und Autopilot-Clustern.
    • Verwenden Sie für Standby-Puffer die Version 1.36.0-gke.2253000 oder höher auf Standard-Clustern oder die Version 1.36.0-gke.2853000 oder höher auf Autopilot-Clustern mit benutzerdefinierten ComputeClasses.
  • Aktivieren Sie die automatische Erstellung von Knotenpools für Ihre Standardcluster. In Autopilot-Clustern ist die automatische Erstellung von Knotenpools bereits aktiviert. Die automatische Erstellung von Knotenpools ist für aktive Puffer optional, wird aber empfohlen. Für Standby-Puffer ist sie erforderlich.

Erforderliche Kubernetes-Objekte erstellen

Zum Konfigurieren eines CapacityBuffer benötigen Sie einen Namespace, der alle erforderlichen Objekte enthält (den CapacityBuffer selbst und zusätzliche Ressourcen wie ein PodTemplate oder eine Arbeitslast). Das PodTemplate und der CapacityBuffer müssen sich im selben Namespace befinden. Sie können einen Namespace erstellen oder einen vorhandenen Namespace verwenden, einschließlich des Namespace default.

Je nachdem, welchen Typ von CapacityBuffer Sie konfigurieren, benötigen Sie außerdem eine der folgenden Optionen:

  • PodTemplate: Definiert die Ressourcenanforderungen für eine einzelne Einheit der Pufferkapazität. Die im CapacityBuffer-Objekt angegebene Konfiguration verweist auf die Pod-Vorlage.
  • Arbeitslast: Eine vorhandene Arbeitslast, auf die Sie im CapacityBuffer-Objekt verweisen. In diesem Leitfaden wird ein Deployment-Objekt als Beispielarbeitslast verwendet. Kapazitätspuffer unterstützen jedoch alle folgenden Ressourcentypen:

    • Bereitstellung
    • ReplicaSet
    • StatefulSet
    • ReplicationController
    • Job
    • CustomResourceDefinitions (CRDs), die die Unterressource scale implementieren.

In diesem Abschnitt finden Sie Beispiele für diese Objekte. Wenn Sie bereits eine Arbeitslast haben, die Sie mit einem Kapazitätspuffer konfigurieren möchten, fahren Sie mit Kapazitätspuffer anwenden fort.

So erstellen Sie eine Kubernetes-Beispielarbeitslast:

  1. Speichern Sie das folgende Manifest als namespace.yaml:

    apiVersion: v1
    kind: Namespace
    metadata:
      name: capacity-buffer-example
      labels:
        name: capacity-buffer-example
    

    Mit diesem Manifest wird ein Namespace namens capacity-buffer-example erstellt.

  2. Optional: Wenn Sie Kapazitätspuffer mit einer benutzerdefinierten ComputeClass verwenden möchten, speichern Sie das folgende Manifest als custom-compute-class.yaml:

    apiVersion: cloud.google.com/v1
    kind: ComputeClass
    metadata:
      name: ccc-example
    spec:
      # Buffers are also created according to these priorities
      priorities:
      - machineFamily: n4
      - machineFamily: n4d
      - machineFamily: c4
      - machineFamily: c4d
      nodePoolAutoCreation:
        enabled: true
    

    Dieses Manifest erstellt eine benutzerdefinierte ComputeClass, die die Computing-Prioritäten für die von GKE bereitgestellten Knoten definiert und steuert. Weitere Informationen finden Sie unter Benutzerdefinierte ComputeClasses.

  3. Speichern Sie das folgende Manifest als buffer-pod-template.yaml:

    apiVersion: v1
    kind: PodTemplate
    metadata:
      name: buffer-unit-template
      namespace: capacity-buffer-example # the namespace must be the same namespace as the CapacityBuffer
    template:
      spec:
        terminationGracePeriodSeconds: 0
        containers:
        - name: buffer-container
          image: registry.k8s.io/pause:3.9
          resources:
            requests:
              cpu: "1"
              memory: "1Gi"
            limits:
              cpu: "1"
              memory: "1Gi"
        # Optional: Using buffers with a custom ComputeClass /
        # controls the properties of the provisioned nodes.
        nodeSelector:
          cloud.google.com/compute-class: ccc-example
    

    Mit diesem Manifest wird ein PodTemplate erstellt, das die Ressourcenanforderungen für eine einzelne Einheit der Pufferkapazität (1 CPU und 1Gi Arbeitsspeicher) definiert. Diese Konfiguration gibt die Größe der Kapazitätseinheiten an, die die GKE für den Zwischenspeicher bereitstellt. Mit dieser PodTemplate berücksichtigt GKE beispielsweise keine Knoten mit weniger als 1 CPU und 1 GiB verfügbaren Ressourcen als Teil des Puffers, wenn der Cluster hochskaliert wird.

  4. Speichern Sie das folgende Manifest als sample-workload-deployment.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: critical-workload-ref
      namespace: capacity-buffer-example # the namespace must be the same namespace as the CapacityBuffer
    spec:
      replicas: 10
      selector:
        matchLabels:
          app: critical-workload
      template:
        metadata:
          labels:
            app: critical-workload
        spec:
          containers:
          - name: busybox
            image: busybox
            command: ["sleep", "3600"]
            resources:
              requests:
                cpu: 100m
          # Optional: Using buffers with a custom ComputeClass /
          # controls the properties of the provisioned nodes.
          nodeSelector:
            cloud.google.com/compute-class: ccc-example
    

    Mit diesem Manifest wird ein Beispiel-Deployment mit 10 Replikaten erstellt. Es dient als Referenzobjekt für das Beispiel mit prozentualem Puffer im nächsten Abschnitt.

  5. Wenden Sie die Manifeste auf Ihren Cluster an:

    kubectl apply -f namespace.yaml -f custom-compute-class.yaml -f buffer-pod-template.yaml -f sample-workload-deployment.yaml
    
  6. Prüfen Sie, ob GKE die Objekte erstellt hat:

    kubectl get podtemplate -n capacity-buffer-example
    kubectl get deployment critical-workload-ref -n capacity-buffer-example
    

    Die Ausgabe sieht etwa so aus:

    NAME                   AGE
    buffer-unit-template   1m
    
    NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
    critical-workload-ref   10/10   10           10          1m
    

Kapazitätspuffer anwenden

In diesem Abschnitt finden Sie Beispiele für die verschiedenen Arten von Kapazitätspuffern, die Sie auf Ihre Arbeitslasten anwenden können.

Puffer mit fester Anzahl von Replikaten konfigurieren

Wenn Sie einen CapacityBuffer mit festen Replikaten konfigurieren, geben Sie die genaue Anzahl der Puffereinheiten an, die Sie basierend auf einem PodTemplate benötigen.

So erstellen Sie einen Puffer mit festen Replikaten:

  1. Speichern Sie das folgende Manifest als cb-fixed-replicas.yaml:

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityBuffer
    metadata:
      name: fixed-replica-buffer
      namespace: NAMESPACE
    spec:
      podTemplateRef:
        name: POD_TEMPLATE
      replicas: 3
      provisioningStrategy: "STRATEGY"
    

    Ersetzen Sie Folgendes:

    • NAMESPACE: Der Name Ihres Namespace, z. B. capacity-buffer-example.
    • POD_TEMPLATE: das PodTemplate, das Ihre Ressourcenanforderungen definiert, z. B. buffer-unit-template.
    • STRATEGY: die Bereitstellungsstrategie, entweder "buffer.x-k8s.io/active-capacity" (Standard) oder "buffer.gke.io/standby-capacity".

    Mit diesem Manifest wird eine CapacityBuffer-Ressource erstellt, die auf ein PodTemplate verweist, um eine bestimmte Anzahl von Puffereinheiten anzufordern.

  2. Wenden Sie das Manifest an:

    kubectl apply -f cb-fixed-replicas.yaml
    
  3. Prüfen Sie, ob GKE den Kapazitätspuffer angewendet hat:

    kubectl get capacitybuffer fixed-replica-buffer -n NAMESPACE
    

    Im Feld replicas im Status sollte 3 angezeigt werden. Das entspricht der Anzahl der Replikate, die Sie im Manifest definiert haben. Im Feld STATUS sollte ReadyForProvisioning angezeigt werden.

Puffer für Ressourcenlimits konfigurieren

Mit dem Feld limits können Sie eine maximale Menge an Ressourcen definieren, die der Puffer verbrauchen soll. Diese wird anhand der Größe Ihres PodTemplate berechnet.

So erstellen Sie einen Puffer für Ressourcenlimits:

  1. Speichern Sie das folgende Manifest als cb-resource-limits.yaml:

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityBuffer
    metadata:
      name: resource-limit-buffer
      namespace: NAMESPACE
    spec:
      podTemplateRef:
        name: POD_TEMPLATE
      limits:
        cpu: "5"
        memory: "5Gi"
      provisioningStrategy: "STRATEGY"
    

    Ersetzen Sie Folgendes:

    • NAMESPACE: Der Name Ihres Namespace, z. B. capacity-buffer-example.
    • POD_TEMPLATE: das PodTemplate, das Ihre Ressourcenanforderungen definiert, z. B. buffer-unit-template.
    • STRATEGY: die Bereitstellungsstrategie, entweder "buffer.x-k8s.io/active-capacity" (Standard) oder "buffer.gke.io/standby-capacity".

    Mit diesem Manifest wird eine CapacityBuffer-Ressource mit einem Gesamtlimit von 5 CPUs und 5 GiB Arbeitsspeicher erstellt. Wenn Sie das PodTemplate-Beispiel aus dem vorherigen Schritt verwenden, definieren Sie jede Einheit als 1 CPU und 1Gi Arbeitsspeicher, was zu 5 Puffereinheiten führen sollte.

  2. Wenden Sie das Manifest an:

    kubectl apply -f cb-resource-limits.yaml
    
  3. Prüfen Sie, ob GKE den Kapazitätspuffer angewendet hat:

    kubectl get capacitybuffer resource-limit-buffer -n NAMESPACE
    

    Prüfen Sie den CapacityBuffer-Status. Im Feld replicas sollte ein Wert angezeigt werden, der sich aus den von Ihnen definierten Limits ergibt. Wenn Sie das PodTemplate-Beispiel aus dem vorherigen Abschnitt verwenden, sollten 5 Puffereinheiten angezeigt werden, da dies die maximale Anzahl von Einheiten ist, die in die definierten Limits passen.

Prozentualen Puffer konfigurieren

Wenn Sie einen prozentualen Puffer konfigurieren, wird die Größe des Puffers dynamisch anhand eines Prozentsatzes einer vorhandenen skalierbaren Arbeitslast festgelegt. Prozentbasierte Kapazitätspuffer werden nur für skalierbare Kubernetes-Objekte unterstützt, die die Skalierungs-Unterressource implementieren, z. B. Deployments, StatefulSets, ReplicaSets oder Jobs. Sie können keinen prozentualen Puffer für Pod-Vorlagen definieren, da sie kein replicas-Feld haben.

In den meisten Fällen sollten Sie mit Strategien für feste Replikate oder Ressourcenlimits beginnen, anstatt prozentuale Puffer zu verwenden. Berücksichtigen Sie bei Ihrer Entscheidung Folgendes:

  • Prozentbasierte Puffer reagieren weniger auf plötzliche Skalierungen, wenn die Arbeitslast auf niedrige Zahlen oder null skaliert wird, da sich die Sicherheitsmarge proportional zu den aktiven Pods verringert.
  • Für Stand-by-Knoten fallen während der Initialisierungsphase vor dem Sperren Rechengebühren an. Die dynamische Skalierung von Standby-Zwischenspeichern bei schwankenden Arbeitslasten verschwendet Rechenressourcen. Verwenden Sie stattdessen feste Replikate oder Ressourcenlimits für Standby-Zwischenspeicher.
  • Prozentbasierte Puffer sind hauptsächlich für aktive Puffer in großen Bereitstellungen nützlich, die nie auf eine geringe Anzahl von Replikaten skaliert werden.

In GKE-Version 1.36.3-gke.1244000 und höher können Sie das Feld replicas zusammen mit dem Feld percentage festlegen, um eine Mindestpuffergröße beizubehalten, wenn die referenzierte Arbeitslast herunterskaliert wird. Die GKE verwendet das Feld, das zu mehr Puffereinheiten führt. Wenn Sie die Puffergröße begrenzen möchten, legen Sie auch das Feld limits fest.

Angenommen, Sie haben einen Puffer mit percentage: 20 und replicas: 3, der auf ein Deployment mit 10 Replikaten verweist. Da 20% von 10 Replikaten 2 sind, was kleiner als der replicas-Wert von 3 ist, stellt GKE 3 Puffereinheiten bereit. Wenn das Deployment auf 20 Replikate skaliert wird, wächst der Puffer auf 4 Einheiten. Weitere Informationen finden Sie in der Referenzdokumentation zu CapacityBuffer.

So erstellen Sie einen prozentualen Puffer:

  1. Speichern Sie das folgende Manifest als cb-percentage-based.yaml:

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityBuffer
    metadata:
      name: percentage-buffer
      namespace: NAMESPACE
    spec:
      scalableRef:
        apiGroup: apps
        kind: Deployment
        name: SCALABLE_RESOURCE_NAME
      percentage: 20
      provisioningStrategy: "STRATEGY"
    

    Ersetzen Sie Folgendes:

    • NAMESPACE: Der Name Ihres Namespace.
    • SCALABLE_RESOURCE_NAME: der Name Ihrer skalierbaren Ressource, z. B. critical-workload-ref.
    • STRATEGY: die Bereitstellungsstrategie, entweder "buffer.x-k8s.io/active-capacity" (Standard) oder "buffer.gke.io/standby-capacity".

    Mit diesem Manifest wird eine CapacityBuffer-Ressource erstellt, die eine Puffergröße anfordert, die 20 % der Replikate der referenzierten Ressource entspricht. Wenn Sie das Deployment-Beispiel aus dem vorherigen Abschnitt verwenden, ist der Replikatwert auf 10 festgelegt.

  2. Wenden Sie das Manifest an:

    kubectl apply -f cb-percentage-based.yaml
    
  3. Prüfen Sie, ob GKE den Kapazitätspuffer angewendet hat:

    kubectl get capacitybuffer percentage-buffer -n NAMESPACE
    

    Prüfen Sie den CapacityBuffer-Status. Im Feld replicas sollte ein Wert aus der Prozentberechnung angezeigt werden. Wenn Sie das Deployment-Beispiel aus dem vorherigen Abschnitt verwenden, sollten Sie 2 Puffereinheiten sehen. Das entspricht 20% der 10 Replikate, die im Deployment definiert sind.

  4. Testen Sie die dynamische Skalierung, indem Sie das Deployment manuell auf 20 Replikate skalieren:

    kubectl scale deployment critical-workload-ref -n NAMESPACE --replicas=20
    

    Der CapacityBuffer-Controller reagiert und skaliert den Zwischenspeicher automatisch auf 4 Replikate.

Verhalten des Stand-by-Puffers anpassen

Sie können Annotationen verwenden, um anzupassen, wie Standby-Puffer gestartet und aktualisiert werden. Fügen Sie dem Feld metadata.annotations Ihrer CapacityBuffer-Ressource die folgenden Annotationen hinzu:

  • buffer.gke.io/standby-capacity-init-time: die Zeit, die ein Knoten nach der Erstellung aktiv bleibt, bevor GKE ihn sperrt. Geben Sie einen Dauerstring wie 5m oder 1h an. Der Standardwert ist 5m.
  • buffer.gke.io/standby-capacity-refresh-frequency: wie oft GKE gesperrte Knoten aktualisiert. Geben Sie einen Dauerstring wie 12h oder 24h an. Der Standardwert ist 24h.

Das folgende Beispiel zeigt ein Manifest mit diesen optionalen Feldern, um das Verhalten von Stand-by-Puffern anzupassen:

apiVersion: autoscaling.x-k8s.io/v1beta1
kind: CapacityBuffer
metadata:
  name: customized-standby-buffer
  namespace: my-namespace
  annotations:
    buffer.gke.io/standby-capacity-init-time: "15m"
    buffer.gke.io/standby-capacity-refresh-frequency: "12h"
spec:
  podTemplateRef:
    name: buffer-unit-template
  replicas: 3
  provisioningStrategy: "buffer.gke.io/standby-capacity"

Bilder in Stand-by-Zwischenspeichern vorab laden

Wenn Sie die Startzeiten von Arbeitslasten beschleunigen möchten, wenn ein Stand-by-Knoten fortgesetzt wird, können Sie Container-Images mithilfe eines DaemonSets vorab laden. Das DaemonSet wird während der Startphase ausgeführt, bevor der Knoten gesperrt wird.

So laden Sie Images mithilfe des DaemonSets vorab:

  1. Speichern Sie das folgende Manifest als image-puller-daemonset.yaml:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: image-prefetch-daemonset
      namespace: NAMESPACE
    spec:
      selector:
        matchLabels:
          name: image-prefetch
      template:
        metadata:
          labels:
            name: image-prefetch
        spec:
          tolerations:
          - key: "buffer.gke.io/standby-capacity-node-suspended"
            operator: "Exists"
          initContainers:
          - name: image-puller
            image: IMAGE_NAME
            command: ["sh", "-c", "true"]
          containers:
          - name: pause
            image: registry.k8s.io/pause:3.9
    

    Ersetzen Sie Folgendes:

    • NAMESPACE: der Namespace für das DaemonSet, z. B. capacity-buffer-example.
    • IMAGE_NAME: der Name des vorab zu ladenden Images, z. B. your-app-image:latest.

    Dieses Manifest enthält die Toleranz buffer.gke.io/standby-capacity-node-suspended, damit das DaemonSet auf Stand-by-Knoten geplant bleibt, nachdem GKE sie gesperrt hat.

  2. Wenden Sie das DaemonSet-Manifest auf Ihren Cluster an:

    kubectl apply -f image-puller-daemonset.yaml
    
  3. Prüfen Sie, ob das DaemonSet erstellt wurde:

    kubectl get daemonset image-prefetch-daemonset -n NAMESPACE
    
  4. Prüfen Sie, ob der Kapazitätspuffer erstellt wurde und für die Bereitstellung bereit ist:

    kubectl get capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE
    

    Prüfen Sie den Status. Im Feld STATUS sollte ReadyForProvisioning angezeigt werden.

Status und Leistung des Kapazitätspuffers überwachen

Sie können den Status und Zustand Ihrer Kapazitätspuffer mithilfe von kubectl-Befehlen und Cloud Monitoring-Messwerten überwachen.

Status der CapacityBuffer-Ressource prüfen

So prüfen Sie den Zustand Ihrer Kapazitätspuffer und stellen fest, ob sie bereit sind, Arbeitslasten zu empfangen:

  1. Rufen Sie den Status aller Kapazitätspuffer im Cluster ab:

    kubectl get capacitybuffer -A
    
  2. Prüfen Sie den detaillierten Status, die Bedingungen und die Ereignisprotokolle eines bestimmten Puffers:

    kubectl describe capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE
    

Gesperrte Stand-by-Pufferknoten identifizieren

Standby-Puffer-VMs sind vorab bereitgestellt, werden aber in einem angehaltenen Zustand gehalten, um die Kosten zu senken. Sie erkennen diese gesperrten Knoten daran, dass sie eine benutzerdefinierte Bedingung haben. Führen Sie den folgenden Befehl aus, um gesperrte Knoteninstanzen zu prüfen:

kubectl get nodes -o custom-columns='NAME:.metadata.name,SUSPENDED:.status.conditions[?(@.type=="Suspended")].status'

Der Status True gibt an, dass eine Standby-VM gesperrt ist. Der Status False oder <none> gibt einen aktiven, laufenden Knoten an.

Leistung mit Cloud Monitoring überwachen

Wenn Sie die End-to-End-Auswirkungen von Kapazitätspuffern auf die Hochskalierungszeiten überwachen möchten, verwenden Sie die Dashboards für die Startlatenz in der Google Cloud Console. Verwenden Sie die Diagramme Verteilung der Pod-Startlatenz und Latenz der Pod-Bereitschaft, um den Messwert kubernetes.io/pod/latencies/pod_first_ready von der Pod-Erstellung bis zur Bereitschaft zu verfolgen. Sie können auch Scheduled-Ereignisse in Cloud Logging abfragen, um die Latenz der Pod-Planung zu messen. Eine Anleitung dazu finden Sie unter Messwerte zur Startlatenz überwachen.

Kapazitätspuffer entfernen

Wenn Sie keinen Kapazitätspuffer mehr für Ihre Arbeitslasten benötigen, löschen Sie das CapacityBuffer-Objekt. Dadurch werden die Platzhalter-Pods entfernt und Cluster Autoscaler kann die Knoten herunterskalieren.

kubectl delete capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE

Ersetzen Sie CAPACITY_BUFFER_NAME durch den Namen des CapacityBuffer, den Sie löschen möchten.

Fehlerbehebung

Der folgende Abschnitt enthält Informationen zur Behebung häufiger Probleme mit Kapazitätspuffern.

Kapazitätspuffer aufgrund des Abrechnungsmodells nicht bereit

Wenn Sie einen CapacityBuffer für eine Arbeitslast erstellen, die das Pod-basierte Abrechnungsmodell (Pay-per-Pod) verwendet, ist der Kapazitätspuffer nicht für die Bereitstellung bereit.

Prüfen Sie den CapacityBuffer-Status, um dieses Problem zu identifizieren:

kubectl describe capacitybuffer BUFFER_NAME -n NAMESPACE

Suchen Sie nach einer Bedingung vom Typ ReadyForProvisioning mit dem Status False.

Achten Sie zur Behebung dieses Problems darauf, dass Ihr CapacityBuffer auf eine Arbeitslast oder ein PodTemplate verweist, die bzw. das mit der knotenbasierten Abrechnung kompatibel ist.

Berechtigungsfehler für benutzerdefinierte skalierbare Ressourcen

Wenn Sie einen CapacityBuffer für die Verwendung mit benutzerdefinierten skalierbaren Objekten konfigurieren (mit dem Feld scalableRef), kann der Cluster Autoscaler den Puffer möglicherweise nicht skalieren, wenn die erforderlichen Berechtigungen fehlen. Dieses Problem tritt nur in GKE-Versionen vor 1.36.0-gke.2459000 auf.

Um dieses Problem zu beheben, weisen Sie die erforderlichen Berechtigungen manuell zu, indem Sie ein ClusterRole und ein ClusterRoleBinding erstellen, wie im folgenden Beispiel:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: custom-scale-getter
rules:
- apiGroups: ["api.example.com"]
  resources: ["customreplicatedresources/scale"]
  verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: ca-custom-scale-getter
subjects:
- kind: User
  name: "system:cluster-autoscaler"
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: custom-scale-getter

Weitere Informationen zum Konfigurieren von RBAC finden Sie in der Kubernetes-Dokumentation zu RBAC.

Puffer-Pods werden nicht auf Knoten geplant, die von benutzerdefinierten ComputeClasses bereitgestellt werden.

Wenn Ihre CapacityBuffer-Konfigurationsabhängigkeit (z. B. ein PodTemplate) eine benutzerdefinierte ComputeClass auswählt, kann es vorkommen, dass Puffer-Pods nicht auf den neu bereitgestellten Knoten geplant werden. Dieses Problem führt dazu, dass der Cluster Autoscaler wiederholt redundante Knotenpools und Knoten erstellt, während inaktive Knoten gelöscht werden.

Dieses Problem tritt auf, wenn die benutzerdefinierte ComputeClass Knoten mit Markierungen oder bestimmten Laufzeitanforderungen bereitstellt und Ihre Puffer-Pods (oder die PodTemplate, auf der sie basieren) keine übereinstimmenden Toleranzen oder Einstellungen haben.

Aktualisieren Sie Ihre CapacityBuffer-Konfiguration, um die erforderlichen Toleranzen, Knotenauswahlen oder Laufzeitklassen anzugeben, um dieses Problem zu beheben. Wenn Ihre Abhängigkeit beispielsweise eine benutzerdefinierte ComputeClass auswählt, die mit GKE Sandbox konfiguriert ist, aktualisieren Sie die Abhängigkeit, um eine der folgenden Aktionen auszuführen:

  • Geben Sie das Feld spec.runtimeClassName: gvisor an.
  • Fügen Sie eine explizite Toleranz für die Markierung sandbox.gke.io/runtime=gvisor:NoSchedule hinzu.

Weitere Informationen finden Sie in der Dokumentation zu benutzerdefinierten ComputeClasses.

Stand-by-Pufferknoten können nicht fortgesetzt werden

Gesperrte Stand-by-Pufferknoten können aus einem der folgenden Gründe möglicherweise nicht fortgesetzt werden:

  • Zum Fortsetzen eines gesperrten Standby-Knotens ist in der Zone für den Maschinentyp des Knotens und die spezifische CPU-Plattformgeneration, z. B. innerhalb der E2- oder N2-Maschinenserie, Compute Engine-Kapazität erforderlich. Wenn die Zone nicht genügend Rechenkapazität für diese genaue Konfiguration hat, kann der Knoten nicht fortgesetzt werden. Weitere Informationen finden Sie unter Einschränkungen beim Sperren und Fortsetzen von Compute Engine.
  • Wenn Ihre benutzerdefinierte ComputeClass die aktive Migration zu Knoten mit höherer Priorität (activeMigration.optimizeRulePriority: true) ermöglicht und Spot-VMs eine höhere Priorität als On-Demand-VMs zuweist, migriert die GKE On-Demand-Standby-Knoten im Laufe der Zeit zu Spot-VMs. Da Spot-VMs stärker von Kapazitätsbeschränkungen betroffen sind und gesperrte Spot-VMs beim Fortsetzen nicht in On-Demand-VMs umgewandelt werden können, können diese Einschränkungen verhindern, dass diese Standby-Knoten fortgesetzt werden.
  • Wenn Sie den Knoten fortsetzen, werden die Compute Engine-Kontingente Ihres Projekts überschritten. Weitere Informationen finden Sie unter Kapazitätspuffer kann aufgrund von Kontingentlimits nicht bereitgestellt werden.

Wenn Sie herausfinden möchten, warum ein Stand-by-Knoten nicht fortgesetzt werden konnte, fragen Sie die Compute Engine-Audit-Logs im Log-Explorer nach ZONE_RESOURCE_POOL_EXHAUSTED- oder QUOTA_EXCEEDED-Fehlern bei compute.instances.resume-Vorgängen ab.

Führen Sie einen oder mehrere der folgenden Schritte aus, um dieses Problem zu beheben oder zu minimieren:

  • Verwenden Sie regionale Cluster, damit Cluster Autoscaler Knoten in mehreren Zonen bereitstellen oder fortsetzen kann.
  • Konfigurieren Sie mehrere Maschinenfamilien in der Liste spec.priorities Ihrer benutzerdefinierten ComputeClass. Wenn gesperrte Knoten nicht fortgesetzt werden können, kann der Cluster Autoscaler auf das Erstellen neuer Knoten basierend auf einer anderen Prioritätsregel zurückgreifen. Es dauert länger, bis diese neuen Knoten bereit sind, als fortgesetzte Stand-by-Knoten. Diese Konfiguration hilft nicht, gesperrte Knoten fortzusetzen, da ein gesperrter Knoten nur mit seinem ursprünglichen Maschinentyp fortgesetzt werden kann.
  • Verwenden Sie eine dedizierte benutzerdefinierte ComputeClass mit On-Demand-VMs oder setzen Sie das Feld activeMigration.optimizeRulePriority für die ComputeClass, die Ihr Standby-Puffer verwendet, auf false.
  • Kombinieren Sie Ihren Standby-Puffer mit einem kleinen aktiven Puffer, um unmittelbare Traffic-Spitzen abzufangen.

Kapazitätspuffer kann aufgrund von Kontingentlimits nicht bereitgestellt werden

Ein Kapazitätspuffer stellt möglicherweise weniger Replikate als angefordert bereit oder kann nicht hochskaliert werden, wenn er die Kubernetes-ResourceQuotas oder Compute Engine-Kontingente überschreitet.

Prüfen Sie eines oder mehrere der folgenden Kontingente, um festzustellen, welches Kontingent den Puffer einschränkt:

  • Prüfen Sie, ob ein Kubernetes-ResourceQuota im Namespace den Puffer einschränkt:

    kubectl describe capacitybuffer \
        CAPACITY_BUFFER_NAME \
        -n NAMESPACE
    

    Suchen Sie in der Ausgabe von status.conditions nach einer LimitedByQuotas-Bedingung mit dem Status True. Sowohl aktive als auch Standby-Puffereinheiten, einschließlich Einheiten, die von gesperrten Standby-Knoten unterstützt werden, werden auf die ResourceQuota-Limits des Namespace angerechnet, als ob die Puffer-Pods ausgeführt würden. Wenn ein Puffer das Namespace-Kontingent überschreitet, begrenzt GKE das Feld status.replicas, damit es in das verfügbare Kontingent passt.

  • Prüfen Sie, ob Compute Engine-Projektkontingente die Knotenbereitstellung blockieren. Suchen Sie im Log-Explorer im Log container.googleapis.com/cluster-autoscaler-visibility nach no.scale.up.nap.quota.exceeded-Ereignissen oder in den Audit-Logs von Compute Engine nach QUOTA_EXCEEDED-Fehlern.

    Prüfen Sie beim Prüfen der Compute Engine-Kontingente für Stand-by-Puffer zusätzlich zu den vCPU- und Arbeitsspeicherkontingenten die beiden folgenden Kontingente:

    • Gesperrte Standby-Knoten behalten ihre internen und externen IP-Adressen bei, wodurch das Kontingent für verwendete IP-Adressen verbraucht wird.
    • Wenn Sie eine Standby-VM sperren, schreibt Compute Engine den Arbeitsspeicher des Knotens auf das Laufwerk. Dadurch wird Persistent disk standard (GB) Laufwerkskontingent proportional zur Arbeitsspeichergröße des Knotens verbraucht.

Führen Sie einen der folgenden Schritte aus, um das Kontingentlimit zu beheben:

DaemonSet-Pods empfangen keine Daten mehr, nachdem ein Stand-by-Knoten fortgesetzt wurde

Nachdem ein gesperrter Stand-by-Pufferknoten fortgesetzt wurde, empfangen DaemonSet-Pods auf diesem Knoten möglicherweise keine Daten mehr über langlebige Verbindungen, die vor dem Sperren des Knotens geöffnet wurden. Die Pods protokollieren keine Fehler und stellen keine Verbindung wieder her.

Dieses Problem tritt auf, wenn ein DaemonSet-Pod als Nur-Empfangs-Client fungiert, z. B. für eine HTTP-Streamingantwort, eine WebSocket-Verbindung, vom Server gesendete Ereignisse oder einen gRPC-Server-Streamingaufruf. Während der Stand-by-Knoten gesperrt ist, kommt es beim Server oder einem zwischengeschalteten Netzwerkgerät zu einer Zeitüberschreitung und die Verbindung wird geschlossen. Wenn der Knoten fortgesetzt wird, wird die Verbindung vom Netzwerkstack des Pods weiterhin als offen betrachtet. Da der Pod keine Daten sendet, erkennt er nie, dass die Verbindung geschlossen wurde, und wartet unbegrenzt auf Daten.

Konfigurieren Sie die Clientanwendung in Ihrem DaemonSet-Pod so, dass geschlossene Verbindungen erkannt und wiederhergestellt werden. Führen Sie dazu einen der folgenden Schritte aus:

  • Konfigurieren Sie clientseitiges TCP-Keepalive in der Anwendung Ihres Pods. Wenn Sie Keepalive nur auf dem Server aktivieren, wird der Pod nicht benachrichtigt. Weitere Informationen zu TCP-Keepalive-Parametern finden Sie unter Inaktive Verbindungen.
    1. Aktivieren Sie die Socket-Option SO_KEEPALIVE in Ihrer Clientbibliothek oder Sprachlaufzeit, z. B. socket.setKeepAlive(true, initialDelay) in Node.js oder net.Dialer.KeepAlive in Go. In einigen Laufzeiten ist TCP-Keepalive standardmäßig deaktiviert.
    2. Konfigurieren Sie eine kurze Keepalive-Inaktivitätszeit (TCP_KEEPIDLE), z. B. einige Sekunden, anstatt sich auf die Standardeinstellung des Betriebssystems zu verlassen.
    3. Aktualisieren Sie Ihre Anwendung, um den Verbindungsfehler (z. B. Zurücksetzen der Verbindung oder Zeitüberschreitung) abzufangen, wenn eine Keepalive-Prüfung fehlschlägt, und öffnen Sie eine neue Verbindung.
  • Konfigurieren Sie Heartbeats oder Zeitüberschreitungen beim Lesen auf Anwendungsebene in Ihrem Client, z. B. WebSocket-Ping- und Pong-Frames oder gRPC-Keepalive-Pings, und aktualisieren Sie Ihre Anwendung, damit sie bei einer Zeitüberschreitung die Verbindung wiederherstellt.

Nächste Schritte