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
<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