O autoescalonamento de clusters no Kubernetes permite gerenciar recursos de forma flexível, adicionando ou removendo nós e pods automaticamente conforme a carga de trabalho.
O número máximo de nós em um grupo não pode exceder o número máximo permitido de nós worker no cluster. Por exemplo, se o limite do cluster for 100 nós e um dos grupos já estiver usando 30 nós, o novo grupo poderá ter no máximo 70 nós.
Para ativar o autoescalonamento durante a criação do cluster, selecione a opção Autoescalonamento na seção Configuração dos nós worker. O número mínimo de nós na criação do cluster é 1.

Se o cluster já foi criado, você pode habilitar o autoescalonamento da seguinte forma:

Parâmetros usados para gerenciar a criação e remoção de nós:
--scale-down-unneeded-time 5m0s
--max-scale-down-parallelism 1
--provisioning-request-max-backoff-time 2m0s
--max-inactivity 3m0s
--scale-down-delay-after-add 2m0s
--max-node-provision-time 10m0s
--scan-interval 2m0s
--scale-up-from-zero=true
--scale-down-unready-enabled=true
--scale-down-unready-time=30m0s
|
Parâmetro |
Descrição |
|
|
Tempo que um nó deve permanecer ocioso antes de ser removido (ex.: 5 minutos). |
|
|
Número máximo de nós que podem ser removidos simultaneamente (ex.: 1). |
|
|
Tempo máximo de espera para criação de um nó (3 minutos). |
|
|
Tempo máximo de inatividade antes de iniciar a redução de nós (3 minutos). |
|
|
Tempo de atraso após adicionar um nó antes de iniciar a redução (3 minutos). |
|
|
Tempo máximo permitido para criar um novo nó (3 minutos). |
Esses parâmetros determinam a velocidade com que os nós são adicionados ou removidos conforme a carga atual. A remoção acontece gradualmente para evitar redução abrupta de recursos. Quando a carga aumenta, novos nós são adicionados com limite de 3 minutos para não causar atrasos.
O autoescalonamento mantém equilíbrio entre disponibilidade de recursos e eficiência de custos.
O autoescalonamento funciona apenas se requests e limits forem especificados no deployment. Exemplo de arquivo de deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-deployment
spec:
selector:
matchLabels:
app: example
template:
metadata:
labels:
app: example
spec:
containers:
- name: example-container
image: example-image
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "400m"
memory: "512Mi"
Se um manifesto de pod utiliza nodeSelector ou nodeAffinity, o Kubernetes agenda o pod apenas em nós que correspondem às condições especificadas. Isso também afeta o autoscaling: o autoscaler só pode criar um novo nó em um grupo onde o pod possa ser agendado.
Se não existir um grupo de nós adequado, o pod permanecerá no estado Pending, mesmo que o autoscaling esteja habilitado no cluster.
O nodeSelector é adequado para casos simples em que os pods devem ser executados apenas em nós com um rótulo específico. Por exemplo, se uma aplicação deve ser executada apenas em um determinado grupo de nós, você pode usar o seguinte manifesto:
apiVersion: apps/v1
kind: Deployment
metadata:
name: worker-deployment
spec:
replicas: 1
selector:
matchLabels:
app: worker
template:
metadata:
labels:
app: worker
spec:
nodeSelector:
workload-type: background
containers:
- name: worker
image: busybox
command: ["sh", "-c", "sleep infinity"]
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "200m"
memory: "256Mi"
Neste exemplo, o pod pode ser agendado apenas em nós com o rótulo workload-type=background. Se não houver nós adequados no cluster, o autoscaler poderá adicionar um novo nó apenas a um grupo que utilize esse rótulo.
O nodeAffinity é utilizado quando são necessárias regras de agendamento mais flexíveis. Diferentemente do nodeSelector, ele permite definir expressões com diferentes operadores e combinar múltiplas condições.
Abaixo está um exemplo equivalente ao nodeSelector anterior, mas implementado com nodeAffinity:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
spec:
replicas: 1
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: workload-type
operator: In
values:
- api
containers:
- name: api
image: nginx:latest
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "400m"
memory: "512Mi"
Neste caso, o pod será agendado apenas em nós com o rótulo workload-type=api. Este exemplo utiliza o operador In, que permite especificar um ou mais valores aceitáveis para um rótulo.
O nodeAffinity também oferece suporte a outros operadores, por exemplo:
In: o valor do rótulo deve estar na lista especificadaNotIn: o valor do rótulo não deve estar na lista especificadaExists: o rótulo deve estar presente no nóDoesNotExist: o rótulo não deve estar presenteGt: o valor do rótulo deve ser maior que o valor especificado (para valores numéricos)Lt: o valor do rótulo deve ser menor que o valor especificado (para valores numéricos)Esses operadores permitem definir regras de agendamento mais avançadas em comparação com o nodeSelector.
Use nodeSelector quando um mapeamento simples por um ou mais valores fixos for suficiente. Para requisitos de posicionamento mais complexos, utilize nodeAffinity.
O Horizontal Pod Autoscaler (HPA) ajusta dinamicamente o número de pods baseado no consumo de recursos, como CPU ou memória. Exemplo de manifest HPA:
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: example-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: example-deployment
minReplicas: 1
maxReplicas: 5
targetCPUUtilizationPercentage: 50
Parâmetros do HPA:
apiVersion: versão da API usada (ex.: autoscaling/v1).
kind: tipo do recurso, HorizontalPodAutoscaler.
metadata: metadados, incluindo nome do HPA (example-hpa).
scaleTargetRef: objeto a ser escalado:
apiVersion: versão da API do recurso.
kind: tipo do recurso, Deployment.
name: nome do recurso (example-deployment).
minReplicas: mínimo de réplicas de pods (ex.: 1).
maxReplicas: máximo de réplicas (ex.: 5).
targetCPUUtilizationPercentage: porcentagem de uso de CPU para ajustar réplicas (ex.: 50%).
Para configurar o autoescalonamento, criaremos um deployment Nginx com limites de recursos:
deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "500m"
memory: "1Gi"
Esse deployment cria um pod Nginx com limites de recursos, essenciais para o HPA.
Para demonstrar o autoescalonamento de pods, use o objeto HPA:
hpa.yaml:
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: nginx-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx-deployment
minReplicas: 1
maxReplicas: 4
targetCPUUtilizationPercentage: 20
Neste exemplo, o HPA ajusta o número de réplicas do nginx-deployment baseado na utilização de CPU, mantendo-a em 20%.
Para distribuir a carga entre os pods, use um Service do tipo LoadBalancer:
service.yaml:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
Este serviço fornece acesso aos pods com balanceamento entre múltiplas portas.
Para aplicar os arquivos YAML, use:
kubectl apply -f nginx-deployment.yaml
kubectl apply -f nginx-hpa.yaml
kubectl apply -f nginx-service.yaml
Esses comandos criam o deployment Nginx, HPA e load balancer, gerando todos os componentes para autoescalonamento.
Antes de gerar carga, certifique-se que todos os recursos estão em estado Running. Para observar o autoescalonamento, use a ferramenta hey para enviar requisições HTTP:
Gerar carga:
hey -z 10m -c 20 http://<load_balancer_ip>
Isso gera 10 minutos de carga com 20 conexões paralelas para o serviço Nginx, acionando o escalonamento de réplicas de pods e nós worker, se necessário.
Verificar escalonamento de nós:
kubectl get nodes
Verificar escalonamento de pods (até 4 réplicas conforme hpa.yaml):
kubectl get pods