O escalonamento é um dos pilares do Kubernetes, permitindo que suas aplicações se adaptem dinamicamente à carga de trabalho. Nesta aula, vamos explorar os mecanismos essenciais para escalar seus pods e nós, garantindo disponibilidade e eficiência de custos. Você aprenderá a configurar o Horizontal Pod Autoscaler (HPA), a definir limites de recursos adequados, e a entender as opções de escalonamento de nós.

Dominar esses conceitos é fundamental para operar clusters em produção, onde a demanda pode variar drasticamente. Vamos abordar desde a teoria até exemplos práticos com YAML e comandos kubectl, para que você possa implementar escalonamento de forma consciente e eficaz.

Horizontal Pod Autoscaler

O Horizontal Pod Autoscaler (HPA) é um recurso nativo do Kubernetes que ajusta automaticamente o número de réplicas de um Deployment, ReplicaSet ou StatefulSet com base em métricas observadas, como uso de CPU, memória ou métricas personalizadas. Ele opera em um ciclo contínuo, consultando o Metrics Server (ou um adaptador de métricas) e calculando o número desejado de réplicas.

O HPA é definido por um objeto YAML que especifica o alvo (scaleTargetRef), os limites mínimo e máximo de réplicas, e as métricas que orientam o escalonamento. O cálculo do número desejado é baseado na razão entre o valor atual da métrica e o valor alvo, com uma fórmula que considera a média sobre os pods.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: minha-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: minha-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

Neste exemplo, o HPA ajusta o número de réplicas para manter a utilização média de CPU em 60% e de memória em 80%. Se a carga aumentar, o HPA adiciona réplicas; se diminuir, remove réplicas, respeitando os limites definidos.

Para que o HPA funcione, é necessário que o Metrics Server esteja instalado no cluster. Ele coleta métricas de uso de recursos dos pods e as expõe através da API de métricas. Sem o Metrics Server, o HPA não consegue obter os dados e não realizará o escalonamento.

Recursos (requests/limits)

Definir requests e limits para contêineres é crucial para o escalonamento eficiente. Requests indicam a quantidade mínima de recursos que o contêiner precisa, usada pelo agendador para alocar o pod em um nó. Limits definem o máximo que o contêiner pode consumir, evitando que um único pod monopolize os recursos do nó.

Quando você define requests, o HPA pode calcular a utilização como a razão entre o uso atual e o request. Isso permite que o escalonamento seja baseado em métricas relativas ao que foi solicitado, em vez de valores absolutos. Definir requests adequados é essencial para que o HPA funcione corretamente.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: minha-app
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: minha-app
    spec:
      containers:
      - name: app
        image: minha-imagem:v1
        resources:
          requests:
            cpu: "250m"
            memory: "128Mi"
          limits:
            cpu: "500m"
            memory: "256Mi"

Neste exemplo, cada pod solicita 250 milicores de CPU (um quarto de um núcleo) e 128 MiB de memória. Os limites são o dobro desses valores. Isso significa que o pod pode usar mais recursos do que o solicitado, mas nunca exceder o limite. O HPA usará o request para calcular a utilização de CPU.

É importante não definir limits sem requests, pois isso pode causar problemas de agendamento e comportamento do HPA. A prática recomendada é sempre definir ambos, ajustando-os conforme o perfil de uso da aplicação.

Escalonamento de nós (visão geral)

Além de escalar pods, também é possível escalar a infraestrutura subjacente: os nós do cluster. O escalonamento de nós é gerenciado por componentes como o Cluster Autoscaler (para clusters em nuvem) ou por soluções específicas de provedores. Ele ajusta o número de nós com base na demanda de recursos dos pods, adicionando nós quando há pods não programáveis e removendo nós quando há excesso de capacidade.

O escalonamento de nós é importante para otimizar custos, pois você paga apenas pelos nós que realmente precisa. No entanto, ele é mais lento que o escalonamento de pods, pois provisionar uma nova máquina pode levar minutos. Por isso, é comum combinar o HPA (que escala pods rapidamente) com o Cluster Autoscaler (que ajusta a infraestrutura a médio prazo).

Em clusters gerenciados (como EKS, GKE, AKS), o escalonamento de nós é configurado através de grupos de nós (node pools) com políticas de escala automática. Por exemplo, no GKE, você pode habilitar o autoscaling em um node pool, definindo o número mínimo e máximo de nós.

# Exemplo conceitual de configuração do Cluster Autoscaler em um cluster na nuvem
# (comandos variam conforme o provedor)
gcloud container clusters update minha-cluster \
  --enable-autoscaling \
  --min-nodes=1 \
  --max-nodes=10 \
  --node-pool=default-pool

O Cluster Autoscaler monitora continuamente os pods não programáveis (Pending) e a utilização dos nós. Se houver pods que não podem ser alocados, ele adiciona um nó. Se houver nós com utilização baixa por um período, ele remove esses nós, respeitando as políticas de segurança (como não remover nós com pods críticos).

Estratégias

Existem várias estratégias para escalonamento em Kubernetes, e a escolha depende do tipo de aplicação e dos requisitos de SLA. As principais abordagens incluem:

  • Escalonamento manual: ajustar manualmente o número de réplicas com kubectl scale. Simples, mas requer intervenção humana e não reage a mudanças de carga.
  • HPA baseado em métricas de recursos: o mais comum, usando CPU e memória. Adequado para aplicações com carga previsível.
  • HPA baseado em métricas personalizadas: usando métricas de aplicação (como número de requisições por segundo) através de adaptadores como Prometheus Adapter. Permite escalonamento mais preciso.
  • Escalonamento preditivo: usando ferramentas como KEDA (Kubernetes Event-driven Autoscaling) que reage a eventos externos (fila de mensagens, por exemplo). Ideal para workloads orientadas a eventos.
  • Vertical Pod Autoscaler (VPA): ajusta os requests e limits dos pods automaticamente, em vez do número de réplicas. Útil quando o workload não pode ser replicado facilmente.

Uma estratégia comum é combinar HPA com Cluster Autoscaler, garantindo que os pods escalem rapidamente e a infraestrutura acompanhe a demanda. Também é importante definir políticas de tolerância a falhas e de orçamento de interrupção (PDB) para evitar indisponibilidade durante escalonamentos.

# Exemplo de escalonamento manual
kubectl scale deployment minha-app --replicas=5

# Verificar o status do HPA
kubectl get hpa

# Ver eventos do HPA para diagnóstico
kubectl describe hpa minha-app-hpa

Para implementar uma estratégia robusta, é essencial monitorar as métricas e ajustar os parâmetros do HPA conforme o comportamento observado. Ferramentas como Grafana podem ajudar a visualizar a utilização e a eficácia do escalonamento.

Boas práticas

Ao configurar escalonamento, siga estas boas práticas:

  • Defina sempre requests e limits para todos os contêineres, mesmo que você não use HPA inicialmente.
  • Use o HPA com base em múltiplas métricas, se possível, para capturar diferentes aspectos da carga.
  • Configure o HPA com limites mínimos e máximos adequados para evitar flutuações extremas (thrashing).
  • Monitore o comportamento do HPA e ajuste os alvos de utilização conforme a experiência.
  • Combine HPA com Cluster Autoscaler para escalonamento completo.
  • Para aplicações stateful, considere o uso de StatefulSets e escalonamento manual ou VPA, pois replicar pode ser complexo.

Referências

Exercícios

  1. Crie um Deployment chamado web com a imagem nginx, 2 réplicas, requests de CPU de 100m e limits de 200m. Em seguida, crie um HPA que escale entre 1 e 5 réplicas com alvo de 50% de utilização de CPU. Use comandos kubectl e mostre o YAML do HPA.

✓ Resposta: Primeiro, crie o Deployment com o comando kubectl create deployment web --image=nginx --replicas=2 e depois edite-o para adicionar os recursos. O YAML do Deployment ficaria assim:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx
        resources:
          requests:
            cpu: "100m"
          limits:
            cpu: "200m"
Para criar o HPA, use o comando kubectl autoscale deployment web --cpu-percent=50 --min=1 --max=5 ou crie o seguinte YAML:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
  1. Explique a diferença entre requests e limits e por que é importante defini-los para o funcionamento do HPA.

✓ Resposta: Requests são a quantidade mínima de recursos que o contêiner precisa, usados pelo agendador para alocar o pod em um nó. Limits são o máximo que o contêiner pode consumir, evitando que ele monopolize recursos. O HPA usa os requests como base para calcular a utilização (uso atual / requests). Se os requests não forem definidos, o HPA não consegue calcular a utilização e pode não escalar corretamente. Definir ambos garante previsibilidade e estabilidade.
  1. Qual é o papel do Metrics Server no contexto do HPA? O que acontece se ele não estiver instalado?

✓ Resposta: O Metrics Server é um componente que coleta métricas de uso de CPU e memória dos pods e nós, expondo-as através da API de métricas. O HPA consulta essas métricas para decidir o número de réplicas. Se o Metrics Server não estiver instalado, o HPA não consegue obter os dados e fica inoperante, mantendo o número de réplicas fixo (ou alertando erro). Portanto, é pré-requisito para o funcionamento do HPA.
  1. Descreva uma estratégia de escalonamento combinando HPA e Cluster Autoscaler, explicando como eles interagem.

✓ Resposta: Uma estratégia comum é configurar o HPA para escalar pods com base em métricas de CPU/memória, e o Cluster Autoscaler para ajustar o número de nós. Quando a carga aumenta, o HPA adiciona réplicas, mas pode não haver capacidade nos nós. Nesse caso, os pods novos ficam em estado Pending, e o Cluster Autoscaler detecta isso e adiciona um novo nó. Quando a carga diminui, o HPA remove réplicas, e o Cluster Autoscaler eventualmente remove nós subutilizados. Essa combinação garante que os pods tenham recursos suficientes e que a infraestrutura seja dimensionada conforme a demanda, otimizando custos.
  1. Crie um HPA que utilize métricas personalizadas baseadas em requisições por segundo (RPS), usando o Prometheus Adapter como exemplo. Explique os passos necessários.

✓ Resposta: Para usar métricas personalizadas, é necessário instalar o Prometheus e o Prometheus Adapter no cluster. O Adapter expõe métricas do Prometheus como métricas de API. Passos: 1) Instalar o Prometheus e o Adapter (via Helm ou YAML). 2) Configurar o Adapter para consultar uma métrica específica, por exemplo, http_requests_per_second. 3) Criar um HPA com type: Object ou Pods apontando para essa métrica. Exemplo de HPA:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: minha-app-hpa-rps
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: minha-app
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: 100
Assim, o HPA ajusta as réplicas para manter uma média de 100 RPS por pod. É necessário que a aplicação exponha métricas no formato Prometheus.