Pular para o conteúdo
Kubernetes 14 min read

Kubernetes Autoscaling: HPA, VPA e KEDA para Escalar Workloads

Guia completo de autoscaling no Kubernetes com HPA, VPA e KEDA. Aprenda a escalar baseado em métricas customizadas, eventos e otimizar recursos.

Por Equipe Integr8 13/01/2025

Por que Autoscaling?

Em ambientes cloud-native, a demanda varia constantemente. Sem autoscaling, você escolhe entre desperdiçar recursos (over-provisioning) ou ter indisponibilidade (under-provisioning).

💰

Redução de Custos

Scale down automaticamente em períodos de baixa demanda

Performance

Scale up para manter latência e throughput sob carga

🔄

Resiliência

Distribuição automática de carga entre réplicas

🎯

Eficiência

Right-sizing automático de recursos (CPU/memória)

Tipos de Autoscaling no Kubernetes

HPA escala horizontalmente, VPA verticalmente, KEDA por eventos, e Cluster Autoscaler gerencia nodes
100%
Tipos de Autoscaling no Kubernetes

HPA escala horizontalmente, VPA verticalmente, KEDA por eventos, e Cluster Autoscaler gerencia nodes

HPA: Horizontal Pod Autoscaler

HPA ajusta o número de réplicas baseado em métricas.

HPA Básico com CPU

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300  # Espera 5min antes de scale down
      policies:
        - type: Percent
          value: 10
          periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0  # Scale up imediato
      policies:
        - type: Percent
          value: 100
          periodSeconds: 15
        - type: Pods
          value: 4
          periodSeconds: 15
      selectPolicy: Max
💡Requests são Essenciais

HPA calcula utilização baseado em requests, não limits. Se você não definir requests, o HPA não funcionará corretamente.

HPA com Métricas Customizadas

Para escalar baseado em métricas de aplicação (latência, fila, etc.):

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa-custom
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  minReplicas: 2
  maxReplicas: 20
  metrics:
    # Métrica do Prometheus Adapter
    - type: Pods
      pods:
        metric:
          name: http_requests_per_second
        target:
          type: AverageValue
          averageValue: "1000"

    # Métrica externa (ex: SQS queue length)
    - type: External
      external:
        metric:
          name: sqs_messages_visible
          selector:
            matchLabels:
              queue: myapp-queue
        target:
          type: AverageValue
          averageValue: "30"

Prometheus Adapter para Métricas Custom

# prometheus-adapter-config
rules:
  - seriesQuery: 'http_requests_total{namespace!="",pod!=""}'
    resources:
      overrides:
        namespace: {resource: "namespace"}
        pod: {resource: "pod"}
    name:
      matches: "^(.*)_total$"
      as: "${1}_per_second"
    metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)'

VPA: Vertical Pod Autoscaler

VPA ajusta automaticamente os requests de CPU e memória dos pods.

Instalação do VPA

git clone https://github.com/kubernetes/autoscaler.git
cd autoscaler/vertical-pod-autoscaler
./hack/vpa-up.sh

Modos do VPA

    apiVersion: autoscaling.k8s.io/v1
    kind: VerticalPodAutoscaler
    metadata:
      name: myapp-vpa
    spec:
      targetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: myapp
      updatePolicy:
        updateMode: "Auto"  # Off, Initial, ou Auto
      resourcePolicy:
        containerPolicies:
          - containerName: myapp
            minAllowed:
              cpu: 100m
              memory: 128Mi
            maxAllowed:
              cpu: 4
              memory: 8Gi
            controlledResources: ["cpu", "memory"]
            controlledValues: RequestsAndLimits
    ⚠️VPA + HPA

    VPA e HPA usando CPU não devem ser usados juntos no mesmo deployment. Use VPA para ajustar resources e HPA com métricas customizadas, ou apenas um deles.

    KEDA: Event-Driven Autoscaling

    KEDA permite escalar baseado em eventos de diversas fontes: filas, streams, métricas, cron, etc.

    Instalação do KEDA

    helm repo add kedacore https://kedacore.github.io/charts
    helm repo update
    
    helm install keda kedacore/keda \
      --namespace keda \
      --create-namespace

    Scale to Zero

    O diferencial do KEDA é permitir scale to zero (0 réplicas quando não há trabalho):

    apiVersion: keda.sh/v1alpha1
    kind: ScaledObject
    metadata:
      name: myapp-scaledobject
    spec:
      scaleTargetRef:
        name: myapp
      minReplicaCount: 0   # Scale to zero!
      maxReplicaCount: 100
      cooldownPeriod: 300  # Tempo antes de scale to zero
    
      triggers:
        - type: prometheus
          metadata:
            serverAddress: http://prometheus:9090
            metricName: http_requests_total
            query: sum(rate(http_requests_total{app="myapp"}[2m]))
            threshold: "100"

    KEDA com AWS SQS

    apiVersion: keda.sh/v1alpha1
    kind: ScaledObject
    metadata:
      name: sqs-consumer
    spec:
      scaleTargetRef:
        name: sqs-consumer
      minReplicaCount: 0
      maxReplicaCount: 50
    
      triggers:
        - type: aws-sqs-queue
          authenticationRef:
            name: aws-credentials
          metadata:
            queueURL: https://sqs.us-east-1.amazonaws.com/123456789/my-queue
            queueLength: "5"  # 1 pod para cada 5 mensagens
            awsRegion: us-east-1
    
    ---
    apiVersion: keda.sh/v1alpha1
    kind: TriggerAuthentication
    metadata:
      name: aws-credentials
    spec:
      secretTargetRef:
        - parameter: awsAccessKeyID
          name: aws-secret
          key: access-key
        - parameter: awsSecretAccessKey
          name: aws-secret
          key: secret-key

    KEDA com Kafka

    apiVersion: keda.sh/v1alpha1
    kind: ScaledObject
    metadata:
      name: kafka-consumer
    spec:
      scaleTargetRef:
        name: kafka-consumer
      minReplicaCount: 1
      maxReplicaCount: 100
    
      triggers:
        - type: kafka
          metadata:
            bootstrapServers: kafka:9092
            consumerGroup: my-consumer-group
            topic: my-topic
            lagThreshold: "100"  # Scale quando lag > 100
            offsetResetPolicy: earliest

    KEDA com Cron Schedule

    apiVersion: keda.sh/v1alpha1
    kind: ScaledObject
    metadata:
      name: scheduled-scaler
    spec:
      scaleTargetRef:
        name: myapp
      minReplicaCount: 1
      maxReplicaCount: 20
    
      triggers:
        # Scale up no horário comercial
        - type: cron
          metadata:
            timezone: America/Sao_Paulo
            start: 0 8 * * 1-5   # 8h, seg-sex
            end: 0 18 * * 1-5    # 18h, seg-sex
            desiredReplicas: "10"
    
        # Scale down fora do horário
        - type: cron
          metadata:
            timezone: America/Sao_Paulo
            start: 0 18 * * 1-5
            end: 0 8 * * 1-5
            desiredReplicas: "2"

    Estratégias Combinadas

    HPA + KEDA para Diferentes Triggers

    # KEDA para scale to zero e triggers baseados em eventos
    apiVersion: keda.sh/v1alpha1
    kind: ScaledObject
    metadata:
      name: myapp-keda
    spec:
      scaleTargetRef:
        name: myapp
      minReplicaCount: 0
      maxReplicaCount: 50
      triggers:
        - type: prometheus
          metadata:
            serverAddress: http://prometheus:9090
            query: sum(rate(http_requests_total{app="myapp"}[2m]))
            threshold: "50"
    
    # HPA assume quando há pelo menos 1 replica (para CPU-based)
    # Usar apenas se KEDA não cobrir seu caso de uso

    Cluster Autoscaler

    Escala os nodes do cluster quando pods não conseguem ser schedulados:

    # Para AWS EKS
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: cluster-autoscaler-config
    data:
      parameters: |
        {
          "scale-down-delay-after-add": "10m",
          "scale-down-unneeded-time": "10m",
          "scale-down-utilization-threshold": "0.5",
          "skip-nodes-with-local-storage": "false",
          "expander": "least-waste"
        }
    Stack Completa

    VPA para right-sizing inicial + KEDA para scale to zero e eventos + Cluster Autoscaler para nodes = máxima eficiência de custos.

    Métricas para Monitorar

    # Prometheus rules para alertas de autoscaling
    groups:
      - name: autoscaling
        rules:
          - alert: HPAMaxedOut
            expr: |
              kube_horizontalpodautoscaler_status_current_replicas
              == kube_horizontalpodautoscaler_spec_max_replicas
            for: 15m
            labels:
              severity: warning
            annotations:
              summary: "HPA {{ $labels.horizontalpodautoscaler }} at max replicas"
    
          - alert: HPANotScaling
            expr: |
              kube_horizontalpodautoscaler_status_desired_replicas
              != kube_horizontalpodautoscaler_status_current_replicas
            for: 15m
            labels:
              severity: warning

    Quer otimizar o autoscaling dos seus workloads Kubernetes? Fale com nossos especialistas para uma análise personalizada.