Compartilhar via


Práticas recomendadas para desempenho e dimensionamento para cargas de trabalho grandes em AKS (Serviço de Kubernetes do Azure)

Observação

Este artigo se concentra nas melhores práticas gerais para cargas de trabalho grandes. Para obter práticas recomendadas específicas de pequenas a médias cargas de trabalho, consulte práticas recomendadas de desempenho e dimensionamento para cargas de trabalho pequenas e médias no AKS (Serviço de Kubernetes do Azure).

Ao implantar e manter clusters no AKS, use as melhores práticas a seguir para ajudar a otimizar o desempenho e a escala.

Tenha em mente que o termo grande é relativo. O Kubernetes tem um envelope de escala multidimensional, e o envelope de escala para sua carga de trabalho depende dos recursos usados. Por exemplo, um cluster com 100 nós e milhares de pods ou CRDs pode ser considerado grande. Um cluster de 1.000 nós com 1.000 pods e vários outros recursos pode ser considerado pequeno da perspectiva do painel de controle. O melhor sinal para a escala de um painel de controle do Kubernetes é a taxa de sucesso e a latência da solicitação HTTP do servidor de API, pois esse é um proxy para a quantidade de carga no painel de controle.

Neste artigo, você aprenderá sobre:

  • Dimensionamento de nó.
  • O AKS e o Kubernetes controlam a escalabilidade do plano.
  • Práticas recomendadas para clientes Kubernetes, incluindo retirada, inspeções e paginação.
  • Limites da limitação de plataforma e de API do Azure.
  • Limitações do recurso.
  • Práticas recomendadas de rede.

Dimensionamento de nós

Ao expandir seus clusters AKS para níveis de escala maiores, tenha em mente as seguintes práticas recomendadas de escalonamento de nós:

  • Ao operar clusters AKS em grande escala, use o dimensionamento automático de cluster ou o provisionamento automático de nós sempre que possível, para garantir o dimensionamento dinâmico dos nós de acordo com a demanda por recursos de computação.
  • Se você está escalando para além de 1.000 nós e não está usando o dimensionador automático de cluster, recomendamos fazer isso em lotes de 500-700 nós por vez. As operações de escala devem ter um tempo de espera de dois a cinco minutos entre as operações de escala vertical para impedir a limitação de API do Azure. Para obter mais informações, confira Gerenciamento de API: políticas de cache e limitação.
  • No caso dos pools de nós do sistema, use o SKU Standard_D16ds_v5 ou um SKU de VM de núcleo/memória equivalente com discos de SO efêmero para fornecer recursos de computação suficientes para os pods do kube-system.
  • Como o AKS tem um limite de 1.000 nós por pool de nós, recomendamos criar, pelo menos, cinco pools de nós de usuário para escalar até 5.000 nós.

Escalabilidade do painel de controle do AKS e do Kubernetes

No Kubernetes, todos os objetos em execução em um cluster são gerenciados pelo plano de controle, que é gerenciado pelo AKS. Embora o AKS otimize o painel de controle do Kubernetes e os respectivos componentes visando a escalabilidade e o desempenho, ele ainda está associado aos limites de projeto upstream.

O Kubernetes tem um envelope de escala multidimensional, com cada tipo de recurso representando uma dimensão, e nem todos os recursos são iguais em seus custos. Por exemplo, os Secrets são frequentemente monitorados por vários controladores e pods, cada um dos quais faz uma chamada LIST inicial para sincronizar o estado. Como os segredos normalmente são grandes e frequentemente atualizados, eles colocam mais carga no plano de controle do que os recursos observados com menos frequência.

Quanto mais você dimensiona o cluster em uma determinada dimensão, menos você pode dimensioná-lo em outras dimensões. Por exemplo, a execução de centenas de milhares de pods em um cluster do AKS afeta a quantidade de rotatividade de pod (mutações de pod por segundo) à qual o painel de controle pode dar suporte.

O AKS dá suporte a três níveis de plano de controle como parte do SKU Base: nível Gratuito, Padrão e Premium. Para obter mais informações, veja os níveis de preços Gratuitos, Standard e Premium para gestão de clusters AKS.

Importante

Use a camada Standard ou Premium para cargas de trabalho em produção ou em grande escala. O AKS aumenta automaticamente o painel de controle do Kubernetes para dar suporte aos seguintes limites de escala:

  • Até 5.000 nós por cluster do AKS
  • 200.000 pods por cluster do AKS (com a sobreposição da CNI do Azure)

Na maioria dos casos, ultrapassar o limite de escala resulta em uma degradação do desempenho, mas isso não faz com que o cluster faça failover imediatamente. Para gerenciar a carga no painel de controle do Kubernetes, considere a escala em lotes de até 10 a 20% da escala atual. Por exemplo, no caso de um cluster de 5.000 nós, escale-o em incrementos de 500 a 1.000 nós. Embora o AKS faça o dimensionamento automático do painel de controle, isso não acontece instantaneamente.

Para confirmar se o plano de controle foi escalado verticalmente, procure o configmap large-cluster-control-plane-scaling-status.

kubectl describe configmap large-cluster-control-plane-scaling-status -n kube-system

Considerações sobre envelope de escala do Kubernetes e plano de controle

Os clientes do Kubernetes são componentes de aplicativo, como operadores ou agentes de monitoramento, que são executados no cluster e se comunicam com o kube-apiserver para ler ou modificar recursos. É importante otimizar como esses clientes se comportam para reduzir a carga que eles colocam no kube-apiserver e no painel de controle do Kubernetes.

O número de solicitações sendo processadas ativamente pelo servidor de API a qualquer momento é determinado pelos sinalizadores --max-requests-inflight e --max-mutating-requests-inflight. O AKS usa os valores padrão de 400 e 200 solicitações para esses sinalizadores, permitindo que um total de 600 solicitações sejam expedidas em um determinado momento. À medida que dimensionamos o servidor de API para tamanhos maiores, aumentamos correspondentemente as solicitações de bordo também.

Dois tipos de objeto kubernetes, PriorityLevelConfiguration e FlowSchema (APF), determinam como o servidor de API divide a capacidade total da solicitação entre os tipos de solicitação. O AKS usa a configuração padrão.

Cada PriorityLevelConfiguration recebe uma parte do total de solicitações permitidas. Para exibir os objetos PriorityLevelConfiguration em seu cluster e seus compartilhamentos de solicitação alocados, execute o comando a seguir.

kubectl get --raw /metrics | grep apiserver_flowcontrol_nominal_limit_seats

O FlowSchema mapeia solicitações do servidor de API para um PriorityLevelConfiguration. Se vários objetos FlowSchema corresponderem a uma solicitação, o servidor de API selecionará aquele com a menor precedência correspondente.

O mapeamento de FlowSchemas para PriorityLevelConfigurations pode ser exibido usando este comando:

kubectl get flowschemas

Para confirmar se alguma solicitação está sendo descartada devido ao APF, execute o seguinte comando:

kubectl get --raw /metrics | grep apiserver_flowcontrol_rejected_requests_total

Práticas recomendadas do cliente do Kubernetes

As chamadas LIST emitidas por clientes não otimizados geralmente são um dos maiores fatores que limitam a escalabilidade de um cluster. Ao trabalhar com listas que podem ter mais de alguns milhares de objetos pequenos ou mais de algumas centenas de objetos grandes, considere as seguintes diretrizes:

  • Considere o número de objetos (CRs) que você espera que existam no final ao definir um novo tipo de recurso (CRD).
  • A carga no servidor de API e etcd depende principalmente do tamanho da resposta. Essa orientação se aplica se o cliente emite um pequeno número de solicitações LIST para objetos grandes ou um grande número de solicitações LIST para objetos menores.

Utilize informantes

  • Se o código precisar manter uma lista atualizada de objetos na memória, o uso de um informador da biblioteca client-go lhe dará os benefícios de monitorar alterações nos recursos com base em eventos em vez de consultar periodicamente por alterações. Essa é a melhor abordagem para evitar LISTs não otimizadas e repetidas.

Usar o cache do servidor de API

  • Use resourceVersion=0 para retornar resultados do cache do servidor de API. Isso pode impedir que objetos sejam buscados de etcd, reduzindo assim a carga etcd, mas não dá suporte à paginação.

    /api/v1/namespaces/default/pods?resourceVersion=0
    

Uso eficiente da API do Kubernetes

  • É recomendável usar o argumento watch sempre que possível. Sem argumentos, o comportamento padrão é listar objetos. Veja o exemplo abaixo.

    /api/v1/namespaces/default/pods?watch=true
    

    Use o relógio com um resourceVersion configurado para ser o valor mais recente conhecido recebido da lista ou observação anterior. Isso é tratado automaticamente no client-go. Mas verifique se você está usando um cliente Kubernetes em outros idiomas.

    /api/v1/namespaces/default/pods?watch=true&resourceVersion=<resourceversion>
    
  • Caso controladores ou operadores precisem usar chamadas LIST, devem evitar consultar recursos em todo o cluster sem seletores de rótulo ou campo, especialmente em clusters grandes. Os exemplos a seguir mostram chamadas LIST otimizadas e não otimizadas.

    LISTA Otimizada:

    /api/v1/namespaces/default/pods?fieldSelector=status.phase=Running
    

    LISTA não otimizada:

    /api/v1/pods
    
  • Use paginação para reduzir o tamanho das respostas LIST se o cliente precisar buscar dados de etcd. O exemplo a seguir usa o argumento limite para restringir a resposta a 100 objetos.

    /api/v1/namespaces/default/pods?fieldSelector=status.phase=Running&limit=100
    

    Se você quiser que a LISTA continue retornando todos os objetos de pod no exemplo acima, use o argumento continue com limite.

    /api/v1/namespaces/default/pods?fieldSelector=status.phase=Running&limit=100&continue=<continue_token>
    

    Se o kubectl estiver sendo utilizado, --chunk-size o argumento poderá ser aplicado diretamente a respostas paginadas.

    kubectl get pods -n default --chunk-size=100
    
  • Se os seus controladores ou operadores usarem atualizações de concessão para a eleição de líderes, verifique se eles são resilientes a problemas transitórios de conectividade ajustando leaseDuration, renewDeadline e retryPeriod que são ideais para suas cargas de trabalho. Para controladores Kubernetes que utilizam a eleição de líder client-go, utilize a seguinte fórmula:

    lease_duration > renew_deadline > retry_period
    

Daemonsets

  • Há uma diferença significativa entre um único controlador listando objetos e um DaemonSet em execução em cada nó fazendo a mesma coisa. Se várias instâncias do aplicativo cliente listar periodicamente um grande número de objetos, a solução não será bem dimensionada em clusters grandes.

  • Em clusters com milhares de nós, criar um novo DaemonSet, atualizar um DaemonSet ou aumentar o número de nós pode resultar em uma alta carga colocada no plano de controle. Se os pods DaemonSet fizerem solicitações caras ao servidor de API na inicialização do pod, isso pode resultar em um alto uso de recursos no plano de controle devido a um grande número de solicitações simultâneas.

  • Use uma estratégia RollingUpdate para implantar novos pods DaemonSet gradualmente. Quando o modelo DaemonSet é atualizado, o controlador substitui pods antigos por novos de maneira controlada. Quando a estratégia de Rolling Update não estiver configurada explicitamente, Kubernetes por padrão criará um RollingUpdate com maxUnavailable definido como 1, maxSurge como 0 e minReadySeconds como 0s. Consulte o exemplo a seguir.

      minReadySeconds: 30
      updateStrategy:
        type: RollingUpdate
        rollingUpdate:
          maxSurge: 0
          maxUnavailable: 1
    
  • A estratégia RollingUpdate só se aplica a pods DaemonSet existentes. Isso não limita o impacto da adição de novos nós, que cria pods DaemonSet adicionais, ou da implantação de DaemonSets inteiramente novos.

  • Para evitar que DaemonSets emitam solicitações LIST simultâneas para o servidor de API durante a inicialização após o aumento da escalabilidade de nós ou novas implantações de DaemonSet, implemente um jitter de inicialização no ponto de entrada do contêiner e configure políticas apropriadas de backoff exponencial e repetição para respostas 5xx ou 429, a fim de evitar a repetição de solicitações LIST grandes.

      spec:
        template:
          spec:
            containers:
            - name: my-daemonset-container
              image: <image>
              command: ["/bin/sh", "-c", "sleep $(( (RANDOM % 60) + 1 )); exec /path/to/your/app --args"]
    

Observação

Você pode analisar o tráfego do servidor API e o comportamento do cliente por meio dos logs de auditoria do Kube. Para obter mais informações, confira Solução de problemas do painel de controle do Kubernetes.

otimizações etcd

  • Mantenha o tamanho geral etcd pequeno e não use etcd como um banco de dados de uso geral. O AKS fornece 8 GB de armazenamento etcd por padrão, mas bancos de dados etcd maiores aumentam o tempo de desfragmentação, o que pode levar a problemas de desempenho de leitura e gravação. Bancos de dados etcd maiores também podem aumentar a probabilidade de problemas de confiabilidade de servidor de API e etcd se um cliente não otimizado busca um grande número de objetos de etcd com frequência. Se o tamanho do banco de dados etcd exceder 2 GB, considere usar as técnicas de redução de tamanho de objeto listadas abaixo.
  • Para reduzir o tamanho das especificações dos pods, mova as variáveis de ambiente das especificações dos pods para ConfigMaps.
  • Divida segredos grandes ou ConfigMaps em partes menores e mais gerenciáveis.
  • Armazene segredos em Azure Key Vault em vez de Secrets do Kubernetes sempre que possível para reduzir o número de segredos armazenados em etcd.
  • Limpar objetos não utilizados
    • Exclua Trabalhos obsoletos e Pods concluídos. Use ttlSecondsAfterFinished em Jobs para que os objetos concluídos sejam removidos automaticamente.
    • Verifique se os controladores definem ownerReferences. Isso permite que a coleta de lixo do Kubernetes remova objetos dependentes automaticamente quando o recurso pai é excluído.
    • Limite o histórico do CronJob definindo os parâmetros successfulJobsHistoryLimit e failedJobsHistoryLimit para manter apenas um número reduzido de registros de jobs concluídos.
    • Reduza o histórico de distribuição de implantação. ReplicaSets antigos também são armazenados como objetos de API. O valor padrão é 10.
  • Reduza o histórico de revisão do Helm com o argumento --history-max. Em clusters grandes, mantenha-o abaixo de 5.

Monitorar métricas e logs do plano de controle do AKS

Monitorar as métricas do plano de controle em clusters do AKS grandes é crucial para garantir a estabilidade e o desempenho das cargas de trabalho do Kubernetes. Essas métricas fornecem visibilidade da integridade e do comportamento de componentes críticos, como o servidor de API, etcd, o gerenciador de controladores e o agendador. Em ambientes em grande escala, em que a contenção de recursos e os volumes de chamadas à API são comuns, o monitoramento das métricas do plano de controle ajuda a identificar gargalos, detectar anomalias e otimizar o uso de recursos. Analisando essas métricas, os operadores podem resolver proativamente problemas como latência do servidor de API, objetos de alta etcd ou consumo excessivo de recursos do plano de controle, garantindo uma operação de cluster eficiente e minimizando o tempo de inatividade.

Azure Monitor oferece métricas e logs abrangentes sobre a integridade do plano de controle por meio das configurações Azure Managed Prometheus e Diagnostic.

Métricas principais da plataforma do plano de controle

O serviço AKS expõe as seguintes métricas de plataforma no Azure Monitor para monitorar o servidor de API e a integridade do etcd. Essas métricas estão disponíveis sem habilitar o Prometheus Gerenciado e podem ser exibidas diretamente no portal do Azure em Metrics para o cluster do AKS.

Métricas do Servidor de API:

Métrica Descrição
apiserver_cpu_usage_percentage Percentual máximo de uso de CPU (com base no limite atual) pelo pod do servidor de API em todas as instâncias.
apiserver_memory_usage_percentage Percentual máximo de memória (com base no limite atual) usado pelo pod do servidor de API ao longo das instâncias.
apiserver_current_inflight_requests (versão prévia) Número máximo de solicitações de inflight ativas no momento no servidor de API, por tipo de solicitação.

Métricas etcd:

Métrica Descrição
etcd_cpu_usage_percentage Percentual máximo de CPU (com base no limite atual) utilizado pelo pod etcd em todas as instâncias.
etcd_memory_usage_percentage Percentual máximo de memória (com base no limite atual) usado pelo pod etcd em todas as instâncias.
etcd_database_usage_percentage Utilização máxima do banco de dados etcd entre instâncias. Monitore isso de perto para evitar exceder o limite de armazenamento etcd.

Consistentemente, monitore apiserver_cpu_usage_percentage e apiserver_memory_usage_percentage para detectar a pressão de recursos no servidor de API. Se etcd_database_usage_percentage estiver consistentemente acima de 50%, examine a seção Otimizações etcd para reduzir o tamanho do banco de dados. Para obter a lista completa de métricas disponíveis, consulte a referência de dados de monitoramento do AKS.

Limitações dos recursos

À medida que você escala seus clusters do AKS para pontos de escala maiores, tenha em mente as seguintes limitações do recurso:

limitação da API e da plataforma Azure

A carga em um aplicativo de nuvem pode variar ao longo do tempo de acordo com fatores como o número de usuários ativos ou os tipos de ações que os usuários executam. Se os requisitos de processamento do sistema excederem a capacidade dos recursos disponíveis, o sistema poderá ficar sobrecarregado e sofrer com baixo desempenho e falhas.

Para lidar com tamanhos de carga variáveis em um aplicativo de nuvem, você pode permitir que o aplicativo use recursos até um limite especificado e, em seguida, limitá-los quando o limite for atingido. No Azure, a limitação ocorre em dois níveis. O ARM (Azure Resource Manager) limita as solicitações para a assinatura e o locatário. Se a solicitação estiver dentro dos limites de limitação da assinatura e do locatário, o ARM roteará a solicitação para o provedor de recursos. O provedor de recursos aplica os limites de limitação que são ajustados às operações. Para obter mais informações, confira Solicitações de limitação do ARM.

Gerenciar a limitação no AKS

Em geral, os limites de API do Azure são definidos em um nível de combinação de assinatura/região. Por exemplo, todos os clientes em uma assinatura em uma região específica compartilham limites de API para uma API específica do Azure, como as APIs de PUT de Conjuntos de Dimensionamento de Máquinas Virtuais. Cada cluster do AKS tem vários clientes geridos pelo AKS, como o provedor de nuvem ou o dimensionador automático de cluster, ou clientes geridos pelo cliente, como o Datadog ou o Prometheus auto-hospedado, que fazem chamadas às APIs do Azure. Ao executar vários clusters do AKS em uma assinatura em determinada região, todos os clientes de propriedade do AKS e de propriedade do cliente nos clusters compartilham um conjunto comum de limites de API. Portanto, o número de clusters que você pode implantar em uma região de assinatura é uma função do número de clientes implantados, dos padrões de chamada e da escala geral e elasticidade dos clusters.

Tendo em mente as considerações acima, normalmente, os clientes têm a capacidade de implantar entre 20 e 40 clusters de pequena a média escala por assinatura/região. Você pode maximizar a escala de assinatura usando as seguintes melhores práticas:

Sempre atualize seus clusters do Kubernetes para a última versão. As versões mais recentes contêm muitos aprimoramentos que resolvem problemas de desempenho e limitação. Se você estiver usando uma versão atualizada do Kubernetes e ainda observar a limitação devido à carga real ou ao número de clientes na assinatura, experimente as seguintes opções:

  • Analisar erros usando o AKS Diagnostic and Solve Problems: você pode usar o Diagnóstico e a Resolução de Problemas do AKS para analisar erros, identificar a causa raiz e obter recomendações de resolução.
  • Dividir os clusters em diferentes assinaturas ou regiões: se você tiver um grande número de clusters e pools de nós que usam Conjuntos de Dimensionamento de Máquinas Virtuais, divida-os em diferentes assinaturas ou em diferentes regiões na mesma assinatura. A maior parte dos limites de API do Azure é compartilhada na assinatura/região, ou seja, você pode mover ou escalar seus clusters para diferentes assinaturas ou regiões a fim de que sejam desbloqueados na limitação de API do Azure. Essa opção é especialmente útil se você espera que seus clusters tenham alta atividade. Não há diretrizes genéricas para esses limites. Se você desejar obter diretrizes específicas, crie um tíquete de suporte.

Rede

À medida que você escala seus clusters do AKS para pontos de escala maiores, tenha em mente as seguintes melhores práticas de rede:

  • Use a NAT gerenciada para uma saída de cluster com, pelo menos, dois IPs públicos no Gateway da NAT. Para obter mais informações, confira Criar um gateway da NAT gerenciada para o cluster do AKS.

  • Se você estiver usando Azure Standard Load Balancer, use pelo menos 2 IPs públicos de saída. Ao planejar grandes clusters, também considere os limites de regras de back-end do serviço LoadBalancer. Azure Standard Load Balancers dão suporte a até 10.000 configurações de IP de back-end por IP de front-end. Cada tipo: O serviço LoadBalancer cria uma regra de balanceamento de carga por porta exposta e associa todos os nós do cluster ao pool de back-end do Load Balancer. Por exemplo, expor 5 portas para um único serviço atingirá esse limite com 2000 nós.

    1 service * 5 ports * 2000 nodes = 10000 backend IP configurations
    
  • Use a Sobreposição da CNI do Azure para escalar verticalmente até 200.000 pods e 5.000 nós por cluster. Para obter mais informações, consulte Configurar rede de sobreposição do Azure CNI no AKS.

  • Se o seu aplicativo precisar de comunicação direta de pod para pod entre clusters, utilize o Azure CNI com alocação dinâmica de IP e escale até 50.000 pods de aplicativo por cluster, com um IP roteável por pod. Para obter mais informações, consulte Configurar rede CNI do Azure para alocação dinâmica de IP no AKS.

  • Durante o uso de serviços internos do Kubernetes com a proteção de um balanceador de carga interno, recomendamos criar um balanceador de carga interno ou um serviço abaixo de uma escala de 750 nós, a fim de obter desempenho de escala ideal e elasticidade no balanceador de carga.

  • Azure NPM (Network Policy Manager) dá suporte apenas a até 250 nós. Se você quiser impor políticas de rede para clusters maiores, considere usar Azure CNI alimentado pelo Cilium, que combina o plano de controle robusto de Azure CNI com o plano de dados Cilium para fornecer segurança e rede de alto desempenho.

  • Habilite o LocalDNS em seus pools de nós para reduzir a latência de resolução DNS e descarregar pods CoreDNS centralizados. Em clusters grandes com grandes volumes de consulta DNS, a resolução DNS centralizada pode se tornar um gargalo. O LocalDNS implanta um proxy DNS como um systemd serviço em cada nó, resolvendo consultas localmente, eliminando conntrack a pressão da tabela e atualizando conexões para TCP para evitar conntrack condições de corrida. O LocalDNS também dá suporte ao serviço de respostas obsoletas armazenadas em cache quando o DNS upstream não está disponível, melhorando a resiliência da carga de trabalho durante falhas transitórias. Para obter mais informações, consulte a resolução de DNS no AKS.

Considerações e melhores práticas para a atualização de clusters

  • Quando um cluster atinge o limite de 5.000 nós, as atualizações do cluster são bloqueadas. Esse limite impede uma atualização porque não há capacidade de nó disponível para realizar atualizações contínuas dentro do limite máximo de propriedades de surto. Se você tiver um cluster nesse limite, recomendamos reduzir a escala do cluster para menos de 3.000 nós antes de tentar uma atualização do cluster. Isso fornecerá capacidade extra para rotatividade de nós e minimizará a carga no plano de controle.
  • Ao atualizar clusters com mais de 500 nós, é recomendável usar uma configuração de pico máximo de 10 a 20% da capacidade do pool de nós. AKS configura atualizações com um valor padrão de 10% para pico máximo. Você pode personalizar as configurações de pico máximo por pool de nós para permitir uma compensação entre a velocidade de atualização e a interrupção da carga de trabalho. Quando você aumenta as configurações máximas do aumento, o processo de atualização é concluído mais rapidamente, mas você pode enfrentar interrupções durante o processo de atualização. Para saber mais, confira Personalizar a atualização de sobretensão de nó.
  • Para saber mais, confira Atualizar um cluster do AKS.