Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Desmistificando o Kubernetes AWS LB Controller

By Chris McGrathMar 20, 202319 min read

Esta página também está disponível em English, Deutsch, Español, Français, Italiano e 日本語.

BLUF

Existe uma convenção dentro da comunidade Kubernetes em que componentes nativos do Kubernetes referenciam kubernetes.io em sua nomenclatura, enquanto add-ons do Kubernetes não. Os add-ons costumam seguir uma convenção autoexplicativa, como ebs.csi.aws.com, em que dá para identificar intuitivamente que se trata de um add-on. O add-on aws-load-balancer-controller foge dessa convenção.

Público-alvo

Este artigo tem três públicos/objetivos:

1. Administradores de Kubernetes que rodam EKS ou distribuições genéricas de Kubernetes na AWS — você não precisa ler isso agora, mas recomendo salvar nos favoritos e lembrar que ele existe como material de referência caso um dia precise depurar o provisionamento de AWS Load Balancers usando Kubernetes Services com annotations do tipo service.beta.kubernetes.io/aws-load-balancer-*.

2. Entusiastas de Kubernetes que curtem artigos de mergulho profundo que ajudam a entender melhor o Kubernetes.

3. Mantenedores de EKS, aws-cloud-controller-manager, aws-load-balancer-controller e da documentação da AWS: minha intenção com este artigo é jogar luz sobre uma inconsistência confusa que é exclusiva do provisionamento de Load Balancers Kubernetes na AWS. Espero que isso incentive uma mudança em direção à consistência com o restante da comunidade Kubernetes. (A questão envolve diversos repositórios git e sites de documentação, então não dá para resolver com poucos merge requests.)

Introdução

Comecei recentemente uma prova de conceito que envolvia provisionar AWS Load Balancers para um cluster EKS (Elastic Kubernetes Service) usando Kubernetes services do tipo LoadBalancer com annotations no formato service.beta.kubernetes.io/aws-load-balancer-*, listadas nesta página.

De início, algumas annotations não funcionaram como eu esperava. Consegui resolver os problemas, mas vale destacar que, para chegar à solução, precisei entender por que não estavam funcionando. A documentação na página linkada faz um trabalho razoável explicando como as coisas funcionam, mas as explicações não são muito amigáveis para iniciantes.

Por isso, este post servirá como uma explicação aprofundada de vários tópicos:

  • Por que o aws-load-balancer-controller é confuso
  • Informações de contexto que vão ajudar iniciantes a se atualizarem
  • Detalhes sobre por que as coisas funcionam do jeito que funcionam
  • Algumas dicas básicas, mas úteis, de troubleshooting
  • Ideias de como diferentes grupos de mantenedores poderiam tornar isso menos confuso no futuro

Desafio: um caso de identidade trocada

Mencionei que não acho a página linkada acima muito amigável para iniciantes. Para deixar claro: achei o projeto confuso o bastante para levar um dia inteiro até eu pegar o jeito da coisa. Isso é um mau sinal, já que sou especialista em Kubernetes desde julho de 2018. Depois de entender, meu primeiro pensamento foi: "Ah, é isso que está acontecendo. Hoje aprendi que existem dois Controllers Kubernetes específicos da AWS diferentes que podem acabar usando annotations anexadas a Kubernetes Services do tipo Load Balancer para provisionar e gerenciar AWS LBs." Meu segundo pensamento foi: "Nossa… Como é que outras pessoas vão entender isso sem um especialista por perto? Preciso escrever um artigo sobre isso."

Aqui está uma lista de itens que tornam o projeto AWS Load Balancer Controller confuso:

1.) Parece uma funcionalidade oficial e nativa, mas não é!

Quando fiz uma busca no Google por "aws service of type lb"

O primeiro resultado: docs.aws.amazon.com/eks/latest/userguide/network-load-balancing.html

O segundo resultado: kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/service/annotations/

E a seção relevante da documentação oficial do Kubernetes, que é o primeiro resultado quando você busca por "kubernetes service of type loadbalancer"

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

As três páginas parecem documentação oficial e dão a impressão de tratar do mesmo assunto, porque as mesmas annotations aparecem em todas elas.

Se você der control+f nas três páginas por:

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

O mesmo recurso aparece nas três páginas. O que faz você pensar, à primeira vista, que os três sites estão falando da mesma coisa.

Na verdade, o aws-load-balancer-controller é um add-on do Kubernetes que estende a funcionalidade nativa. Ou seja, dois dos links acima cobrem funcionalidade nativa, e o terceiro é um add-on que oferece funcionalidade estendida.

2.) A convenção de nomenclatura usada pelo site do projeto e pelas annotations é bem pouco intuitiva. Ela engana você, fazendo parecer que as annotations referenciam funcionalidade nativa:

2A.) O nome DNS onde a documentação do projeto está hospedada é kubernetes-sigs.github.io, o que dá a impressão de ser uma funcionalidade nativa do Kubernetes.

2B.) As annotations do add-on referenciam service.beta.kubernetes.io, que normalmente é reservado para funcionalidades nativas.

3.) A página inicial do site de documentação do projeto não deixa imediatamente óbvio que se trata de um add-on do Kubernetes voltado a estender a funcionalidade nativa.

Só perto do final da segunda página da documentação

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

e ao se deparar com helm install aws-load-balancer-controller, você pensa: "Ahhh! Então é um add-on. Beleza, agora faz sentido."

4.) O padrão usado pela API é inconsistente com o padrão normal adotado pela comunidade Kubernetes em geral: Vou usar o Cert Manager e o EBS Volume CSI (Container Storage Interface) Driver como dois exemplos de padrões normais:

  • No caso da documentação do cert-manager, 95% das annotations usam cert-manager.io. Isso deixa intuitivamente óbvio, à primeira vista, que as annotations se referem a um add-on de terceiros.
  • A primeira frase da página inicial da documentação é "cert-manager adiciona certificados e emissores de certificados como tipos de recurso em clusters Kubernetes…", o que ajuda a deixar claro logo de cara que o projeto é uma extensão que adiciona funcionalidade.
  • No caso do EBS Volume CSI Driver, é usada uma convenção de nomenclatura que ajuda a distinguir claramente, à primeira vista, que ele é diferente da funcionalidade nativa.

A Storage Class nativa da AWS usa provisioner: kubernetes.io/aws-ebs

A Storage Class do add-on EBS usa provisioner:ebs.csi.aws.com

  • É bem comum que as páginas iniciais de várias documentações do EBS CSI deixem claro logo de cara, e de forma repetida, que se trata de um add-on que não é instalado por padrão. A documentação desse projeto chega a incluir propositalmente a palavra-chave "driver" para tornar isso mais intuitivo: "O Amazon EBS CSI driver não é instalado quando você cria um cluster pela primeira vez. Para usar o driver, você precisa adicioná-lo como um add-on do Amazon EKS ou como um add-on autogerenciado." E, caso a pessoa caia na página do GitHub em vez da documentação, até a página inicial do projeto no GitHub tem um link para "Driver Installation"

5.) A interface e a documentação da AWS também são inconsistentes quando o assunto é o aws-load-balancer-controller: O AWS Load Balancer Controller tem um guia do usuário em docs.aws.amazon.com intitulado "Installing the AWS Load Balancer Controller add-on"

Mas se você olhar na GUI, ele não aparece como add-on oficial — nem mesmo quando você clica em Get more add-ons e vê o Amazon EBS CSI Driver e o AWS Distro for OpenTelemetry

6.) Falta contexto no projeto

A página de annotations de service da documentação menciona brevemente dois tópicos que são úteis de entender (já que entender ajuda no troubleshooting) e quase impossíveis para um iniciante absorver sem explicações adicionais. Se você tentar pesquisar esses tópicos no Google, as informações que vai encontrar são vagas, fragmentadas e aparentemente contraditórias, a menos que consiga captar muitas nuances.

Os dois tópicos a que me refiro, mencionados rapidamente sem explicação na documentação, são:

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."

Em um mundo ideal, haveria uma definição resumida do que esses termos significam e um link para leitura adicional para quem tivesse interesse. É assim que eu resumiria: tecnicamente, são duas coisas diferentes, mas, na prática, podem ser tratadas como a mesma coisa. O Legacy AWS Cloud Provider é o que fornece a funcionalidade nativa padrão de provisionar services do tipo Load Balancer para clusters Kubernetes rodando na AWS.

Informações de contexto

Sempre que estou fazendo troubleshooting de algo, a primeira coisa que faço é tentar entender o assunto. O tópico de provisionamento de AWS LBs exige bastante contexto para ser entendido por completo. Infelizmente, até hoje essas informações estavam dispersas, nunca eram explicadas a fundo e estavam cheias de nuances que dificultam a compreensão. Esta é minha tentativa de consolidar algumas informações de contexto importantes e torná-las fáceis de entender.

Contexto dos tópicos principais:

1.) kube-controller-manager vs cloud-controller-manager vs aws-cloud-controller-manager Existem nuances no que "in-tree" e "Legacy AWS Cloud Provider" significam que são difíceis de entender sem o contexto sobre esses tópicos relacionados, então vamos começar por aqui.

No passado, o Kubernetes tinha quatro componentes do control plane: o controller-manager, o scheduler, o api-server e o etcd. Você executava ou o kube-controller-manager ou o cloud-controller-manager, não os dois.

O cloud-controller-manager era a opção usada em 95% dos casos. Ele tinha a mesma funcionalidade do kube-controller-manager, além de suporte nativo para fazer interface com várias APIs de CSP (Cloud Service Provider). Como sabia conversar com APIs de CSPs, conseguia fazer coisas como provisionar volumes AWS EBS e AWS Load Balancers.

Já o kube-controller-manager é uma implementação cloud-agnostic, então não tem a capacidade nativa de fazer coisas como provisionar automaticamente storage e Load Balancers de CSPs.

Hoje, o Kubernetes normalmente tem cinco componentes do control plane:

etcd, kube-api-server, kube-scheduler, kube-controller-manager e um controller manager específico do CSP, como o aws-cloud-controller-manager. Os diagramas dentro da documentação oficial do Kubernetes foram atualizados para refletir essa nova arquitetura. Você também pode confirmar isso usando métodos de deploy como kops ou kubeadm, que permitem ver o control plane. A principal mudança é que agora você tem cloud controller managers dedicados a um único cloud service provider, pensados para rodar junto com o kube-controller-manager. Já o cloud-controller-manager original era mais uma solução universal, tudo-em-um.

2.) "In-tree" se refere à época em que as bibliotecas em Go que sabiam fazer interface com várias APIs de CSPs ficavam no repositório do Kubernetes para construir uma imagem de container universal do Kubernetes Cloud Controller Manager:

In-tree: código que vive no repositório principal do Kubernetes k8s.io/kubernetes.

Out-of-Tree: código que vive em um repositório externo, fora do repositório git k8s.io/kubernetes.

O code base do Kubernetes 1.14 já trazia APIs para 8 CSPs diferentes embutidas. Outros queriam ser adicionados, e o fato de todos estarem agrupados significava que todos precisavam atingir estabilidade ao mesmo tempo para um release. Era um padrão insustentável do ponto de vista de manutenibilidade. Para resolver o problema, foi aprovada uma KEP (Kubernetes Enhancement Proposal). Ela propunha que a funcionalidade dos CSPs fosse desacoplada do Kubernetes e refatorada em add-ons.

Esse desacoplamento de funcionalidade simplificaria o processo de release do Kubernetes e permitiria que os cloud providers liberassem features e correções de bugs independentemente do ciclo e dos processos de release do Kubernetes. Foi uma decisão de quitar dívida técnica para garantir a saúde do projeto a longo prazo.

3.) Se você tentar pesquisar esse tópico por conta própria, é fácil esbarrar em informações que à primeira vista parecem conflitantes, até começar a captar várias nuances. Aqui vão algumas nuances, sem ordem específica:

Mas a KEP sugere que a migração será concluída por volta da versão 1.27?

É por causa de coisas assim que escolhi escrever um artigo em vez de contribuir corrigindo um problema na documentação. Embora a AWS e outros CSPs ainda existam in-tree/em uma versão universal de cloud controller manager, não é essa versão que se usa na prática. A AWS e outros CSPs usam suas próprias implementações específicas de CSP, como o aws-cloud-controller-manager, em vez do antigo cloud-controller-manager universal tudo-em-um in-tree.

Diferentes CSPs vêm concluindo sua migração do universal in-tree para o específico de CSP out-of-tree em ritmos diferentes. Outra coisa um tanto confusa é que esse esforço complexo foi dividido em duas partes. A funcionalidade nativa original in-tree incluía lógica para provisionar storage de CSPs e LBs de CSPs. Não só isso foi tirado do in-tree, como foi ainda mais desacoplado, de modo que os CSI drivers para storage de CSP viraram um componente isolado, com seus próprios cronogramas de migração.

  • Quando você se dá conta da escala da complexidade envolvida nessa refatoração, algumas coisas começam a fazer sentido. Primeiro, não é à toa que a refatoração levou mais de 4 anos. As implementações out-of-tree de cloud provider chegaram ao status beta na versão 1.11, lá em maio de 2019. Segundo, quando você percebe que houve vários feature freezes implementados para apoiar o processo de migração, começa a fazer sentido por que coisas como bugs associados à implementação de ExternalTrafficPolicy: Local em AWS LBs levaram anos para ser corrigidas. Isso também explica por que não houve muitas melhorias de features na lógica nativa de provisionamento de AWS LBs por anos.

4.) "Legacy AWS Cloud Provider" basicamente se refere à funcionalidade padrão de provisionamento de load balancers à qual você tem acesso em uma instalação padrão de EKS ou Kubernetes na AWS.

Há algumas nuances que impedem a afirmação acima de ser 100% precisa, mas ela está perto o bastante da verdade para ser útil.

As nuances são as seguintes:

  • Legacy AWS Cloud Provider pode se referir à lógica específica da AWS que existia in-tree, no cloud-controller-manager (CSP universal), que conseguia provisionar volumes AWS EBS e AWS LBs.
  • Legacy AWS Cloud Provider também pode se referir à lógica padrão de provisionamento de load balancer presente no aws-cloud-controller-manager.
  • O aws-cloud-controller-manager muitas vezes é invisível para os usuários.

– Se você usa EKS, o aws-cloud-controller-manager está rodando nos nós master gerenciados, que você não consegue ver.

– Se você usa kops ou kubeadm, que usam nós master self-hosted, você consegue vê-lo.

– Se você usa RKE2, não vai vê-lo, por causa de alguns detalhes de implementação de segurança em camadas (defense in-depth) usados para rodar certos componentes do control plane como processos isolados do Kubernetes.

  • O Legacy AWS Cloud Provider pode se referir a duas coisas diferentes, mas, no contexto dos AWS LBs, são efetivamente a mesma coisa, já que dão suporte às mesmas annotations. Você encontra as 22 annotations originais buscando esta página pela string const ServiceAnnotationLoadBalancer. Note que, no momento em que escrevo isso, se você buscar a string service.beta.kubernetes.io/aws-load-balancer na página da documentação, vai ver apenas 21 annotations. Isso é só um problema na documentação, não uma mudança no código.

Aqui está a lista das 22 annotations às quais você tem acesso por padrão:

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.) O projeto AWS Load Balancer Controller é conceitualmente parecido com o projeto AWS EBS CSI Driver: Ambos representam o desacoplamento da lógica de Controller do Kubernetes que costumava existir in-tree no cloud-controller-manager universal tudo-em-um. Ambos tinham o objetivo comum de garantir compatibilidade retroativa. Parte de mim se pergunta se isso teve algum papel na decisão do projeto de reaproveitar algumas annotations.

6.) Os projetos do EBS CSI Driver Add-on e do AWS LB Controller Add-on foram iniciados por grupos diferentes.

O projeto EBS CSI Driver Add-on foi iniciado pela AWS. Já o projeto AWS LB Controller Add-on foi originalmente iniciado pela Ticketmaster e pela CoreOS, e antes era conhecido como "AWS ALB Ingress Controller". Ele foi doado ao Kubernetes SIG-AWS em 2018. Originalmente, o ALB Ingress Controller era melhor descrito como um Application Load Balancer Controller. Depois de um tempo, o escopo do projeto se expandiu para também controlar NLBs. Por isso, em julho de 2021, o projeto foi rebatizado como "AWS Load Balancer Controller."

Por que as coisas são do jeito que são?

Se a lógica do cloud-controller-manager universal tudo-em-um não tivesse sido migrada para fora do tree em add-ons externos desacoplados, a dívida técnica teria desacelerado permanentemente todo o desenvolvimento futuro de features e correções de bugs. Lembro de uma época em que bugs relacionados a externalTrafficPolicy: local ficavam reaparecendo e levaram anos para ser corrigidos como deve. Agora que a lógica está desacoplada do código, do processo de release e dos testes do projeto oficial do Kubernetes, os bugs são corrigidos em meses, e não em anos, e pedidos de novas features podem voltar a ser considerados.

O desenvolvimento mais rápido trouxe grandes melhorias, como tornar o conceito de Software Defined Perimeter via proxy de Authn/z mais fácil de implementar, graças à nova integração do AWS Cognito com a lógica de provisionamento de ALB. O projeto AWS LB Controller também tem mais opções na hora de provisionar NLBs via annotations. Uma feature nova de que gosto bastante é a annotation service.beta.kubernetes.io/aws-load-balancer-nlb-target-type:, que permite escolher como você vai rotear o tráfego para os pods de backend. O valor padrão "instance" faz com que o tráfego vá do nELB -> NodePort -> Kube service -> Pod. Um valor adicionado recentemente, "ip", faz com que o tráfego possa ir do nELB -> Pod, parecido com a forma como o aELB funciona.

Referência abreviada:

nELB = network Elastic Load Balancer (LB L4 como serviço)

aELB/ALB = application Elastic Load Balancer (LB L7 como serviço)

cELB = classic Elastic Load Balancer (LB L4/L7 como serviço)

Suspeito que parte da razão pela qual ocorreu o scope creep de trazer o gerenciamento de nELBs para o projeto antes conhecido como ALB Ingress Controller foi que o ALB Ingress Controller provavelmente estava mais aberto a mudanças e novas features em uma época em que o aws-cloud-controller-manager estava em feature freeze para apoiar a migração in-tree.

Quanto a por que o AWS Load Balancer Controller não é mais parecido com o AWS EBS CSI Driver Add-on? Acho que tem a ver com o fato de que a AWS teve controle sobre o projeto EBS CSI do início ao fim. Já o projeto LB Controller foi adotado, e organizações grandes tendem a implementar mudanças mais devagar por causa da lei de Brooks. (O overhead de comunicação em organizações grandes desacelera bastante as mudanças.)

Dicas de troubleshooting do AWS LB Controller

Estas dicas de troubleshooting não pretendem ser extensas nem exaustivas. Elas são úteis o bastante para destravar você e apontar a direção certa para os tópicos que valem uma pesquisa de acompanhamento.

1.) Verifique se o AWS LB Controller está instaladokubectl get deployments --namespace=kube-system

Isso é importante porque pode causar mudanças significativas de comportamento. Se você tem dois clusters com 99% dos mesmos workloads YAML e configuração implantados, e a diferença de 1% entre eles é se o AWS LB Controller está instalado ou não, os 99% de YAML iguais podem produzir resultados diferentes.

2.) Considere seriamente atualizar para a versão mais nova

Você pode usar o seguinte comando para ver qual versão está rodando

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

Aqui vai um cenário real recente em que a prática de manter-se atualizado foi útil:

O EKS 1.21 chegou ao fim de vida em 15/02/2023. Alguns usuários do AWS LB Controller passaram por interrupções, até atualizarem da 2.3.x → 2.4.x. As interrupções aconteceram porque o upgrade do Kubernetes 1.21 para 1.22 removeu várias APIs depreciadas. O AWS LB Controller 2.4.x suporta a API de Ingress mais recente networking.k8s.io/v1. A 2.3.x só suporta a API mais antiga networking.k8s.io/v1beta1, que foi removida no Kubernetes 1.22. Os tickets de issue do projeto aws-lb-controller notaram que isso seria um problema e fizeram com que as versões 2.4.x funcionassem com Kubernetes 1.19++, o que deu tempo para as organizações migrarem. As organizações que seguem a boa prática de manter seus add-ons atualizados evitaram interrupções. Já as outras, que fazem manutenção mínima, provavelmente esbarraram nesse problema depois de atualizarem o Kubernetes para se manter em uma release suportada.

3.) Faça uma leitura completa, do começo ao fim, de toda a documentação de instalação — é fácil deixar passar alguns requisitos:

Além de instalar o aws-load-balancer-controller no namespace kube-system e configurar corretamente as IAM roles, você também precisa taggear corretamente as subnets das VPCs.

# Trecho da configuração de VPC em Terraform como código
module vpc {
  ...
  public_subnet_tags = {
    "kubernetes.io/role/elb"           = "1"
  }
  private_subnet_tags = {
    "kubernetes.io/role/internal-elb"  = "1"
  }
}

/*
Informação contextual adicional:
Se você olhar a documentação do EKS
https://aws.amazon.com/premiumsupport/knowledge-center/eks-load-balancer-controller-subnets/
Vai ver uma referência a
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
Essa tag costumava ser obrigatória em versões mais antigas do aws-load-balancer-controller
*/

4.) Se você precisar depurar um objeto ingress, verifique quais Ingressclasses estão instaladas

kubectl get ingressclass

Se aparecer mais de uma, rode kubectl describe ingressclass e veja se uma das ingress classes tem uma annotation marcando-a como padrão.

Se a ingress class do alb não estiver marcada como padrão, liste explicitamente a ingress class desejada no objeto ingress que você está tentando depurar.

5. Se você precisar depurar annotations de provisionamento de LB específicas a objetos service, as coisas ficam um pouco mais complicadas…

O que torna tudo complicado:

  • Você teria, na prática, dois controllers diferentes rodando no mesmo cluster ao mesmo tempo.
  • No caso do EKS, como é um serviço gerenciado/tem nós master Kubernetes gerenciados, você só consegue ver visualmente um dos dois controllers. (Você não vai ver o aws-cloud-controller-manager, já que ele está rodando nos nós master gerenciados.)
  • Os dois controllers têm bastante sobreposição em termos de funcionalidade de features e dos objetos pelos quais são responsáveis:

– aws-cloud-controller-manager: provisiona cELBs e nELBs

– aws-load-balancer-controller: provisiona aELBs e nELBs

5A.) Determine qual controller está gerenciando ativamente o seu objeto Kubernetes service. De acordo com esta documentação, se você anotar um Kubernetes service com qualquer uma destas opções:

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

Então o controller aws-cloud-controller-manager vai ignorar o objeto, para que o aws-load-balancer-controller possa gerenciá-lo.

5B.) Se o aws-load-balancer-controller está gerenciando um service, o kubectl describe service se torna útil! Quem já tentou opções avançadas de LB provavelmente já se deparou com um cenário em que o LB fica preso no status pending e se recusa a provisionar. Digamos que você rode kubectl describe service $NAME para depurar. Se o Legacy AWS Controller Manager estiver gerenciando o service, você provavelmente vai receber uma mensagem de erro inútil. Se o aws-load-balancer-controller estiver gerenciando o service, você vai realmente receber mensagens de erro úteis para depuração. (Elas são ótimas para apontar se você errou alguma etapa de instalação, como permissões IAM faltantes, ou se esqueceu da parte de taggear subnets.)

5C.) Dê uma olhada nas release notes para revisar quaisquer mudanças que precisam ser consideradas:

  • O aws-cloud-controller-manager, por padrão, provisiona LBs com IPs públicos. Você precisa adicionar configuração para provisionar IPs privados. O contrário vale para o aws-load-balancer-controller. (desde a v2.2.0)
  • O aws-cloud-controller-manager, por padrão, provisiona cELBs. O aws-load-balancer-controller, por padrão, provisiona nELBs (para qualquer service anotado com service.beta.kubernetes.io/aws-load-balancer-type: external, já que é isso que controla qual controller está no comando.)
  • As imagens de container do aws-cloud-controller-manager costumavam estar disponíveis no Docker Hub, mas, a partir da v2.4.6, elas só serão hospedadas no container registry public.ecr.aws daqui para frente

5D.) A maioria dos objetos Kubernetes suporta loops de reconciliação que levam o estado atual ao estado desejado. Os controllers de Load Balancer costumam ter alguns casos de borda em que você precisa deletar e recriar para que mudanças iterativas tenham efeito.

Isso normalmente não é necessário, mas às vezes vale a pena tentar; a annotation em 5A é um exemplo em que a documentação recomenda recriar em vez de modificar. Também vale ressaltar que os valores nlb-ip e external são específicos do AWS LB Controller; o Legacy Controller usa os valores nlb e (em branco vai provisionar um cELB). Essa pegadinha pode ser importante para quem usa um controller de GitOps como ArgoCD ou Flux para fazer mudanças iterativas, já que essas ferramentas tendem a atualizar manifestos em vez de deletar e recriar recursos. Então, se um usuário de ArgoCD ou Flux estiver testando mudanças iterativas em um ambiente de dev, pode ser que precise fazer intervenção manual nesse caso de borda para ver suas mudanças aplicadas.

Tive duas razões principais para escrever este artigo. A primeira foi compartilhar conhecimento, e essa parte está pronta. A segunda foi ajudar a incentivar mudanças que possam tornar tudo isso menos confuso. Há três mudanças que mantenedores do projeto e da documentação poderiam fazer e que ajudariam muito a esclarecer a confusão. Todas envolvem deixar o aws-load-balancer-controller mais parecido com o projeto EBS-CSI:

  1. Adicionar o projeto à lista de add-ons oficiais do EKS, que são instaláveis pela GUI do AWS Console.
  2. Atualizar a documentação em vários lugares para deixar imediatamente óbvio que o aws-load-balancer-controller é um add-on.
  3. Atualizar as annotations, deixando de referenciar kubernetes.io para algo mais parecido com ebs.csi.aws.com. Isso porque torna o status de add-on óbvio à inspeção e tem um efeito de SEO (search engine optimization) que melhoraria a experiência do usuário ao buscar a documentação relevante.