Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Multi-Cluster Load Balancing mit GKE einrichten

By StepanAug 17, 202010 min read

Diese Seite ist auch in English, Español, Français, Italiano, 日本語 und Português verfügbar.

Lernen Sie die Komponenten des GCP Load Balancing kennen und richten Sie Schritt für Schritt einen global verfügbaren GKE Multi-Cluster Load Balancer ein.

Eines meiner liebsten Features in GCP ist das externe HTTP(S) Load Balancing. Dabei handelt es sich um einen globalen Load Balancer, der Ihnen eine einzige Anycast-IP-Adresse bereitstellt – DNS-basiertes Load Balancing entfällt, ein Segen! Anfragen treffen das globale Google-Netzwerk an einem der Edge Points of Presence (POPs) in der Nähe des Nutzers¹ und werden zur nächstgelegenen Region mit freier Kapazität weitergereicht. Das Ergebnis: ein hochverfügbares, global verteiltes, skalierbares und vollständig verwaltetes Load-Balancing-Setup. Ergänzend lässt es sich mit DDoS- und WAF-Schutz durch Cloud Armor, Cloud CDN oder Identity-Aware Proxy (IAP) absichern, um den Zugriff auf Ihre Webanwendungen zu schützen.

Damit drängt sich Multi-Cluster Load Balancing mit GKE förmlich auf – und ist tatsächlich ein Thema, das unsere Kunden häufig umtreibt. Auch wenn es derzeit keine native Unterstützung in GKE/Kubernetes gibt,² stellt GCP alle nötigen Bausteine bereit, um es selbst aufzubauen.

Im ersten Teil machen wir uns mit den Komponenten des GCP Load Balancing vertraut. Wir verfolgen den Weg einer Anfrage durch das System und sehen uns an, wofür die einzelnen Bausteine stehen. Im zweiten Teil richten wir dann Schritt für Schritt Load Balancing über zwei GKE-Cluster hinweg ein.

GCP Load Balancing im Überblick

Abb. 1: GCP Load Balancing im Überblick

Beginnen wir mit einem groben Überblick über den Load-Balancing-Flow. Die HTTP(S)-Verbindung des Clients wird am Edge-Standort von Google Front Ends (GFEs)³ terminiert – auf Basis der Konfiguration von HTTP(S) Target Proxy und Forwarding Rule. Der Target Proxy zieht die zugehörigen Definitionen von URL Map und Backend Service heran, um zu entscheiden, wie der Traffic geroutet wird. Von den GFEs aus wird eine neue Verbindung aufgebaut; der Traffic fließt über das Google-Netzwerk zum nächstgelegenen, gesunden Backend mit freier Kapazität. Innerhalb der Region wird der Traffic anschließend entsprechend der Kapazität auf die einzelnen Backend Endpoints verteilt.

Komponenten des GCP Load Balancing

Abb. 2: Komponenten des GCP Load Balancing

  • Forwarding Rule — jede Regel ist mit einer bestimmten IP und einem bestimmten Port verknüpft. Da es um globales HTTP(S) Load Balancing geht, ist das eine globale Anycast-IP-Adresse (optional eine reservierte statische IP). Der zugehörige Port ist jener, auf dem der Load Balancer Traffic von externen Clients annimmt.⁴
  • Target HTTP(S) Proxy — der Traffic wird auf Basis der Target-Proxy-Konfiguration terminiert. Jeder Target Proxy ist mit genau einer URL Map verknüpft (N:1-Beziehung). Bei einem HTTPS Proxy müssen Sie zudem mindestens ein SSL-Zertifikat einbinden und eine SSL Policy konfigurieren.
  • URL Map — ist die zentrale Komponente für das Traffic Management und verteilt eingehenden Traffic auf verschiedene Backend Services (inkl. GCS Buckets). Das Basis-Routing erfolgt anhand von Hostname und Pfad, doch auch fortgeschrittenes Traffic Management ist möglich – etwa URL-Redirects, URL Rewriting sowie Routing auf Basis von Headern und Query-Parametern. Jede Regel leitet Traffic an genau einen Backend Service weiter.
  • Backend Service — ist eine logische Gruppierung von Backends für denselben Service samt zugehöriger Konfigurationsoptionen, etwa Traffic-Verteilung zwischen einzelnen Backends, Protokolle, Session Affinity oder Features wie Cloud CDN, Cloud Armor oder IAP. Jeder Backend Service ist außerdem mit einem Health Check verknüpft.
  • Health Check — bestimmt, wie einzelne Backend-Endpunkte auf Verfügbarkeit geprüft werden, und liefert daraus den Gesamtzustand jedes Backends. Beim Anlegen sind Protokoll und Port verpflichtend; hinzu kommen optionale Parameter wie Prüfintervall, Schwellenwerte für "healthy" und "unhealthy" oder Timeout. Wichtig: Es müssen Firewall-Regeln existieren, die Health-Check-Traffic aus bestimmten internen IP-Bereichen⁵ erlauben.
  • Backend — repräsentiert eine Gruppe einzelner Endpunkte an einem bestimmten Standort. Bei GKE sind unsere Backends Network Endpoint Groups (NEGs),⁶ jeweils eine pro Zone unseres GKE-Clusters (GKE-NEGs sind zonal, andere Backend-Typen hingegen regional).
  • Backend Endpoint — ist eine Kombination aus IP-Adresse und Port; bei GKE mit Container-native Load Balancing⁷ verweisen sie direkt auf einzelne Pods.

Setup

Wir richten Multi-Cluster Load Balancing für zwei Services ein – Foo und Bar – die über zwei Cluster verteilt sind (Abb. 3). Wir nutzen einfache pfadbasierte Regeln und routen jede Anfrage für /foo/* an Service Foo bzw. /bar/* an Service Bar.

Abb. 3: GKE Multi-Cluster Foo Bar

Voraussetzungen

git clone https://github.com/stepanstipl/gke-multi-cluster-native.gitcd gke-multi-cluster-native

Anwendungen und Services in den GKE-Clustern bereitstellen

Abb. 4: K8s Demo App

Beginnen wir damit, einfache Demo-Anwendungen in jedem Cluster auszurollen. Die Anwendung zeigt Details zum bedienenden Cluster und zur Region; den Quellcode finden Sie unter stepanstipl/k8s-demo-app.

Wiederholen Sie die folgenden Schritte für jeden Ihrer Cluster.

Credentials für kubectl abrufen

gcloud container clusters get-credentials [cluster] \
  --region [cluster-region]

Foo- und Bar-Anwendungen ausrollen

kubectl apply -f deploy-foo.yaml
kubectl apply -f deploy-bar.yaml

Mit kubectl get pods prüfen Sie, ob die Pods für beide Services laufen.

K8s-Services für beide Anwendungen anlegen

kubectl apply -f svc-foo.yaml kubectl apply -f svc-bar.yaml

Beachten Sie die Annotation cloud.google.com/neg: '{"exposed_ports": {"80":{}}}' auf den Services – sie weist GKE an, eine NEG für den Service zu erstellen.

Ob die Services korrekt eingerichtet sind, prüfen Sie, indem Sie einen lokalen Port mit kubectl port-forward service/foo 8888:80 weiterleiten und den Service unter http://localhost:8888/ aufrufen.

Vergessen Sie nicht, die obigen Schritte für alle Cluster zu wiederholen.

Load-Balancing-Komponenten (GCLB) einrichten

Health Check anlegen

gcloud compute health-checks create http health-check-foobar \
  --use-serving-port \
  --request-path="/healthz"

Backend Services anlegen

Legen Sie für jeden Service einen Backend Service an, plus einen weiteren als Default-Backend für Traffic, der keiner pfadbasierten Regel entspricht.

gcloud compute backend-services create backend-service-default \
  --globalgcloud compute backend-services create backend-service-foo \
  --global \
  --health-checks health-check-foobargcloud compute backend-services create backend-service-bar \
  --global \
  --health-checks health-check-foobar

URL Map anlegen

gcloud compute url-maps create foobar-url-map \
 --global \
 --default-service backend-service-default

Pfadregeln zur URL Map hinzufügen

gcloud compute url-maps add-path-matcher foobar-url-map \
  --global \
  --path-matcher-name=foo-bar-matcher \
  --default-service=backend-service-default \
  --backend-service-path-rules='/foo/*=backend-service-foo,/bar/*=backend-service-bar'

Statische IP-Adresse reservieren

gcloud compute addresses create foobar-ipv4 \
  --ip-version=IPV4 \
  --global

DNS einrichten

Lassen Sie Ihren DNS-Eintrag auf die zuvor reservierte statische IP-Adresse zeigen. Notieren Sie sich die angeforderte IP-Adresse:

gcloud compute addresses list --global

Erstellen Sie einen A-Record foobar.[your_domain_name], der auf diese IP verweist. Den Eintrag können Sie mit Cloud DNS oder einem beliebigen anderen Dienst verwalten. Dieser Schritt sollte abgeschlossen sein, bevor Sie weitermachen.¹⁰

Managed SSL-Zertifikat erstellen

gcloud beta compute ssl-certificates create foobar-cert \
 --domains "foobar.[your_domain_name]"

Target HTTPS Proxy erstellen

gcloud compute target-https-proxies create foobar-https-proxy \
  --ssl-certificates=foobar-cert \
  --url-map=foobar-url-map

Forwarding Rule erstellen

gcloud compute forwarding-rules create foobar-fw-rule \
  --target-https-proxy=foobar-https-proxy \
  --global \
  --ports=443 \
  --address=foobar-ipv4

TLS-Zertifikat verifizieren

Die Bereitstellung des Zertifikats kann eine Weile dauern. Den Status prüfen Sie mit:

gcloud beta compute ssl-certificates describe foobar-cert

Bei korrekter Einrichtung sollte managed.status innerhalb der nächsten 60 Minuten – meist deutlich früher – auf ACTIVE wechseln.

K8s-Services mit dem Load Balancer verbinden

Für jeden K8s-Service mit der Annotation cloud.google.com/neg hat GKE bereits NEGs angelegt. Diese NEGs müssen wir nun als Backends zu den entsprechenden Backend Services hinzufügen.

Namen der bereitgestellten NEGs abrufen

kubectl get svc \
  -o custom-columns='NAME:.metadata.name,NEG:.metadata.annotations.cloud\.google\.com/neg-status'

Notieren Sie sich Name und Zonen der NEG je Service.

Wiederholen Sie das für alle Ihre GKE-Cluster.

NEGs zu Backend Services hinzufügen

Wiederholen Sie das Folgende für jede NEG und Zone aus beiden Clustern. Verwenden Sie ausschließlich NEGs, die zum Foo-Service gehören.

gcloud compute backend-services add-backend backend-service-foo \
 --global \
 --network-endpoint-group [neg_name] \
 --network-endpoint-group-zone=[neg_zone] \
 --balancing-mode=RATE \
 --max-rate-per-endpoint=100

Und genauso für den Bar-Service – wieder für beide Cluster, jede NEG und jede Zone:

gcloud compute backend-services add-backend backend-service-bar \
 --global \
 --network-endpoint-group [neg_name] \
 --network-endpoint-group-zone=[neg_zone] \
 --balancing-mode=RATE \
 --max-rate-per-endpoint=100

GCLB-Traffic erlauben

gcloud compute firewall-rules create fw-allow-gclb \
  --network=[vpc_name] \
  --action=allow \
  --direction=ingress \
  --source-ranges=130.211.0.0/22,35.191.0.0/16 \
  --rules=tcp:8080

Prüfen, ob die Backends gesund sind

gcloud compute backend-services get-health \
  --global backend-service-foo gcloud compute backend-services get-health \
  --global backend-service-bar

Pro Backend Service sollten Sie typischerweise 6 Backends sehen (3 pro Cluster,¹¹ 1 pro Zone) mit healthState: HEALTHY. Nach dem Anlegen der Firewall-Regeln kann es einen Moment dauern, bis alle Backends als gesund erkannt werden.

Funktion testen

Rufen Sie Ihren DNS-Namen https://foobar.[your-domain] per curl auf (oder öffnen Sie ihn im Browser). Für den Root-Pfad sollten Sie ein 502 erhalten, da wir keine Backends für den Default Service hinterlegt haben.

curl -v "https://foobar.[your-domain]"

Rufen Sie nun die Pfade der einzelnen Services auf – https://foobar.[your-domain]/foo/ oder https://foobar.[your-domain]/bar/ – und Sie sollten 200 sowie Inhalte des entsprechenden Service erhalten.

curl -v "https://foobar.[your-domain]/foo/"
curl -v "https://foobar.[your-domain]/bar/"

Wenn Sie es mehrmals probieren, sollten Sie sehen, dass Traffic von verschiedenen Pods und Clustern bedient wird.¹²

Wenn Sie etwas Last simulieren – etwa mit einem meiner liebsten CLI-Tools, vegeta – lässt sich die Traffic-Verteilung über die Backends in der GCP Console schön beobachten. Gehen Sie zu Network services -> Load balancing -> wählen Sie Ihren Load Balancer aus -> Tab Monitoring, und wählen Sie das entsprechende Backend. Sie sollten ein Dashboard ähnlich Abb. 5 sehen.

Abb. 5: GKE Console — Load Balancing (beide Cluster lagen in derselben Region, daher wird der Traffic gleichmäßig auf alle Backends verteilt)

Jetzt ist ein guter Moment, um etwas zu experimentieren. Schauen Sie sich an, was passiert, wenn die Cluster in derselben Region liegen – und was, wenn sie in verschiedenen Regionen sind. Drehen Sie die Last hoch und beobachten Sie, wie Traffic in eine andere Region überläuft (Tipp: Erinnern Sie sich an das vorhin gesetzte --max-rate-per-endpoint?). Sehen Sie, was passiert, wenn Sie einen der Cluster offline nehmen. Und wie wäre es mit einem dritten Cluster im Mix?

(optional) `gke-autoneg-controller`

Beachten Sie die Annotation anthos.cft.dev/autoneg auf den K8s-Services. Für unser Setup ist sie nicht nötig, optional können Sie aber den gke-autoneg-controller ¹³ in Ihrem Cluster ausrollen, um die von GKE erstellten NEGs automatisch den passenden Backend Services zuzuordnen. Das erspart einiges an mühsamer Handarbeit.

Gut gemacht!

Das war's. Wir haben den Zweck der einzelnen GCLB-Komponenten erläutert und gezeigt, wie sich Multi-Cluster Load Balancing zwischen Services umsetzen lässt, die in zwei oder mehr GKE-Clustern in unterschiedlichen Regionen laufen. Für den produktiven Einsatz empfehle ich, dieses Setup mit einem Configuration-Management-Tool wie Terraform zu automatisieren.

Dieses Setup erhöht die Verfügbarkeit Ihres Service – mehrere unabhängige GKE-Cluster bedienen den Traffic – und senkt zugleich die Latenz. Bei HTTPS verkürzt sich die Time to First Byte, weil die initiale TLS-Aushandlung am GFE-Server in der Nähe des Nutzers stattfindet. Und mit mehreren Clustern wird die Anfrage vom jeweils nächstgelegenen Cluster bedient.

Sagen Sie mir gerne Bescheid, ob Sie das nützlich finden, und stellen Sie weitere Fragen – hier oder unter @stepanstipl. 🚀🚀🚀 Serve fast and prosper!

  • [1] Über 90 Standorte weltweit – Load Balancing — Locations und werden zur nächstgelegenen Region mit verfügbarer Kapazität weitergeleitet.
  • [2] Lassen wir Anthos vorerst außen vor. Anthos ist eine Plattform für Anwendungsmanagement, mit der sich K8s-Cluster on-prem und in anderen Clouds betreiben lassen und die zudem die Funktionalität von GKE-Clustern erweitert, inkl. Multi-Cluster Ingress Controller .)
  • [3] GFEs sind softwaredefinierte, skalierbare verteilte Systeme an Edge-POPs.
  • [4] Der Port kann 80 oder 8080 sein, wenn das Ziel ein HTTP Proxy ist, oder 443 bei einem HTTPS Proxy.
  • [5] Für External HTTP(S) Load Balancing sind das die Bereiche35.191.0.0/16 und130.211.0.0/22 .
  • [6] Network endpoint groups overview
  • [7] Container-native load balancing setzt einen Cluster im VPC-native Mode voraus und ermöglicht es Load Balancern, einzelne Pods direkt anzusteuern (statt der Cluster-Knoten).
  • [8] Cluster in unterschiedlichen Regionen sind interessanter.
  • [9] Alle in den Befehlen dieses Beitrags referenzierten Dateien beziehen sich auf das Root-Verzeichnis dieses Repositories.
  • [10] Der DNS-Eintrag muss bestehen, damit die Bereitstellung des von Google verwalteten SSL-Zertifikats funktioniert. Andernfalls kann das Zertifikat dauerhaft als fehlgeschlagen markiert werden (da die Certificate Authority es nicht signieren kann) und muss neu erstellt werden.
  • [11] Vorausgesetzt, Sie nutzen regionale Cluster, die jeweils auf drei Zonen verteilt sind – andernfalls passen Sie das entsprechend an.
  • [12] Liegen Ihre Cluster in verschiedenen Regionen, bedient GCLB den Traffic bevorzugt aus der dem Client nächstgelegenen Region – erwarten Sie also keine gleichmäßige Verteilung zwischen den Regionen.
  • [13] Auf Details zu Deployment und Nutzung gehe ich hier nicht ein – bitte folgen Sie der readme . Im Kern fügen Sie Ihrem Service eine Annotation mit dem Namen der NEG hinzu, z. B.anthos.cft.dev/autoneg: '{"name":"autoneg_test", "max_rate_per_endpoint":1000}'.