Découvrez les composants de GCP Load Balancing et apprenez, pas à pas, à configurer un load balancer multi-cluster GKE accessible mondialement.

L'une des fonctionnalités que je préfère sur GCP, c'est le HTTP(S) Load Balancing externe. Il s'agit d'un load balancer global qui vous donne une seule adresse IP anycast (sans DNS load balancing, et c'est tant mieux !). Les requêtes entrent dans le réseau global de Google par l'un des points de présence (POPs) en bordure les plus proches de l'utilisateur,¹ puis sont relayées vers la région la plus proche disposant de capacité disponible. Résultat : un load balancing hautement disponible, distribué mondialement, scalable et entièrement managé. On peut encore le renforcer avec Cloud Armor (protection DDoS et WAF), Cloud CDN ou Identity-Aware Proxy (IAP) pour sécuriser l'accès à vos applications web.

Cela fait immédiatement penser au load balancing multi-cluster avec GKE, un sujet qui revient souvent chez nos clients. Et même s'il n'existe pas pour l'instant de support natif dans GKE/Kubernetes,² GCP fournit toutes les briques nécessaires pour le mettre en place soi-même.
Dans une première partie, familiarisons-nous avec les composants de GCP Load Balancing. Nous allons suivre le parcours d'une requête lorsqu'elle entre dans le système et comprendre ce que représente chacune des briques du load balancing. Dans la seconde partie, nous configurerons pas à pas le load balancing entre deux clusters GKE.
Vue d'ensemble de GCP Load Balancing

Fig. 1 : Vue d'ensemble de GCP Load Balancing
Commençons par une vue d'ensemble du flux de Load Balancing. La connexion HTTP(S) du client est terminée en bordure de réseau par les Google Front Ends (GFEs),³ selon la configuration du Target Proxy HTTP(S) et de la Forwarding Rule. Le Target Proxy consulte ensuite l'URL Map et les définitions de Backend Service associées pour décider du routage du trafic. Depuis les GFEs, une nouvelle connexion est établie et le trafic transite par le réseau Google jusqu'au Backend sain le plus proche disposant de capacité. À l'intérieur de la région, le trafic est ensuite réparti entre les différents Backend Endpoints en fonction de leur capacité.
Composants de GCP Load Balancing

Fig. 2 : Composants de GCP Load Balancing
- Forwarding Rule — chaque règle est associée à une IP et à un port spécifiques. Puisqu'il s'agit ici de HTTP(S) load balancing global, ce sera une adresse IP anycast globale (éventuellement une IP statique réservée). Le port associé est celui sur lequel le load balancer accepte le trafic des clients externes.⁴
- Target HTTP(S) Proxy — le trafic est ensuite terminé selon la configuration du Target Proxy. Chaque Target Proxy est lié à exactement une URL Map (relation N:1). Vous devrez aussi attacher au moins un certificat SSL et configurer une SSL Policy dans le cas d'un proxy HTTPS.
- URL Map — c'est le composant central de gestion du trafic. Il permet de router le trafic entrant entre différents Backend Services (y compris des buckets GCS). Le routage de base s'appuie sur le hostname et le chemin, mais une gestion plus avancée est aussi possible : redirections d'URL, réécriture d'URL et routage basé sur les en-têtes ou les paramètres de requête. Chaque règle dirige le trafic vers un Backend Service.
- Backend Service — regroupement logique de backends pour un même service, accompagné de ses options de configuration : répartition du trafic entre les Backends, protocoles, affinité de session ou fonctionnalités telles que Cloud CDN, Cloud Armor ou IAP. Chaque Backend Service est également associé à un Health Check.
- Health Check — détermine comment chaque endpoint du backend est sondé pour vérifier qu'il est actif, et sert à calculer l'état de santé global de chaque Backend. Le protocole et le port doivent être précisés à la création, ainsi que des paramètres optionnels comme l'intervalle de vérification, les seuils healthy et unhealthy ou le timeout. Point important : des règles de firewall autorisant le trafic des health checks depuis un ensemble de plages IP internes⁵ doivent être en place.
- Backend — représente un groupe d'endpoints individuels dans un emplacement donné. Dans le cas de GKE, nos backends seront des Network Endpoint Groups (NEGs),⁶ un par zone du cluster GKE (les NEGs GKE sont zonaux, mais certains types de backends sont régionaux).
- Backend Endpoint — combinaison d'une adresse IP et d'un port, pointant directement vers les Pods individuels dans le cas de GKE avec container-native load balancing.⁷
Mise en place
Nous allons mettre en place un load balancing multi-cluster pour deux services — Foo et Bar — déployés sur deux clusters (fig. 3). Nous utiliserons des règles simples basées sur le chemin : toute requête vers /foo/* sera routée vers le service Foo, et /bar/* vers le service Bar.

Fig. 3 : GKE Multi-Cluster Foo Bar
Prérequis
- 2 clusters GKE en mode VPC-native, que nous appellerons primary et secondary ⁸
- Un enregistrement DNS pointant vers l'IP statique
- Une version récente de la CLI gcloud
- Un clone du dépôt stepanstipl/gke-multi-cluster-native⁹
git clone https://github.com/stepanstipl/gke-multi-cluster-native.gitcd gke-multi-cluster-native
Déployer les applications et services sur les clusters GKE

Fig. 4 : Application de démo K8s
Commençons par déployer une application de démo simple sur chacun des clusters. L'application affiche les informations sur le cluster et la région qui servent la requête. Le code source est disponible sur stepanstipl/k8s-demo-app.
Répétez les étapes suivantes pour chacun de vos clusters.
Récupérer les credentials pour kubectl
gcloud container clusters get-credentials [cluster] \
--region [cluster-region]
Déployer les applications Foo et Bar
kubectl apply -f deploy-foo.yaml
kubectl apply -f deploy-bar.yaml
Vous pouvez vérifier que les Pods des deux services sont bien opérationnels avec kubectl get pods.
Créer les Services K8s pour les deux applications
kubectl apply -f svc-foo.yaml kubectl apply -f svc-bar.yaml
Notez l'annotation cloud.google.com/neg: '{"exposed_ports": {"80":{}}}' sur les services : c'est elle qui indique à GKE de créer un NEG pour le Service.
Vous pouvez vérifier que les services sont correctement configurés en redirigeant un port local avec kubectl port-forward service/foo 8888:80, puis en accédant au service à http://localhost:8888/.
N'oubliez pas de répéter ces étapes pour tous vos clusters.
Configurer les composants du Load Balancing (GCLB)
Créer un Health Check
gcloud compute health-checks create http health-check-foobar \
--use-serving-port \
--request-path="/healthz"
Créer les Backend Services
Créez un backend service pour chacun des services, plus un autre qui servira de backend par défaut pour le trafic ne correspondant à aucune règle de chemin.
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
Créer une URL Map
gcloud compute url-maps create foobar-url-map \
--global \
--default-service backend-service-default
Ajouter des règles de chemin à l'URL Map
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'
Réserver une adresse IP statique
gcloud compute addresses create foobar-ipv4 \
--ip-version=IPV4 \
--global
Configurer le DNS
Faites pointer votre DNS vers l'adresse IP statique réservée précédemment. Notez l'adresse IP que vous avez demandée :
gcloud compute addresses list --global
Créez un enregistrement A foobar.[your_domain_name] pointant vers cette IP. Vous pouvez utiliser Cloud DNS pour gérer l'enregistrement, ou tout autre service de votre choix. Cette étape doit être terminée avant de poursuivre.¹⁰
Créer un certificat SSL managé
gcloud beta compute ssl-certificates create foobar-cert \
--domains "foobar.[your_domain_name]"
Créer un Target HTTPS Proxy
gcloud compute target-https-proxies create foobar-https-proxy \
--ssl-certificates=foobar-cert \
--url-map=foobar-url-map
Créer une Forwarding Rule
gcloud compute forwarding-rules create foobar-fw-rule \
--target-https-proxy=foobar-https-proxy \
--global \
--ports=443 \
--address=foobar-ipv4
Vérifier le certificat TLS
Le provisionnement du certificat peut prendre un certain temps. Vous pouvez en vérifier le statut avec :
gcloud beta compute ssl-certificates describe foobar-cert
Le managed.status doit passer à ACTIVE dans les 60 minutes environ, généralement plus tôt, si tout a été correctement configuré.
Connecter les Services K8s au Load Balancer
GKE a provisionné un NEG pour chaque Service K8s déployé avec l'annotation cloud.google.com/neg. Il nous reste à ajouter ces NEGs comme backends aux backend services correspondants.
Récupérer les noms des NEGs provisionnés
kubectl get svc \
-o custom-columns='NAME:.metadata.name,NEG:.metadata.annotations.cloud\.google\.com/neg-status'
Notez le nom du NEG et les zones pour chaque service.
Répétez l'opération pour tous vos clusters GKE.
Ajouter les NEGs aux Backend Services
Répétez l'opération suivante pour chaque NEG et chaque zone des deux clusters. Veillez à n'utiliser que les NEGs appartenant au service Foo.
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
Faites de même pour le service Bar, à répéter sur les deux clusters, pour chaque NEG et chaque 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
Autoriser le trafic GCLB
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
Vérifier que les backends sont sains
gcloud compute backend-services get-health \
--global backend-service-foo gcloud compute backend-services get-health \
--global backend-service-bar
Vous devriez normalement voir 6 backends (3 par cluster,¹¹ 1 par zone) pour chaque backend service, avec healthState: HEALTHY. Il peut s'écouler un certain délai avant que tous les backends passent au statut sain après l'ajout des règles de firewall.
Tester que tout fonctionne
Faites un curl sur votre nom DNS https://foobar.[your-domain] (ou ouvrez-le dans le navigateur). Vous devriez obtenir un 502 sur la racine, puisque nous n'avons ajouté aucun backend pour le service par défaut.
curl -v "https://foobar.[your-domain]"
Faites maintenant un curl sur les chemins propres à chaque service, https://foobar.[your-domain]/foo/ ou https://foobar.[your-domain]/bar/ : vous devriez recevoir un 200 et le contenu du service correspondant.
curl -v "https://foobar.[your-domain]/foo/"
curl -v "https://foobar.[your-domain]/bar/"
En réessayant plusieurs fois, vous devriez voir le trafic servi par différents Pods et Clusters.¹²
Si vous simulez un peu de trafic, par exemple avec l'un de mes outils CLI préférés, vegeta, vous pourrez observer la répartition du trafic entre les backends dans la console GCP. Allez dans Network services -> section Load balancing -> sélectionnez votre load balancer -> onglet Monitoring, puis choisissez le backend correspondant. Vous devriez voir un dashboard semblable à la fig. 5.

Fig. 5 : Console GKE — Load Balancing (les deux clusters étant dans la même région, le trafic est réparti équitablement entre tous les backends)
C'est le bon moment pour expérimenter. Voyez ce qui se passe avec des clusters dans la même région, puis dans des régions différentes. Augmentez la charge et observez le trafic déborder vers une autre région (indice : souvenez-vous du --max-rate-per-endpoint utilisé plus tôt). Voyez ce qui se passe si vous coupez l'un des clusters. Et pourquoi pas en ajouter un troisième dans la boucle ?
(optionnel) `gke-autoneg-controller`
Vous remarquerez l'annotation anthos.cft.dev/autoneg sur les Services K8s. Elle n'est pas nécessaire pour notre setup, mais vous pouvez aussi déployer gke-autoneg-controller ¹³ sur votre cluster pour associer automatiquement les NEGs créés par GKE aux backend services correspondants. Cela vous évitera un travail manuel fastidieux.
Bien joué !
Et voilà. Nous avons expliqué le rôle de chacun des composants GCLB et montré comment mettre en place un load balancing multi-cluster entre des services déployés sur 2 clusters GKE ou plus, dans des régions différentes. Pour un usage en production, je recommanderais d'automatiser cette configuration avec un outil de gestion de configuration tel que Terraform.
Cette configuration augmente la disponibilité de votre service, puisque plusieurs clusters GKE indépendants servent le trafic, et réduit également la latence. En HTTPS, le time to first byte est plus court, car la négociation TLS initiale a lieu sur le serveur GFE proche de l'utilisateur. Et avec plusieurs clusters, la requête est servie par celui le plus proche de l'utilisateur.
N'hésitez pas à me dire si cela vous a été utile et à me poser toute autre question, ici ou sur @stepanstipl. 🚀🚀🚀 Serve fast and prosper !
- [1] Plus de 90 emplacements à travers le monde — Load Balancing — Locations et sont relayées vers la région la plus proche disposant de capacité.
- [2] En laissant Anthos de côté pour le moment. Anthos est une plateforme de gestion d'applications qui permet d'exécuter des clusters K8s on-prem et dans d'autres clouds, et étend également les fonctionnalités des clusters GKE, notamment multi-cluster ingress controller .)
- [3] Les GFEs sont des systèmes distribués software-defined et scalables, situés sur les Edge POPs.
- [4] Le port peut être 80 ou 8080 si la cible est un proxy HTTP, ou 443 dans le cas d'un proxy HTTPS.
- [5] Pour le HTTP(S) Load Balancing externe, ces plages sont
35.191.0.0/16et130.211.0.0/22. - [6] Présentation des Network endpoint groups
- [7] Container-native load balancing nécessite un cluster en mode VPC-native et permet aux load balancers de cibler directement les Pods individuels (au lieu de cibler les nœuds du cluster).
- [8] Utiliser des clusters dans des régions différentes est plus intéressant.
- [9] Tous les fichiers référencés dans les commandes de cet article sont relatifs à la racine de ce dépôt.
- [10] L'enregistrement DNS doit être en place pour que le provisionnement du certificat SSL managé par Google fonctionne. Sans cela, le certificat risque d'être marqué comme définitivement échoué (l'autorité de certification ne pouvant pas le signer) et devra être recréé.
- [11] En supposant que vous ayez utilisé des clusters régionaux, chacun déployé sur 3 zones, sinon ajustez en conséquence.
- [12] Si vos clusters sont dans des régions différentes, GCLB privilégiera celle la plus proche du client pour servir le trafic ; ne vous attendez donc pas à une répartition équitable entre les régions.
- [13] Je n'entrerai pas dans les détails du déploiement et de l'utilisation ici, reportez-vous plutôt au readme ; en résumé, ajoutez sur votre service une annotation contenant le nom du NEG, par exemple
anthos.cft.dev/autoneg: '{"name":"autoneg_test", "max_rate_per_endpoint":1000}'.