Economize nos custos da nuvem Kubernetes na AWS

A tradução do artigo foi preparada na véspera do início do curso "Plataforma de infraestrutura baseada em Kubernetes".

Economize nos custos da nuvem Kubernetes na AWS

Como economizar nos custos de nuvem ao trabalhar com Kubernetes? Não existe uma solução única certa, mas este artigo descreve diversas ferramentas que podem ajudá-lo a gerenciar seus recursos de maneira mais eficaz e a reduzir os custos de computação em nuvem.

Escrevi este artigo pensando no Kubernetes para AWS, mas ele se aplicará (quase) exatamente da mesma forma a outros provedores de nuvem. Presumo que seus clusters já tenham escalonamento automático configurado (escalonador automático de cluster). A remoção de recursos e a redução de sua implantação só economizarão dinheiro se também reduzirem sua frota de nós de trabalho (instâncias EC2).

Este artigo abordará:

  • limpando recursos não utilizados (zelador kube)
  • Reduzir o escalonamento fora do horário comercial (kube-downscaler)
  • usando escalonamento automático horizontal (HPA),
  • redução da reserva excessiva de recursos (relatório de recurso kube, VPA)
  • usando instâncias spot

Limpando recursos não utilizados

Trabalhar em um ambiente de ritmo acelerado é ótimo. Queremos organizações de tecnologia acelerado. A entrega mais rápida de software também significa mais implantações de relações públicas, ambientes de visualização, protótipos e soluções analíticas. Tudo é implantado no Kubernetes. Quem tem tempo para limpar manualmente as implantações de teste? É fácil esquecer a exclusão de um experimento de uma semana. A conta da nuvem vai acabar aumentando devido a algo que esquecemos de fechar:

Economize nos custos da nuvem Kubernetes na AWS

(Henning Jacobs:
Jiza:
(citações) Corey Quinn:
Mito: sua conta AWS é uma função do número de usuários que você possui.
Fato: sua pontuação na AWS é função do número de engenheiros que você possui.

Ivan Kurnosov (em resposta):
Fato real: sua pontuação na AWS é uma função do número de coisas que você esqueceu de desabilitar/excluir.)

Zelador do Kubernetes (kube-janitor) ajuda a limpar seu cluster. A configuração do zelador é flexível para uso global e local:

  • As regras em todo o cluster podem definir o tempo máximo de vida (TTL) para implantações de PR/teste.
  • Recursos individuais podem ser anotados com zelador/ttl, por exemplo, para remover automaticamente o pico/protótipo após 7 dias.

As regras gerais são definidas no arquivo YAML. Seu caminho é passado através do parâmetro --rules-file em kube-zelador. Aqui está um exemplo de regra para remover todos os namespaces com -pr- no nome depois de dois dias:

- id: cleanup-resources-from-pull-requests
  resources:
    - namespaces
  jmespath: "contains(metadata.name, '-pr-')"
  ttl: 2d

O exemplo a seguir regula o uso do rótulo do aplicativo nos pods Deployment e StatefulSet para todos os novos Deployments/StatefulSets em 2020, mas ao mesmo tempo permite a execução de testes sem esse rótulo por uma semana:

- id: require-application-label
  # удалить deployments и statefulsets без метки "application"
  resources:
    - deployments
    - statefulsets
  # см. http://jmespath.org/specification.html
  jmespath: "!(spec.template.metadata.labels.application) && metadata.creationTimestamp > '2020-01-01'"
  ttl: 7d

Execute uma demonstração por tempo limitado de 30 minutos em um cluster executando kube-janitor:

kubectl run nginx-demo --image=nginx
kubectl annotate deploy nginx-demo janitor/ttl=30m

Outra fonte de aumento de custos são os volumes persistentes (AWS EBS). Excluir um StatefulSet do Kubernetes não exclui seus volumes persistentes (PVC – PersistentVolumeClaim). Volumes EBS não utilizados podem facilmente resultar em custos de centenas de dólares por mês. O Kubernetes Janitor possui um recurso para limpar PVCs não utilizados. Por exemplo, esta regra removerá todos os PVCs que não são montados por um módulo e que não são referenciados por um StatefulSet ou CronJob:

# удалить все PVC, которые не смонтированы и на которые не ссылаются StatefulSets
- id: remove-unused-pvcs
  resources:
  - persistentvolumeclaims
  jmespath: "_context.pvc_is_not_mounted && _context.pvc_is_not_referenced"
  ttl: 24h

O Kubernetes Janitor pode ajudá-lo a manter seu cluster limpo e evitar que os custos de computação em nuvem aumentem lentamente. Para obter instruções de implantação e configuração, siga README kube-zelador.

Reduza o escalonamento fora do horário comercial

Os sistemas de teste e preparação normalmente são necessários para operação apenas durante o horário comercial. Alguns aplicativos de produção, como ferramentas de back office/administração, também exigem apenas disponibilidade limitada e podem ser desativados durante a noite.

Redutor de escala do Kubernetes (kube-downscaler) permite que usuários e operadores reduzam o sistema fora do horário comercial. Implantações e StatefulSets podem ser dimensionadas para zero réplicas. CronJobs podem ser suspensos. O Kubernetes Downscaler é configurado para um cluster inteiro, um ou mais namespaces ou recursos individuais. Você pode definir “tempo ocioso” ou, inversamente, “tempo de trabalho”. Por exemplo, para reduzir ao máximo o dimensionamento durante as noites e fins de semana:

image: hjacobs/kube-downscaler:20.4.3
args:
  - --interval=30
  # не отключать компоненты инфраструктуры
  - --exclude-namespaces=kube-system,infra
  # не отключать kube-downscaler, а также оставить Postgres Operator, чтобы исключенными БД можно было управлять
  - --exclude-deployments=kube-downscaler,postgres-operator
  - --default-uptime=Mon-Fri 08:00-20:00 Europe/Berlin
  - --include-resources=deployments,statefulsets,stacks,cronjobs
  - --deployment-time-annotation=deployment-time

Aqui está um gráfico para dimensionar nós de trabalho do cluster nos finais de semana:

Economize nos custos da nuvem Kubernetes na AWS

A redução de aproximadamente 13 para 4 nós de trabalho certamente faz uma diferença notável em sua conta da AWS.

Mas e se eu precisar trabalhar durante o “tempo de inatividade” do cluster? Certas implantações podem ser excluídas permanentemente do dimensionamento adicionando a anotação downscaler/exclude: true. As implantações podem ser temporariamente excluídas usando a anotação downscaler/exclude-until com um carimbo de data/hora absoluto no formato AAAA-MM-DD HH:MM (UTC). Se necessário, todo o cluster pode ser reduzido implantando um pod com a anotação downscaler/force-uptime, por exemplo, iniciando o nginx em branco:

kubectl run scale-up --image=nginx
kubectl annotate deploy scale-up janitor/ttl=1h # удалить развертывание через час
kubectl annotate pod $(kubectl get pod -l run=scale-up -o jsonpath="{.items[0].metadata.name}") downscaler/force-uptime=true

ver README kube-downscaler, se você estiver interessado em instruções de implantação e opções adicionais.

Usar escalonamento automático horizontal

Muitas aplicações/serviços lidam com um padrão de carregamento dinâmico: às vezes seus módulos ficam ociosos e às vezes funcionam em capacidade total. Operar uma frota permanente de pods para lidar com picos de carga máximos não é econômico. Kubernetes oferece suporte ao escalonamento automático horizontal em um recurso HorizontalPodAutoscaler (HPA). O uso da CPU costuma ser um bom indicador de dimensionamento:

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        averageUtilization: 100
        type: Utilization

Zalando criou um componente para conectar facilmente métricas personalizadas para escalonamento: Adaptador de métricas Kube (kube-metrics-adapter) é um adaptador de métricas genérico para Kubernetes que pode coletar e servir métricas personalizadas e externas para escalonamento automático horizontal de pods. Ele oferece suporte ao dimensionamento com base em métricas do Prometheus, filas SQS e outras configurações. Por exemplo, para dimensionar sua implantação para uma métrica personalizada representada pelo próprio aplicativo como JSON em /metrics use:

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa
  annotations:
    # metric-config.<metricType>.<metricName>.<collectorName>/<configKey>
    metric-config.pods.requests-per-second.json-path/json-key: "$.http_server.rps"
    metric-config.pods.requests-per-second.json-path/path: /metrics
    metric-config.pods.requests-per-second.json-path/port: "9090"
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Pods
    pods:
      metric:
        name: requests-per-second
      target:
        averageValue: 1k
        type: AverageValue

A configuração do escalonamento automático horizontal com HPA deve ser uma das ações padrão para melhorar a eficiência dos serviços sem estado. O Spotify fez uma apresentação com sua experiência e recomendações para HPA: dimensione suas implantações, não sua carteira.

Reduza a reserva excessiva de recursos

As cargas de trabalho do Kubernetes determinam suas necessidades de CPU/memória por meio de “solicitações de recursos”. Os recursos da CPU são medidos em núcleos virtuais ou mais comumente em “milicores”, por exemplo 500m implica 50% de vCPU. Os recursos de memória são medidos em bytes e podem ser usados ​​sufixos comuns, como 500Mi, que significa 500 megabytes. As solicitações de recursos "bloqueiam" a capacidade nos nós de trabalho, o que significa que um pod com uma solicitação de CPU de 1000 m em um nó com 4 vCPUs deixará apenas 3 vCPUs disponíveis para outros pods. [1]

Folga (excesso de reserva) é a diferença entre os recursos solicitados e o uso real. Por exemplo, um pod que solicita 2 GiB de memória, mas usa apenas 200 MiB, tem aproximadamente 1,8 GiB de memória “excedente”. Excesso custa dinheiro. Pode-se estimar aproximadamente que 1 GiB de memória redundante custa cerca de US$ 10 por mês. [2]

Relatório de recursos do Kubernetes (kube-resource-report) exibe reservas excedentes e pode ajudá-lo a determinar o potencial de economia:

Economize nos custos da nuvem Kubernetes na AWS

Relatório de recursos do Kubernetes mostra o excesso agregado por aplicação e comando. Isto permite-lhe encontrar locais onde as exigências de recursos podem ser reduzidas. O relatório HTML gerado fornece apenas um instantâneo do uso de recursos. Você deve observar o uso de CPU/memória ao longo do tempo para determinar solicitações de recursos adequadas. Aqui está um gráfico Grafana para um serviço "típico" com uso intenso de CPU: todos os pods estão usando significativamente menos do que os três núcleos de CPU solicitados:

Economize nos custos da nuvem Kubernetes na AWS

Reduzir a solicitação de CPU de 3000m para aproximadamente 400m libera recursos para outras cargas de trabalho e permite que o cluster seja menor.

“O uso médio da CPU de instâncias EC2 geralmente oscila na faixa percentual de um dígito”, escreve Corey Quinn. Enquanto para EC2 estimar o tamanho certo pode ser uma má decisãoAlterar algumas consultas de recursos do Kubernetes em um arquivo YAML é fácil e pode trazer grandes economias.

Mas será que realmente queremos que as pessoas alterem valores em arquivos YAML? Não, as máquinas podem fazer isso muito melhor! Kubernetes Autoescalador vertical de pod (VPA) faz exatamente isso: adapta solicitações e restrições de recursos de acordo com a carga de trabalho. Aqui está um exemplo de gráfico de solicitações de CPU do Prometheus (linha azul fina) adaptadas pelo VPA ao longo do tempo:

Economize nos custos da nuvem Kubernetes na AWS

Zalando usa VPA em todos os seus clusters para componentes de infraestrutura. Aplicativos não críticos também podem usar VPA.

ranúnculo do Fairwind é uma ferramenta que cria um VPA para cada implantação em um namespace e, em seguida, exibe uma recomendação de VPA em seu painel. Ele pode ajudar os desenvolvedores a definir as solicitações corretas de CPU/memória para seus aplicativos:

Economize nos custos da nuvem Kubernetes na AWS

Escrevi um pequeno postagem no blog sobre VPA em 2019 e recentemente em Comunidade de usuários finais do CNCF discutiu o problema do VPA.

Usando instâncias spot do EC2

Por último, mas não menos importante, os custos do AWS EC2 podem ser reduzidos usando instâncias Spot como nós de trabalho do Kubernetes [3]. As instâncias spot estão disponíveis com um desconto de até 90% em comparação com os preços sob demanda. Executar o Kubernetes no EC2 Spot é uma boa combinação: você precisa especificar vários tipos de instância diferentes para maior disponibilidade, o que significa que você pode obter um nó maior pelo mesmo preço ou menor, e a capacidade aumentada pode ser usada por cargas de trabalho conteinerizadas do Kubernetes.

Como executar o Kubernetes no EC2 Spot? Existem várias opções: usar um serviço de terceiros como o SpotInst (agora chamado de "Spot", não me pergunte por quê) ou simplesmente adicionar um Spot AutoScalingGroup (ASG) ao seu cluster. Por exemplo, aqui está um snippet do CloudFormation para um Spot ASG "com capacidade otimizada" com vários tipos de instância:

MySpotAutoScalingGroup:
 Properties:
   HealthCheckGracePeriod: 300
   HealthCheckType: EC2
   MixedInstancesPolicy:
     InstancesDistribution:
       OnDemandPercentageAboveBaseCapacity: 0
       SpotAllocationStrategy: capacity-optimized
     LaunchTemplate:
       LaunchTemplateSpecification:
         LaunchTemplateId: !Ref LaunchTemplate
         Version: !GetAtt LaunchTemplate.LatestVersionNumber
       Overrides:
         - InstanceType: "m4.2xlarge"
         - InstanceType: "m4.4xlarge"
         - InstanceType: "m5.2xlarge"
         - InstanceType: "m5.4xlarge"
         - InstanceType: "r4.2xlarge"
         - InstanceType: "r4.4xlarge"
   LaunchTemplate:
     LaunchTemplateId: !Ref LaunchTemplate
     Version: !GetAtt LaunchTemplate.LatestVersionNumber
   MinSize: 0
   MaxSize: 100
   Tags:
   - Key: k8s.io/cluster-autoscaler/node-template/label/aws.amazon.com/spot
     PropagateAtLaunch: true
     Value: "true"

Algumas notas sobre o uso do Spot com Kubernetes:

  • Você precisa lidar com encerramentos spot, por exemplo, mesclando o nó quando a instância for interrompida
  • Zalando usa garfo escalonamento automático de cluster oficial com prioridades de pool de nós
  • Nós pontuais pode ser forçado aceitar “cadastros” de cargas de trabalho para rodar no Spot

Resumo

Espero que algumas das ferramentas apresentadas sejam úteis para você reduzir sua conta de nuvem. Você pode encontrar a maior parte do conteúdo do artigo também em minha palestra no DevOps Gathering 2019 no YouTube e em slides.

Quais são suas práticas recomendadas para economizar custos de nuvem no Kubernetes? Por favor, deixe-me saber em Twitter (@try_except_).

[1] Na verdade, menos de 3 vCPUs permanecerão utilizáveis, pois a taxa de transferência do nó é reduzida pelos recursos reservados do sistema. O Kubernetes distingue entre capacidade de nó físico e recursos "provisionados" (Nó alocável).

[2] Exemplo de cálculo: uma instância m5.large com 8 GiB de memória custa ~$84 ​​​​por mês (eu-central-1, On-Demand), ou seja, bloquear 1/8 do nó custa aproximadamente US$ 10/mês.

[3] Existem muitas outras maneiras de reduzir sua fatura do EC2, como Instâncias Reservadas, Plano de Poupança, etc. - Não abordarei esses tópicos aqui, mas você definitivamente deveria investigá-los!

Saiba mais sobre o curso.

Fonte: habr.com

Adicionar um comentário