Como acelerar um cluster do Kubernetes em 100 mil pods em 10 vezes

O que fazer quando um cacho se transforma em abóbora? Começamos a responder a essa pergunta no artigo anterior. Hoje continuaremos a analisar os métodos de construção de grandes clusters.

O primeiro passo dBrain.cloud para a construção de grandes clusters foi dividir o etcd. Em seguida, abordamos o controlador-gerente.

Como não perder tempo coletando lixo?

controller-managers têm uma caixa de seleção “controllers”. Existem muitos controladores internos, cada um dos quais é responsável por seus próprios objetos: replicasets, pods, etc. Exemplo: existem três réplicas de controladores-gerentes, eles escolhem um mestre entre si - e no final apenas um funciona.

O que faz o controlador-gerente? Ele compara o status do cluster com o de referência. O Controller-manager anda constantemente pelo cluster e compara o estado atual com o registrado no etcd, Kubernetes, etc. O Controller-manager verifica todas as descrições de objetos no Kubernetes e procura objetos sem proprietário, ou seja, Kubernetes criado dinamicamente, não usuários. Em um de nossos projetos de alta carga com mais de 100 mil pods, descobrimos que o controlador-gerente gastava 90% de seu tempo na coleta de lixo. Ele simplesmente não tinha tempo para fazer seu trabalho direto: verificar o número de pods, réplicas de implantações, serviços, endereços de registro, etc.

Graças à caixa de seleção “controladores”, dividimos o controlador-gerenciador em três clusters. Aconteceu como com o etcd: três clusters com três gerenciadores de controladores em cada um, e um deles é o mestre. Assim, temos três instâncias de controlador-gerenciador rodando em paralelo e executando tarefas diferentes.

Agora, o esquema dos gerenciadores de controladores é assim: o primeiro assumiu toda a carga de trabalho: ReplicaSet, Services, Deployments, StatefulSet, etc., o segundo - coleta de lixo, cálculo de ttl, etc., o terceiro - todo o resto: nó, pv, pvc, certs, etc.

Foi assim que tornamos o cluster mais responsivo a várias mudanças. A coleta de lixo ocorre em um controlador-gerenciador separado, o processo pode continuar continuamente, agora não afeta a operação do cluster.

HPA para controle de carga e enviado

No dBrain, como em outros lugares, os servidores de API estão localizados em pods estáticos e agora são usados como bootstraps para iniciar clusters, a rede de sobreposição e os principais servidores de API estão na implantação. Colocamos seus certificados em segredos do Kubernetes, então agora os servidores de API podem percorrer todo o cluster e não estar estaticamente em alguns nós. Graças a essas manipulações, todas as vantagens do Kubernetes aparecem na forma de fensy, autoscaling e tolerância a falhas. Agora que configuramos o HPA (Horizontal Pod Autoscaler) nos servidores de API no dBrain, eles serão dimensionados automaticamente dependendo da utilização. Esperamos que você ache nosso hack de vida útil :)

O dBrain tem um enviado (proxy L4-L7) que reside em cada host. Ele funciona como um proxy para pods estáticos de servidores de API e para servidores de API em implantações e implementa a disponibilidade de APIs kube em todos os hosts no cluster para que kubelets, gerenciadores de controlador e agendadores possam funcionar. E aqui surge a eterna pergunta: o que veio primeiro, a galinha ou o ovo? O cluster precisa aumentar e, para isso, você precisa de servidores de API em funcionamento. Se os servidores de API estiverem em implantação, o cluster não será gerado. Portanto, o envoy implementa prioridades para verificações de integridade, se os servidores de API em uma implantação dimensionada horizontalmente de forma flexível estiverem disponíveis, todo o tráfego vai para eles, caso contrário, para servidores de API em pods estáticos.

Na plataforma de versões anteriores, tínhamos um enviado por meio do qual os componentes do sistema Kubernetes iam para servidores de API em pods estáticos. Anteriormente, os servidores de API em implantações processavam solicitações exclusivamente de dentro do cluster (do serviço kubernetes.default.svc) e os usuários que trabalham com o cluster também se conectavam a eles. Os componentes do sistema funcionavam exclusivamente com servidores de API em pods estáticos.

Quanto ao agendador, ao contrário do controlador-gerenciador, ele não precisa ser dimensionado. Um agendador em uma única instância é um componente que não experimenta carga constante e é executado próximo ao evento. Por exemplo, em grandes clusters, ele não varre todos os hosts, tentando ir a algum lugar. O padrão é cerca de 10% dos hosts e tenta inserir pods neles, se falhar, pega os próximos 10% e assim por diante.

Para resumir: separando o etcd e o controller-manager, podemos trabalhar com clusters grandes tão rapidamente quanto com os pequenos. Graças a duas ações, conseguimos eliminar problemas que levavam a uma operação inadequada e outros efeitos colaterais à medida que o cluster crescia em tamanho.

Agora temos um aglomerado de qualquer tamanho muito mais responsivo: suas partes deixaram de influenciar umas às outras. Ao administrar o cluster por meio do kubectl, o componente não fica atrasado, independentemente do tamanho do cluster. Os serviços vinculados aos recursos do próprio Kubernetes começaram a funcionar instantaneamente. Indo para 200 mil pods no cluster, não troque ;)

Se você achou nosso artigo útil, compartilhe-o com seus colegas ou amigos - materiais envolventes e de leitura nos carregam de entusiasmo para encontrar e revelar novos tópicos interessantes para você.


Artigo Original