Cette page explique comment utiliser l'équilibrage de charge natif en conteneurs dans Google Kubernetes Engine (GKE). L'équilibrage de charge natif en conteneurs permet aux équilibreurs de charge de cibler directement les pods Kubernetes et de répartir le trafic de manière homogène entre ceux-ci.
Pour en savoir plus sur les avantages, les exigences et les limites de l'équilibrage de charge natif en conteneurs, consultez la page Équilibrage de charge natif en conteneurs.
Avant de commencer
Avant de commencer, effectuez les tâches suivantes :
- Activez l'API Google Kubernetes Engine. Activer l'API Google Kubernetes Engine
- Si vous souhaitez utiliser Google Cloud CLI pour cette tâche, installez puis initialisez gcloud CLI. Si vous avez déjà installé gcloud CLI, assurez-vous de disposer de la dernière version en exécutant la commande
gcloud components update
.
Utiliser l'équilibrage de charge natif en conteneurs
Les sections suivantes présentent les étapes de configuration de l'équilibrage de charge natif en conteneurs sur GKE. Notez que, pour les clusters GKE exécutant la version 1.17 ou ultérieure, et sous certaines conditions, l'équilibrage de charge natif en conteneurs est utilisé par défaut et ne nécessite pas d'annotation de service cloud.google.com/neg: '{"ingress": true}'
explicite.
Créer un cluster de VPC natif
Pour utiliser l'équilibrage de charge natif en conteneurs, des adresses IP d'alias doivent être activées sur votre cluster GKE.
Par exemple, la commande suivante crée un cluster GKE, neg-demo-cluster
, avec un sous-réseau provisionné automatiquement :
En mode Autopilot, les adresses IP d'alias sont activées par défaut :
gcloud container clusters create-auto neg-demo-cluster \ --location=COMPUTE_LOCATION
Remplacez
COMPUTE_LOCATION
par l'emplacement Compute Engine du cluster.
En mode standard, activez les adresses IP d'alias lors de la création du cluster:
gcloud container clusters create neg-demo-cluster \ --enable-ip-alias \ --create-subnetwork="" \ --network=default \ --zone=us-central1-a
Créer un déploiement
L'exemple de déploiement suivant, neg-demo-app
, exécute une seule instance d'un serveur HTTP conteneurisé. Nous vous recommandons d'utiliser des charges de travail qui font appel au retour d'informations via la disponibilité des pods.
Utiliser le retour d'informations via la disponibilité des pods
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
Utiliser un délai codé en dur
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
Dans ce déploiement, chaque conteneur exécute un serveur HTTP. En réponse, le serveur HTTP renvoie le nom d'hôte du serveur d'applications (le nom du pod sur lequel le serveur est exécuté).
Enregistrez ce fichier manifeste sous le nom neg-demo-app.yaml
, puis créez le déploiement :
kubectl apply -f neg-demo-app.yaml
Créer un service pour un équilibreur de charge natif en conteneurs
Après avoir créé un déploiement, vous devez regrouper ses pods dans un service.
L'exemple de service suivant, neg-demo-svc
, cible le déploiement que vous avez créé dans la section précédente :
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
L'annotation du service, cloud.google.com/neg: '{"ingress": true}'
, active l'équilibrage de charge natif en conteneurs. Cependant, l'équilibreur de charge n'est pas créé tant que vous n'avez pas créé une entrée pour le service.
Enregistrez ce fichier manifeste sous le nom neg-demo-svc.yaml
, puis créez le service :
kubectl apply -f neg-demo-svc.yaml
Créer un objet Ingress pour le service
L'exemple d'entrée suivant, neg-demo-ing
, cible le service que vous avez créé :
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
Enregistrez ce fichier manifeste sous le nom neg-demo-ing.yaml
, puis créez l'objet Ingress :
kubectl apply -f neg-demo-ing.yaml
La création de cette entrée entraîne celle d'un équilibreur de charge d'application au sein du projet ainsi que celle d'un groupe de points de terminaison réseau (NEG) dans chacune des zones où le cluster est exécuté. Les points de terminaison des NEG et ceux du service sont synchronisés.
Vérifier l'objet Ingress
Après avoir déployé une charge de travail, regroupé ses pods dans un service et créé une entrée pour le service, vous devez vérifier que l'entrée a correctement provisionné l'équilibreur de charge natif en conteneurs.
Récupérez l'état de l'objet Ingress :
kubectl describe ingress neg-demo-ing
Le résultat inclut les événements ADD
et 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
Tester l'équilibreur de charge
Dans les sections suivantes, nous expliquons comment tester le fonctionnement d'un équilibreur de charge natif en conteneurs.
Accéder à l'adresse IP de l'entrée
Attendez plusieurs minutes que l'équilibreur de charge d'application soit configuré.
Vous pouvez vérifier le fonctionnement de l'équilibreur de charge natif en conteneurs en accédant à l'adresse IP de l'entrée.
Pour obtenir l'adresse IP de l'entrée, exécutez la commande suivante :
kubectl get ingress neg-demo-ing
Dans le résultat de la commande, l'adresse IP de l'entrée est affichée dans la colonne ADDRESS
. Accédez à l'adresse IP dans un navigateur Web.
Vérifier l'état de santé du service de backend
Vous pouvez également vérifier l'état de santé du service de backend de l'équilibreur de charge.
Obtenez la liste des services de backend qui s'exécutent dans votre projet :
gcloud compute backend-services list
Enregistrez le nom du service de backend qui inclut le nom du Service (par exemple
neg-demo-svc
).Obtenez l'état de santé du service de backend :
gcloud compute backend-services get-health BACKEND_SERVICE_NAME --global
Remplacez
BACKEND_SERVICE_NAME
par le nom du service de backend.
Tester l'objet Ingress
Un autre moyen vous permet de vérifier que l'équilibreur de charge fonctionne : effectuer un scaling de l'exemple de déploiement, envoyer des requêtes test à l'entrée et vérifier que le bon nombre d'instances dupliquées répond.
Effectuez le scaling du déploiement
neg-demo-app
d'une instance à deux instances :kubectl scale deployment neg-demo-app --replicas 2
Cette commande peut prendre plusieurs minutes.
Vérifiez que le déploiement est terminé :
kubectl get deployment neg-demo-app
Le résultat doit inclure deux instances dupliquées disponibles :
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE neg-demo-app 2 2 2 2 26m
Récupérez l'adresse IP de l'objet Ingress :
kubectl describe ingress neg-demo-ing
Si cette commande renvoie une erreur 404, attendez quelques minutes que l'équilibreur de charge démarre, puis réessayez.
Comptez le nombre de réponses distinctes de l'équilibreur de charge :
for i in `seq 1 100`; do \ curl --connect-timeout 1 -s IP_ADDRESS && echo; \ done | sort | uniq -c
Remplacez
IP_ADDRESS
par l'adresse IP d'entrée.Le résultat ressemble à ce qui suit :
44 neg-demo-app-7f7dfd7bc6-dcn95 56 neg-demo-app-7f7dfd7bc6-jrmzf
Dans ce résultat, le nombre de réponses distinctes est identique au nombre d'instances dupliquées, ce qui indique que tous les pods backend diffusent du trafic.
Effectuer un nettoyage
Une fois les tâches de cette page terminées, procédez comme suit pour supprimer les ressources afin d'éviter que des frais inutiles ne vous soient facturés sur votre compte :
Supprimer le cluster
gcloud
gcloud container clusters delete neg-demo-cluster
Console
Accédez à la page Google Kubernetes Engine dans Google Cloud Console.
Sélectionnez neg-demo-cluster, puis cliquez sur delete Supprimer.
Lorsque vous êtes invité à confirmer votre choix, cliquez sur Supprimer.
Dépannage
Utilisez les techniques ci-dessous pour valider votre configuration réseau. Dans les sections suivantes, nous expliquons comment résoudre des problèmes spécifiques liés à l'équilibrage de charge natif en conteneurs.
Consultez la documentation sur l'équilibrage de charge pour savoir comment répertorier vos groupes de points de terminaison réseau.
Vous pouvez trouver le nom et les zones du NEG correspondant à un service donné dans l'annotation
neg-status
de ce service. Vous pouvez obtenir les spécifications du service avec la commande :kubectl get svc SVC_NAME -o yaml
L'annotation
metadata:annotations:cloud.google.com/neg-status
contient le nom du NEG correspondant au service et les zones de ce groupe.Vous pouvez vérifier l'état du service de backend correspondant à un NEG à l'aide de la commande suivante :
gcloud compute backend-services --project PROJECT_NAME \ get-health BACKEND_SERVICE_NAME --global
Le service de backend porte le même nom que le NEG associé.
Pour imprimer les journaux d'événements d'un service, utilisez la commande :
kubectl describe svc SERVICE_NAME
La chaîne de caractères du nom du service inclut le nom et l'espace de noms du service GKE correspondant.
Impossible de créer un cluster avec des adresses IP d'alias
- Symptômes
Lorsque vous tentez de créer un cluster à l'aide d'adresses IP d'alias, vous pouvez rencontrer le message d'erreur suivant :
ResponseError: code=400, message=IP aliases cannot be used with a legacy network.
- Causes probables
Cette erreur se produit lorsque vous tentez de créer un cluster doté d'adresses IP d'alias qui utilise également un réseau ancien.
- Solution
Assurez-vous de ne pas créer de cluster utilisant simultanément des adresses IP d'alias et un ancien réseau. Pour en savoir plus sur l'utilisation d'adresses IP d'alias, consultez la page Créer un cluster de VPC natif.
Le trafic n'atteint pas les points de terminaison
- Symptômes
- Erreurs 502/503 ou connexions refusées .
- Causes probables
Les nouveaux points de terminaison sont généralement accessibles une fois qu'ils sont reliés à l'équilibreur de charge, à condition qu'ils répondent aux vérifications d'état. Vous pouvez rencontrer des erreurs 502 ou des connexions refusées si le trafic ne peut pas atteindre les points de terminaison.
Les erreurs 502 et les connexions refusées peuvent également être causées par un conteneur qui ne gère pas le signal
SIGTERM
. Si un conteneur ne gère pas explicitement le signalSIGTERM
, il s'interrompt immédiatement et cesse de traiter les requêtes. L'équilibreur de charge continue d'envoyer du trafic entrant à destination du conteneur arrêté, ce qui entraîne des erreurs.L'équilibreur de charge natif du conteneur ne comporte qu'un seul point de terminaison backend. Lors d'une mise à jour progressive, l'ancien point de terminaison est automatiquement déprogrammé avant la programmation du nouveau point de terminaison.
Le ou les pods de backend sont déployés dans une nouvelle zone pour la première fois après le provisionnement d'un équilibreur de charge natif en conteneurs. L'infrastructure de l'équilibreur de charge est programmée dans une zone lorsqu'elle comporte au moins un point de terminaison. Lorsqu'un nouveau point de terminaison est ajouté à une zone, l'infrastructure de l'équilibreur de charge est programmée et entraîne des interruptions de service.
- Solution
Configurez les conteneurs afin qu'ils puissent gérer le signal
SIGTERM
et continuer à répondre aux requêtes tout au long du délai de grâce pour la résiliation (par défaut, 30 secondes). Configurez les pods afin qu'ils se mettent à échouer aux vérifications d'état lorsqu'ils reçoivent un signalSIGTERM
. Cela indique à l'équilibreur de charge qu'il doit arrêter d'envoyer du trafic vers le pod lorsque la déprogrammation du point de terminaison est en cours.Si votre application ne se ferme pas correctement et cesse de répondre aux requêtes lors de la réception d'un
SIGTERM
, le hook d'arrêt préalable peut servir à gérerSIGTERM
et continuer à diffuser le trafic pendant la déprogrammation du point de terminaison.lifecycle: preStop: exec: # if SIGTERM triggers a quick exit; keep serving traffic instead command: ["sleep","60"]
Consultez la documentation sur l'arrêt d'un pod.
Si le backend de votre équilibreur de charge ne comporte qu'une seule instance, veuillez configurer la stratégie de déploiement pour éviter de supprimer la seule instance avant que la nouvelle instance ne soit complètement programmée. Pour les pods d'application gérés par la charge de travail
Deployment
, cette opération peut être effectuée en configurant la stratégie de déploiement avec le paramètremaxUnavailable
égal à0
.strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 0
Pour résoudre les cas où le trafic n'atteint pas les points de terminaison, vérifiez que les règles de pare-feu autorisent le trafic TCP entrant vers vos points de terminaison sur les plages
130.211.0.0/22
et35.191.0.0/16
. Pour en savoir plus, consultez la page Ajouter des vérifications d'état dans la documentation Cloud Load Balancing.Affichez les services de backend dans votre projet. La chaîne de caractères du nom du service de backend concerné inclut le nom et l'espace de noms du service GKE correspondant :
gcloud compute backend-services list
Retrouvez l'état de santé du service de backend :
gcloud compute backend-services get-health BACKEND_SERVICE_NAME
Si aucun des services de backend n'est opérationnel, il se peut que votre pare-feu, votre entrée ou votre service soient mal configurés.
Si certains services de backend ne sont pas opérationnels pendant une courte période, cela peut s'expliquer par la latence de la programmation réseau.
Si certains services de backend ne figurent pas dans la liste, cela peut être dû à la latence de la programmation. Vous pouvez vous en assurer en exécutant la commande suivante, où
NEG_NAME
est le nom du service de backend (les NEG et les services de backend portent le même nom) :gcloud compute network-endpoint-groups list-network-endpoints NEG_NAME
Vérifiez que tous les points de terminaison prévus se trouvent dans le NEG.
Si vous avez un petit nombre de backends (par exemple, 1 Pod) sélectionnés par un équilibreur de charge natif en conteneurs, envisagez d'augmenter le nombre d'instances dupliquées et de répartir les pods de backend sur toutes les zones couvertes par le cluster GKE. Cela garantit que l'infrastructure de l'équilibreur de charge sous-jacent est entièrement programmée. Sinon, envisagez de limiter les pods de backend à une seule zone.
Si vous configurez une règle de réseau pour le point de terminaison, assurez-vous que le trafic entrant provenant du sous-réseau proxy réservé est autorisé.
Blocage du déploiement
- Symptômes
- Le déploiement d'une mise à jour se bloque et le nombre d'instances dupliquées à jour ne correspond pas au nombre visé .
- Causes probables
Les vérifications d'état du déploiement échouent. Il est possible que l'image du conteneur soit incorrecte ou que la vérification d'état soit mal configurée. Le remplacement progressif des pods attend jusqu'à ce qu'un pod qui vient d'être lancé passe sa porte de disponibilité de pod. Cela se produit uniquement si le pod répond aux vérifications d'état de l'équilibreur de charge. Si le pod ne répond pas ou si la vérification d'état est mal configurée, les conditions de la porte de disponibilité ne peuvent pas être remplies et le déploiement ne peut pas se poursuivre.
Si vous utilisez
kubectl
1.13 ou une version ultérieure, vous pouvez vérifier l'état des portes de disponibilité d'un pod à l'aide de la commande suivante :kubectl get pod POD_NAME -o wide
Vérifiez le contenu de la colonne
READINESS GATES
.Cette colonne n'existe pas dans les versions 1.12 et antérieures de
kubectl
. Un pod identifié comme étant dans l'étatREADY
(prêt) peut néanmoins présenter une porte de disponibilité en échec. Pour le vérifier, exécutez la commande suivante :kubectl get pod POD_NAME -o yaml
Les portes de disponibilité et leur état sont répertoriés dans le résultat.
- Solution
Vérifiez que l'image du conteneur référencée dans la spécification de déploiement de pod fonctionne correctement et qu'elle est en mesure de répondre aux vérifications d'état. Assurez-vous que les vérifications d'état sont correctement configurées.
Erreurs en mode dégradé
- Symptômes
À partir de la version 1.29.2-gke.1643000 de GKE, vous pouvez recevoir les avertissements suivants sur votre service dans l'explorateur de journaux lorsque des NEG sont mis à jour :
Entering degraded mode for NEG <service-namespace>/<service-name>-<neg-name>... due to sync err: endpoint has missing nodeName field
- Causes probables
Ces avertissements indiquent que GKE a détecté des erreurs de configuration des points de terminaison lors d'une mise à jour du NEG basée sur des objets
EndpointSlice
, ce qui déclenche un processus de calcul plus approfondi appelé "mode dégradé". GKE continue de mettre à jour les NEG au mieux, en corrigeant l'erreur de configuration ou en excluant les points de terminaison non valides des mises à jour de NEG.Voici quelques erreurs courantes :
endpoint has missing pod/nodeName field
endpoint corresponds to an non-existing pod/node
endpoint information for attach/detach operation is incorrect
- Solution
En règle générale, les états transitoires sont à l'origine de ces événements, et ils se résolvent d'eux-mêmes. Toutefois, les événements causés par des erreurs de configuration dans les objets
EndpointSlice
personnalisés restent non résolus. Pour comprendre l'erreur de configuration, examinez les objetsEndpointSlice
correspondant au service :kubectl get endpointslice -l kubernetes.io/service-name=<service-name>
Validez chaque point de terminaison en fonction de l'erreur dans l'événement.
Pour résoudre le problème, vous devez modifier manuellement les objets
EndpointSlice
. La mise à jour déclenche une nouvelle mise à jour des NEG. Une fois que l'erreur de configuration n'existe plus, le résultat ressemble à ce qui suit :NEG <service-namespace>/<service-name>-<neg-name>... is no longer in degraded mode
Problèmes connus
Sur GKE, l'équilibrage de charge natif en conteneurs présente les problèmes connus suivants :
Récupération de mémoire incomplète
GKE effectue la récupération de mémoire sur les équilibreurs de charge natifs en conteneurs toutes les deux minutes. Si un cluster est supprimé avant la suppression complète des équilibreurs de charge, vous devez supprimer manuellement les NEG de l'équilibreur de charge.
Affichez les NEG de votre projet en exécutant la commande suivante :
gcloud compute network-endpoint-groups list
Dans le résultat de la commande, recherchez les NEG concernés.
Pour supprimer un NEG, exécutez la commande suivante, en remplaçant NEG_NAME
par le nom du NEG :
gcloud compute network-endpoint-groups delete NEG_NAME
Aligner les déploiements de charges de travail avec la propagation des points de terminaison
Lorsque vous déployez une charge de travail sur votre cluster ou lorsque vous mettez à jour une charge de travail existante, l'équilibreur de charge natif en conteneurs peut nécessiter plus de temps pour propager les nouveaux points de terminaison que pour terminer le déploiement de la charge de travail. L'exemple de déploiement que vous créez dans ce guide utilise deux champs pour s'aligner sur la propagation des points de terminaison : terminationGracePeriodSeconds
et minReadySeconds
.
terminationGracePeriodSeconds
permet au pod de s'arrêter normalement en attendant l'arrêt des connexions après sa suppression programmée.
minReadySeconds
ajoute une période de latence après la création d'un pod. Vous devez spécifier le nombre minimal de secondes pendant lesquelles un nouveau pod doit se trouver à l'état Ready
sans connaître aucun plantage de conteneur pour être considéré comme disponible.
Vous devez configurer les valeurs minReadySeconds
et terminationGracePeriodSeconds
de vos charges de travail sur 60 secondes ou plus pour vous assurer que le service n'est pas interrompu en raison de déploiements de charges de travail.
terminationGracePeriodSeconds
est disponible dans toutes les spécifications de pod, et minReadySeconds
est disponible pour les déploiements et les DaemonSets.
Pour savoir comment configurer avec précision des déploiements, consultez la section sur RollingUpdateStrategy.
La contrainte initialDelaySeconds
du champ readinessProbe
du pod n'est pas respectée
Vous pourriez vous attendre à ce que la contrainte initialDelaySeconds
configurée dans le champ readinessProbe
du pod soit respectée par l'équilibreur de charge natif en conteneurs. Cependant, readinessProbe
est mis en œuvre par kubelet, et la configuration initialDelaySeconds
contrôle la vérification d'état du kubelet, et non de l'équilibreur de charge natif en conteneurs. L'équilibrage de charge natif en conteneurs dispose de sa propre vérification d'état.