Como acessar os recursos do Kubernetes Pod

Como acessar os recursos do Kubernetes PodA Recompensa de Tohad

No início do trabalho com Kubernetes, geralmente se esquece de configurar os recursos dos contêineres. Nessa etapa, é suficiente garantir que a imagem Docker funcione e possa ser implantada no cluster Kubernetes.

Mas mais tarde, é necessário implantar o aplicativo em um cluster de produção junto com outros aplicativos. Para isso, é preciso alocar recursos para o contêiner e garantir que haja o suficiente para iniciar e operar o aplicativo, sem causar problemas em outros aplicativos em execução.

Time Kubernetes aaS da Mail.ru traduziu um artigo sobre recursos de contêineres (CPU & MEM), solicitações e limites de recursos. Você descobrirá quais são as vantagens dessas configurações e o que acontecerá se não forem definidas.

Recursos Computacionais

Temos dois tipos de recursos com as seguintes unidades:

  • Processador Central (CPU) — núcleos;
  • Memória (MEM) — bytes.

Os recursos são especificados para cada contêiner. No seguinte arquivo YAML do Pod, você verá a seção de recursos que contém os recursos solicitados e limites:

  • Recursos solicitados do Pod = soma dos recursos solicitados de todos os contêineres;
  • Limites de recursos do Pod = soma dos limites de recursos de todos os contêineres.

apiVersion: v1
kind: Pod
metadata:
  name: backend-pod-name
  labels:
    application: backend
spec:
  containers:
    - name: main-container
      image: my-backend
      tag: v1
      ports:
      - containerPort: 8080
      resources:
        requests:
          cpu: 0.2 # CPU SOLICITADA: 200m núcleos
          memory: "1Gi" # MEM SOLICITADA: 1Gi
        limits:
          cpu: 1 # USO MÁXIMO DE CPU: 1 núcleo
          memory: "1Gi" # USO MÁXIMO DE MEM:  1Gi
    - name: other-container
      image: other-app
      tag: v1
      ports:
      - containerPort: 8000
      resources:
        requests:
          cpu: "200m" # CPU SOLICITADA: 200m núcleos
          memory: "0.5Gi" # MEM SOLICITADA: 0.5Gi
        limits:
          cpu: 1 # USO MÁXIMO DE CPU: 1 núcleo
          memory: "1Gi" # USO MÁXIMO DE MEM:  1Gi

Exemplo de recursos solicitados e limites

Campo resources.requested da especificação do Pod — um dos elementos utilizados para encontrar o nó adequado. Já é possível agendar a implantação do Pod nele. Como se busca um nó apropriado?

Kubernetes é composto por vários componentes, incluindo um nó principal ou nó mestre (Kubernetes Control Plane). No nó mestre, há vários processos: kube-apiserver, kube-controller-manager e kube-scheduler.

O processo kube-scheduler é responsável por visualizar os módulos recém-criados e procurar nós de trabalho possíveis que atendam a todas as solicitações dos módulos, incluindo a quantidade de recursos solicitados. A lista de nós encontrada pelo kube-scheduler é classificada. O Pod é agendado no nó com as melhores pontuações.

Como acessar os recursos do Kubernetes PodOnde será colocado o Pod roxo?

Na imagem, podemos ver que o kube-scheduler deve agendar um novo Pod roxo. O cluster Kubernetes contém dois nós: A e B. Como se pode notar, o kube-scheduler não consegue agendar o Pod no nó A — os recursos disponíveis (não solicitados) não atendem às solicitações do Pod roxo. Assim, a memória solicitada pelo Pod roxo de 1 GB não cabe no nó A, uma vez que a quantidade de memória disponível é de 0,5 GB. Mas o nó B tem recursos suficientes. No final, o kube-scheduler decide que o destino do Pod roxo é o nó B.

Agora sabemos como os recursos solicitados afetam a escolha do nó para executar um Pod. Mas como os recursos limites influenciam?

Os recursos limites são a fronteira que o CPU/MEM não pode ultrapassar. No entanto, o recurso CPU é flexível, portanto, contêineres que atingem os limites de CPU não farão com que o Pod seja encerrado. Em vez disso, ocorrerá throttling de CPU. Se o limite de uso de MEM for atingido, o contêiner será interrompido devido ao OOM-Killer e reiniciado, se permitido pela configuração RestartPolicy.

Recursos solicitados e limites em detalhes

Como acessar os recursos do Kubernetes PodRelação entre recursos do Docker e Kubernetes

A melhor maneira de explicar como funcionam os recursos solicitados e limites é apresentar a relação entre Kubernetes e Docker. Na figura acima, você pode ver como os campos do Kubernetes e as flags de inicialização do Docker estão relacionados.

Memória: solicitação e limite

containers:
...
 resources:
   requests:
     memory: "0.5Gi"
   limits:
     memory: "1Gi"

Como mencionado acima, a memória é medida em bytes. Com base em documentação do Kubernetes, podemos especificar a memória como um número. Geralmente, é um número inteiro, por exemplo, 2678 — ou seja, 2678 bytes. Também é possível usar sufixos G e Gi, o importante é lembrar que eles não são equivalentes. O primeiro é decimal, enquanto o segundo é binário. Como exemplo, mencionado na documentação do k8s: 128974848, 129e6, 129M, 123Mi — eles são praticamente equivalentes.

O parâmetro Kubernetes limits.memory corresponde à flag --memory do Docker. No caso de request.memory a seta para o Docker está ausente, pois o Docker não usa esse campo. Você pode perguntar se isso é realmente necessário? Sim, é. Como já mencionei, o campo é significativo para o Kubernetes. Com base nas informações desse campo, o kube-scheduler decide em qual nó agendar o Pod.

O que acontece se a solicitação de memória for insuficiente?

Se o contêiner atingir os limites de memória solicitada, o Pod será colocado em um grupo de Pods que são interrompidos quando há falta de memória no nó.

O que acontece se você definir um limite de memória muito baixo?

Se o contêiner exceder o limite de memória, ele será finalizado devido ao OOM-Killed. E será reiniciado, se possível, com base no RestartPolicy, onde o valor padrão é Sempre.

O que acontece se não especificar a memória solicitada?

O Kubernetes pegará o limite e o definirá como valor padrão.

O que pode acontecer se não especificar a memória máxima?

O contêiner não tem restrições, podendo usar quanto quiser de memória. Se começar a usar toda a memória disponível no nó, será terminado pelo OOM. Em seguida, o contêiner será reiniciado, se possível, com base no RestartPolicy.

O que acontece se não definir limites de memória?

Esse é o pior cenário: o agendador não sabe quantos recursos o contêiner precisa, o que pode causar sérios problemas no nó. Nesse caso, é bom ter limites padrão no namespace (definidos pelo LimitRange). Sem limites padrão, o Pod não tem restrições, podendo usar quanto quiser de memória.

Se a memória solicitada for maior do que o nó pode oferecer, o Pod não será agendado. É importante lembrar que Requests.memory não é um valor mínimo. É uma descrição da quantidade de memória suficiente para o funcionamento contínuo do contêiner.

Normalmente, recomenda-se definir o mesmo valor para request.memory e limit.memory. Com isso, o Kubernetes não agendará o Pod em um nó que tenha memória suficiente para iniciar o Pod, mas não o suficiente para operá-lo. Lembre-se: ao agendar o Pod, o Kubernetes considera apenas requests.memory, e limits.memory e não considera.

CPU: solicitação e limite

containers:
...
 resources:
   requests:
     cpu: 1
   limits:
     cpu: "1200m"

Para a CPU, é um pouco mais complicado. Voltando à imagem da relação entre Kubernetes e Docker, pode-se notar que request.cpu -nó, e o outro — --cpu-shares, enquanto limit.cpu corresponde à flag cpus no Docker.

A CPU solicitada pelo Kubernetes é multiplicada por 1024 — a proporção de ciclos de CPU. Se você quiser solicitar 1 núcleo completo, deve adicionar cpu: 1, conforme mostrado acima.

Solicitar um núcleo completo (proporção = 1024) não significa que seu contêiner o receberá. Se seu host tiver apenas um núcleo e você usar mais de um contêiner, todos os contêineres devem compartilhar a CPU disponível entre si. Como isso acontece? Vamos dar uma olhada na imagem.

Como acessar os recursos do Kubernetes Pod
Requisição de CPU — sistema com um núcleo

Vamos imaginar que você tem um sistema de hospedagem com um único núcleo, onde estão rodando contêineres. A mãe (Kubernetes) assou uma torta (CPU) e quer dividi-la entre os filhos (contêineres). Três filhos querem uma torta inteira (proporção = 1024), e outro filho quer metade da torta (512). A mãe quer ser justa e faz um cálculo simples.

# Сколько пирогов хотят дети?
# 3 ребенка хотят по целому пирогу и еще один хочет половину пирога
cakesNumberKidsWant = (3 * 1) + (1 * 0.5) = 3.5
# Выражение получается так:
3 (ребенка/контейнера) * 1 (целый пирог/полное ядро) + 1 (ребенок/контейнер) * 0.5 (половина пирога/половина ядра)
# Сколько пирогов испечено?
availableCakesNumber = 1
# Сколько пирога (максимально) дети реально могут получить?
newMaxRequest = 1 / 3.5 =~ 28%

De acordo com o cálculo, três filhos receberão 28% de um núcleo, e não um núcleo inteiro. O quarto filho receberá 14% de um núcleo completo, e não metade. Mas tudo será diferente se você tiver um sistema com múltiplos núcleos.

Como acessar os recursos do Kubernetes Pod
Requisição de CPU — sistema multicore (4)

Na imagem acima, é visível que três filhos querem uma torta inteira, e um quer metade. Como a mãe assou quatro tortas, cada um de seus filhos receberá exatamente o que deseja. Em um sistema multicore, os recursos do processador são distribuídos entre todos os núcleos de processador disponíveis. Se o contêiner é limitado a menos do que um núcleo completo de CPU, ele ainda pode utilizá-lo a 100%.

Os cálculos acima são simplificados para entender como a CPU é distribuída entre os contêineres. Claro, além dos próprios contêineres, há outros processos que também utilizam os recursos da CPU. Quando os processos em um contêiner estão inativos, outros podem usar seus recursos. CPU: "200m" -nó, e o outro — CPU: 0,2, o que significa aproximadamente 20% de um núcleo.

Agora vamos falar sobre limit.cpu. A CPU que o Kubernetes limita é multiplicada por 100. O resultado é a quantidade de tempo que o contêiner pode usar a cada 100 microssegundos (cpu-period).

limit.cpu corresponde à flag do Docker --cpus. Esta é uma nova combinação de antigas --cpu-period e --cpu-quota. Ao configurar isso, indicamos quanto dos recursos da CPU o contêiner pode usar no máximo até que ocorra a limitação:

  • cpus — combinação cpu-period e cpu-quota. cpus = 1.5 equivale a configurar cpu-period = 100000 e cpu-quota = 150000;
  • cpu-period — período do planejador de CPU CFS, por padrão 100 microssegundos;
  • cpu-quota — quantidade de microssegundos dentro cpu-period, onde o contêiner é limitado.

O que acontece se a quantidade de CPU requisitada for insuficiente?

Se o contêiner precisar de mais do que foi configurado, ele roubará CPU de outros processos.

O que ocorrerá se o limite de CPU for insuficiente?

Como o recurso de CPU é regulável, a limitação será ativada.

O que acontece se não for especificada uma requisição de CPU?

Assim como no caso da memória, o valor da solicitação é igual ao limite.

O que acontece se não for definido um limite de CPU?

O contêiner usará toda a CPU de que necessita. Se uma política de CPU padrão (LimitRange) estiver definida no namespace, esse limite será usado também para o contêiner.

O que acontecerá se não forem especificados nem a solicitação nem o limite de CPU?

Assim como no caso da memória, este é o pior cenário. O escalonador não sabe quantos recursos o seu contêiner precisa, e isso pode causar sérios problemas no nó. Para evitar isso, é necessário definir limites padrão para os namespaces (LimitRange).

Lembre-se: se você solicitar mais CPU do que os nós podem fornecer, o Pod não será agendado. Requests.cpu — não é o valor mínimo, mas o valor suficiente para iniciar o Pod e funcionar sem falhas. Se o aplicativo não realiza cálculos complexos, a melhor opção é definir request.cpu <= 1 e executar o número necessário de réplicas.

A quantidade ideal de recursos solicitados ou limite de recursos

Aprendemos sobre limites de recursos computacionais. Agora é hora de responder à pergunta: "Quais recursos meu Pod precisa para executar o aplicativo sem problemas? Qual é a quantidade ideal?".

Infelizmente, não há respostas claras para essas perguntas. Se você não sabe como seu aplicativo funciona, quanta CPU ou memória precisa, a melhor opção é fornecer ao aplicativo bastante memória e CPU e, em seguida, rodar testes de desempenho.

Além dos testes de desempenho, observe o comportamento do aplicativo durante uma semana através da monitoração. Se os gráficos indicarem que seu aplicativo consome menos recursos do que você solicitou, você pode reduzir a quantidade de CPU ou memória solicitada.

Como exemplo, veja este painel Grafana. Ele mostra a diferença entre os recursos solicitados ou o limite de recursos e o uso atual de recursos.

Conclusão

Solicitações e limites de recursos ajudam a manter a operação do cluster Kubernetes. Uma configuração correta dos limites minimiza custos e mantém os aplicativos em funcionamento constante.

Em resumo, é importante lembrar de alguns pontos:

  1. Recursos solicitados são a configuração considerada durante a inicialização (quando o Kubernetes planeja a distribuição do aplicativo). Por outro lado, o limite de recursos é importante durante a execução — quando o aplicativo já está em execução em um nó.
  2. Comparado à memória, a CPU é um recurso regulável. Em caso de falta de CPU, seu Pod não será finalizado, mas sim ativará o mecanismo de estrangulamento.
  3. Recursos solicitados e limites de recursos não são valores mínimos e máximos! Ao definir os recursos solicitados, você garante que o aplicativo funcionará sem problemas.
  4. Uma boa prática é definir a solicitação de memória igual ao limite de memória.
  5. É bom definir a solicitação de CPU <=1, se o aplicativo não estiver realizando cálculos complexos.
  6. Se você solicitar mais recursos do que existem no nó, o Pod nunca será agendado nesse nó.
  7. Para determinar a quantidade correta de recursos solicitados/límite de recursos, use testes de carga e monitoramento.

Espero que este artigo ajude você a entender o conceito básico de limitação de recursos. E que você possa aplicar esse conhecimento em seu trabalho.

Sucesso!

O que mais ler:

  1. Observabilidade SRE: namespaces e estrutura de métricas.
  2. 90+ ferramentas úteis para Kubernetes: implantação, gerenciamento, monitoramento, segurança e muito mais.
  3. Nosso canal Ao Redor do Kubernetes no Telegram.

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster