Containernatives Load-Balancing über Ingress


Auf dieser Seite wird erläutert, wie Sie containernatives Load-Balancing in Google Kubernetes Engine (GKE) verwenden. Containernatives Load-Balancing ermöglicht es Load-Balancern, Pods direkt anzusteuern und Traffic gleichmäßig auf Pods zu verteilen.

Weitere Informationen zu den Vorteilen, Anforderungen und Einschränkungen des containernativen Load-Balancing finden Sie unter Containernatives Load-Balancing.

Hinweise

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 gcloud components update ab.

Containernatives Load-Balancing verwenden

In den folgenden Abschnitten werden Sie Schritt für Schritt durch die Konfiguration eines containernativen Load-Balancings in GKE geführt. Beachten Sie, dass für GKE-Cluster ab Version 1.17 und unter bestimmten Bedingungen containernatives Load-Balancing standardmäßig ist und keine explizite cloud.google.com/neg: '{"ingress": true}' Dienstannotation erfordert.

VPC-nativen Cluster erstellen

Damit das containernative Load-Balancing verwendet werden kann, müssen im GKE-Cluster Alias-IP-Adressen aktiviert sein.

Mit dem folgenden Befehl wird beispielsweise der GKE-Cluster neg-demo-cluster mit einem automatisch bereitgestellten Subnetzwerk erstellt:

  • Für den Autopilot-Modus sind Alias-IP-Adressen standardmäßig aktiviert:

    gcloud container clusters create-auto neg-demo-cluster \
        --location=COMPUTE_LOCATION
    

    Ersetzen Sie COMPUTE_LOCATION durch den Compute Engine-Standort für den Cluster.

  • Aktivieren Sie für den Standardmodus beim Erstellen des Clusters Alias-IP-Adressen:

    gcloud container clusters create neg-demo-cluster \
        --enable-ip-alias \
        --create-subnetwork="" \
        --network=default \
        --zone=us-central1-a
    

Deployment erstellen

Im folgenden Beispiel-Deployment (neg-demo-app) wird eine einzelne Instanz eines containerisierten HTTP-Servers ausgeführt. Wir empfehlen Ihnen, Arbeitslasten zu verwenden, bei denen Pod-Bereitschaftsfeedback zum Einsatz kommt.

Mithilfe von Pod-Bereitschaftsfeedback

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: neg-demo-app # Label for the Deployment
  name: neg-demo-app # Name of Deployment
spec:
  selector:
    matchLabels:
      run: neg-demo-app
  template: # Pod template
    metadata:
      labels:
        run: neg-demo-app # Labels Pods from this Deployment
    spec: # Pod specification; each Pod created by this Deployment has this specification
      containers:
      - image: registry.k8s.io/serve_hostname:v1.4 # Application to run in Deployment's Pods
        name: hostname # Container name
        ports:
        - containerPort: 9376
          protocol: TCP
  

Mithilfe von hartcodierter Verzögerung

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: neg-demo-app # Label for the Deployment
  name: neg-demo-app # Name of Deployment
spec:
  minReadySeconds: 60 # Number of seconds to wait after a Pod is created and its status is Ready
  selector:
    matchLabels:
      run: neg-demo-app
  template: # Pod template
    metadata:
      labels:
        run: neg-demo-app # Labels Pods from this Deployment
    spec: # Pod specification; each Pod created by this Deployment has this specification
      containers:
      - image: registry.k8s.io/serve_hostname:v1.4 # Application to run in Deployment's Pods
        name: hostname # Container name
      # Note: The following line is necessary only on clusters running GKE v1.11 and lower.
      # For details, see https://cloud.google.com/kubernetes-engine/docs/how-to/container-native-load-balancing#align_rollouts
        ports:
        - containerPort: 9376
          protocol: TCP
      terminationGracePeriodSeconds: 60 # Number of seconds to wait for connections to terminate before shutting down Pods
  

In diesem Deployment führt jeder Container einen HTTP-Server aus. Der HTTP-Server gibt den Hostnamen des Anwendungsservers (den Namen des Pods, auf dem der Server ausgeführt wird) als Antwort zurück.

Speichern Sie dieses Manifest als neg-demo-app.yaml und erstellen Sie dann das Deployment:

kubectl apply -f neg-demo-app.yaml

Dienst für einen containernativen Load Balancer erstellen

Nachdem Sie ein Deployment erstellt haben, müssen Sie die zugehörigen Pods in einem Dienst zusammenfassen.

Der folgende Beispieldienst neg-demo-svc zielt auf das im vorangegangenen Abschnitt erstellte Beispiel-Deployment ab:

apiVersion: v1
kind: Service
metadata:
  name: neg-demo-svc # Name of Service
  annotations:
    cloud.google.com/neg: '{"ingress": true}' # Creates a NEG after an Ingress is created
spec: # Service's specification
  type: ClusterIP
  selector:
    run: neg-demo-app # Selects Pods labelled run: neg-demo-app
  ports:
  - name: http
    port: 80 # Service's port
    protocol: TCP
    targetPort: 9376

Das containernative Load-Balancing wird mit der Annotation des Diensts (cloud.google.com/neg: '{"ingress": true}') aktiviert. Der Load-Balancer wird jedoch erst erstellt, wenn Sie für den Dienst eine Ingress-Ressource erstellen.

Speichern Sie dieses Manifest als neg-demo-svc.yaml und erstellen Sie dann den Dienst:

kubectl apply -f neg-demo-svc.yaml

Ingress für den Dienst erstellen

Die folgende exemplarische Ingress-Ressource neg-demo-ing steuert den von Ihnen erstellten Dienst an:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: neg-demo-ing
spec:
  defaultBackend:
    service:
      name: neg-demo-svc # Name of the Service targeted by the Ingress
      port:
        number: 80 # Should match the port used by the Service

Speichern Sie dieses Manifest als neg-demo-ing.yaml und erstellen Sie dann die Ingress-Ressource:

kubectl apply -f neg-demo-ing.yaml

Beim Erstellen der Ingress-Ressource wird im Projekt ein Application Load Balancer erstellt. Außerdem werden in jeder Zone, in der der Cluster ausgeführt wird, NEGs erstellt. Die Endpunkte in der NEG und die Endpunkte des Dienstes werden synchronisiert.

Ingress prüfen

Nachdem Sie eine Arbeitslast bereitgestellt, die Pods in einem Dienst zusammengefasst und eine Ingress-Ressource für den Dienst erstellt haben, sollten Sie prüfen, ob die Ingress-Ressource den containernativen Load-Balancer erfolgreich bereitgestellt hat.

Rufen Sie den Status des Ingress ab:

kubectl describe ingress neg-demo-ing

Die Ausgabe enthält die Ereignisse ADD und CREATE:

Events:
Type     Reason   Age                From                     Message
----     ------   ----               ----                     -------
Normal   ADD      16m                loadbalancer-controller  default/neg-demo-ing
Normal   Service  4s                 loadbalancer-controller  default backend set to neg-demo-svc:32524
Normal   CREATE   2s                 loadbalancer-controller  ip: 192.0.2.0

Load-Balancer testen

In den folgenden Abschnitten wird erläutert, wie Sie die Funktionalität eines containernativen Load-Balancers testen können.

Ingress-IP-Adresse aufrufen

Warten Sie einige Minuten, bis der Application Load Balancer konfiguriert ist.

Sie können die Funktion des containernativen Load-Balancers durch Aufruf der IP-Adresse des Ingress prüfen.

Führen Sie den folgenden Befehl aus, um die Ingress-IP-Adresse abzurufen:

kubectl get ingress neg-demo-ing

In der Befehlsausgabe wird die IP-Adresse des Ingress in der Spalte ADDRESS angezeigt. Rufen Sie in einem Webbrowser die IP-Adresse auf.

Systemstatus des Backend-Diensts prüfen

Sie können auch den Systemstatus des Backend-Diensts des Load-Balancers abrufen.

  1. Dazu müssen Sie zuerst eine Liste der Backend-Dienste abrufen, die in Ihrem Projekt ausgeführt werden:

    gcloud compute backend-services list
    

    Notieren Sie sich den Namen des Backend-Dienstes, der den Namen des Dienstes enthält, z B. neg-demo-svc.

  2. Dann rufen Sie den Systemstatus des Backend-Diensts ab:

    gcloud compute backend-services get-health BACKEND_SERVICE_NAME --global
    

    Ersetzen Sie BACKEND_SERVICE_NAME durch den Namen des Backend-Dienstes.

Ingress-Objekt testen

Eine weitere Möglichkeit, um zu testen, ob der Load Balancer wie erwartet funktioniert, besteht darin, das Beispiel-Deployment zu skalieren und Testanfragen an den Ingress zu senden. Anschließend überprüfen Sie, ob die Anzahl der Replikatantworten stimmt.

  1. Skalieren Sie das neg-demo-app-Deployment von einer Instanz auf zwei Instanzen:

    kubectl scale deployment neg-demo-app --replicas 2
    

    Die Ausführung dieses Befehls kann mehrere Minuten dauern.

  2. Prüfen Sie, ob die Einführung abgeschlossen ist:

    kubectl get deployment neg-demo-app
    

    Die Ausgabe sollte zwei verfügbare Replikate enthalten:

    NAME           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    neg-demo-app   2         2         2            2           26m
    
  3. Rufen Sie die Ingress-IP-Adresse ab:

    kubectl describe ingress neg-demo-ing
    

    Wenn dieser Befehl einen 404-Fehler zurückgibt, warten Sie einige Minuten, bis der Load Balancer gestartet wurde. Versuchen Sie es dann noch einmal.

  4. Zählen Sie die Anzahl unterschiedlicher Antworten vom Load Balancer:

    for i in `seq 1 100`; do \
      curl --connect-timeout 1 -s IP_ADDRESS && echo; \
    done  | sort | uniq -c
    

    Ersetzen Sie IP_ADDRESS durch die IP-Adresse der Ingress-Ressource.

    Die Ausgabe sieht in etwa so aus:

    44 neg-demo-app-7f7dfd7bc6-dcn95
    56 neg-demo-app-7f7dfd7bc6-jrmzf
    

    In dieser Ausgabe entspricht die Anzahl der unterschiedlichen Antworten der Anzahl der Replikate, was darauf hinweist, dass alle Backend-Pods Traffic verarbeiten.

Bereinigen

Wenn Sie mit den Aufgaben auf dieser Seite fertig sind, entfernen Sie die Ressourcen anhand der folgenden Schritte, sodass keine unerwünschten Kosten für Ihr Konto entstehen:

Cluster löschen

gcloud

gcloud container clusters delete neg-demo-cluster

Console

  1. Rufen Sie in der Google Cloud Console die Seite Google Kubernetes Engine auf.

    Zur Seite "Google Kubernetes Engine"

  2. Wählen Sie neg-demo-cluster aus und klicken Sie auf Löschen.

  3. Wenn Sie zur Bestätigung aufgefordert werden, klicken Sie auf Löschen.

Fehlerbehebung

Verwenden Sie die folgenden Methoden, um Ihre Netzwerkkonfiguration zu prüfen. In den folgenden Abschnitten wird erläutert, wie Sie spezifische Probleme im Zusammenhang mit containernativem Load-Balancing lösen.

  • Informationen zum Auflisten von Netzwerk-Endpunktgruppen finden Sie in der Dokumentation zum Load-Balancing.

  • Den Namen und die Zonen der NEG, die einem bestimmten Dienst entspricht, finden Sie in der neg-status-Annotation des Diensts. Rufen Sie die Dienstspezifikation mit folgendem Befehl ab:

    kubectl get svc SVC_NAME -o yaml
    

    In der metadata:annotations:cloud.google.com/neg-status-Annotation sind der Name der NEG des Diensts und die Zonen der NEG aufgelistet.

  • Mit dem folgenden Befehl können Sie den Status des Back-End-Diensts, der einer bestimmten NEG entspricht, prüfen:

    gcloud compute backend-services --project PROJECT_NAME \
        get-health BACKEND_SERVICE_NAME --global
    

    Der Back-End-Dienst trägt denselben Namen wie seine NEG.

  • So drucken Sie die Ereignislogs eines Diensts:

    kubectl describe svc SERVICE_NAME
    

    Der Namensstring des Diensts enthält den Namen und den Namespace des zugehörigen GKE-Diensts.

Cluster mit Alias-IP-Adressen kann nicht erstellt werden

Symptome

Wenn Sie einen Cluster mit Alias-IP-Adressen erstellen, wird möglicherweise der folgende Fehler ausgegeben:

ResponseError: code=400, message=IP aliases cannot be used with a legacy network.
Mögliche Ursachen

Dieser Fehler tritt auf, wenn der mit Alias-IP-Adressen zu erstellende Cluster auch ein Legacy-Netzwerk verwendet.

Lösung

Achten Sie darauf, dass Sie keinen Cluster mit Alias-IP-Adressen erstellen, für den gleichzeitig ein Legacy-Netzwerk aktiviert ist. Weitere Informationen zur Verwendung von Alias-IP-Adressen finden Sie unter VPC-nativen Cluster erstellen.

Traffic erreicht Endpunkte nicht

Symptome
502-Fehler oder abgelehnte Verbindungen
Mögliche Ursachen

Normalerweise sind neue Endpunkte erreichbar, nachdem sie dem Load-Balancer hinzugefügt wurden – sofern sie auf Systemdiagnosen reagieren. Wenn der Traffic die Endpunkte nicht erreicht, können 502-Fehler auftreten oder Verbindungen abgelehnt werden.

502-Fehler und abgelehnte Verbindungen können auch durch einen Container verursacht werden, der SIGTERM nicht verarbeitet. Wenn ein Container SIGTERM nicht explizit verarbeitet, wird er sofort beendet und verarbeitet keine Anfragen mehr. Der Load-Balancer sendet weiterhin eingehenden Traffic an den beendeten Container, was zu Fehlern führt.

Der native Container-Load-Balancer hat nur einen Back-End-Endpunkt. Während eines Rolling Updates wird der alte Endpunkt deprogrammiert, bevor der neue Endpunkt programmiert wird.

Back-End-Pods werden zum ersten Mal in einer neuen Zone bereitgestellt, nachdem ein containernativer Load-Balancer bereitgestellt wurde. Die Load-Balancer-Infrastruktur wird in einer Zone programmiert, wenn mindestens ein Endpunkt in der Zone vorhanden ist. Wenn ein neuer Endpunkt zu einer Zone hinzugefügt wird, wird die Infrastruktur des Load-Balancers programmiert und führt zu Dienstunterbrechungen.

Lösung

Konfigurieren Sie die Container so, dass sie SIGTERM verarbeiten und während des gesamten Kulanzzeitraums für die Beendigung, der standardmäßig 30 Sekunden beträgt, weiterhin auf Anfragen antworten. Konfigurieren Sie die Pods so, dass Systemdiagnosen fehlschlagen, wenn sie SIGTERM empfangen. Dies signalisiert dem Load-Balancer, dass er keinen Traffic mehr an den Pod senden soll, solange die Endpunkt-Deprogrammierung ausgeführt wird.

Wenn Ihre Anwendung nicht ordnungsgemäß heruntergefahren wird und nicht mehr auf Anfragen reagiert, wenn sie einen SIGTERM empfängt, kann der PreStop-Hook verwendet werden, um SIGTERM zu verarbeiten und den Traffic weiterhin weiterzuleiten, während die Endpunkt-Deprogrammierung ausgeführt wird.

lifecycle:
  preStop:
    exec:
      # if SIGTERM triggers a quick exit; keep serving traffic instead
      command: ["sleep","60"]

Weitere Informationen finden Sie in der Dokumentation zum Beenden von Pods.

Wenn das Back-End Ihres Load-Balancers nur eine Instanz hat, konfigurieren Sie die Rollout-Strategie so, dass nicht die einzige Instanz gelöscht wird, bevor die neue Instanz vollständig programmiert ist. Konfigurieren Sie bei Anwendungs-Pods, die von der Deployment-Arbeitslast verwaltet werden, die Rollout-Strategie so, dass der Parameter maxUnavailable dem Wert 0 entspricht.

strategy:
  rollingUpdate:
    maxSurge: 1
    maxUnavailable: 0

Um das Problem zu beheben, dass Traffic die Endpunkte nicht erreicht, prüfen Sie, ob die Firewallregeln eingehenden TCP-Traffic an die Endpunkte in den Bereichen 130.211.0.0/22 und 35.191.0.0/16 zulassen. Weitere Informationen finden Sie in der Dokumentation zu Cloud Load Balancing unter Systemdiagnosen erstellen.

Listen Sie die Backend-Dienste in Ihrem Projekt auf. Der Namensstring des relevanten Back-End-Dienstes enthält den Namen und den Namespace des zugehörigen GKE-Dienstes:

gcloud compute backend-services list

Rufen Sie den Back-End-Systemstatus aus dem Back-End-Dienst ab:

gcloud compute backend-services get-health BACKEND_SERVICE_NAME

Wenn alle Back-Ends fehlerhaft sind, ist Ihre Firewall, Ihre Ingress-Ressource oder Ihr Dienst möglicherweise falsch konfiguriert.

Wenn einige Back-Ends für kurze Zeit fehlerhaft sind, könnte dies auf Netzwerk-Programmierlatenz zurückzuführen sein.

Wenn einige Back-Ends nicht in der Liste der Back-End-Dienste aufgeführt werden, könnte dies auf Programmierlatenz zurückzuführen sein. Sie können dies mit folgendem Befehl überprüfen, wobei NEG_NAME der Name des Back-End-Diensts ist. NEGs und Back-End-Dienste haben denselben Namen:

gcloud compute network-endpoint-groups list-network-endpoints NEG_NAME

Prüfen Sie, ob alle erwarteten Endpunkte in der NEG enthalten sind.

Wenn Sie eine kleine Anzahl von Back-Ends (z. B. 1 Pod) haben, die von einem nativen Container-Load-Balancer ausgewählt werden, sollten Sie die Anzahl der Replikate erhöhen und die Back-End-Pods auf alle Zonen verteilen, die der GKE-Cluster umfasst. Dadurch wird die zugrunde liegende Load-Balancer-Infrastruktur vollständig programmiert. Andernfalls sollten Sie die Back-End-Pods auf eine einzelne Zone beschränken.

Wenn Sie eine Netzwerkrichtlinie für den Endpunkt konfigurieren, achten Sie darauf, dass eingehender Traffic aus dem Nur-Proxy-Subnetz zulässig ist.

Einführung wurde angehalten

Symptome
Die Einführung eines aktualisierten Deployments wird angehalten und die Anzahl der Replikate, die auf dem neuesten Stand sind, stimmt nicht mit der gewünschten Anzahl an aktualisierten Replikaten überein.
Mögliche Ursachen

Die Systemdiagnosen des Deployments können nicht ausgeführt werden. Möglicherweise ist das Container-Image fehlerhaft oder die Systemdiagnose falsch konfiguriert. Mit dem rollierenden Ersetzen der Pods wird gewartet, bis das Pod-Readiness-Gate des neu gestarteten Pods den Status "True" aufweist. Dies geschieht nur, wenn der Pod auf Load-Balancer-Systemdiagnosen reagiert. Wenn der Pod nicht reagiert oder die Systemdiagnose falsch konfiguriert ist, können die Bedingungen des Readiness-Gates nicht erfüllt werden und die Einführung kann nicht fortgesetzt werden.

Wenn Sie kubectl ab Version 1.13 verwenden, können Sie den Status der Readiness-Gates eines Pods mit dem folgenden Befehl prüfen:

kubectl get pod POD_NAME -o wide

Prüfen Sie die Spalte READINESS GATES.

Diese Spalte ist in kubectl bis zu Version 1.12 nicht vorhanden. Ein Pod, für den der Status READY angegeben wird, weist möglicherweise ein fehlgeschlagenes Readiness-Gate auf. Verwenden Sie den folgenden Befehl, um dies zu prüfen:

kubectl get pod POD_NAME -o yaml

Die Readiness-Gates und der Status der einzelnen Gates werden in der Ausgabe aufgeführt.

Lösung

Prüfen Sie, ob das in der Pod-Spezifikation Ihres Deployments genannte Container-Image richtig funktioniert und auf Systemdiagnosen reagieren kann. Prüfen Sie, ob die Systemdiagnosen korrekt konfiguriert sind.

Bekannte Probleme

Beim containernativen Load-Balancing in GKE treten die folgenden bekannten Probleme auf:

Unvollständige Speicherbereinigung

GKE-Speicherbereinigung führt alle zwei Minuten containernative Load-Balancer aus. Wenn ein Cluster gelöscht wird, bevor Load-Balancer vollständig entfernt wurden, müssen Sie die NEGs des Load-Balancers manuell löschen.

Führen Sie folgenden Befehl aus, um die NEGs in Ihrem Projekt aufzulisten:

gcloud compute network-endpoint-groups list

Suchen Sie in der Befehlsausgabe nach den relevanten NEGs.

Führen Sie zum Löschen einer NEG folgenden Befehl aus und ersetzen Sie dabei NEG_NAME durch den Namen der NEG:

gcloud compute network-endpoint-groups delete NEG_NAME

Arbeitslast-Rollouts auf Endpunktweitergabe abstimmen

Wenn Sie eine Arbeitslast in Ihrem Cluster bereitstellen oder eine vorhandene Arbeitslast aktualisieren, kann der containernative Load-Balancer zur Weitergabe neuer Endpunkte mehr Zeit benötigen als für das Arbeitslast-Rollout erforderlich ist. Das im Rahmen dieser Anleitung bereitgestellte Beispiel-Deployment verwendet zwei Felder, um seine Einführung auf die Weitergabe von Endpunkten abzustimmen: terminationGracePeriodSeconds und minReadySeconds

terminationGracePeriodSeconds ermöglicht, dass der Pod richtig heruntergefahren wird. Dafür wird auf das Beenden von Verbindungen gewartet, nachdem ein Pod zum Löschen vorgemerkt wurde.

Mit minReadySeconds wird nach dem Erstellen eines Pods eine Latenzzeit hinzugefügt. Sie sollten einen Mindestzeitraum in Sekunden angeben, in dem sich ein neuer Pod ohne Absturz eines zugehörigen Containers im Status Ready befinden muss, um als verfügbar angesehen zu werden.

Für Ihre Arbeitslasten sollten Sie die Werte von minReadySeconds und terminationGracePeriodSeconds auf mindestens 60 Sekunden festlegen, damit der Dienst nicht aufgrund von Arbeitslast-Einführungen unterbrochen wird.

terminationGracePeriodSeconds ist in allen Pod-Spezifikationen verfügbar und minReadySeconds ist für Deployments und DaemonSets verfügbar.

Weitere Informationen zur Feinabstimmung von Rollouts finden Sie unter RollingUpdateStrategy.

initialDelaySeconds in Pod readinessProbe nicht berücksichtigt

Man könnte erwarten, dass die Konfigurationseinstellung initialDelaySeconds in der readinessProbe des Pods vom containernativen Load-Balancer berücksichtigt wird. readinessProbe wird jedoch von kubelet implementiert und die Konfigurationseinstellung initialDelaySeconds steuert die kubelet-Systemdiagnose, nicht den containernativen Load-Balancer. Das containernative Load-Balancing hat eine eigene Systemdiagnose für das Load-Balancing.

Nächste Schritte