As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.
Workloads
As cargas de trabalho têm um impacto no tamanho que seu cluster pode escalar. As cargas de trabalho que usam APIs muito o Kubernetes limitarão a quantidade total de cargas de trabalho que você pode ter em um único cluster, mas há alguns padrões que você pode alterar para ajudar a reduzir a carga.
As cargas de trabalho em um cluster Kubernetes têm acesso a recursos que se integram à API do Kubernetes (por exemplo, segredos e ServiceAccounts), mas esses recursos nem sempre são necessários e devem ser desativados se não estiverem sendo usados. Limitar o acesso à carga de trabalho e a dependência do plano de controle do Kubernetes aumentará o número de cargas de trabalho que você pode executar no cluster e melhorará a segurança de seus clusters removendo o acesso desnecessário às cargas de trabalho e implementando práticas de privilégios mínimos. Leia as melhores práticas de segurança para obter mais informações.
Uso IPv6 para rede de pods
Você não pode fazer a transição de uma VPC de IPv4 para, IPv6 portanto, habilitar IPv6 antes de provisionar um cluster é importante. Se você habilitar IPv6 em uma VPC, isso não significa que você precisa usá-la. Se seus pods e serviços usarem, IPv6 você ainda poderá rotear o tráfego de e para endereços. IPv4 Consulte as melhores práticas de rede EKS para obter mais informações.
O uso IPv6 em seu cluster evita alguns dos limites mais comuns de escalabilidade de clusters e cargas de trabalho. IPv6 evita o esgotamento do endereço IP quando pods e nós não podem ser criados porque nenhum endereço IP está disponível. Ele também tem melhorias no desempenho por nó porque os pods recebem endereços IP mais rapidamente ao reduzir o número de anexos ENI por nó. Você pode obter um desempenho de nó semelhante usando o modo de IPv4 prefixo na VPC CNI, mas ainda precisa se certificar de que tem endereços IP suficientes disponíveis na VPC.
Limitar o número de serviços por namespace
O número máximo de serviços em um namespace é 5.000 e o número máximo de serviços em um cluster é
O número de regras de tabelas IP criadas por nó com o kube-proxy cresce com o número total de serviços no cluster. A geração de milhares de regras de tabelas IP e o roteamento de pacotes por meio dessas regras têm um impacto no desempenho dos nós e aumentam a latência da rede.
Crie namespaces Kubernetes que englobem um único ambiente de aplicativo, desde que o número de serviços por namespace seja inferior a 500. Isso manterá a descoberta de serviços pequena o suficiente para evitar limites de descoberta de serviços e também pode ajudá-lo a evitar colisões de nomenclatura de serviços. Ambientes de aplicativos (por exemplo, dev, test, prod) devem usar clusters EKS separados em vez de namespaces.
Entenda as cotas do Elastic Load Balancer
Ao criar seus serviços, considere o tipo de balanceamento de carga que você usará (por exemplo, Network Load Balancer (NLB) ou Application Load Balancer (ALB)). Cada tipo de balanceador de carga fornece funcionalidades diferentes e tem cotas diferentes. Algumas das cotas padrão podem ser ajustadas, mas há algumas cotas máximas que não podem ser alteradas. Para ver as cotas e o uso da sua conta, acesse o painel Service Quotas
Por exemplo, os alvos padrão do ALB são 1000. Se você tiver um serviço com mais de 1.000 endpoints, precisará aumentar a cota, dividir o serviço em vários ALBs ou usar o Kubernetes Ingress. Os alvos padrão do NLB são 3000, mas estão limitados a 500 alvos por AZ. Se seu cluster executar mais de 500 pods para um serviço NLB, você precisará usar vários AZs ou solicitar um aumento do limite de cota.
Uma alternativa ao uso de um balanceador de carga acoplado a um serviço é usar um controlador de entrada
Use o Route 53, o Global Accelerator ou CloudFront
Para disponibilizar um serviço usando vários balanceadores de carga como um único endpoint, você precisa usar o Amazon CloudFront
O Route 53 pode expor vários balanceadores de carga com um nome comum e pode enviar tráfego para cada um deles com base no peso atribuído. Você pode ler mais sobre os pesos do DNS na documentação e ler como implementá-los com o controlador DNS externo do Kubernetes na documentação do AWS Load
O Global Accelerator pode rotear cargas de trabalho para a região mais próxima com base no endereço IP solicitado. Isso pode ser útil para cargas de trabalho implantadas em várias regiões, mas não melhora o roteamento para um único cluster em uma única região. Usar o Route 53 em combinação com o Global Accelerator tem benefícios adicionais, como verificação de integridade e failover automático se um AZ não estiver disponível. Você pode ver um exemplo do uso do Global Accelerator com o Route 53 nesta postagem do blog
CloudFront pode ser usado com o Route 53 e o Global Accelerator ou sozinho para rotear o tráfego para vários destinos. CloudFront armazena em cache os ativos que estão sendo servidos pelas fontes de origem, o que pode reduzir os requisitos de largura de banda, dependendo do que você está servindo.
Use EndpointSlices em vez de endpoints
Ao descobrir pods que correspondem a uma etiqueta de serviço, você deve usar EndpointSlices
Nem todos os controladores usam EndpointSlices por padrão. Você deve verificar as configurações do controle e ativá-lo, se necessário. Para o AWS Load Balancer Controller--enable-endpoint-slices
opcional. EndpointSlices
Use segredos imutáveis e externos, se possível
O kubelet mantém um cache das chaves e valores atuais dos segredos que são usados em volumes para pods nesse nó. O kubelet monitora os segredos para detectar alterações. À medida que o cluster se expande, o número crescente de relógios pode afetar negativamente o desempenho do servidor da API.
Existem duas estratégias para reduzir o número de relógios em Secrets:
-
Para aplicativos que não precisam de acesso aos recursos do Kubernetes, você pode desativar a montagem automática de segredos da conta de serviço definindo Token: false automountServiceAccount
-
Se os segredos do seu aplicativo forem estáticos e não forem modificados no futuro, marque-os como imutáveis
. O kubelet não mantém um monitor de API para segredos imutáveis.
Para desativar a montagem automática de uma conta de serviço em pods, você pode usar a seguinte configuração em sua carga de trabalho. Você pode substituir essas configurações se cargas de trabalho específicas precisarem de uma conta de serviço.
apiVersion: v1 kind: ServiceAccount metadata: name: app automountServiceAccountToken: true
Monitore o número de segredos no cluster antes que ele exceda o limite de 10.000. Você pode ver uma contagem total de segredos em um cluster com o comando a seguir. Você deve monitorar esse limite por meio de suas ferramentas de monitoramento de cluster.
kubectl get secrets -A | wc -l
Você deve configurar o monitoramento para alertar o administrador do cluster antes que esse limite seja atingido. Considere usar opções externas de gerenciamento de segredos, como o AWS Key Management Service (AWS KMS)
Limitar o histórico de implantação
Os pods podem ser lentos ao criar, atualizar ou excluir porque objetos antigos ainda são rastreados no cluster. Você pode reduzir o número revisionHistoryLimit
de implantações
Se o cluster criar muitos objetos de trabalho por meio CronJobs de outros mecanismos, use a ttlSecondsAfterFinished
configuração
Desativar enableServiceLinks por padrão
Quando um pod é executado em um Node, o kubelet adiciona um conjunto de variáveis de ambiente para cada serviço ativo. Os processos Linux têm um tamanho máximo para seu ambiente, que pode ser alcançado se você tiver muitos serviços em seu namespace. O número de serviços por namespace não deve exceder 5.000. Depois disso, o número de variáveis do ambiente de serviço ultrapassa os limites do shell, fazendo com que os pods falhem na inicialização.
Há outros motivos pelos quais os pods não devem usar variáveis de ambiente de serviço para descoberta de serviços. Conflitos de nomes de variáveis de ambiente, nomes de serviços vazados e tamanho total do ambiente são alguns exemplos. Você deve usar o CoreDNS para descobrir endpoints de serviço.
Limite os webhooks de admissão dinâmica por recurso
Os webhooks de admissão dinâmica incluem webhooks
Certifique-se de que seus webhooks estejam altamente disponíveis, especialmente durante um incidente de AZ, e que a FailurePolicy esteja configurada corretamente para rejeitar o recurso ou ignorar a falha
apiVersion: admission.k8s.io/v1 kind: AdmissionReview request: dryRun: False
Webhooks mutantes podem modificar recursos em sucessão frequente. Se você tiver 5 webhooks mutantes e implantar 50 recursos, o etcd armazenará todas as versões de cada recurso até que a compactação seja executada — a cada 5 minutos — para remover as versões antigas dos recursos modificados. Nesse cenário, quando o etcd remover recursos substituídos, haverá 200 versões de recursos removidas do etcd e, dependendo do tamanho dos recursos, poderão usar um espaço considerável no host etcd até que a desfragmentação seja executada a cada 15 minutos.
Essa desfragmentação pode causar pausas no etcd, o que pode ter outros efeitos na API e nos controladores do Kubernetes. Você deve evitar a modificação frequente de grandes recursos ou a modificação de centenas de recursos em rápida sucessão.
Compare cargas de trabalho em vários clusters
Se você tiver dois clusters que deveriam ter desempenho semelhante, mas não têm, tente comparar as métricas para identificar o motivo.
Por exemplo, comparar a latência do cluster é um problema comum. Isso geralmente é causado pela diferença no volume de solicitações de API. Você pode executar a CloudWatch LogInsight consulta a seguir para entender a diferença.
filter @logStream like "kube-apiserver-audit" | stats count(*) as cnt by objectRef.apiGroup, objectRef.apiVersion, objectRef.resource, userAgent, verb, responseStatus.code | sort cnt desc | limit 1000
Você pode adicionar filtros adicionais para restringi-lo. por exemplo, focando em todas as solicitações de lista defoo
.
filter @logStream like "kube-apiserver-audit" | filter verb = "list" | filter user.username like "foo" | stats count(*) as cnt by objectRef.apiGroup, objectRef.apiVersion, objectRef.resource, responseStatus.code | sort cnt desc | limit 1000