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á.
Computação e escalonamento automático
Como desenvolvedor, você fará estimativas sobre os requisitos de recursos do seu aplicativo, por exemplo, CPU e memória, mas se você não os estiver ajustando continuamente, eles podem ficar desatualizados, o que pode aumentar seus custos e piorar o desempenho e a confiabilidade. Ajustar continuamente os requisitos de recursos de um aplicativo é mais importante do que acertá-los na primeira vez.
As melhores práticas mencionadas abaixo ajudarão você a criar e operar cargas de trabalho com reconhecimento de custos que alcancem resultados comerciais, minimizando os custos e permitindo que sua organização maximize o retorno sobre o investimento. Uma ordem de importância de alto nível para otimizar os custos de computação do cluster é:
-
Cargas de trabalho do tamanho certo
-
Reduza a capacidade não utilizada
-
Otimize os tipos de capacidade computacional (por exemplo, Spot) e aceleradores (por exemplo) GPUs
Dimensione corretamente suas cargas de trabalho
Na maioria dos clusters EKS, a maior parte do custo vem das EC2 instâncias usadas para executar suas cargas de trabalho em contêineres. Você não conseguirá dimensionar corretamente seus recursos computacionais sem entender seus requisitos de cargas de trabalho. É por isso que é essencial que você use as solicitações e os limites apropriados e faça ajustes nessas configurações conforme necessário. Além disso, dependências, como tamanho da instância e seleção de armazenamento, podem afetar o desempenho da carga de trabalho, o que pode ter várias consequências não intencionais nos custos e na confiabilidade.
As solicitações devem estar alinhadas com a utilização real. Se as solicitações de um contêiner forem muito altas, haverá capacidade não utilizada, o que é um grande fator nos custos totais do cluster. Cada contêiner em um pod, por exemplo, aplicativo e sidecars, deve ter suas próprias solicitações e limites definidos para garantir que os limites agregados do pod sejam os mais precisos possíveis.
Utilize ferramentas como Goldilocks
Recomendamos usar o Horizontal Pod Autoscaler (HPA) para controlar quantas réplicas do seu aplicativo devem ser executadas, o Vertical Pod Autoscaler (VPA) para ajustar quantas solicitações e limites seu aplicativo precisa por réplica e um autoescalador de nós, como Karpenter
O Vertical Pod Autoscaler pode ajustar as solicitações e os limites atribuídos aos contêineres para que as cargas de trabalho funcionem de forma ideal. Você deve executar o VPA no modo de auditoria para que ele não faça alterações automaticamente e reinicie seus pods. Ele sugerirá mudanças com base nas métricas observadas. Com quaisquer alterações que afetem as cargas de trabalho de produção, você deve analisar e testar essas alterações primeiro em um ambiente que não seja de produção, pois elas podem ter impacto na confiabilidade e no desempenho do seu aplicativo.
Reduzir o consumo
A melhor maneira de economizar dinheiro é provisionar menos recursos. Uma forma de fazer isso é ajustar as cargas de trabalho com base nos requisitos atuais. Você deve iniciar qualquer esforço de otimização de custos certificando-se de que suas cargas de trabalho definam seus requisitos e sejam escalonadas dinamicamente. Isso exigirá a obtenção de métricas de seus aplicativos e a definição de configurações, como PodDisruptionBudgets
O Horizontal Pod Autoscaler é um autoescalador flexível de carga de trabalho que pode ajustar quantas réplicas são necessárias para atender aos requisitos de desempenho e confiabilidade do seu aplicativo. Ele tem um modelo flexível para definir quando aumentar e diminuir a escala com base em várias métricas, como CPU, memória ou métricas personalizadas, por exemplo, profundidade da fila, número de conexões com um pod etc.
O Kubernetes Metrics Server permite o escalonamento em resposta a métricas integradas, como uso de CPU e memória, mas se você quiser escalar com base em outras métricas, como a profundidade da fila da Amazon CloudWatch ou do SQS, considere projetos de escalonamento automático orientados por eventos, como o KEDA.
A redução do consumo da carga de trabalho cria excesso de capacidade em um cluster e, com a configuração adequada de escalonamento automático, permite que você reduza os nós automaticamente e reduza seu gasto total. Recomendamos que você não tente otimizar a capacidade computacional manualmente. O programador Kubernetes e os autoescaladores de nós foram projetados para lidar com esse processo para você.
Reduza a capacidade não utilizada
Depois de determinar o tamanho correto dos aplicativos, reduzindo o excesso de solicitações, você pode começar a reduzir a capacidade computacional provisionada. Você deve ser capaz de fazer isso dinamicamente se tiver reservado um tempo para dimensionar corretamente suas cargas de trabalho nas seções acima. Há dois autoescaladores de nós principais usados com o Kubernetes na AWS.
Karpenter e Cluster Autoscaler
Tanto o Karpenter quanto o Kubernetes Cluster Autoscaler escalarão o número de nós em seu cluster à medida que os pods forem criados ou removidos e os requisitos de computação mudarem. O objetivo principal de ambos é o mesmo, mas a Karpenter adota uma abordagem diferente para gerenciamento, provisionamento e desprovisionamento de nós, o que pode ajudar a reduzir custos e otimizar o uso em todo o cluster.
À medida que os clusters aumentam de tamanho e a variedade de cargas de trabalho aumenta, fica mais difícil pré-configurar grupos de nós e instâncias. Assim como nas solicitações de carga de trabalho, é importante definir uma linha de base inicial e ajustá-la continuamente conforme necessário.
Se você estiver usando o Cluster Autoscaler, ele respeitará os valores “mínimo” e “máximo” de cada grupo de Auto Scaling (ASG) e ajustará somente o valor “desejado”. É importante prestar atenção ao definir esses valores para o ASG subjacente, pois o Cluster Autoscaler não conseguirá reduzir um ASG além de sua contagem “mínima”. Defina a contagem “desejada” como o número de nós necessários durante o horário comercial normal e “mínima” como o número de nós necessários fora do horário comercial. Consulte o documento de perguntas frequentes do Cluster Autoscaler
Expansor prioritário do escalador automático de cluster
O Kubernetes Cluster Autoscaler funciona escalando grupos de nós — chamados de grupo de nós — para cima e para baixo à medida que os aplicativos aumentam e diminuem a escala. Se você não estiver escalando dinamicamente as cargas de trabalho, o autoescalador de cluster não ajudará você a economizar dinheiro. O escalador automático de cluster exige que um administrador de cluster crie grupos de nós com antecedência para que as cargas de trabalho sejam consumidas. Os grupos de nós precisam ser configurados para usar instâncias que tenham o mesmo “perfil”, ou seja, aproximadamente a mesma quantidade de CPU e memória.
Você pode ter vários grupos de nós e o autoescalador de cluster pode ser configurado para definir níveis de escalabilidade prioritária, e cada grupo de nós pode conter nós de tamanhos diferentes. Os grupos de nós podem ter diferentes tipos de capacidade e o expansor prioritário pode ser usado primeiro para escalar grupos mais baratos.
Abaixo está um exemplo de um trecho de configuração de cluster que usa a ConfigMap`
para priorizar a capacidade reservada antes de usar instâncias sob demanda. Você pode usar a mesma técnica para priorizar instâncias Graviton ou Spot em relação a outros tipos.
apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: my-cluster managedNodeGroups: - name: managed-ondemand minSize: 1 maxSize: 7 instanceType: m5.xlarge - name: managed-reserved minSize: 2 maxSize: 10 instanceType: c5.2xlarge
apiVersion: v1 kind: ConfigMap metadata: name: cluster-autoscaler-priority-expander namespace: kube-system data: priorities: |- 10: - .*ondemand.* 50: - .*reserved.*
O uso de grupos de nós pode ajudar os recursos computacionais subjacentes a fazer o esperado por padrão, por exemplo, distribuir nós entre si AZs, mas nem todas as cargas de trabalho têm os mesmos requisitos ou expectativas, e é melhor deixar que os aplicativos declarem seus requisitos explicitamente. Para obter mais informações sobre o Cluster Autoscaler, consulte a seção de melhores práticas
Desagendador
O escalador automático de cluster pode adicionar e remover a capacidade de nós de um cluster com base na necessidade de programar novos pods ou na subutilização dos nós. Ele não tem uma visão holística do posicionamento do pod depois de ter sido programado para um nó. Se você estiver usando o autoescalador de cluster, você também deve consultar o desagendador do Kubernetes para evitar o desperdício
Se você tem 10 nós em um cluster e cada nó é 60% utilizado, você não está usando 40% da capacidade provisionada no cluster. Com o autoescalador de cluster, você pode definir o limite de utilização por nó para 60%, mas isso só tentaria reduzir um único nó depois que a utilização caísse abaixo de 60%.
Com o desagendador, ele pode analisar a capacidade e a utilização do cluster após os pods terem sido programados ou os nós terem sido adicionados ao cluster. Ele tenta manter a capacidade total do cluster acima de um limite especificado. Ele também pode remover pods com base em contaminações de nós ou em novos nós que se juntam ao cluster para garantir que os pods sejam executados em seu ambiente computacional ideal. Observe que o desagendador não agenda a substituição dos pods despejados, mas depende do agendador padrão para isso.
Consolidação Karpenter
O Karpenter adota uma abordagem “sem grupos” para o gerenciamento de nós. Essa abordagem é mais flexível para diferentes tipos de carga de trabalho e requer menos configuração inicial para administradores de cluster. Em vez de predefinir grupos e escalar cada grupo conforme a necessidade das cargas de trabalho, o Karpenter usa provisionadores e modelos de nós para definir amplamente quais tipos de EC2 instâncias podem ser criadas e configurações sobre as instâncias à medida que são criadas.
O empacotamento em compartimentos é a prática de utilizar mais recursos da instância agrupando mais cargas de trabalho em menos instâncias de tamanho ideal. Embora isso ajude a reduzir seus custos de computação ao provisionar apenas os recursos que suas cargas de trabalho usam, isso tem uma desvantagem. Pode levar mais tempo para iniciar novas cargas de trabalho porque a capacidade precisa ser adicionada ao cluster, especialmente durante grandes eventos de escalabilidade. Considere o equilíbrio entre otimização de custos, desempenho e disponibilidade ao configurar o empacotamento de lixo.
O Karpenter pode monitorar e agrupar continuamente para melhorar a utilização dos recursos da instância e reduzir seus custos de computação. O Karpenter também pode selecionar um nó de trabalho mais econômico para sua carga de trabalho. Isso pode ser feito ativando o sinalizador de “consolidação” como verdadeiro no provisionador (exemplo de trecho de código abaixo). O exemplo abaixo mostra um exemplo de provisionador que permite a consolidação. No momento em que escrevo este guia, o Karpenter não substituirá uma instância Spot em execução por uma instância Spot mais barata. Para obter mais detalhes sobre a consolidação do Karpenter, consulte este blog.
apiVersion: karpenter.sh/v1 kind: Provisioner metadata: name: enable-binpacking spec: consolidation: enabled: true
Para cargas de trabalho que podem não ser interrompidas, por exemplo, trabalhos em lotes de longa execução sem ponto de verificação, considere anotar pods com a anotação. do-not-evict
Ao desativar o despejo dos pods, você está dizendo ao Karpenter que ele não deve remover voluntariamente os nós que contêm esse pod. No entanto, se um do-not-evict
pod for adicionado a um nó enquanto o nó estiver sendo drenado, os pods restantes ainda serão despejados, mas esse pod bloqueará o encerramento até que seja removido. Em ambos os casos, o nó será isolado para evitar que trabalhos adicionais sejam agendados no nó. Abaixo está um exemplo mostrando como definir a anotação:
8"" linenumbering="unnumbered">apiVersion: v1 kind: Pod metadata: name: label-demo labels: environment: production annotations: + "karpenter.sh/do-not-evict": "true" spec: containers: * name: nginx image: nginx ports: ** containerPort: 80
Remova nós subutilizados ajustando os parâmetros do autoescalador de cluster
A utilização do nó é definida como a soma dos recursos solicitados dividida pela capacidade. Por padrão, scale-down-utilization-threshold
está definido como 50%. Esse parâmetro pode ser usado junto com escale-down-unneeded-time
, que determina por quanto tempo um nó deve ser desnecessário antes de ser elegível para redução de escala — o padrão é 10 minutos. Os pods ainda em execução em um nó que foi reduzido serão programados em outros nós pelo kube-scheduler. O ajuste dessas configurações pode ajudar a remover nós que estão subutilizados, mas é importante testar esses valores primeiro para não forçar o cluster a ser reduzido prematuramente.
Você pode evitar que a redução ocorra garantindo que os pods que são caros de remover sejam protegidos por um rótulo reconhecido pelo escalador automático de cluster. Para fazer isso, certifique-se de que os pods que são caros de despejar tenham a anotação. cluster-autoscaler.kubernetes.io/safe-to-evict=false
Abaixo está um exemplo de yaml para definir a anotação:
8"" linenumbering="unnumbered">apiVersion: v1 kind: Pod metadata: name: label-demo labels: environment: production annotations: + "cluster-autoscaler.kubernetes.io/safe-to-evict": "false" spec: containers: * name: nginx image: nginx ports: ** containerPort: 80