Kubernetes: por que é tão importante configurar o gerenciamento de recursos do sistema?

Como regra, sempre há a necessidade de fornecer um conjunto dedicado de recursos a qualquer aplicativo para sua operação correta e estável. Mas e se vários aplicativos funcionarem com as mesmas capacidades ao mesmo tempo? Como fornecer os recursos mínimos necessários para cada um deles? Como posso limitar o consumo de recursos? Como distribuir corretamente a carga entre nós? Como garantir o mecanismo de escala horizontal em caso de aumento de carga na aplicação?



Você precisa começar com quais tipos básicos de recursos existem no sistema - é claro, tempo do processador e RAM. Nos manifestos do k8s, esses tipos de recursos são medidos nas seguintes unidades:


  • CPU - nos núcleos
  • RAM - em bytes

Além disso, para cada recurso, há uma oportunidade de definir dois tipos de requisitos - solicitações e limites . Solicitações - descreve os requisitos mínimos para os recursos livres do nó executarem o contêiner (e a lareira como um todo), enquanto os limites definem um limite estrito nos recursos disponíveis para o contêiner.


É importante entender que no manifesto não é necessário definir explicitamente os dois tipos, e o comportamento será o seguinte:


  • Se apenas os limites do recurso forem definidos explicitamente, as solicitações para esse recurso terão automaticamente um valor igual a limites (isso pode ser verificado chamando entidades de descrição). I.e. de fato, a operação do contêiner será limitada pela mesma quantidade de recursos necessária para executar.
  • Se apenas solicitações forem explicitamente definidas para um recurso, nenhuma restrição será definida sobre ele - ou seja, o contêiner é limitado apenas pelos recursos do próprio nó.

Também é possível configurar o gerenciamento de recursos não apenas no nível de um contêiner específico, mas também no nível do namespace, usando as seguintes entidades:


  • LimitRange - descreve a política de restrição no nível do contêiner / lareira em ns e é necessária para descrever as restrições padrão no contêiner / lareira, além de impedir a criação de contêineres / lareiras obviamente gordas (ou vice-versa), limitar seu número e determinar a possível diferença nos valores dentro dos limites e pedidos
  • ResourceQuotas - descreva a política de restrição em geral para todos os contêineres em ns e é usada, como regra, para diferenciar recursos entre ambientes (útil quando os ambientes não são rigidamente delimitados no nível dos nós)

A seguir, exemplos de manifestos em que os limites de recursos são definidos:


  • No nível do contêiner específico:


    containers: - name: app-nginx image: nginx resources: requests: memory: 1Gi limits: cpu: 200m 

    I.e. nesse caso, para iniciar um contêiner com nginx, você precisará pelo menos da presença de 1G OP e 0,2 CPU livre no nó, enquanto o contêiner máximo pode consumir 0,2 CPU e todo o OP disponível no nó.


  • No nível inteiro ns:


     apiVersion: v1 kind: ResourceQuota metadata: name: nxs-test spec: hard: requests.cpu: 300m requests.memory: 1Gi limits.cpu: 700m limits.memory: 2Gi 

    I.e. a soma de todos os contêineres de solicitação nos ns padrão não pode exceder 300m para a CPU e 1G para o OP e a soma de todo o limite é 700m para a CPU e 2G para o OP.


  • Restrições padrão para contêineres em ns:


     apiVersion: v1 kind: LimitRange metadata: name: nxs-limit-per-container spec: limits: - type: Container defaultRequest: cpu: 100m memory: 1Gi default: cpu: 1 memory: 2Gi min: cpu: 50m memory: 500Mi max: cpu: 2 memory: 4Gi 

    I.e. no espaço de nome padrão para todos os contêineres, por padrão, a solicitação será definida como 100m para a CPU e 1G para o OP, limite - 1 CPU e 2G. Ao mesmo tempo, também foi estabelecida uma restrição sobre os possíveis valores em solicitação / limite para a CPU (50m <x <2) e RAM (500M <x <4G).


  • Limitações no nível da lareira ns:


     apiVersion: v1 kind: LimitRange metadata: name: nxs-limit-pod spec: limits: - type: Pod max: cpu: 4 memory: 1Gi 

    I.e. para cada lareira nos ns padrão, será definido um limite de 4 vCPU e 1G.



Agora, gostaria de dizer quais vantagens a instalação dessas restrições pode nos dar.


O mecanismo de balanceamento de carga entre nós


Como você sabe, o componente k8s, como o agendador , que funciona de acordo com um determinado algoritmo, é responsável pela distribuição dos lares pelos nós. Esse algoritmo no processo de escolha do nó ideal para execução passa por dois estágios:


  1. Filtragem
  2. Ranking

I.e. de acordo com a política descrita, os nós são selecionados inicialmente no qual uma lareira pode ser iniciada com base em um conjunto de predicados (incluindo se o nó possui recursos suficientes para executar uma lareira - PodFitsResources) e, em seguida, são concedidos pontos para cada um desses nós, de acordo com as prioridades (incluindo, quanto mais recursos livres o nó tiver - mais pontos ele será atribuído - LeastResourceAllocation / LeastRequestedPriority / BalancedResourceAllocation) e será executado no nó com mais pontos (se vários nós atenderem a essa condição ao mesmo tempo, será selecionado um aleatório).


Ao mesmo tempo, você precisa entender que o planejador, ao avaliar os recursos disponíveis do nó, se concentra nos dados armazenados no etcd - ou seja, pela quantidade do recurso solicitado / limite de cada pod em execução neste nó, mas não pelo consumo real de recursos. Esta informação pode ser obtida na saída do comando kubectl describe node $NODE do kubectl describe node $NODE , por exemplo:


 # kubectl describe nodes nxs-k8s-s1 .. Non-terminated Pods: (9 in total) Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE --------- ---- ------------ ---------- --------------- ------------- --- ingress-nginx nginx-ingress-controller-754b85bf44-qkt2t 0 (0%) 0 (0%) 0 (0%) 0 (0%) 233d kube-system kube-flannel-26bl4 150m (0%) 300m (1%) 64M (0%) 500M (1%) 233d kube-system kube-proxy-exporter-cb629 0 (0%) 0 (0%) 0 (0%) 0 (0%) 233d kube-system kube-proxy-x9fsc 0 (0%) 0 (0%) 0 (0%) 0 (0%) 233d kube-system nginx-proxy-k8s-worker-s1 25m (0%) 300m (1%) 32M (0%) 512M (1%) 233d nxs-monitoring alertmanager-main-1 100m (0%) 100m (0%) 425Mi (1%) 25Mi (0%) 233d nxs-logging filebeat-lmsmp 100m (0%) 0 (0%) 100Mi (0%) 200Mi (0%) 233d nxs-monitoring node-exporter-v4gdq 112m (0%) 122m (0%) 200Mi (0%) 220Mi (0%) 233d Allocated resources: (Total limits may be over 100 percent, ie, overcommitted.) Resource Requests Limits -------- -------- ------ cpu 487m (3%) 822m (5%) memory 15856217600 (2%) 749976320 (3%) ephemeral-storage 0 (0%) 0 (0%) 

Aqui vemos todos os pods em execução em um nó específico, bem como os recursos solicitados por cada um dos pods. E aqui está a aparência dos logs do planejador ao iniciar o pod cronjob-cron-events-1573793820-xt6q9 (essas informações aparecem no log do planejador ao definir o 10º nível de log nos argumentos do comando start --v = 10):


gaivota larga
 I1115 07:57:21.637791 1 scheduling_queue.go:908] About to try and schedule pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 I1115 07:57:21.637804 1 scheduler.go:453] Attempting to schedule pod: nxs-stage/cronjob-cron-events-1573793820-xt6q9 I1115 07:57:21.638285 1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s5 is allowed, Node is running only 16 out of 110 Pods. I1115 07:57:21.638300 1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s6 is allowed, Node is running only 20 out of 110 Pods. I1115 07:57:21.638322 1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s3 is allowed, Node is running only 20 out of 110 Pods. I1115 07:57:21.638322 1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s4 is allowed, Node is running only 17 out of 110 Pods. I1115 07:57:21.638334 1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s10 is allowed, Node is running only 16 out of 110 Pods. I1115 07:57:21.638365 1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s12 is allowed, Node is running only 9 out of 110 Pods. I1115 07:57:21.638334 1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s11 is allowed, Node is running only 11 out of 110 Pods. I1115 07:57:21.638385 1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s1 is allowed, Node is running only 19 out of 110 Pods. I1115 07:57:21.638402 1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s2 is allowed, Node is running only 21 out of 110 Pods. I1115 07:57:21.638383 1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s9 is allowed, Node is running only 16 out of 110 Pods. I1115 07:57:21.638335 1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s8 is allowed, Node is running only 18 out of 110 Pods. I1115 07:57:21.638408 1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s13 is allowed, Node is running only 8 out of 110 Pods. I1115 07:57:21.638478 1 predicates.go:1369] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s10 is allowed, existing pods anti-affinity terms satisfied. I1115 07:57:21.638505 1 predicates.go:1369] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s8 is allowed, existing pods anti-affinity terms satisfied. I1115 07:57:21.638577 1 predicates.go:1369] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s9 is allowed, existing pods anti-affinity terms satisfied. I1115 07:57:21.638583 1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s7 is allowed, Node is running only 25 out of 110 Pods. I1115 07:57:21.638932 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: BalancedResourceAllocation, capacity 39900 millicores 66620178432 memory bytes, total request 2343 millicores 9640186880 memory bytes, score 9 I1115 07:57:21.638946 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: LeastResourceAllocation, capacity 39900 millicores 66620178432 memory bytes, total request 2343 millicores 9640186880 memory bytes, score 8 I1115 07:57:21.638961 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: BalancedResourceAllocation, capacity 39900 millicores 66620170240 memory bytes, total request 4107 millicores 11307422720 memory bytes, score 9 I1115 07:57:21.638971 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: BalancedResourceAllocation, capacity 39900 millicores 66620178432 memory bytes, total request 5847 millicores 24333637120 memory bytes, score 7 I1115 07:57:21.638975 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: LeastResourceAllocation, capacity 39900 millicores 66620170240 memory bytes, total request 4107 millicores 11307422720 memory bytes, score 8 I1115 07:57:21.638990 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: LeastResourceAllocation, capacity 39900 millicores 66620178432 memory bytes, total request 5847 millicores 24333637120 memory bytes, score 7 I1115 07:57:21.639022 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: TaintTolerationPriority, Score: (10) I1115 07:57:21.639030 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: TaintTolerationPriority, Score: (10) I1115 07:57:21.639034 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: TaintTolerationPriority, Score: (10) I1115 07:57:21.639041 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: NodeAffinityPriority, Score: (0) I1115 07:57:21.639053 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: NodeAffinityPriority, Score: (0) I1115 07:57:21.639059 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: NodeAffinityPriority, Score: (0) I1115 07:57:21.639061 1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: InterPodAffinityPriority, Score: (0) I1115 07:57:21.639063 1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: SelectorSpreadPriority, Score: (10) I1115 07:57:21.639073 1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: InterPodAffinityPriority, Score: (0) I1115 07:57:21.639077 1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: SelectorSpreadPriority, Score: (10) I1115 07:57:21.639085 1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: InterPodAffinityPriority, Score: (0) I1115 07:57:21.639088 1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: SelectorSpreadPriority, Score: (10) I1115 07:57:21.639103 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: SelectorSpreadPriority, Score: (10) I1115 07:57:21.639109 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: SelectorSpreadPriority, Score: (10) I1115 07:57:21.639114 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: SelectorSpreadPriority, Score: (10) I1115 07:57:21.639127 1 generic_scheduler.go:781] Host nxs-k8s-s10 => Score 100037 I1115 07:57:21.639150 1 generic_scheduler.go:781] Host nxs-k8s-s8 => Score 100034 I1115 07:57:21.639154 1 generic_scheduler.go:781] Host nxs-k8s-s9 => Score 100037 I1115 07:57:21.639267 1 scheduler_binder.go:269] AssumePodVolumes for pod "nxs-stage/cronjob-cron-events-1573793820-xt6q9", node "nxs-k8s-s10" I1115 07:57:21.639286 1 scheduler_binder.go:279] AssumePodVolumes for pod "nxs-stage/cronjob-cron-events-1573793820-xt6q9", node "nxs-k8s-s10": all PVCs bound and nothing to do I1115 07:57:21.639333 1 factory.go:733] Attempting to bind cronjob-cron-events-1573793820-xt6q9 to nxs-k8s-s10 

Aqui vemos que, inicialmente, o planejador realiza a filtragem e forma uma lista de 3 nós nos quais é possível executar (nxs-k8s-s8, nxs-k8s-s9, nxs-k8s-s10). Em seguida, calcula os pontos de acordo com vários parâmetros (incluindo BalancedResourceAllocation, LeastResourceAllocation) para cada um desses nós, a fim de determinar o nó mais adequado. No final, ele é planejado no nó com mais pontos (aqui, dois nós ao mesmo tempo têm o mesmo número de pontos 100037, portanto, um aleatório é selecionado - nxs-k8s-s10).


Conclusão : se os pods funcionam no nó para o qual não há restrições, então para os k8s (do ponto de vista do consumo de recursos) isso será equivalente a se esses pods estavam completamente ausentes nesse nó. Portanto, se você possui um pod condicionalmente com um processo voraz (por exemplo, wowza) e não há restrições para isso, uma situação pode surgir quando, de fato, o usuário consumiu todos os recursos do nó, mas para o k8s esse nó é considerado descarregado e ele receberá o mesmo número de pontos na classificação (ou seja, em pontos com uma avaliação dos recursos disponíveis), bem como um nó que não possui campos de trabalho, o que pode levar a uma distribuição desigual da carga entre os nós.


Despejo da lareira


Como você sabe, cada um dos pods recebe uma das três classes de QoS:


  1. garantido - é atribuído quando a solicitação e o limite são definidos para cada contêiner na lareira para memória e CPU, e esses valores devem corresponder
  2. estourável - pelo menos um contêiner na lareira tem solicitação e limite, enquanto solicitação <limite
  3. melhor esforço - quando nenhum recipiente na lareira é limitado em recursos

Ao mesmo tempo, quando há uma escassez de recursos (disco, memória) no nó, o kubelet começa a classificar e despejar os pods de acordo com um determinado algoritmo que leva em consideração a prioridade do pod e sua classe de QoS. Por exemplo, se estivermos falando sobre RAM, os pontos de classe de QoS serão atribuídos com base no seguinte princípio:


  • Garantido : -998
  • Melhor esforço : 1000
  • Burstable : min (max (2, 1000 - (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999)

I.e. com a mesma prioridade, o kubelet expelirá os pods com a melhor classe de esforço de QoS do nó.


Conclusão : se você deseja reduzir a probabilidade de remoção do pod necessário do nó em caso de recursos insuficientes, em seguida, juntamente com a prioridade, também deve definir a solicitação / limite para ele.


Mecanismo de auto-dimensionamento horizontal (HPA)


Quando a tarefa é aumentar e diminuir automaticamente o número de pod, dependendo do uso de recursos (sistema - CPU / RAM ou usuário - rps), uma entidade k8s como HPA (Horizontal Pod Autoscaler) pode ajudar em sua solução. O algoritmo é o seguinte:


  1. As leituras atuais do recurso observado (currentMetricValue) são determinadas
  2. Os valores desejados para o recurso (desejadoMétricoValorado) são determinados, que são configurados para recursos do sistema usando solicitação
  3. O número atual de réplicas é determinado (currentReplicas)
  4. A fórmula a seguir calcula o número de réplicas desejado (réplicas desejadas)
    allowedReplicas = [currentReplicas * (currentMetricValue / desejadoMetricValue)]

No entanto, a escala não ocorrerá quando o coeficiente (currentMetricValue / desejadoMetricValue) estiver próximo de 1 (podemos definir o erro permitido, por padrão, é 0,1).


Considere hpa usando o aplicativo de teste de aplicativo (descrito como Implantação), onde é necessário alterar o número de réplicas, dependendo do consumo da CPU:


  • Manifesto de aplicativo


     kind: Deployment apiVersion: apps/v1beta2 metadata: name: app-test spec: selector: matchLabels: app: app-test replicas: 2 template: metadata: labels: app: app-test spec: containers: - name: nginx image: registry.nixys.ru/generic-images/nginx imagePullPolicy: Always resources: requests: cpu: 60m ports: - name: http containerPort: 80 - name: nginx-exporter image: nginx/nginx-prometheus-exporter resources: requests: cpu: 30m ports: - name: nginx-exporter containerPort: 9113 args: - -nginx.scrape-uri - http://127.0.0.1:80/nginx-status 

    I.e. vemos que, com o aplicativo, ele é iniciado inicialmente em duas instâncias, cada uma contendo dois contêineres nginx e nginx-exportador, para cada um dos quais são solicitados pedidos de CPU.


  • Manifesto HPA


     apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: app-test-hpa spec: maxReplicas: 10 minReplicas: 2 scaleTargetRef: apiVersion: extensions/v1beta1 kind: Deployment name: app-test metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 30 

    I.e. criamos um hpa que monitora o aplicativo de teste de implantação e ajusta o número de lares com o aplicativo com base no indicador da CPU (esperamos que o lar consuma 30% por cento da CPU solicitada por ele), enquanto o número de réplicas está entre 2 e 10.


    Agora, consideraremos o mecanismo de operação hpa se aplicarmos uma carga a uma das lareiras:


      # kubectl top pod NAME CPU(cores) MEMORY(bytes) app-test-78559f8f44-pgs58 101m 243Mi app-test-78559f8f44-cj4jz 4m 240Mi 


Total, temos o seguinte:


  • Valor desejado (valorMétrico desejado) - de acordo com as configurações de hpa, temos 30%
  • Valor atual (currentMetricValue) - para cálculo, o controlador-gerente calcula o valor médio do consumo de recursos em%, ou seja, condicionalmente faz o seguinte:
    1. Obtém os valores absolutos das métricas do coração do servidor de métricas, ou seja, 101m e 4m
    2. Calcula o valor absoluto médio, ou seja, (101m + 4m) / 2 = 53m
    3. Obtém o valor absoluto para o consumo de recursos desejado (para isso, a solicitação de todos os contêineres é somada) 60m + 30m = 90m
    4. Calcula a porcentagem média de consumo de CPU em relação à lareira da solicitação, ou seja, 53m / 90m * 100% = 59%

Agora temos todo o necessário para determinar se é necessário alterar o número de réplicas, para isso calculamos o coeficiente:


ratio = 59% / 30% = 1.96


I.e. o número de réplicas deve ser aumentado ~ 2 vezes e compor [2 * 1,96] = 4.


Conclusão: Como você pode ver, para que esse mecanismo funcione, um pré-requisito é incluir a disponibilidade de solicitações para todos os contêineres na lareira observada.


O mecanismo de dimensionamento automático horizontal de nós (Cluster Autoscaler)


Para neutralizar o impacto negativo no sistema durante explosões de carga, a presença de um hpa ajustado não é suficiente. Por exemplo, de acordo com as configurações no gerenciador do controlador hpa, decide que o número de réplicas precisa ser aumentado em 2 vezes, no entanto, não há recursos livres nos nós para executar esse número de pods (ou seja, o nó não pode fornecer os recursos solicitados para as solicitações de pod) e esses pods insira o estado Pendente.


Nesse caso, se o provedor tiver IaaS / PaaS apropriado (por exemplo, GKE / GCE, AKS, EKS etc.), uma ferramenta como o Node Autoscaler pode nos ajudar. Permite definir o número máximo e mínimo de nós no cluster e ajustar automaticamente o número atual de nós (acessando a API do provedor de nuvem para solicitar / excluir nós) quando houver falta de recursos no cluster e os pods não puderem ser agendados (eles estão no estado Pendente).


Conclusão: para poder dimensionar automaticamente os nós, é necessário especificar solicitações nos contêineres da lareira, para que os k8s possam avaliar corretamente a carga dos nós e, consequentemente, informar que não há recursos no cluster para iniciar a próxima lareira.




Conclusão


Deve-se observar que definir limites de recursos para o contêiner não é um pré-requisito para o lançamento bem-sucedido do aplicativo, mas ainda é melhor fazer isso pelos seguintes motivos:


  1. Para uma operação mais precisa do planejador em termos de balanceamento de carga entre os nós k8s
  2. Para reduzir a probabilidade de um evento de despejo da lareira
  3. Para fornos de aplicativos de dimensionamento automático horizontal (HPA)
  4. Para dimensionamento automático horizontal de nós (escalonamento automático de cluster) para provedores de nuvem

Leia também outros artigos em nosso blog:


Source: https://habr.com/ru/post/pt480072/


All Articles