Otimizando requests no Kubernetes para evitar overcost

A configuração de requests e limits no Kubernetes é uma prática essencial para garantir que suas aplicações tenham os recursos necessários para operar de maneira eficiente. No entanto, o uso inadequado dessas configurações pode levar ao consumo excessivo de recursos, resultando em custos elevados e a necessidade de provisionar novos nodes. Este artigo explora como otimizar o uso de requests no Kubernetes para evitar esses problemas.

Minha experiência com ambientes de larga escala me faz enxergar todos os tipos imagináveis de situação. Uma delas foi encontrar clusters gigantes, com dezenas e centenas de nodes, consumindo recursos fantasmas simplesmente por estarem com as configurações de request inadequadas.

Kubernetes gerenciados em clouds públicas

Nas clouds públicas, como AWS, Azure e Google Cloud, os serviços de Kubernetes gerenciados (EKS, AKS, GKE) geralmente incluem configurações pré-definidas para ajudar a gerenciar recursos de forma eficiente. Essas configurações otimizadas incluem métricas de monitoramento e escalabilidade automáticas que facilitam a administração dos recursos. Entretanto, em ambientes on-premises, essas configurações precisam ser implementadas manualmente. Sem essas otimizações, é fácil superestimar ou subestimar as necessidades de recursos, levando a desperdícios ou falta de capacidade.

A prática de FinOps

FinOps é a prática de gerenciar custos em ambientes de cloud computing, unindo as melhores práticas de finanças e operações. No contexto do Kubernetes, FinOps visa otimizar o uso de recursos para evitar gastos excessivos. Este artigo pode contribuir significativamente para as práticas de FinOps, ajudando as equipes a entender e ajustar melhor os requests e limits, garantindo uma utilização mais eficiente e econômica dos recursos de computação.

1. Instalando o metrics server

O Kubernetes utiliza o Metrics Server para fornecer informações sobre o uso de recursos no cluster, que podem ser acessadas pela CLI usando o comando kubectl top.

Instalando o metrics server

  1. Instale o Metrics Server: Você pode instalar o Metrics Server usando o seguinte comando:
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
  1. Verifique se o Metrics Server está funcionando corretamente: Após a instalação, verifique se o Metrics Server está funcionando:
kubectl get deployment metrics-server -n kube-system

Você deve ver algo assim:

NAME             DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
metrics-server   1         1         1            1           10s

2. Configurando o Horizontal Pod Autoscaler (HPA)

O Horizontal Pod Autoscaler (HPA) ajusta automaticamente o número de pods em uma replicaset, deployment ou statefulset com base na utilização observada de métricas como CPU ou memória. O HPA é uma ferramenta essencial para garantir que suas aplicações possam escalar de acordo com a demanda.

Configurando o HPA

Para usar o HPA, primeiro certifique-se de que o Metrics Server está instalado, pois ele fornece as métricas necessárias para o HPA.

  1. Exemplo de Deployment com Requests e Limits Definidos:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-apache
spec:
  replicas: 1
  selector:
    matchLabels:
      run: php-apache
  template:
    metadata:
      labels:
        run: php-apache
    spec:
      containers:
      - name: php-apache
        image: k8s.gcr.io/hpa-example
        resources:
          requests:
            cpu: 200m
          limits:
            cpu: 500m
        ports:
        - name: http
          containerPort: 80
  1. Criar o Deployment:
kubectl apply -f deployment.yaml
  1. Configurar o HPA:
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10

Este comando cria um HPA que mantém o uso médio de CPU dos pods em 50%, escalando entre 1 e 10 réplicas conforme necessário.

  1. Verificar o HPA:
kubectl get hpa

Você deve ver algo assim:

NAME         REFERENCE               TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   <unknown>/50%   1         10        1          30s

Funcionamento do cálculo e tempo do HPA

O HPA ajusta o número de pods com base em métricas como uso de CPU e memória. Aqui está como funciona o cálculo e os tempos de escala para up e down:

Cálculo do HPA
  1. Coleta de métricas:
    O HPA obtém métricas de uso de CPU e memória do metrics server a cada 30 segundos (por padrão).
  2. Cálculo de targets:
    O HPA compara o uso atual de recursos com o target definido (por exemplo, 50% de uso de CPU).
  3. Cálculo do número de réplicas:
    O HPA usa a seguinte fórmula para calcular o número desejado de réplicas:
desiredReplicas = ceil(currentReplicas * (currentMetricValue / desiredMetricValue))

Por exemplo, se o target de uso de CPU é 50% e o uso atual é 100%, o HPA tentará dobrar o número de réplicas.

Tempo de escala
  1. Scale Up:
  • Quando a métrica de uso de recursos excede o target, o HPA escala rapidamente para adicionar mais pods. O tempo de detecção e escala depende da frequência de coleta de métricas (30 segundos) e do tempo necessário para iniciar novos pods.
  1. Scale Down:
  • O HPA escala para baixo de forma mais conservadora para evitar flutuações frequentes (churning). Por padrão, o HPA espera 5 minutos antes de reduzir o número de pods.
Parâmetros configuráveis

Você pode ajustar os parâmetros do HPA, incluindo os tempos de escala, alterando a configuração do controlador de HPA no Kubernetes.

spec:
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300 # Tempo de espera antes de escalar para baixo (5 minutos)
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60 # Reduzir no máximo 10% dos pods a cada minuto
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 100
        periodSeconds: 15 # Aumentar no máximo 100% dos pods a cada 15 segundos

3. Verificando o consumo de requests e limits

Para obter o total de requests e limits de CPU e memória no cluster, por namespace e por pod, você pode usar os seguintes comandos kubectl junto com jq e awk para processar a saída JSON:

Verificando métricas com a CLI

Depois de instalar o Metrics Server, você pode usar o kubectl top para verificar o uso de recursos dos nodes e pods.

  1. Verificar o uso de recursos dos nodes:
kubectl top nodes

Este comando mostrará a utilização de CPU e memória para cada node no cluster.

  1. Verificar o uso de recursos dos pods:
kubectl top pods --all-namespaces

Este comando mostrará a utilização de CPU e memória para cada pod em todos os namespaces.

Verificando o total de requests e limits

  1. Obter o total de requests e limits por pod:
kubectl get pods --all-namespaces -o json | jq -r '.items[] | "\(.metadata.namespace) \(.metadata.name) \(.spec.containers[]?.resources.requests.cpu) \(.spec.containers[]?.resources.limits.cpu) \(.spec.containers[]?.resources.requests.memory) \(.spec.containers[]?.resources.limits.memory)"' | awk '
   {
     if ($3) cpu_requests += substr($3, 1, length($3)-1) * (substr($3, length($3)) == "m" ? 0.001 : 1)
     if ($4) cpu_limits += substr($4, 1, length($4)-1) * (substr($4, length($4)) == "m" ? 0.001 : 1)
     if ($5) memory_requests += substr($5, 1, length($5)-2) * (substr($5, length($5)-1) == "Ki" ? 1024 : 1)
     if ($6) memory_limits += substr($6, 1, length($6)-2) * (substr($6, length($6)-1) == "Ki" ? 1024 : 1)
     print $1, $2, "CPU Requests:", cpu_requests, "CPU Limits:", cpu_limits, "Memory Requests:", memory_requests/1024/1024, "Mi", "Memory Limits:", memory_limits/1024/1024, "Mi"
     cpu_requests = 0
     cpu_limits = 0
     memory_requests = 0
     memory_limits = 0
   }'
  1. Obter o total de requests e limits por namespace:
kubectl get pods --all-namespaces -o json | jq -r '.items[] | "\(.metadata.namespace) \(.spec.containers[]?.resources.requests.cpu) \(.spec.containers[]?.resources.limits.cpu) \(.spec.containers[]?.resources.requests.memory) \(.spec.containers[]?.resources.limits.memory)"' | awk '
   {
     cpu_requests[$1] += substr($2, 1, length($2)-1) * (substr($2, length($2)) == "m" ? 0.001 : 1)
     cpu_limits[$1] += substr($3, 1, length($3)-1) * (substr($3, length($3)) == "m" ? 0.001 : 1)
     memory_requests[$1] += substr($4, 1, length($4)-2) * (substr($4, length($4)-1) == "Ki" ? 1024 : 1)
     memory_limits[$1] += substr($5, 1, length($5)-2) * (substr($5, length($5)-1) == "Ki" ? 1024 : 1)
   }
   END {
     for (ns in cpu_requests) {
       print ns, "CPU Requests:", cpu_requests[ns], "CPU Limits:", cpu_limits[ns], "Memory Requests:", memory_requests[ns]/1024/1024, "Mi", "Memory Limits:", memory_limits[ns]/1024/1024, "Mi"
     }
   }'
  1. Obter o total de requests e limits do cluster:
kubectl get pods --all-namespaces -o json | jq -r '.items[] | "\(.spec.containers[]?.resources.requests.cpu) \(.spec.containers[]?.resources.limits.cpu) \(.spec.containers[]?.resources.requests.memory) \(.spec.containers[]?.resources.limits.memory)"' | awk '
   {
     if ($1) cpu_requests += substr($1, 1, length($1)-1) * (substr($1, length($1)) == "m" ? 0.001 : 1)
     if ($2) cpu_limits += substr($2, 1, length($2)-1) * (substr($2, length($2)) == "m" ? 0.001 : 1)
     if ($3) memory_requests += substr($3, 1, length($3)-2) * (substr($3, length($3)-1) == "Ki" ? 1024 : 1)
     if ($4) memory_limits += substr($4, 1, length($4)-2) * (substr($4, length($4)-1) == "Ki" ? 1024 : 1)
   }
   END {
     print "Total CPU Requests:", cpu_requests, "Total CPU Limits:", cpu_limits, "Total Memory Requests:", memory_requests/1024/1024, "Mi", "Total Memory Limits:", memory_limits/1024/1024, "Mi"
   }'

Conclusão

O uso inadequado de requests no Kubernetes pode levar a custos desnecessários e ineficiências operacionais. Ao monitorar o uso de recursos com o metrics server, configurar o Horizontal Pod Autoscaler e ajustar requests e limits com base em dados reais, você pode otimizar o uso de recursos no seu cluster Kubernetes, garantindo eficiência e economia.

Implementar práticas de FinOps em seus ambientes Kubernetes é crucial para garantir que os recursos sejam usados de forma eficiente e econômica. Este artigo mostrou como configurar e usar o metrics server e o HPA para monitorar e ajustar o uso de recursos, ajudando a evitar desperdícios e controlar os custos operacionais.

O autoscaler ajuda com scale-up e scale-down, porém, quem define o tamanho do request é o pod e não tem como o autoscaler controlar isso. Portanto, é importante medir o consumo de requests conforme mencionado no artigo para garantir que os recursos sejam usados de maneira eficiente e econômica.

Leave a Reply

Your email address will not be published. Required fields are marked *