Fehlerbehebung beim Load-Balancing in GKE


Auf dieser Seite wird beschrieben, wie Sie Probleme im Zusammenhang mit dem Load-Balancing in Google Kubernetes Engine-Clustern (GKE) mithilfe von Dienst-, Ingress- oder Gateway-Ressourcen beheben.

BackendConfig wurde nicht gefunden

Dieser Fehler tritt auf, wenn in der Dienstannotation eine BackendConfig-Ressource für einen Dienstport angegeben wurde, die eigentliche BackendConfig-Ressource jedoch nicht gefunden werden konnte.

Führen Sie den folgenden Befehl aus, um ein Kubernetes-Ereignis auszuwerten:

kubectl get event

Die folgende Ausgabe zeigt an, dass Ihre BackendConfig nicht gefunden wurde:

KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: error getting BackendConfig for port 80 on service "default/my-service":
no BackendConfig for service port exists

Achten Sie zur Behebung dieses Problems darauf, dass Sie die BackendConfig-Ressource nicht im falschen Namespace erstellt oder ihren Verweis in der Dienstannotation falsch geschrieben haben.

Ingress-Sicherheitsrichtlinie nicht gefunden

Wenn die Sicherheitsrichtlinie nach der Erstellung des Ingress-Objekts nicht ordnungsgemäß dem Load-Balancer-Dienst zugeordnet wird, sollten Sie das Kubernetes-Ereignis auf Konfigurationsfehler prüfen. Wenn Ihre BackendConfig eine Sicherheitsrichtlinie angibt, die nicht vorhanden ist, wird regelmäßig ein Warnungsereignis ausgegeben.

Führen Sie den folgenden Befehl aus, um ein Kubernetes-Ereignis auszuwerten:

kubectl get event

Die folgende Ausgabe zeigt an, dass Ihre Sicherheitsrichtlinie nicht gefunden wurde:

KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: The given security policy "my-policy" does not exist.

Geben Sie zur Behebung dieses Problems den richtigen Namen der Sicherheitsrichtlinie in Ihrer BackendConfig an.

500er-Fehler bei NEGs während der Arbeitslastskalierung in GKE beheben

Symptom:

Wenn Sie von GKE bereitgestellte NEGs für das Load-Balancing verwenden, können während des Herunterskalierens der Arbeitslast 502- oder 503-Fehler für die Dienste auftreten. 502-Fehler treten auf, wenn Pods beendet werden, bevor vorhandene Verbindungen geschlossen werden. Die 503-Fehler treten auf, wenn Traffic an gelöschte Pods weitergeleitet wird.

Dieses Problem kann Cluster betreffen, wenn Sie in GKE verwaltete Load-Balancing-Produkte verwenden, die NEGs verwenden, einschließlich Gateway, Ingress und eigenständige NEGs. Wenn Sie Ihre Arbeitslasten häufig skalieren, besteht ein höheres Risiko, dass sie betroffen sind.

Diagnose:

Das Entfernen eines Pods in Kubernetes, ohne seinen Endpunkt zu leeren und ihn aus der NEG zu entfernen, führt zuerst zu 500-Fehlern der Reihe. Wenn Sie Probleme während der Beendigung des Pods vermeiden möchten, müssen Sie die Reihenfolge der Vorgänge berücksichtigen. Die folgenden Images zeigen Szenarien, wenn BackendService Drain Timeout nicht festgelegt und BackendService Drain Timeout mit BackendConfig festgelegt ist.

Szenario 1: BackendService Drain Timeout ist nicht festgelegt.

Die folgende Abbildung zeigt ein Szenario, in dem BackendService Drain Timeout nicht festgelegt ist.

Zeitlimit für BackendService-Drain wird nicht festgelegt

Szenario 2: BackendService Drain Timeout ist festgelegt.

In der folgenden Abbildung sehen Sie ein Szenario, in dem BackendService Drain Timeout festgelegt wird.

Zeitlimit für Back-End-Drain-Wert ist festgelegt

Die genaue Zeit, zu der die 500-Fehler auftreten, hängt von folgenden Faktoren ab:

  • NEG API-Trennlatenz: Die Trennungslatenz der NEG API stellt die aktuelle Zeit dar, die für den Abschluss des Trennvorgangs in Google Cloud benötigt wurde. Dies wird durch verschiedene Faktoren außerhalb von Kubernetes beeinflusst, einschließlich des Typs des Load-Balancers und der jeweiligen Zone.

  • Drain-Latenz: Die Drain-Latenz stellt die Zeit dar, die für das Load-Balancing benötigt wird, um Traffic von einem bestimmten Teil Ihres Systems wegzuleiten. Nachdem der Drain-Vorgang initiiert wurde, sendet der Load-Balancer keine neuen Anfragen mehr an den Endpunkt. Es gibt jedoch immer noch eine Latenz beim Auslösen des Drain-Vorgangs (Drain-Latenz), was zu einem vorübergehenden 503-Fehler führen kann, wenn der Pod nicht mehr vorhanden ist. eine

  • Konfiguration der Systemdiagnose: Schwellenwerte für sensible Systemdiagnosen reduzieren die Dauer von 503-Fehlern, da sie dem Load-Balancer signalisieren können, keine Anfragen mehr an Endpunkte zu senden, auch wenn der Trennvorgang nicht abgeschlossen ist.

  • Kulanzzeitraum für die Beendigung: Der Kulanzzeitraum für die Beendigung bestimmt die maximale Zeit, die ein Pod zum Beenden gewährt wird. Ein Pod kann jedoch beendet werden, bevor der Kulanzzeitraum für die Beendigung abgeschlossen ist. Wenn ein Pod länger als dieser Zeitraum dauert, wird der Pod zum Ende dieses Zeitraums gezwungen. Dies ist eine Einstellung für den Pod und muss in der Arbeitslastdefinition konfiguriert werden.

Mögliche Lösung:

Wenden Sie die folgenden Einstellungen an, um diese 5XX-Fehler zu vermeiden. Die Zeitüberschreitungswerte sind aussagekräftig und Sie müssen sie möglicherweise für Ihre spezifische Anwendung anpassen. Der folgende Abschnitt führt Sie durch den Anpassungsprozess.

Die folgende Abbildung zeigt, wie der Pod mit preStopHook aktiv bleibt:

Zeitlimit für Back-End-Drain-Wert ist festgelegt

Führen Sie die folgenden Schritte aus, um Fehler aufgrund von 500 Serien zu vermeiden:

  1. Legen Sie BackendService Drain Timeout für Ihren Dienst auf 1 Minute fest.

  2. Erweitern Sie terminationGracePeriod auf dem Pod.

    Legen Sie terminationGracePeriodSeconds auf dem Pod auf 3,5 Minuten fest. In Kombination mit den empfohlenen Einstellungen hat Ihr Pod 30 bis 45 Sekunden Zeit für ein ordnungsgemäßes Herunterfahren, nachdem der Endpunkt des Pods aus der NEG entfernt wurde. Wenn Sie mehr Zeit für das ordnungsgemäße Herunterfahren benötigen, können Sie den Kulanzzeitraum verlängern oder der Anleitung im Abschnitt Zeitüberschreitungen anpassen folgen.

    Das folgende BackendConfig-Manifest gibt ein Zeitlimit für den Verbindungsausgleich von 210 Sekunden (3,5 Minuten) an:

    apiVersion: v1
    kind: BackendConfig
    metadata:
      name: my-backendconfig
    spec:
      terminationGracePeriodSeconds: 210
      containers:
      - name: my-app
        image: my-app-image:latest
        ports:
        - containerPort: 80
    
  3. Wenden Sie ein preStopHook auf alle Container an.

    Wenden Sie eine preStopHook an, die dafür sorgt, dass der Pod 120 Sekunden länger aktiv ist, während der Endpunkt des Pods im Load-Balancer per Drain beendet wird und der Endpunkt aus der NEG entfernt wird.

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
      - name: my-app
        # Container configuration details...
        lifecycle:
          preStop:
            exec:
              command: ["/bin/sh", "-c", "sleep 120s"]
    

Zeitlimits anpassen

Zur Gewährleistung der Pod-Kontinuität und zur Vermeidung von 500-Fehlern der Reihe muss der Pod aktiv sein, bis der Endpunkt aus der NEG entfernt wird. Insbesondere zur Vermeidung von 502- und 503-Fehlern sollten Sie eine Kombination aus Zeitüberschreitungen und einem preStopHook implementieren.

Fügen Sie dem Pod einen preStopHook hinzu, um den Pod während des Herunterfahrens länger aktiv zu lassen. Führen Sie den preStopHook aus, bevor ein Pod zum Beenden des Signals signalisiert wird. Damit kann preStopHook den Pod so lange behalten, bis der entsprechende Endpunkt aus der NEG entfernt wird.

Um die Dauer zu verlängern, die ein Pod während des Herunterfahrens aktiv bleibt, fügen Sie einen preStopHook in die Pod-Konfiguration ein:

spec:
  containers:
  - name: my-app
    ...
    lifecycle:
      preStopHook:
        exec:
          command: ["/bin/sh", "-c", "sleep <latency time>"]

Sie können Zeitlimits und zugehörige Einstellungen konfigurieren, um das ordnungsgemäße Herunterfahren von Pods während des Herunterskalierens von Arbeitslasten zu verwalten. Sie können Zeitlimits anhand bestimmter Anwendungsfälle anpassen. Wir empfehlen, mit längeren Zeitüberschreitungen zu beginnen und die Dauer nach Bedarf zu reduzieren. Sie können die Zeitlimits anpassen, indem Sie Zeitparameter und die preStopHook auf folgende Weise konfigurieren:

Zeitlimit für Back-End-Dienst-Drain

Der Parameter Backend Service Drain Timeout ist standardmäßig nicht festgelegt und hat keine Auswirkungen. Wenn Sie den Parameter Backend Service Drain Timeout festlegen und aktivieren, beendet der Load-Balancer die Weiterleitung neuer Anfragen an den Endpunkt und wartet das Zeitlimit, bevor vorhandene Verbindungen beendet werden.

Sie können den Parameter Backend Service Drain Timeout mit BackendConfig mit Ingress, GCPBackendPolicy mit Gateway oder manuell auf dem BackendService mit eigenständigen NEGs festlegen. eine Das Zeitlimit sollte 1,5- bis 2-mal länger sein als die Zeit für die Verarbeitung einer Anfrage. Dadurch wird sichergestellt, dass eine Anfrage direkt vor dem Start des Drains eingegangen ist, bevor sie abgeschlossen ist. Wenn Sie den Parameter Backend Service Drain Timeout auf einen Wert größer als 0 setzen, werden 503-Fehler minimiert, da keine neuen Anfragen an Endpunkte gesendet werden, die zum Entfernen vorgemerkt sind. Damit dieses Zeitlimit wirksam ist, müssen Sie es in Verbindung mit preStopHook verwenden. So bleibt der Pod während des Verbindungsausgleichs aktiv. Ohne diese Kombination erhalten vorhandene Anfragen, die nicht abgeschlossen wurden, den Fehler 502.

Zeit preStopHook

Der preStopHook muss das Herunterfahren des Pods ausreichend verzögern, damit die Drain-Latenz und das Zeitlimit für den Drain-Dienst-Drain vollständig abgeschlossen werden, um einen ordnungsgemäßen Verbindungsausgleich und die Entfernung des Endpunkts aus der NEG zu gewährleisten, bevor der Pod heruntergefahren wird.

Achten Sie für optimale Ergebnisse darauf, dass die Ausführungszeit von preStopHook kleiner oder gleich der Summe von Backend Service Drain Timeout und der Drain-Latenz ist.

Der Wert kann so berechnet werden:

preStopHook >= Backend Service Drain Timeout + Drain Latency

Wir empfehlen, die Drain-Latenz auf 1 Minute festzulegen. Wenn 500-Fehler bestehen bleiben, schätzen Sie die Gesamtdauer des Vorkommens und fügen Sie der Latenz das Doppelte hinzu. Dadurch wird sichergestellt, dass der Pod ausreichend Zeit zum ordnungsgemäßen Leeren hat, bevor er aus dem Dienst entfernt wird. Sie können diesen Wert anpassen, wenn er für Ihren spezifischen Anwendungsfall zu lang ist.

Alternativ können Sie den Zeitpunkt schätzen, indem Sie den Löschzeitstempel vom Pod und den Zeitstempel für die Entfernung des Endpunkts aus der NEG in den Cloud-Audit-Logs untersuchen.

Parameter für den Kulanzzeitraum für die Beendigung

Sie müssen den Parameter terminationGracePeriod so konfigurieren, dass ausreichend Zeit für den Abschluss des preStopHook und für das ordnungsgemäße Herunterfahren des Pods bleibt.

Wenn nicht explizit festgelegt, beträgt der terminationGracePeriod standardmäßig 30 Sekunden. Sie können den optimalen terminationGracePeriod mit der folgenden Formel berechnen:

terminationGracePeriod >= preStopHook Time + Pod shutdown time

So definieren Sie terminationGracePeriod in der Pod-Konfiguration so:

  spec:
    terminationGracePeriodSeconds: <terminationGracePeriod>
    containers:
    - name: my-app
      ...
    ...

NEG beim Erstellen einer internen Ingress-Ressource nicht gefunden

Der folgende Fehler kann auftreten, wenn Sie ein internes Ingress in GKE erstellen:

Error syncing: error running backend syncing routine: googleapi: Error 404: The resource 'projects/PROJECT_ID/zones/ZONE/networkEndpointGroups/NEG' was not found, notFound

Dieser Fehler tritt auf, weil Ingress für interne Anwendungs-Load-Balancer Netzwerk-Endpunktgruppen (NEGs) als Back-Ends erfordert.

In Umgebungen mit freigegebener VPC oder Clustern mit aktivierten Netzwerkrichtlinien müssen Sie die Annotation cloud.google.com/neg: '{"ingress": true}' dem Servicemanifest hinzufügen.

504 Gateway-Zeitüberschreitung: Upstream-Zeitüberschreitung bei Anfrage

Der folgende Fehler kann auftreten, wenn Sie über einen internen Ingress in GKE auf einen Dienst zugreifen:

HTTP/1.1 504 Gateway Timeout
content-length: 24
content-type: text/plain

upsteam request timeout

Dieser Fehler tritt auf, weil Traffic, der an interne Anwendungs-Load-Balancer gesendet wird, von Envoy-Proxys im Nur-Proxy-Subnetzbereich weitergeleitet wird.

Sie müssen eine Firewallregel erstellen, um Traffic aus dem Nur-Proxy-Subnetzbereich des targetPort des Dienstes zuzulassen.

Fehler 400: Ungültiger Wert für das Feld "resource.target"

Der folgende Fehler kann auftreten, wenn Sie über einen internen Ingress in GKE auf einen Dienst zugreifen:

Error syncing:LB_NAME does not exist: googleapi: Error 400: Invalid value for field 'resource.target': 'https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION_NAME/targetHttpProxies/LB_NAME. A reserved and active subnetwork is required in the same region and VPC as the forwarding rule.

Stellen Sie ein Nur-Proxy-Subnetz bereit, um dieses Problem zu beheben.

Fehler während der Synchronisierung: Fehler beim Ausführen der Synchronisierungsroutine des Load-Balancers: Load-Balancer existiert nicht

Einer der folgenden Fehler kann auftreten, wenn die GKE-Steuerungsebene aktualisiert wird oder Sie ein Ingress-Objekt ändern:

"Error during sync: error running load balancer syncing routine: loadbalancer
INGRESS_NAME does not exist: invalid ingress frontend configuration, please
check your usage of the 'kubernetes.io/ingress.allow-http' annotation."
Error during sync: error running load balancer syncing routine: loadbalancer LOAD_BALANCER_NAME does not exist:
googleapi: Error 400: Invalid value for field 'resource.IPAddress':'INGRESS_VIP'. Specified IP address is in-use and would result in a conflict., invalid

Versuchen Sie Folgendes, um diese Fehler zu beheben:

  • Fügen Sie das Feld hosts im Abschnitt tls des Ingress-Manifests hinzu und löschen Sie dann das Ingress-Objekt. Warten Sie fünf Minuten, bis GKE die nicht verwendeten Ingress-Ressourcen gelöscht hat. Erstellen Sie dann das Ingress neu. Weitere Informationen finden Sie unter Feld „Hosts“ eines Ingress-Objekts.
  • Setzen Sie die Änderungen zurück, die Sie am Ingress-Objekt vorgenommen haben. Fügen Sie dann ein Zertifikat mit einer Annotation oder einem Kubernetes-Secret hinzu.

Externer Ingress erzeugt HTTP-502-Fehler

Folgen Sie der nachstehenden Anleitung, um HTTP-502-Fehler mit externen Ingress-Ressourcen zu beheben:

  1. Aktivieren Sie Logs für jeden Backend-Dienst, der jedem GKE-Dienst zugeordnet ist, auf den der Ingress verweist.
  2. Verwenden Sie Statusdetails, um Ursachen für HTTP-502-Antworten zu identifizieren. Statusdetails, die angeben, dass die HTTP-502-Antwort vom Backend stammt, erfordern eine Fehlerbehebung innerhalb der Bereitstellungs-Pods, nicht im Load-Balancer.

Nicht verwaltete Instanzgruppen

Es können HTTP-502-Fehler mit externen Ingress-Ressourcen auftreten, wenn Ihr externes Ingress nicht verwaltete Instanzgruppen-Back-Ends verwendet. Dieses Problem tritt auf, wenn alle der folgenden Bedingungen erfüllt sind:

  • Der Cluster hat eine große Gesamtzahl von Knoten unter allen Knotenpools.
  • Die Bereitstellungs-Pods für einen oder mehrere Services, auf die vom Ingress verwiesen wird, befinden sich nur auf wenigen Knoten.
  • Dienste, auf die vom Ingress verwiesen wird, verwenden externalTrafficPolicy: Local.

So ermitteln Sie, ob Ihr externes Ingress nicht verwaltete Instanzgruppen-Back-Ends verwendet:

  1. Rufen Sie in der Google Cloud Console die Seite Ingress auf:

    Zum Ingress

  2. Klicken Sie auf den Namen Ihres externen Ingress.

  3. Klicken Sie auf den Namen des Load-Balancers. Die Seite Details zum Load-Balancing wird angezeigt.

  4. Prüfen Sie in der Tabelle im Abschnitt Backend-Dienste, ob Ihr externes Ingress NEGs oder Instanzgruppen verwendet.

Verwenden Sie eine der folgenden Lösungen, um dieses Problem zu beheben.

  • Verwenden Sie einen VPC-nativen Cluster.
  • Verwenden Sie externalTrafficPolicy: Cluster für jeden Service, auf den der externe Ingress verweist. Bei dieser Lösung gehen die ursprüngliche Client-IP-Adresse in den Quellen des Pakets verloren.
  • Verwenden Sie die Annotation node.kubernetes.io/exclude-from-external-load-balancers=true. Fügen Sie den Knoten oder Knotenpools, die keinen Bereitstellungs-Pod ausführen, die Annotation für einen Dienst hinzu, auf den von einem externen Ingress- oder LoadBalancer-Dienst in Ihrem Cluster verwiesen wird.

Load-Balancer-Logs zur Fehlerbehebung verwenden

Sie können Logs von internen Passthrough-Netzwerk-Load-Balancers und Logs von externen Passthrough-Netzwerk-Load-Balancer dazu verwenden, Probleme mit Load-Balancern zu beheben und Traffic von Load-Balancern mit GKE-Ressourcen zu korrelieren.

Logs werden pro Verbindung zusammengefasst und nahezu in Echtzeit exportiert. Logs werden sowohl für eingehenden als auch für ausgehenden Traffic für jeden GKE-Knoten generiert, der am Datenpfad eines LoadBalancer-Dienstes beteiligt ist. Logeinträge umfassen zusätzliche Felder für GKE-Ressourcen, z. B.: – Clustername – Clusterstandort – Dienstname – Dienstname – Pod-Name – Pod-Namespace

Preise

Für die Verwendung von Logs fallen keine zusätzlichen Gebühren an. Je nachdem, wie Sie Logs aufnehmen, gelten die Standardpreise für Cloud Logging, BigQuery oder Pub/Sub. Das Aktivieren von Logs hat keine Auswirkungen auf die Leistung des Load-Balancers.

Diagnosetools zur Fehlerbehebung verwenden

Das Diagnosetool check-gke-ingress prüft Ingress-Ressourcen auf häufige Fehlkonfigurationen. Sie können das check-gke-ingress-Tool so verwenden:

  • Das gcpdiag-Befehlszeilentool auf Ihrem Cluster ausführen. Die Ergebnisse des eingehenden Traffics werden im Abschnitt gke/ERR/2023_004 der Prüfregel angezeigt.
  • Verwenden Sie das check-gke-ingress-Tool allein oder als kubectl-Plug-in. Folgen Sie dazu der Anleitung unter check-gke-ingress.