HPA é uma forma de auto-scaling que aumenta ou diminui o número de Pods em um Replication Controller, Deployment, Replica Set ou Stateful Set de acordo com a utilização de CPU. O scaling é horizontal porque afeta o número de instâncias ao invés dos recursos alocados para um único container. O HPA consegue tomar decisões baseadas em métricas customizadas ou externas e trabalha automaticamente após a sua configuração inicial. Uma vez configurado, o HPA ficará encarregado de monitorar constantemente as métricas e aumentar ou diminuir a quantidade de réplicas do Pod conforme leituras destas métricas. fonte

A figura abaixo ilustra um HPA que escalará o número de replicas se a média de uso da CPU de todos os Pods gerenciados pelo Deployment atingir 70%.

Figure 6-7. Autoscaling a Deployment horizontally

Figure 6-7. Autoscaling a Deployment horizontally

<aside> 💡 ué, [ (22 + 58) / 2 ] é diferente de 80, não?

” HPA calculates pod CPU utilization as total CPU usage of all containers in pod divided by total request. ” - Stack Overflow ” HPA calculates pod utilization as total usage of all containers in the pod divided by total request. It looks at all containers individually and returns if container doesn't have request. “ DIGIT-DevOps

Se for assim, no exemplo acima ocorre apenas uma request pois: [ (22 + 58) / 1 ] = 80

</aside>

O Deployment pode ser escalado usando o comando autoscale deployment passando o nome do Deployment e os thresholds(limites) nos quais você gostaria que o autoscaler atuasse.

No exemplo a seguir, estamos especificando a existência obrigatória de no mínimo duas réplicas do Pod a qualquer momento, um número máximo de 8 réplicas escaláveis pelo HPA e um threshold de utilização de CPU em 70%.

$ kubectl autoscale \\
	--name my-hpa \\
	deployment my-deploy \\
	--cpu-percent=70 \\
	--min=2 \\
	--max=8
	horizontalpodautoscaler.autoscaling/my-hpa autoscaled

$ kubectl get hpa               
	NAME     REFERENCE             TARGETS        MINPODS  MAXPODS  REPLICAS 
	my-hpa   Deployment/my-deploy  <unknown>/70%  2        8        0

Também é possível criar o Horizontal Pod Autoscaler de forma declarativa. O manifesto abaixo foi gerado a partir do comando visto acima utilizando a flag --dry-run=client -o yaml > hpa.yaml.

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: my-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-deploy
  maxReplicas: 8
  minReplicas: 2
  targetCPUUtilizationPercentage: 70

O status do HPA exibe o threshold de CPU correto, 70%, mas retorna <unknown> para o consumo de CPU atual. Este erro costuma acontecer quando o metrics server não esta em execução, possui erros de configuração ou quando o template do Pod não define seus requisitos para recursos de CPU e memória(Exploring ResourceQuota Enforcement ).

$ kubectl get hpa my-hpa     
	NAME     REFERENCE              TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
	my-hpa   Deployment/my-deploy   <unknown>/70%   2         8         5          11m

Verifique os eventos do HPA utilizando comando kubectl describe hpa my-deploy.

$ kubectl describe hpa my-hpa             
	Name:                                                  my-hpa
	Namespace:                                             develop
	Reference:                                             Deployment/my-deploy
	Deployment pods:                                       5 current / 0 desired
	Conditions:
	  Type           Status  Reason                   Message
	  ----           ------  ------                   -------
	  AbleToScale    True    SucceededGetScale        the HPA controller was able to get the target's current scale
	  ScalingActive  False   FailedGetResourceMetric  the HPA was unable to compute the replica count: failed to get cpu utilization: missing request for cpu
	Events:
	  Type     Reason                        Age                  From                       Message
	  ----     ------                        ----                 ----                       -------
	  Warning  FailedComputeMetricsReplicas  17s (x12 over 3m3s)  horizontal-pod-autoscaler  invalid metrics (1 invalid out of 1), first error is: failed to get cpu utilization: missing request for cpu
	  Warning  FailedGetResourceMetric       2s (x13 over 3m3s)   horizontal-pod-autoscaler  failed to get cpu utilization: missing request for cpu

O erro acima já vem ocorrendo desde a sessão 03 Configuration quando tentei definir as Resource Quotas. Não importa como a Resource Quota seja configurada ou como os Deployments são configurados, os containers nunca são iniciados, sempre ficam no status ContainerCreating com a seguinte mensagem de erro:

Warning FailedCreatePodSandBox  1s  kubelet 
Failed to create pod sandbox: rpc error:
code = Unknown desc = failed to create containerd task:
failed to create shim: OCI runtime create failed: container_linux.go:380:
starting container process caused: process_linux.go:385:
applying cgroup configuration for process caused:
mkdir /sys/fs/cgroup/kubelet/kubepods/burstable/podb(...):
cannot allocate memory: unknown

A especificação da API autoscaling/v1 suporta scaling baseado apenas na utilização da CPU. A nova especificação autoscaling/v2beta2 fornece uma abordagem mais genérica na definição de thresholds. Por exemplo, você pode especificar um scaling threshold para consumo de memória.

# Versão disponivel no meu cluster - autoscaling/v1
$ kubectl api-resources | grep horizontal 
	NAME                     SHORTNAMES  APIVERSION      NAMESPACED   KIND                             VERBS
	horizontalpodautoscalers hpa         autoscaling/v1  true         HorizontalPodAutoscaler

# Tentando criar HPA com versão autoscaling/v2
#
# apiVersion: autoscaling/v2
# kind: HorizontalPodAutoscaler
#
$ kubectl apply -f autoscale.yaml           
error: unable to recognize "autoscale.yaml":
		no matches for kind "HorizontalPodAutoscaler" in version "autoscaling/v2"

Exemplo Utilizando Metrics HPA v2

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
  - type: Pods
    pods:
      metric:
        name: packets-per-second
      target:
        type: AverageValue
        averageValue: 1k
  - type: Object
    object:
      metric:
        name: requests-per-second
      describedObject:
        apiVersion: networking.k8s.io/v1
        kind: Ingress
        name: main-route
      target:
        type: Value
        value: 10k

Documentação Kubernetes