Aqui na Lambda3, é muito comum publicarmos aplicações em clusters de kubernetes compartilhados entre uma organização inteira. Por isso temos que lidar diretamente com o gerenciamento de consumo de recursos dessas aplicações.

Recentemente atuei em um time que estava utilizando um namespace no cluster de k8s para realizar processamento massivo de dados,conforme o projeto foi crescendo, começamos a criar diversas apis + processos até que tínhamos por volta de uns 20 pods apenas para esse sistema e todos com seus requests e limits setados. Entretanto, como não éramos responsáveis pelo gerenciamento do cluster, não sabíamos o que isso poderia impactar em outras aplicações e vimos a necessidade de estimar um limite inicial para o sistema/namespace para já deixar acordado com a área de infraestrutura e que caso o sistema precisasse de mais recursos, marcaríamos uma conversa com a equipe para apresentar os possíveis cenários de custos e etc.

A preocupação veio devido ao cenário de nesse mesmo cluster o cliente ter outras aplicações que poderiam ter seus desempenhos degradados devido aos diversos processos que vários times estavam publicando nesse cluster e nesse post, vou mostrar uma forma de limitar o uso de recursos por namespace, permitindo que o planejamento de recursos do cluster seja antecipado aos problemas que podem acontecer.

Prática

Executei os comandos abaixo no kubernetes que vem junto com o docker desktop pra facilitar a reprodução.

A primeira coisa que precisamos criar é um objeto chamado Resource Quota em nosso cluster:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


kubectl create -n default -f- <<EOF
apiVersion: v1
kind: ResourceQuota
metadata:
name: limitacao-recursos
spec:
hard:
requests.cpu: "50m"
limits.cpu: "100m"
EOF

Depois disso, vamos criar um pod que pede mais recurso do que o resource quota permite no namespace “default”:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


kubectl create -n default -f- <<EOF
apiVersion: v1
kind: Pod
metadata:
name: teste-recursos
spec:
containers:
– name: teste-recursos
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Executando ; sleep 10000']
resources:
requests:
cpu: "100m"
limits:
cpu: "200m"
restartPolicy: Never
EOF
view raw

pod1.sh

hosted with ❤ by GitHub

Ao aplicar o pod, o kubernetes nos dá um erro dizendo que os recursos ultrapassam o valor permitido:

kubectl apply -f .\pod.yaml -n teste
Error from server (Forbidden): error when creating ".\\pod.yaml": pods "teste-recursos" is forbidden: exceeded quota: limitacao-recursos, requested: limits.cpu=200m,requests.cpu=100m, used: limits.cpu=0,requests.cpu=0, limited: limits.cpu=100m,requests.cpu=50m

Vamos alterar o valor dos recursos do pod para ficar menor/igual ao valor que definimos no resource quota:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


kubectl create -n default -f- <<EOF
apiVersion: v1
kind: Pod
metadata:
name: teste-recursos
spec:
containers:
– name: teste-recursos
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Executando ; sleep 10000']
resources:
requests:
cpu: "50m"
limits:
cpu: "100m"
restartPolicy: Never
EOF
view raw

pod2.sh

hosted with ❤ by GitHub

kubectl apply -f .\pod.yaml -n default
pod/teste-recursos created

Rodando um describe no resource quota, vemos a quantidade de recursos que estão sendo usados no namespace:

kubectl describe resourcequota limitacao-recursos -n default
Name: limitacao-recursos
Namespace: default
Resource Used Hard
-------- ---- ----
limits.cpu 100m 100m
requests.cpu 50m 50m

Com o retorno acima, vemos que estamos usando a capacidade máxima do que definimos para o namespace. “Used” é a coluna que representa o que todos os recursos do namespace estão utilizando e a coluna hard são os valores limite que definimos no resource quota.

Com esse recurso, podemos definir por exemplo que um determinado projeto pode consumir até 10gb de memória e quando chegar um número de pods que seus requisitos de memória excedam esses 10gb o kubernetes retornará erro como acima, dizendo que não é possível alocar o pod no cluster e é onde deverão acontecer conversas para entender o custo para adicionar mais nós ou aumentar os recursos do cluster.

Espero ter ajudado, até a próxima.