Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Démystifier le Kubernetes AWS LB Controller

By Chris McGrathMar 20, 202319 min read

Cette page est également disponible en English, Deutsch, Español, Italiano, 日本語 et Português.

BLUF

Au sein de la communauté Kubernetes, une convention veut que les éléments natifs de Kubernetes fassent référence à kubernetes.io dans leur nommage, contrairement aux Add-ons Kubernetes. Ces derniers suivent en général une convention auto-documentée, comme ebs.csi.aws.com, qui permet d'identifier intuitivement un add-on. L'add-on aws-load-balancer-controller, lui, déroge à cette règle.

Public visé

Cet article s'adresse à trois publics avec trois objectifs distincts :

1. Administrateurs Kubernetes exploitant EKS ou des distributions Kubernetes génériques sur AWS : vous n'avez pas besoin de lire cet article, mais je vous recommande de le mettre en favori et de garder en tête qu'il existe comme document de référence à consulter le jour où vous devrez déboguer le provisionnement d'AWS Load Balancers via des Services Kubernetes annotés avec service.beta.kubernetes.io/aws-load-balancer-*.

2. Passionnés de Kubernetes qui apprécient les articles approfondis pour mieux comprendre Kubernetes.

3. Mainteneurs d'EKS, d'aws-cloud-controller-manager, d'aws-load-balancer-controller et de la documentation AWS : mon objectif est de mettre en lumière une incohérence déroutante propre au provisionnement de Load Balancers Kubernetes sur AWS. J'espère que cela encouragera un alignement avec les pratiques du reste de la communauté Kubernetes. (Le problème touche plusieurs dépôts git et sites de documentation, il n'est donc pas réglable par quelques merge requests.)

Introduction

J'ai récemment démarré une preuve de concept impliquant le provisionnement d'AWS Load Balancers pour un cluster EKS (Elastic Kubernetes Service) à l'aide de services Kubernetes de type LoadBalancer, avec des annotations de la forme service.beta.kubernetes.io/aws-load-balancer-* listées sur cette page.

Au départ, certaines annotations ne fonctionnaient pas comme prévu. J'ai pu les déboguer, mais pour y parvenir il a fallu comprendre pourquoi elles ne marchaient pas. La documentation de la page liée explique correctement le fonctionnement, mais ses explications restent peu accessibles aux débutants.

Cet article propose donc une analyse approfondie de plusieurs sujets :

  • Pourquoi aws-load-balancer-controller prête à confusion
  • Le contexte de fond qui aidera les débutants à se mettre à niveau
  • Les détails expliquant pourquoi les choses fonctionnent ainsi
  • Quelques conseils de dépannage simples mais utiles
  • Des pistes pour rendre tout cela moins confus à l'avenir, à l'attention des différents groupes de mainteneurs

Le défi : un cas d'identité confondue

J'ai indiqué que la page liée plus haut n'est pas très accessible aux débutants. Pour être plus clair : j'ai trouvé le projet suffisamment déroutant pour qu'il me faille une journée entière pour bien le saisir. C'est mauvais signe, sachant que je suis SME Kubernetes depuis juillet 2018. Une fois compris, ma première pensée a été : Ah voilà ce qui se passe. TIL (Today I learned) : il existe deux Controllers Kubernetes spécifiques à AWS qui peuvent finir par utiliser des annotations attachées à des Services Kubernetes de type Load Balancer pour provisionner et gérer des LBs AWS. Ma deuxième pensée : Wow… Comment les autres sont-ils censés comprendre ça sans expert ? Je devrais écrire un article là-dessus.

Voici la liste des éléments qui rendent le projet AWS Load Balancer Controller déroutant :

1.) Cela ressemble à une fonctionnalité officielle intégrée, mais ce n'en est pas une !

Quand j'ai fait une recherche Google pour aws service of type lb :

Premier résultat : docs.aws.amazon.com/eks/latest/userguide/network-load-balancing.html

Deuxième résultat : kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/service/annotations/

Et la section pertinente de la documentation officielle Kubernetes, qui est le premier résultat lorsque vous recherchez kubernetes service of type loadbalancer :

https://kubernetes.io/docs/concepts/services-networking/service/

Ces trois pages ressemblent toutes à de la documentation officielle, et donnent l'impression d'aborder le même sujet, puisque les mêmes annotations apparaissent sur les trois.

Si vous lancez un Ctrl+F sur les trois pages avec :

service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags

La même ressource apparaît sur les trois. Ce qui laisse penser, à première vue, qu'elles parlent toutes du même sujet.

En réalité, aws-load-balancer-controller est un Add-on Kubernetes qui étend la fonctionnalité native. Deux des liens ci-dessus traitent de la fonctionnalité native, et le troisième concerne un add-on qui propose des fonctionnalités étendues.

2.) La convention de nommage utilisée par le site et les annotations du projet est très peu intuitive. Elle vous laisse croire que les annotations renvoient à une fonctionnalité native :

2A.) Le nom de domaine où la documentation du projet est hébergée est kubernetes-sigs.github.io, ce qui donne l'impression qu'il pourrait s'agir d'une fonctionnalité native de Kubernetes.

2B.) Les annotations de l'add-on font référence à service.beta.kubernetes.io, généralement réservé à la fonctionnalité native.

3.) La page d'accueil du site de documentation du projet n'indique pas immédiatement qu'il s'agit d'un Add-on Kubernetes destiné à étendre la fonctionnalité native.

Ce n'est qu'en arrivant en bas de la deuxième page de la documentation

https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/deploy/installation/#add-controller-to-cluster

et en repérant helm install aws-load-balancer-controller que votre cerveau se dit : Aaah ! C'est un add-on, ok, ça a du sens.

4.) Le pattern utilisé par l'API n'est pas conforme au pattern habituel adopté par la communauté Kubernetes au sens large : je prendrai Cert Manager et le driver CSI (Container Storage Interface) pour les volumes EBS comme deux exemples de patterns standards :

  • Dans le cas de la documentation de cert-manager, 95 % de leurs annotations utilisent cert-manager.io. Cela rend immédiatement évident, d'un simple coup d'œil, que les annotations renvoient à un add-on tiers.
  • La première phrase de la page d'accueil de la documentation indique : cert-manager adds certificates and certificate issuers as resource types in Kubernetes clusters…, ce qui clarifie d'emblée qu'il s'agit d'une extension qui ajoute des fonctionnalités.
  • Dans le cas du driver CSI pour volumes EBS, une convention de nommage permet de distinguer clairement et intuitivement, d'un coup d'œil, qu'il diffère de la fonctionnalité native.

La Storage Class AWS native utilise provisioner: kubernetes.io/aws-ebs

La Storage Class de l'add-on EBS utilise provisioner :ebs.csi.aws.com

  • Il est très courant que les pages d'accueil des différents sites de documentation EBS CSI précisent à plusieurs reprises et d'emblée qu'il s'agit d'un add-on non installé par défaut. La documentation de ce projet va même jusqu'à intégrer délibérément le mot-clé driver pour rendre la chose plus intuitive : The Amazon EBS CSI driver isn't installed when you first create a cluster. To use the driver, you must add it as an Amazon EKS add-on or as a self-managed add-on. De plus, au cas où l'on tomberait sur la page GitHub plutôt que sur la documentation, même la page d'accueil GitHub du projet propose un lien vers Driver Installation.

5.) L'interface et la documentation d'AWS ne sont pas non plus cohérentes concernant aws-load-balancer-controller : AWS Load Balancer Controller dispose d'un guide utilisateur sur docs.aws.amazon.com intitulé Installing the AWS Load Balancer Controller add-on.

Mais si vous regardez l'interface graphique, il n'apparaît pas comme un add-on officiel, même quand vous cliquez sur Get more add-ons et que s'affichent Amazon EBS CSI Driver et AWS Distro for OpenTelemetry.

6.) Le projet manque d'éléments de contexte

La page consacrée aux annotations de service de la documentation évoque brièvement deux sujets à la fois utiles à comprendre (la compréhension facilitant le dépannage) et quasi impossibles à appréhender pour un nouveau venu sans explications complémentaires. Si vous tentez de chercher ces sujets sur Google, l'information disponible est très vague, fragmentée et apparemment contradictoire, à moins de saisir de nombreuses nuances.

Les deux sujets en question, brièvement mentionnés sans explication dans la documentation, sont :

1. in-tree : the k8s in-tree kube-controller-manager

2. Legacy AWS Cloud Provider : The AWS Load Balancer Controller manages Kubernetes Services in a compatible way with the legacy aws cloud provider.

Dans un monde idéal, on trouverait une définition synthétique de ces termes et un lien vers des lectures complémentaires pour les personnes intéressées. Voici comment je les résumerais : ce sont techniquement deux choses différentes, mais cela revient pratiquement au même. Le Legacy AWS Cloud Provider fournit la fonctionnalité par défaut, intégrée, qui permet de provisionner les services de type Load Balancer pour les clusters Kubernetes exécutés sur AWS.

Contexte de fond

Lorsque je dépanne quelque chose, la première chose que je fais est d'essayer de le comprendre. Le sujet du provisionnement de LBs AWS exige beaucoup de contexte de fond pour être pleinement compris. Malheureusement, jusqu'à aujourd'hui, ces informations étaient dispersées, jamais expliquées en profondeur, et truffées de nuances qui rendent la compréhension difficile. Voici ma tentative de regrouper quelques éléments-clés de contexte et de les rendre faciles à comprendre.

Contexte des sujets clés :

1.) kube-controller-manager vs cloud-controller-manager vs aws-cloud-controller-manager Il existe des nuances dans ce que désignent in-tree et Legacy AWS Cloud Provider, difficiles à saisir sans le contexte de fond de ces sujets connexes. Commençons donc par là.

Par le passé, Kubernetes comptait quatre composants de plan de contrôle : controller-manager, scheduler, api-server et etcd. Vous exécutiez soit kube-controller-manager, soit cloud-controller-manager, mais pas les deux.

Le cloud-controller-manager était l'option utilisée 95 % du temps. Il offrait les mêmes fonctionnalités que le kube-controller-manager, plus le support natif pour interagir avec plusieurs APIs de CSP (Cloud Service Provider). Comme il savait dialoguer avec les APIs des CSP, il pouvait par exemple provisionner des volumes AWS EBS et des AWS Load Balancers.

Le kube-controller-manager est une implémentation indépendante du cloud, donc il ne dispose pas nativement de la capacité à provisionner automatiquement le stockage CSP ou les Load Balancers CSP.

Aujourd'hui, Kubernetes possède normalement cinq composants de plan de contrôle :

etcd, kube-api-server, kube-scheduler, kube-controller-manager, et un controller manager spécifique au CSP comme aws-cloud-controller-manager. Les schémas de la documentation officielle Kubernetes ont été mis à jour pour refléter cette nouvelle architecture. Vous pouvez aussi le vérifier en utilisant des méthodes de déploiement comme kops ou kubeadm, qui vous permettent de visualiser le plan de contrôle. Le changement principal : il existe désormais des cloud controller managers dédiés à un seul fournisseur de services cloud, conçus pour s'exécuter aux côtés du kube-controller-manager. Tandis que le cloud-controller-manager d'origine était plutôt une solution universelle tout-en-un.

2.) In-tree fait référence à l'époque où les bibliothèques Go capables d'interagir avec plusieurs APIs de CSP étaient situées dans le dépôt Kubernetes pour construire une image de conteneur Cloud Controller Manager universelle :

In-tree : du code qui réside dans le dépôt principal de Kubernetes k8s.io/kubernetes.

Out-of-tree : du code qui réside dans un dépôt externe, en dehors du dépôt git k8s.io/kubernetes.

La base de code de Kubernetes 1.14 intégrait des APIs pour 8 CSPs différents. D'autres demandaient à s'ajouter, et le fait qu'ils soient tous regroupés signifiait qu'ils devaient tous atteindre la stabilité simultanément pour une release. Un modèle insoutenable du point de vue de la maintenabilité. Pour résoudre le problème, un KEP (Kubernetes Enhancement Proposal) a été approuvé. Il proposait de découpler la fonctionnalité CSP de Kubernetes et de la refactoriser en add-ons.

Ce découplage simplifierait le processus de release de Kubernetes et permettrait aux fournisseurs cloud de publier des fonctionnalités et des correctifs indépendamment du cycle et des processus de release de Kubernetes. Une décision visant à rembourser la dette technique afin d'assurer la pérennité du projet.

3.) Si vous tentez de faire vos propres recherches sur le sujet, vous trouverez facilement des informations qui semblent contradictoires à première vue, jusqu'à ce que vous saisissiez plusieurs nuances. En voici quelques-unes, dans le désordre :

Or le KEP suggère que la migration s'achèvera vers la version 1.27 ?

C'est précisément pour ce genre de raisons que j'ai choisi d'écrire un article plutôt que de contribuer à corriger un problème de documentation. Bien qu'AWS et d'autres CSPs existent toujours in-tree, dans une version universelle CSP du cloud controller manager, cette version n'est pas celle utilisée en pratique. AWS et les autres CSPs utilisent leur propre implémentation spécifique, comme aws-cloud-controller-manager, plutôt que l'ancien cloud-controller-manager universel tout-en-un in-tree.

Les différents CSPs ont achevé leur migration de l'universel in-tree vers le CSP-spécifique out-of-tree à des rythmes différents. Autre source de confusion : ce chantier complexe a été divisé en deux parties. La fonctionnalité native d'origine intégrée comprenait la logique de provisionnement du stockage CSP et des LBs CSP. Non seulement elle est passée out-of-tree, mais elle a en plus été davantage découplée, si bien que les drivers CSI pour le stockage CSP sont devenus un composant isolé, avec ses propres calendriers de migration.

  • Lorsqu'on prend conscience de l'ampleur de la complexité de cette refactorisation, plusieurs choses prennent du sens. D'abord, il n'est pas étonnant qu'elle ait pris plus de 4 ans. La fonctionnalité d'implémentations cloud provider out-of-tree a atteint le statut bêta dans la version 1.11, en mai 2019. Ensuite, quand on réalise que plusieurs gels de fonctionnalités ont été mis en place pour soutenir le processus de migration, on comprend mieux pourquoi des bugs liés à l'implémentation d'ExternalTrafficPolicy: Local sur les LBs AWS ont mis des années à être corrigés. Cela explique aussi pourquoi il y a eu peu d'améliorations fonctionnelles sur la logique native de provisionnement de LBs AWS pendant des années.

4.) Legacy AWS Cloud Provider désigne en gros la fonctionnalité par défaut de provisionnement de load balancers à laquelle vous avez accès dans une installation par défaut d'EKS ou de Kubernetes sur AWS.

Quelques nuances empêchent cette affirmation d'être exacte à 100 %, mais elle est suffisamment proche de la vérité pour être utile.

Voici ces nuances :

  • Legacy AWS Cloud Provider peut désigner la logique spécifique à AWS qui existait in-tree dans le cloud-controller-manager (universel CSP), capable de provisionner des volumes AWS EBS et des LBs AWS.
  • Legacy AWS Cloud Provider peut aussi désigner la logique de provisionnement de load balancer par défaut présente dans aws-cloud-controller-manager.
  • aws-cloud-controller-manager est souvent invisible pour les utilisateurs.

– Si vous utilisez EKS, aws-cloud-controller-manager s'exécute sur les nœuds master managés que vous ne pouvez pas voir.

– Si vous utilisez kops ou kubeadm avec des nœuds master auto-hébergés, vous le verrez.

– Si vous utilisez RKE2, vous ne le verrez pas en raison de certains détails d'implémentation de défense en profondeur qu'ils utilisent pour exécuter certains composants du plan de contrôle en tant que processus isolés de Kubernetes.

  • Legacy AWS Cloud Provider peut désigner deux choses distinctes, mais dans le contexte des LBs AWS, c'est en pratique la même chose puisqu'elles supportent les mêmes annotations. Vous pouvez retrouver les 22 annotations d'origine en cherchant la chaîne const ServiceAnnotationLoadBalancer sur cette page. Notez qu'à l'heure où j'écris ces lignes, en cherchant la chaîne service.beta.kubernetes.io/aws-load-balancer sur la page de doc, vous ne verrez que 21 annotations. Il s'agit simplement d'un problème de documentation, pas d'un changement de code.

Voici la liste des 22 annotations disponibles par défaut :

service.beta.kubernetes.io/aws-load-balancer-type
service.beta.kubernetes.io/aws-load-balancer-internal
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol
service.beta.kubernetes.io/aws-load-balancer-access-log-emit-interval
service.beta.kubernetes.io/aws-load-balancer-access-log-enabled
service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-name
service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-prefix
service.beta.kubernetes.io/aws-load-balancer-connection-draining-enabled
service.beta.kubernetes.io/aws-load-balancer-connection-draining-timeout
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled
service.beta.kubernetes.io/aws-load-balancer-extra-security-groups
service.beta.kubernetes.io/aws-load-balancer-security-groups
service.beta.kubernetes.io/aws-load-balancer-ssl-cert
service.beta.kubernetes.io/aws-load-balancer-ssl-ports
service.beta.kubernetes.io/aws-load-balancer-ssl-negotiation-policy
service.beta.kubernetes.io/aws-load-balancer-backend-protocol
service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags
service.beta.kubernetes.io/aws-load-balancer-healthcheck-healthy-threshold
service.beta.kubernetes.io/aws-load-balancer-healthcheck-unhealthy-threshold
service.beta.kubernetes.io/aws-load-balancer-healthcheck-timeout
service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval

5.) Le projet AWS Load Balancer Controller est conceptuellement similaire au projet AWS EBS CSI Driver : tous deux représentent le découplage d'une logique de Controller Kubernetes qui existait auparavant in-tree dans le cloud-controller-manager universel tout-en-un. Tous deux poursuivaient l'objectif commun d'assurer la rétrocompatibilité. Une partie de moi se demande si cela a joué un rôle dans la décision du projet de réutiliser certaines annotations.

6.) Les projets EBS CSI Driver Add-on et AWS LB Controller Add-on ont été lancés par des groupes différents.

Le projet EBS CSI Driver Add-on a été lancé par AWS. Le projet AWS LB Controller Add-on, lui, a été initialement lancé par Ticketmaster et CoreOS et était autrefois connu sous le nom d'AWS ALB Ingress Controller. Il a été cédé à Kubernetes SIG-AWS en 2018. Le ALB Ingress Controller était à l'origine surtout un Application Load Balancer Controller. Avec le temps, le périmètre du projet s'est élargi pour couvrir aussi le contrôle des NLBs. Ainsi, en juillet 2021, le projet a été rebaptisé AWS Load Balancer Controller.

Pourquoi en est-on arrivé là ?

Si la logique du cloud-controller-manager universel tout-en-un n'avait pas été migrée out-of-tree dans des add-ons externes découplés, la dette technique aurait définitivement ralenti tout développement futur de fonctionnalités et toute correction de bugs. Je me souviens d'une époque où des bugs liés à externalTrafficPolicy: local ne cessaient de réapparaître et mettaient des années à être correctement corrigés. Maintenant que la logique est découplée du code, du processus de release et des tests du projet officiel Kubernetes, les bugs sont corrigés en quelques mois plutôt qu'en années, et les demandes de fonctionnalités peuvent à nouveau être prises en compte.

Un développement plus rapide a permis de belles avancées, comme la simplification de l'implémentation du concept de Software Defined Perimeter via un proxy Authn/z, grâce à la nouvelle intégration d'AWS Cognito avec la logique de provisionnement des ALBs. Le projet AWS LB Controller propose également davantage d'options pour provisionner des NLBs via des annotations. Une nouvelle fonctionnalité que j'apprécie particulièrement est l'annotation service.beta.kubernetes.io/aws-load-balancer-nlb-target-type:, qui permet de choisir comment router le trafic vers les pods backend. La valeur par défaut "instance" fait transiter le trafic via nELB -> NodePort -> service Kube -> Pod. Une nouvelle valeur "ip" permet au trafic d'aller directement de nELB -> Pod, à la manière du fonctionnement d'aELB.

Référence abrégée :

nELB = network Elastic Load Balancer (LB L4 as a service)

aELB/ALB = application Elastic Load Balancer (LB L7 as a service)

cELB = classic Elastic Load Balancer (LB L4/L7 as a service)

Je suspecte que l'élargissement du périmètre du projet anciennement appelé ALB Ingress Controller pour inclure la gestion des nELBs s'explique en partie par le fait que le projet ALB Ingress Controller était probablement plus ouvert aux changements et nouvelles fonctionnalités à une époque où aws-cloud-controller-manager appliquait un gel de fonctionnalités pour faciliter la migration in-tree.

Quant à la question de savoir pourquoi AWS Load Balancer Controller ne ressemble pas davantage à l'AWS EBS CSI Driver Add-on, je pense que cela tient au fait qu'AWS a contrôlé le projet EBS CSI du début à la fin. Le projet LB Controller, lui, a été adopté, et les grandes organisations tendent à mettre en œuvre les changements lentement en raison de la loi de Brooks. (Les coûts de communication dans les grandes organisations ralentissent considérablement les changements.)

Conseils de dépannage pour AWS LB Controller

Ces conseils de dépannage ne se veulent ni étendus ni exhaustifs. Ils visent simplement à être suffisamment utiles pour vous débloquer et vous orienter vers les sujets pertinents pour approfondir vos recherches.

1.) Vérifiez si AWS LB Controller est installékubectl get deployments --namespace=kube-system

C'est important parce que cela peut entraîner des changements de comportement significatifs. Si vous avez deux clusters avec 99 % des mêmes workloads YAML et de la même configuration déployée, et que la différence de 1 % entre eux est la présence ou non d'AWS LB Controller, ce YAML pourtant identique à 99 % peut produire des résultats différents.

2.) Envisagez sérieusement de mettre à jour vers la dernière version

Vous pouvez utiliser la commande suivante pour voir la version exécutée :

kubectl get deploy aws-load-balancer-controller -n=kube-system -o yaml | grep image:

image: public.ecr.aws/eks/aws-load-balancer-controller:v2.4.6

Voici un scénario réel récent qui illustre l'utilité de rester à jour :

EKS 1.21 a atteint sa fin de vie le 15 février 2023. Quelques utilisateurs d'AWS LB Controller ont subi des interruptions, jusqu'à ce qu'ils passent de 2.3.x → 2.4.x. Ces interruptions étaient dues à la mise à jour de Kubernetes 1.21 vers 1.22, qui a supprimé de nombreuses APIs dépréciées. AWS LB Controller 2.4.x prend en charge la nouvelle API Ingress networking.k8s.io/v1. La 2.3.x ne supportait que l'ancienne API networking.k8s.io/v1beta1, supprimée de Kubernetes 1.22. Les tickets d'issue du projet aws-lb-controller avaient anticipé ce problème et fait en sorte que les versions 2.4.x fonctionnent avec Kubernetes 1.19++, donnant ainsi du temps aux organisations pour migrer. Celles qui suivent la bonne pratique consistant à maintenir leurs add-ons à jour ont évité les interruptions. Les autres, qui ne font qu'une maintenance minimale, ont probablement rencontré ce problème après avoir fini par mettre à jour Kubernetes pour rester sur une version supportée.

3.) Lisez attentivement, du début à la fin, l'ensemble de la documentation d'installation : il est facile de manquer certains prérequis :

En plus d'installer aws-load-balancer-controller dans le namespace kube-system et de configurer correctement les rôles IAM, vous devez aussi taguer correctement les sous-réseaux des VPCs.

# Extrait de configuration Terraform VPC as Code
module vpc {
  ...
  public_subnet_tags = {
    "kubernetes.io/role/elb"           = "1"
  }
  private_subnet_tags = {
    "kubernetes.io/role/internal-elb"  = "1"
  }
}

/*
Contexte supplémentaire :
Si vous consultez la documentation EKS
https://aws.amazon.com/premiumsupport/knowledge-center/eks-load-balancer-controller-subnets/
Vous y trouverez une référence à
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
Ce tag était requis par les anciennes versions d'aws-load-balancer-controller
*/

4.) Si vous devez déboguer un objet ingress, vérifiez quelles Ingressclasses sont installées

kubectl get ingressclass

Si vous en voyez plusieurs, exécutez kubectl describe ingressclass et vérifiez si l'une d'elles porte une annotation la marquant comme valeur par défaut.

Si la classe ingress alb n'est pas marquée comme valeur par défaut, vous devez explicitement spécifier la classe ingress souhaitée sur l'objet ingress que vous tentez de déboguer.

5. Si vous devez déboguer des annotations de provisionnement de LB spécifiques aux objets service, c'est un peu plus compliqué…

En quoi c'est compliqué :

  • Vous avez en pratique deux Controllers différents qui s'exécutent en même temps dans le même cluster.
  • Dans le cas d'EKS, comme c'est un service managé / les nœuds master Kubernetes sont managés, vous ne pouvez voir visuellement qu'un seul des deux Controllers. (Vous ne verrez pas aws-cloud-controller-manager, car il s'exécute sur les nœuds master managés.)
  • Les deux Controllers présentent de nombreux recoupements en termes de fonctionnalités et d'objets dont ils sont responsables :

– aws-cloud-controller-manager : provisionne les cELBs et les nELBs

– aws-load-balancer-controller : provisionne les aELBs et les nELBs

5A.) Identifiez quel Controller gère activement votre objet service Kubernetes. D'après cette doc, si vous annotez un service Kubernetes avec l'une de ces options :

service.beta.kubernetes.io/aws-load-balancer-type: nlb-ip service.beta.kubernetes.io/aws-load-balancer-type: external

Alors le Controller aws-cloud-controller-manager ignorera l'objet, ce qui permet à aws-load-balancer-controller de le gérer.

5B.) Si aws-load-balancer-controller gère un service, kubectl describe service devient utile ! Beaucoup de ceux qui ont essayé des options LB avancées ont probablement rencontré un scénario où le LB reste bloqué en statut pending et refuse de se provisionner. Disons que vous lancez kubectl describe service $NAME pour le déboguer. Si Legacy AWS Controller Manager gère le service, vous obtiendrez probablement un message d'erreur inutile. Si aws-load-balancer-controller gère le service, vous obtiendrez en revanche des messages d'erreur réellement utiles pour le débogage. (Ils sont parfaits pour signaler une étape d'installation manquée, comme l'absence de droits IAM, ou l'oubli du tagging des sous-réseaux.)

5C.) Parcourez les notes de release pour repérer les changements à prendre en compte :

  • aws-cloud-controller-manager provisionne par défaut des LBs avec des IPs publiques. Vous devez ajouter une configuration pour provisionner des IPs privées. C'est l'inverse pour aws-load-balancer-controller. (depuis la v2.2.0)
  • aws-cloud-controller-manager provisionne par défaut des cELBs. aws-load-balancer-controller, lui, provisionne par défaut des nELBs (pour tout objet annoté avec service.beta.kubernetes.io/aws-load-balancer-type: external, qui détermine quel Controller est aux commandes).
  • Les images de conteneurs d'aws-cloud-controller-manager étaient auparavant disponibles sur Docker Hub, mais à partir de la v2.4.6, elles ne seront hébergées que sur le registre de conteneurs public.ecr.aws.

5D.) La plupart des objets Kubernetes prennent en charge des boucles de réconciliation qui font passer l'état actuel à l'état souhaité. Les Controllers de Load Balancer comportent toutefois quelques cas particuliers où il faut supprimer puis recréer pour que les changements itératifs prennent effet.

Ce n'est généralement pas nécessaire, mais cela vaut parfois la peine d'essayer. L'annotation du point 5A est un exemple où la documentation recommande la recréation plutôt que la modification. Il convient également de noter que les valeurs nlb-ip et external sont spécifiques à AWS LB Controller, tandis que le Legacy Controller utilise les valeurs nlb et (vide pour provisionner un cELB). Cette subtilité peut s'avérer importante pour quiconque utilise un controller GitOps comme ArgoCD ou Flux pour effectuer des changements itératifs, car ceux-ci tendent à mettre à jour les manifestes plutôt qu'à supprimer et recréer les ressources. Ainsi, un utilisateur d'ArgoCD ou de Flux qui testerait des changements itératifs dans un environnement de dev pourrait avoir besoin d'une intervention manuelle dans ce cas particulier pour voir ses changements appliqués.

J'avais deux raisons principales d'écrire cet article. La première était de partager des connaissances, et cette partie est faite. La seconde était d'encourager des changements susceptibles de rendre tout cela moins déroutant. Trois changements pourraient être apportés par les mainteneurs de projets et de documentation pour considérablement réduire la confusion. Tous consistent à rapprocher aws-load-balancer-controller du projet EBS-CSI :

  1. Ajouter le projet à la liste EKS des add-ons officiels installables via la console graphique AWS.
  2. Mettre à jour la documentation à plusieurs endroits pour qu'il soit immédiatement évident qu'aws-load-balancer-controller est un add-on.
  3. Mettre à jour les annotations qui font référence à kubernetes.io pour qu'elles ressemblent davantage à ebs.csi.aws.com. Cela rendrait le statut d'add-on évident à l'inspection et aurait un effet SEO (search engine optimization) qui améliorerait l'expérience utilisateur lors de la recherche de la documentation pertinente.