Para cada recurso do Kubernetes, é possível configurar dois tipos de requisitos — Requests e Limits. O primeiro descreve os requisitos mínimos para a disponibilidade de recursos do nó, necessários para iniciar um contêiner ou pod; o segundo limita rigidamente os recursos disponíveis para o contêiner.
Quando o Kubernetes agenda um pod, é muito importante que os contêineres tenham recursos suficientes para funcionar corretamente. Se você planeja implantar um grande aplicativo em um nó com recursos limitados, é bem provável que ele não funcione devido à falta de memória ou capacidade do processador. Neste artigo, discutiremos como resolver problemas de escassez de recursos computacionais por meio de solicitações de recursos e limites.
Requests e Limits são mecanismos que o Kubernetes usa para gerenciar recursos como CPU e memória. Requests garantem que o contêiner receba o recurso solicitado. Se um contêiner solicitar um recurso, o Kubernetes o agendará apenas em um nó que pode fornecê-lo. Os limites Limits controlam que os recursos solicitados pelo contêiner nunca excedam um determinado valor.

Um contêiner pode aumentar a capacidade computacional apenas até um certo limite, após o qual será restrito. Vamos ver como isso funciona. Existem dois tipos de recursos — CPU e memória. O agendador do Kubernetes usa dados sobre esses recursos para determinar onde executar seus pods. Uma especificação típica de recursos para um pod se parece assim.

Cada contêiner em um pod pode definir suas próprias solicitações e limites de recursos, sendo tudo isso aditivo. Os recursos de CPU são definidos em milicore. Se seu contêiner precisa de dois núcleos completos para funcionar, você define o valor como 2000m. Se o contêiner precisa apenas de 1/4 de núcleo, o valor será 250m. Tenha em mente que, se você alocar um valor de recursos de CPU maior do que a quantidade de núcleos do maior nó, o agendamento do seu pod não será realizado. Uma situação semelhante ocorrerá se você tiver um pod que precisa de quatro núcleos, enquanto o cluster Kubernetes consiste em apenas duas máquinas virtuais principais.
A menos que seu aplicativo tenha sido projetado especificamente para tirar proveito de múltiplos núcleos (como ocorre com programas de cálculos científicos complexos e operações com bancos de dados), a melhor prática é definir as Solicitações de CPU para 1 ou menos, com o subsequente aumento do número de réplicas para escalabilidade. Essa abordagem proporcionará maior flexibilidade e confiabilidade ao sistema.
Quando se trata de limites de CPU, fica mais interessante, pois esse recurso é considerado comprimível. Se seu aplicativo começar a se aproximar do limite de capacidade de processamento, o Kubernetes começará a desacelerar seu contêiner, usando o CPU Throttling — a redução da frequência do processador. Isso significa que a CPU será artificialmente limitada, proporcionando potencialmente um desempenho inferior ao aplicativo, no entanto, o processo não será interrompido nem finalizado.
Os recursos de memória são definidos em bytes. Normalmente, o valor nas configurações é medido em mebibytes (Mib), mas você pode definir qualquer valor, desde bytes até petabytes. Aqui, a mesma situação ocorre com a CPU — se você solicitar uma quantidade de memória que exceda a memória disponível em seus nós, a execução desse pod não será agendada. Mas, ao contrário dos recursos de CPU, a memória não é comprimível, pois não existe uma maneira de limitar seu uso. Portanto, a execução do contêiner será interrompida assim que ele ultrapassar os limites de memória alocados.

É importante lembrar que você não pode configurar solicitações que excedam a capacidade dos recursos que seus nós podem fornecer. As características dos recursos compartilhados para máquinas virtuais GKE podem ser encontradas nos links colocados abaixo deste vídeo.
Em um mundo ideal, as configurações padrão do contêiner seriam mais do que suficientes para que os fluxos de trabalho fluíssem suavemente. Mas o mundo real não é assim, as pessoas facilmente podem esquecer de configurar o uso de recursos ou hackers podem definir solicitações e limites que superem as capacidades reais da infraestrutura. Para evitar o desenvolvimento de cenários semelhantes, é possível configurar as quotas de recursos ResourceQuota e os limites de range LimitRange.
Após a criação dos namespaces, eles podem ser bloqueados com quotas. Por exemplo, se você tem namespaces de produção e desenvolvimento, utiliza um padrão onde não há quotas para produção, enquanto as quotas para desenvolvimento são extremamente rigorosas. Isso permite que a produção, em caso de um aumento repentino de tráfego, possa usar todos os recursos disponíveis, bloqueando completamente o desenvolvimento.
Uma quota de recursos pode parecer assim. Neste exemplo, existem 4 seções – são as 4 linhas de código abaixo.

Vamos analisar cada uma delas. requests.cpu é a quantidade máxima combinada de solicitações de capacidade de CPU que podem ser feitas por todos os contêineres no namespace. Neste exemplo, você pode ter 50 contêineres com solicitações de 10m, cinco contêineres com solicitações de 100m ou simplesmente um contêiner com uma solicitação de 500m. Enquanto o total de requests.cpu desse namespace for inferior a 500m, tudo estará bem.
A memória solicitada requests.memory é a quantidade máxima combinada de solicitações de memória que todos os contêineres podem ter no namespace. Assim como no caso anterior, você pode ter 50 contêineres com 2 MiB, cinco contêineres com 20 MiB ou um único contêiner com 100 MiB, contanto que o total de memória solicitada no namespace seja inferior a 100 mebibytes.
Limits.cpu é o valor máximo combinado de capacidade de CPU que todos os contêineres podem usar no namespace. Pode-se considerar que este é o limite das solicitações de capacidade de CPU.
Finalmente, limits.memory – o volume máximo de memória total que todos os contêineres em um espaço de nome podem usar. Esta é uma limitação de solicitações de memória somadas.
Assim, por padrão, os contêineres em um cluster Kubernetes operam com recursos computacionais ilimitados. Com as quotas de recursos, os administradores do cluster podem limitar o consumo de recursos e sua criação com base no espaço de nome. Dentro do espaço de nome, um módulo pod ou contêiner pode consumir tanta CPU e memória quanto definido pela quota de recursos do espaço de nome. No entanto, há preocupação de que um pod ou contêiner possa monopolizar todos os recursos disponíveis. Para evitar essa situação, utiliza-se o limite de faixa limit Range – uma política de limitação da distribuição de recursos (para pods ou contêineres) dentro do espaço de nome.
O limite de faixa fornece limitações que podem:
- garantir o uso mínimo e máximo de recursos computacionais para cada módulo ou contêiner no espaço de nome;
- forçar a aplicação de solicitações mínimas e máximas de armazenamento Storage Request para cada PersistentVolumeClaim no espaço de nome;
- forçar a definição de uma proporção entre a solicitação Request e o limite Limit para o recurso no espaço de nome;
- definir Requests/Limits padrão para recursos computacionais no espaço de nome e automaticamente aplicá-los aos contêineres durante a execução.
Dessa forma, você pode criar um limite de faixa no seu espaço de nome. Diferente da quota, que se aplica a todo o espaço de nome, o Limit Range é usado para contêineres individuais. Isso pode prevenir a criação de contêineres muito pequenos ou, ao contrário, gigantescos dentro do espaço de nome. O limite de faixa Limit Range poderia ser configurado desta forma.

Assim como no caso anterior, aqui podemos destacar 4 seções. Vamos analisar cada uma delas.
Na seção default, são definidas as limitações padrão para o contêiner no pod. Se você definir esses valores na faixa de limite, então quaisquer contêineres para os quais esses valores não foram explicitamente definidos obedecerão aos valores padrão.
Na seção de solicitações padrão defaultRequest, são configuradas as solicitações padrão para o contêiner no pod. Novamente, se você definir esses valores no intervalo máximo, qualquer contêiner para o qual esses parâmetros não estejam explicitamente definidos usará esses valores como padrão.
Na seção max, estão especificados os limites máximos que podem ser estabelecidos para o contêiner no pod. Os valores na seção default e os limites para o contêiner não podem ser definidos acima desse limite. É importante notar que, se um valor max estiver definido e a seção default estiver ausente, o valor máximo se tornará o valor padrão.
Na seção min, estão especificadas as solicitações mínimas que podem ser estabelecidas para o contêiner no pod. Os valores na seção default e as solicitações para o contêiner não podem ser definidos abaixo desse limite.
Novamente, é importante notar que, se esse valor for definido e o valor default não estiver, o valor mínimo se tornará a solicitação padrão.
No final, essas solicitações de recursos são usadas pelo agendador do Kubernetes para executar suas cargas de trabalho. Para que você possa configurar corretamente seus contêineres, é muito importante entender como isso funciona. Suponha que você queira executar vários módulos em seu cluster. Supondo que as especificações do pod sejam válidas, será utilizada a balanceamento cíclico no agendamento do Kubernetes para selecionar um nó para executar a carga de trabalho.

O Kubernetes verificará se há recursos suficientes no nó Node 1 para atender às solicitações dos contêineres do pod, e se não houver, ele passará para o próximo nó. Se nenhum dos nós do sistema for capaz de atender às solicitações, os pods passarão para o estado de espera Pending state. Com funcionalidades como o escalonamento automático de nós do Google Kubernetes Engine, o GKE pode automaticamente detectar o estado de espera e criar mais nós adicionais.
Se, posteriormente, houver capacidade excessiva nos nós, a função de escalonamento automático reduzirá seu número para economizar dinheiro. É por isso que o Kubernetes agenda os pods com base nas solicitações. No entanto, o limite pode ser superior às solicitações, e em alguns casos, um nó pode realmente esgotar os recursos. Chamamos esse estado de overcommitment state.

Como eu já disse, quando se trata do processador, o Kubernetes começará a limitar os pods. Cada pod receberá o que pediu, mas se não atingir o limite, a limitação começará a ser aplicada.
No que diz respeito aos recursos de memória, o Kubernetes é forçado a tomar decisões sobre quais pods remover e quais manter, até que você libere recursos do sistema, caso contrário, todo o sistema falhará.
Vamos imaginar um cenário em que você tem uma máquina que esgotou o limite de memória - como o Kubernetes reagirá a isso?
O Kubernetes procurará pods que estão utilizando mais recursos do que pediram. Assim, se seus contêineres não tiverem pedidos de Requests, isso significa que, por padrão, estão utilizando mais do que pediram, simplesmente porque não solicitaram nada! Esses contêineres se tornam os principais candidatos para desligamento. Os próximos candidatos são os contêineres que atenderam a todos os seus pedidos, mas ainda estão abaixo do limite máximo.
Assim, se o Kubernetes encontrar vários pods que excederam os parâmetros de seus pedidos, ele os ordenará por prioridade e então removerá os módulos de menor prioridade. Se todos os módulos tiverem a mesma prioridade, o Kubernetes interromperá os pods que excederam seus pedidos mais do que os outros pods.
Em casos muito raros, o Kubernetes pode interromper pods que ainda estão dentro de seus pedidos. Isso pode ocorrer quando componentes críticos do sistema, como o agente Kubelet ou o Docker, começam a consumir mais recursos do que foi reservado para eles.
Portanto, nas fases iniciais das pequenas empresas, um cluster Kubernetes pode funcionar bem sem a configuração de pedidos de recursos e limites, mas à medida que suas equipes e projetos começam a crescer, você pode enfrentar problemas nessa área. Adicionar pedidos e limites nos seus módulos e namespaces requer um esforço adicional muito pequeno e pode evitar muitas dores de cabeça.

Um pouco de publicidade 🙂
Obrigado por permanecer conosco. Você gosta dos nossos artigos? Quer ver mais materiais interessantes? Apoie-nos fazendo um pedido ou recomendando para conhecidos. , uma alternativa única aos servidores entry-level, que criamos para você: (disponíveis opções com RAID1 e RAID10, até 24 núcleos e até 40GB DDR4).
Dell R730xd por 2 vezes mais barato no datacenter Equinix Tier IV em Amsterdã? Somente conosco na Holanda! Dell R420 — 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — a partir de $99! Leia sobre
Fonte: habr.com
