Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Équilibrage de charge
Astuce
Découvrez les
Les équilibreurs de charge reçoivent le trafic entrant et le distribuent entre les cibles de l'application prévue hébergée dans un cluster EKS. Cela améliore la résilience de l'application. Lorsqu'il est déployé dans un cluster EKS, le contrôleur https://docs.aws.amazon.com/eks/latest/userguide/aws-load-balancer-controller.html AWS Load Balancer crée et gère les équilibreurs de charge élastiques AWS pour ce cluster. Lorsqu'un service Kubernetes de type LoadBalancer est créé, le contrôleur AWS Load Balancer crée un Network Load Balancer (NLB) qui équilibre la charge du trafic reçu au niveau de la couche 4 du modèle OSI. Lors de la création d'un objet Kubernetes Ingress, le contrôleur AWS Load Balancer crée un équilibreur de charge d'application (ALB) qui équilibre la charge du trafic au niveau de la couche 7 du modèle OSI.
Choix du type d'équilibreur de charge
Le portefeuille AWS Elastic Load Balancing (ELB) prend en charge les équilibreurs de charge suivants : équilibreurs de charge d'application (ALB), équilibreurs de charge réseau (NLB), équilibreurs de charge de passerelle (GWLB) et équilibreurs de charge classiques (CLB). Cette section sur les meilleures pratiques se concentrera sur l'ALB et le NLB, qui sont les deux plus pertinents pour les clusters EKS.
Le principal facteur à prendre en compte lors du choix du type d'équilibreur de charge est la charge de travail requise.
Pour des informations plus détaillées et comme référence pour tous les équilibreurs de charge AWS, consultez la section Comparaisons de produits
Choisissez l'équilibreur de charge d'application (ALB) si votre charge de travail est HTTP/HTTPS
Si une charge de travail nécessite un équilibrage de charge au niveau de la couche 7 du modèle OSI, le contrôleur AWS Load Balancer peut être utilisé pour provisionner un ALB ; nous aborderons le provisionnement dans la section suivante. L'ALB est contrôlé et configuré par la ressource Ingress mentionnée précédemment et achemine le trafic HTTP ou HTTPS vers différents pods du cluster. L'ALB offre aux clients la flexibilité de modifier l'algorithme de routage du trafic des applications ; l'algorithme de routage par défaut est le round robin, l'algorithme de routage des demandes les moins en attente étant également une alternative.
Choisissez le Network Load Balancer (NLB) si votre charge de travail est TCP ou si votre charge de travail nécessite la préservation de l'adresse IP source des clients
Un équilibreur de charge réseau fonctionne au niveau de la quatrième couche (transport) du modèle OSI (Open Systems Interconnection). Il convient aux charges de travail basées sur TCP et UDP. L'équilibreur de charge réseau préserve également par défaut l'adresse IP source des clients lors de la présentation du trafic au pod.
Choisissez le Network Load Balancer (NLB) si votre charge de travail ne peut pas utiliser le DNS
Une autre raison essentielle d'utiliser le NLB est que vos clients ne peuvent pas utiliser le DNS. Dans ce cas, le NLB peut être mieux adapté à votre charge de travail car les adresses IP d'un Network Load Balancer sont statiques. Bien qu'il soit recommandé aux clients d'utiliser le DNS pour résoudre des noms de domaine en adresses IP lors de la connexion à des équilibreurs de charge, si l'application d'un client ne prend pas en charge la résolution DNS et n'accepte que des adresses IP codées en dur, un NLB est préférable car les adresses IP sont statiques et restent les mêmes pendant toute la durée de vie du NLB.
Provisionnement des équilibreurs de charge
Après avoir déterminé l'équilibreur de charge le mieux adapté à vos charges de travail, les clients disposent de plusieurs options pour provisionner un équilibreur de charge.
Provisionnez des équilibreurs de charge en déployant le contrôleur AWS Load Balancer
Il existe deux méthodes principales pour provisionner des équilibreurs de charge au sein d'un cluster EKS.
-
Tirer parti du contrôleur de service dans le fournisseur de cloud AWS (ancien)
-
Tirer parti du contrôleur AWS Load Balancer (recommandé)
Par défaut, le contrôleur de service Kubernetes, également appelé contrôleur intégré à l'arborescence, réconcilie le type de ressource de service Kubernetes. LoadBalancer Ce contrôleur est intégré au composant
La configuration de l'Elastic Load Balancer provisionné est contrôlée par des annotations qui doivent être ajoutées au manifeste du service Kubernetes. Les annotations utilisées par le Service Controller
Le Service Controller est obsolète et ne reçoit actuellement que des corrections de bogues critiques. Lorsque vous créez un service Kubernetes de type LoadBalancer, le contrôleur de service crée un AWS CLB par défaut, mais peut également créer AWS NLB si vous utilisez la bonne annotation. Il convient de noter que Service Controller ne prend pas en charge les ressources Kubernetes Ingress et qu'il ne prend pas non plus en charge IPv6.
Nous vous recommandons d'utiliser le contrôleur AWS Load Balancer dans vos clusters EKS pour réconcilier les ressources Kubernetes Service et Ingress. Vous devez utiliser les bonnes annotations dans votre manifeste Kubernetes Service ou Ingress afin qu'AWS Load Balancer Controller soit responsable du processus de réconciliation. (au lieu de Service Controller)
Si vous utilisez le mode automatique EKS, le contrôleur AWS Load Balancer vous est fourni automatiquement ; aucune installation n'est nécessaire.
Choisir un équilibreur de charge Target-Type
Enregistrer les pods en tant que cibles à l'aide d'une adresse Target-Type
Un AWS Elastic Load Balancer : réseau et application envoie le trafic reçu aux cibles enregistrées dans un groupe cible. Pour un cluster EKS, vous pouvez enregistrer deux types de cibles dans le groupe cible : Instance et IP, le type de cible utilisé a des implications sur ce qui est enregistré et sur la manière dont le trafic est acheminé du Load Balancer vers le pod. Par défaut, le contrôleur AWS Load Balancer enregistre les cibles en utilisant le type « Instance » et cette cible sera l'adresse IP du Worker NodeNodePort, ce qui implique :
-
Le trafic provenant de l'équilibreur de charge sera transféré au nœud Worker sur le NodePort, il est traité par les règles iptables (configurées par kube-proxy s'exécutant sur le nœud), et est transféré au service sur son ClusterIP (toujours sur le nœud), enfin le service sélectionne au hasard un pod qui y est enregistré et lui transmet le trafic. Ce flux implique plusieurs sauts et une latence supplémentaire peut être occasionnée, notamment parce que le Service sélectionne parfois un pod s'exécutant sur un autre nœud de travail qui peut également se trouver dans une autre zone de disponibilité.
-
Étant donné que le Load Balancer enregistre le Worker Node comme cible, cela signifie que son bilan de santé envoyé à la cible ne sera pas directement reçu par le pod mais par le Worker Node sur celui-ci NodePort et le trafic du bilan de santé suivra le même chemin décrit ci-dessus.
-
La surveillance et le dépannage sont plus complexes car le trafic transféré par le Load Balancer n'est pas directement envoyé aux pods et vous devrez corréler soigneusement le paquet reçu sur le Worker Node avec le Service ClusterIP et, éventuellement, le pod pour avoir une visibilité complète de bout en bout sur le chemin du paquet pour un dépannage correct.
En revanche, si vous configurez le type de cible comme « IP », comme nous le recommandons, les implications seront les suivantes :
-
Le trafic provenant de l'équilibreur de charge sera transféré directement vers le pod, ce qui simplifie le chemin réseau car il contourne les sauts supplémentaires précédents des nœuds de travail et de l'adresse IP du cluster de services, cela réduit la latence qui aurait autrement été générée si le service transférait le trafic vers un pod dans une autre zone de disponibilité et, enfin, cela supprime le traitement de surcharge des règles iptables sur les nœuds de travail.
-
Le bilan de santé du Load Balancer est directement reçu par le pod et y répond, ce qui signifie que l'état cible « sain » ou « insalubre » est une représentation directe de l'état de santé du pod.
-
La surveillance et le dépannage sont plus faciles et tout outil utilisé pour capturer l'adresse IP des paquets révélera directement le trafic bidirectionnel entre l'équilibreur de charge et le pod dans ses champs source et destination.
Pour créer un AWS Elastic Load Balancing qui utilise des cibles IP, vous ajoutez :
-
alb.ingress.kubernetes.io/target-type: ipannotation au manifeste de votre Ingress lors de la configuration de votre Kubernetes Ingress (Application Load Balancer) -
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ipannotation au manifeste de votre service lors de la configuration de votre service Kubernetes de type LoadBalancer (Network Load Balancer).
Configuration des contrôles de santé de l'équilibreur de charge
Bien que Kubernetes fournisse ses propres mécanismes de contrôle de santé (détaillés dans la section suivante), nous vous recommandons de mettre en œuvre des bilans de santé ELB en tant que protection complémentaire qui fonctionne en dehors du plan de contrôle de Kubernetes. Cette couche indépendante continue de surveiller votre application même pendant :
-
Perturbations du plan de contrôle de Kubernetes
-
Retards d'exécution de la sonde
-
Partitions réseau entre Kubelet et Pod
Pour les charges de travail critiques nécessitant une disponibilité maximale et une restauration accélérée dans les scénarios mentionnés ci-dessus, les bilans de santé ELB constituent un filet de sécurité essentiel qui fonctionne parallèlement aux mécanismes natifs de Kubernetes, et non les remplacer.
Afin de configurer et d'affiner les contrôles de santé de votre ELB, vous devez utiliser des annotations dans votre manifeste Kubernetes Service ou Ingress qui seraient réconciliées par Service Controller ou AWS Load Balancer Controller.
Disponibilité et cycle de vie des pods
Lors de la mise à niveau d'une application, vous devez vous assurer que votre application est toujours disponible pour traiter les demandes afin d'éviter toute interruption de service pour les utilisateurs. Dans ce scénario, l'un des défis courants consiste à synchroniser l'état de disponibilité de vos charges de travail entre la couche Kubernetes et l'infrastructure, par exemple des équilibreurs de charge externes. Les sections suivantes mettent en lumière les meilleures pratiques pour faire face à de tels scénarios.
Note
Les explications ci-dessous sont basées sur le EndpointSlices
Utilisez des bilans de santé
Par défaut, Kubernetes exécute le contrôle de l'état du processus
Veuillez consulter la section Création d'un pod dans l'annexe ci-dessous pour revoir la séquence des événements du processus de création d'un pod.
Utiliser des sondes de préparation
Par défaut, lorsque tous les conteneurs d'un Pod sont en cours d'exécution, success. En revanche, si la sonde tombe en panne plus loin dans la ligne, le Pod est retiré de l' EndpointSlice objet. Vous pouvez configurer une sonde de préparation dans le manifeste du pod pour chaque conteneur. kubeletUn processus sur chaque nœud exécute la sonde de préparation sur les conteneurs de ce nœud.
Utilisez les portes de préparation des Pod
L'un des aspects de la sonde de préparation est le fait qu'elle ne contient aucun feedback/influence mécanisme externe. Le processus kubelet sur le nœud exécute la sonde et définit l'état de la sonde. Cela n'a aucun impact sur les requêtes entre les microservices eux-mêmes dans la couche Kubernetes (trafic est-ouest) puisque le EndpointSlice Controller tient la liste des points de terminaison (Pods) toujours à jour. Pourquoi et quand auriez-vous besoin d'un mécanisme externe ?
Lorsque vous exposez vos applications à l'aide du type d'équilibreur de charge Kubernetes Service ou Kubernetes Ingress (pour le trafic nord-sud), la liste des adresses IP des pods pour le service Kubernetes concerné doit être propagée à l'équilibreur de charge de l'infrastructure externe afin que l'équilibreur de charge dispose également d'une liste de cibles à jour. AWS Load Balancer Controller comble cette lacune à cet égard. Lorsque vous utilisez AWS Load Balancer Controller et que kube-proxy vous en tirez partitarget group: IP, AWS Load Balancer Controller reçoit également une mise à jour (viawatch), puis communique avec l'API ELB pour configurer et commencer à enregistrer l'IP du pod en tant que cible sur l'ELB.
Lorsque vous effectuez une mise à jour continue d'un déploiement, de nouveaux pods sont créés et dès que l'état d'un nouveau pod est « prêt », un old/existing pod est résilié. Au cours de ce processus, l' EndpointSliceobjet Kubernetes est mis à jour plus rapidement que le temps nécessaire à l'ELB pour enregistrer les nouveaux pods en tant que cibles (voir enregistrement des cibles). https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-register-targets.html Pendant une courte période, vous pourriez avoir un décalage d'état entre la couche Kubernetes et la couche d'infrastructure où les demandes des clients pourraient être supprimées. Au cours de cette période, au sein de la couche Kubernetes, les nouveaux pods seraient prêts à traiter les demandes, mais du point de vue de l'ELB, ils ne le sont pas.
Les portes de préparation du pod vous
Arrêtez les applications en douceur
Votre application doit répondre à un signal SIGTERM en démarrant son arrêt progressif afin que les clients ne subissent aucune interruption de service. Cela signifie que votre application doit exécuter des procédures de nettoyage telles que la sauvegarde des données, la fermeture des descripteurs de fichiers, la fermeture des connexions à la base de données, le traitement des demandes en vol avec élégance et la sortie en temps opportun pour répondre à la demande de résiliation du Pod. Vous devez régler la période de grâce sur une durée suffisante pour que le nettoyage puisse se terminer. Pour savoir comment répondre au signal SIGTERM, vous pouvez consulter les ressources du langage de programmation correspondant que vous utilisez pour votre application.
Si votre application ne parvient pas à s'arrêter correctement à la réception d'un signal SIGTERM ou si elle ignores/does ne reçoit pas le signal
La séquence globale des événements est illustrée dans le diagramme ci-dessous. Remarque : quel que soit le résultat de la procédure d'arrêt progressif de l'application ou le résultat du PreStop hook, les conteneurs de l'application sont finalement fermés à la fin de la période de grâce via SIGKILL.
Veuillez consulter la section Suppression des pods dans la section Annexe ci-dessous pour revoir la séquence des événements du processus de suppression des pods.
Gérez avec élégance les demandes des clients
La séquence des événements lors de la suppression d'un pod est différente de celle de la création d'un pod. Lorsqu'un pod est créé, l'adresse IP du pod est kubelet mise à jour dans l'API Kubernetes et c'est alors seulement que l' EndpointSlice objet est mis à jour. D'autre part, lorsqu'un Pod est résilié, l'API Kubernetes avertit à la fois le kubelet et EndpointSlice le contrôleur. Examinez attentivement le schéma suivant qui montre la séquence des événements.
La façon dont l'état se propage depuis le serveur API jusqu'aux règles iptables sur les nœuds expliquées ci-dessus crée une condition de concurrence intéressante. Comme il y a de fortes chances que le conteneur reçoive le signal SIGKILL bien avant que le kube-proxy de chaque nœud ne mette à jour les règles iptables locales. Dans un tel cas, deux scénarios méritent d'être mentionnés :
-
Si votre application supprime immédiatement et brutalement les demandes et les connexions en vol dès la réception de SIGTERM, cela signifie que les clients verraient 50 fois plus d'erreurs sur tous les sites.
-
Même si votre application garantit que toutes les demandes et connexions en vol sont entièrement traitées à la réception de SIGTERM, pendant la période de grâce, les nouvelles demandes des clients seront toujours envoyées au conteneur de l'application car les règles iptables peuvent ne pas encore être mises à jour. Jusqu'à ce que la procédure de nettoyage ferme le socket du serveur sur le conteneur, ces nouvelles demandes entraîneront de nouvelles connexions. À la fin de la période de grâce, ces connexions, qui sont établies après le SIGTERM, sont interrompues sans condition puisque SIGKILL est envoyé.
La définition d'une période de grâce suffisamment longue dans la spécification du pod peut résoudre ce problème, mais en fonction du délai de propagation et du nombre de demandes clients réelles, il est difficile d'anticiper le temps nécessaire à l'application pour fermer correctement les connexions. Par conséquent, l'approche pas si parfaite mais la plus réalisable consiste à utiliser un PreStop hook pour retarder le signal SIGTERM jusqu'à ce que les règles iptables soient mises à jour afin de s'assurer qu'aucune nouvelle demande client n'est envoyée à l'application. Seules les connexions existantes sont maintenues. PreStop hook peut être un simple gestionnaire Exec tel que. sleep 10
Le comportement et la recommandation mentionnés ci-dessus seraient également applicables lorsque vous exposez vos applications à l'aide du type d'équilibreur de charge Kubernetes Service ou de Kubernetes Ingress (pour le trafic nord-sud) à l'aide d'AWS Load Balancer Controller et de tirer parti de l'effet de levier. target group: IP Parce que tout comme kube-proxy AWS Load Balancer Controller reçoit également une mise à jour (via une montre) sur l' EndpointSlice objet, puis il communique avec l'API ELB pour commencer à désenregistrer l'IP du pod de l'ELB. Cependant, selon la charge de l'API Kubernetes ou de l'API ELB, cela peut également prendre du temps et le SIGTERM a peut-être déjà été envoyé à l'application il y a longtemps. Une fois que l'ELB commence à désenregistrer la cible, il arrête d'envoyer des demandes à cette cible, de sorte que l'application ne recevra aucune nouvelle demande. L'ELB déclenche également un délai de désenregistrement qui est de 300 secondes par défaut. Pendant le processus de désenregistrement, la cible est l'drainingendroit où l'ELB attend essentiellement que les requests/existing connexions en vol vers cette cible soient épuisées. Une fois le délai de désenregistrement expiré, la cible n'est pas utilisée et toutes les demandes en vol adressées à cette cible sont supprimées de force.
Utilisez le budget d'interruption du Pod
Configurez un budget d'interruption des pods
Références
Annexe
Création d'un pod
Il est impératif de comprendre quelle est la séquence des événements dans un scénario où un Pod est déployé healthy/ready pour ensuite recevoir et traiter les demandes des clients. Parlons de la séquence des événements.
-
Un pod est créé sur le plan de contrôle de Kubernetes (c'est-à-dire par une commande kubectl, une mise à jour du déploiement ou une action de dimensionnement).
-
kube-schedulerassigne le Pod à un nœud du cluster. -
Le processus kubelet qui s'exécute sur le nœud attribué reçoit la mise à jour (via
watch) et communique avec le moteur d'exécution du conteneur pour démarrer les conteneurs définis dans la spécification du pod. -
Lorsque les conteneurs commencent à fonctionner, le kubelet met à jour l'état du Pod
comme Readydans l'objet Pod de l'API Kubernetes. -
Le EndpointSlice Controller
reçoit la mise à jour de l'état du pod (via watch) et ajoute le pod IP/Port en tant que nouveau point de terminaison à l'EndpointSliceobjet (liste des adresses IP des pods) du service Kubernetes concerné. -
Le
processus kube-proxy sur chaque nœud reçoit la mise à jour (via watch) sur l'EndpointSlice objet, puis met à jour les règlesiptables sur chaque nœud, avec le nouveau Pod. IP/port
Suppression du pod
Tout comme pour la création d'un Pod, il est impératif de comprendre quelle est la séquence des événements lors de la suppression d'un Pod. Parlons de la séquence des événements.
-
Une demande de suppression de pod est envoyée au serveur API Kubernetes (c'est-à-dire par une
kubectlcommande, une mise à jour du déploiement ou une action de dimensionnement). -
Le serveur API Kubernetes lance une période de grâce
, qui est de 30 secondes par défaut, en définissant le champ https://kubernetes.io/docs/concepts/architecture/garbage-collection/#foreground-deletion DeletionTimestamp dans l'objet Pod. (La période de grâce peut être configurée dans les spécifications du pod via terminationGracePeriodSeconds) -
Le
kubeletprocessus qui s'exécute sur le nœud reçoit la mise à jour (via une montre) sur l'objet Pod et envoie un signalSIGTERM à l'identifiant de processus 1 (PID 1) à l'intérieur de chaque conteneur de ce Pod. Il regarde ensuite le terminationGracePeriodSeconds. -
Le EndpointSlice contrôleur reçoit
également la mise à jour (via watch) à partir de l'étape 2 et définit la condition du terminal sur « terminaison » dans l'EndpointSliceobjet (liste des adresses IP des pods) du service Kubernetes concerné. -
Le
processus kube-proxy sur chaque nœud reçoit la mise à jour (via watch) sur l'EndpointSlice objet, puis les règlesiptables sur chaque nœud sont mises à jour par le kube-proxy pour arrêter de transmettre les demandes des clients au Pod. -
À l'
terminationGracePeriodSecondsexpiration, ilkubeletenvoie le signalSIGKILL au processus parent de chaque conteneur du Pod et les arrête de force. -
TheEndpointSliceLe contrôleur
supprime le point de terminaison de l'EndpointSlice objet. -
Le serveur API supprime l'objet Pod.