Kubernetes: Warum ist es so wichtig, ein Systemressourcenmanagement einzurichten?

In der Regel muss jeder Anwendung immer ein dedizierter Ressourcenpool zur Verfügung gestellt werden, damit sie ordnungsgemäß und stabil funktioniert. Was aber, wenn mehrere Anwendungen gleichzeitig mit derselben Kapazität arbeiten? Wie kann man die minimal notwendigen Ressourcen für jeden von ihnen bereitstellen? Wie kann ich den Ressourcenverbrauch begrenzen? Wie verteile ich die Last richtig auf die Knoten? Wie kann der Mechanismus der horizontalen Skalierung bei erhöhter Belastung der Anwendung sichergestellt werden?



Sie müssen damit beginnen, welche grundlegenden Arten von Ressourcen im System vorhanden sind - natürlich Prozessorzeit und RAM. In k8s-Manifesten werden diese Ressourcentypen in den folgenden Einheiten gemessen:


  • CPU - in den Kernen
  • RAM - in Bytes

Darüber hinaus gibt es für jede Ressource die Möglichkeit, zwei Arten von Anforderungen festzulegen - Anforderungen und Grenzwerte . Anforderungen - beschreibt die Mindestanforderungen an die freien Ressourcen des Knotens zum Ausführen des Containers (und des Herds im Allgemeinen), während Grenzwerte eine strikte Begrenzung der für den Container verfügbaren Ressourcen festlegen.


Es ist wichtig zu verstehen, dass es im Manifest nicht erforderlich ist, beide Typen explizit zu definieren. Das Verhalten ist wie folgt:


  • Wenn nur die Grenzwerte der Ressource explizit festgelegt werden, erhalten Anforderungen für diese Ressource automatisch einen Wert, der den Grenzwerten entspricht (dies kann durch Aufrufen von describe entitys überprüft werden). Das heißt Tatsächlich wird der Betrieb des Containers durch dieselbe Menge an Ressourcen begrenzt, die für die Ausführung erforderlich sind.
  • Wenn nur Anforderungen explizit für eine Ressource festgelegt werden, werden keine Einschränkungen für diese Ressource festgelegt - d. H. Der Container ist nur durch die Ressourcen des Knotens selbst begrenzt.

Es ist auch möglich, die Ressourcenverwaltung nicht nur auf der Ebene eines bestimmten Containers, sondern auch auf der Namespace-Ebene mithilfe der folgenden Entitäten zu konfigurieren:


  • LimitRange - beschreibt die Einschränkungsrichtlinie auf Container- / Herdebene in ns und wird benötigt, um die Standardeinschränkungen für den Container / Herd zu beschreiben sowie die Erzeugung offensichtlich fetter Container / Herde (oder umgekehrt) zu verhindern, deren Anzahl zu begrenzen und mögliche Wertunterschiede innerhalb von Grenzen zu ermitteln und Anfragen
  • ResourceQuotas - Beschreibt die Einschränkungsrichtlinie im Allgemeinen für alle Container in ns und wird in der Regel zum Abgrenzen von Ressourcen zwischen Umgebungen verwendet (nützlich, wenn Umgebungen auf Knotenebene nicht starr abgegrenzt sind).

Im Folgenden finden Sie Beispiele für Manifeste, für die Ressourcenlimits festgelegt sind:


  • Auf der spezifischen Containerebene:


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

    Das heißt In diesem Fall benötigen Sie zum Starten eines Containers mit nginx mindestens das Vorhandensein von freiem 1G-OP und 0,2 CPU auf dem Knoten, während der maximale Container 0,2 CPU und alle verfügbaren OP auf dem Knoten aufnehmen kann.


  • Auf ganzzahliger Ebene ns:


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

    Das heißt Die Summe aller Anforderungscontainer in der Standardeinstellung ns darf 300 m für die CPU und 1 G für das OP nicht überschreiten, und die Summe aller Grenzwerte beträgt 700 m für die CPU und 2 G für das OP.


  • Standardeinschränkungen für Container in 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 

    Das heißt Im Standard-Namespace für alle Container wird die Anforderung standardmäßig auf 100 m für die CPU und auf 1 G für das OP festgelegt, das Limit auf 1 CPU und 2 G. Gleichzeitig wurde eine Einschränkung der möglichen Werte in Request / Limit für die CPU (50m <x <2) und RAM (500M <x <4G) festgelegt.


  • Einschränkungen auf der ns Herdebene:


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

    Das heißt Für jeden Herd in der Standardeinstellung ns wird ein Limit von 4 vCPU und 1G festgelegt.



Nun möchte ich Ihnen mitteilen, welche Vorteile die Installation dieser Einschränkungen für uns hat.


Der Mechanismus des Lastenausgleichs zwischen Knoten


Wie Sie wissen, ist die k8s-Komponente wie Scheduler , die nach einem bestimmten Algorithmus arbeitet, für die Verteilung der Herde nach Knoten verantwortlich. Dieser Algorithmus bei der Auswahl des optimalen auszuführenden Knotens durchläuft zwei Stufen:


  1. Filtern
  2. Ranking

Das heißt Gemäß der beschriebenen Richtlinie werden zunächst Knoten ausgewählt, auf deren Grundlage ein Herd basierend auf einer Reihe von Prädikaten gestartet werden kann (einschließlich der Frage, ob der Knoten über genügend Ressourcen verfügt, um einen Herd auszuführen - PodFitsResources), und anschließend werden für jeden dieser Knoten Punkte entsprechend den Prioritäten vergeben (einschließlich Je mehr freie Ressourcen ein Knoten hat - desto mehr Punkte werden ihm zugewiesen - LeastResourceAllocation / LeastRequestedPriority / BalancedResourceAllocation) und werden auf dem Knoten mit den meisten Punkten ausgeführt (wenn mehrere Knoten diese Bedingung gleichzeitig erfüllen, wird ein zufälliger Knoten ausgewählt).


Gleichzeitig müssen Sie verstehen, dass sich der Scheduler bei der Bewertung der verfügbaren Ressourcen des Knotens auf die in etcd gespeicherten Daten konzentriert - d. H. nach der Menge der angeforderten / begrenzten Ressource jedes Pods, der auf diesem Knoten ausgeführt wird, aber nicht nach dem tatsächlichen Ressourcenverbrauch. Diese Informationen können in der Ausgabe des kubectl describe node $NODE abgerufen werden. Beispiel:


 # 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%) 

Hier sehen wir alle Pods, die auf einem bestimmten Knoten ausgeführt werden, sowie die Ressourcen, die jeder der Pods anfordert. Und so sehen die Scheduler-Protokolle beim Starten des Pods cronjob-cron-events-1573793820-xt6q9 aus (diese Informationen werden im Scheduler-Protokoll angezeigt, wenn die 10. Protokollebene in den Argumenten des Startbefehls --v = 10 festgelegt wird):


breite Möwe
 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 

Hier sehen wir, dass der Scheduler anfänglich eine Filterung durchführt und eine Liste von 3 Knoten generiert, auf denen ein Start möglich ist (nxs-k8s-s8, nxs-k8s-s9, nxs-k8s-s10). Anschließend werden Punkte anhand mehrerer Parameter (einschließlich BalancedResourceAllocation, LeastResourceAllocation) für jeden dieser Knoten berechnet, um den am besten geeigneten Knoten zu ermitteln. Am Ende ist geplant, unter dem Knoten mit den meisten Punkten zu laufen (hier haben zwei Knoten bei 100037 die gleiche Anzahl von Punkten, daher wird eine zufällige ausgewählt - nxs-k8s-s10).


Fazit : Wenn Pods auf dem Knoten funktionieren, für den keine Einschränkungen festgelegt wurden, ist dies für k8s (aus Sicht des Ressourcenverbrauchs) so, als ob solche Pods auf diesem Knoten vollständig fehlen würden. Wenn Sie also unter bestimmten Bedingungen einen Pod mit einem unersättlichen Prozess haben (z. B. wowza) und für diesen keine Einschränkungen bestehen, kann eine Situation eintreten, in der der betreffende Knoten tatsächlich alle Ressourcen des Knotens verbraucht hat, dieser Knoten jedoch für k8s als entladen gilt Es wird die gleiche Anzahl von Punkten für die Rangfolge vergeben (dh in Punkten mit einer Bewertung der verfügbaren Ressourcen) sowie für einen Knoten, der keine Arbeitsabstände aufweist, was letztendlich zu einer ungleichmäßigen Lastverteilung zwischen den Knoten führen kann.


Herdräumung


Wie Sie wissen, ist jedem Pod eine der 3 QoS-Klassen zugeordnet:


  1. guaranuted - wird zugewiesen, wenn für jeden Container im Herd eine Anforderung und ein Limit für Speicher und CPU festgelegt wurden und diese Werte übereinstimmen müssen
  2. Berstbar - Mindestens ein Behälter im Herd hat eine Anforderung und ein Limit, während die Anforderung <Limit ist
  3. bester aufwand - wenn kein container im feuerraum in ressourcen begrenzt ist

Zur gleichen Zeit, wenn auf dem Knoten ein Mangel an Ressourcen (Festplatte, Speicher) besteht, beginnt kubelet, Pods nach einem bestimmten Algorithmus, der die Priorität des Pods und seiner QoS-Klasse berücksichtigt, zu klassifizieren und zu entfernen. Wenn es sich zum Beispiel um RAM handelt, werden basierend auf der QoS-Klasse Punkte nach dem folgenden Prinzip vergeben:


  • Garantiert : -998
  • BestEffort : 1000
  • Burstable : min (max (2, 1000 - (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999)

Das heißt Bei gleicher Priorität werden zuerst die Pods mit der bestmöglichen QoS-Klasse aus dem Knoten entfernt.


Fazit : Wenn Sie die Wahrscheinlichkeit verringern möchten, dass der erforderliche Pod bei unzureichenden Ressourcen vom Knoten entfernt wird, müssen Sie neben der Priorität auch die Anforderung / das Limit dafür festlegen.


Horizontaler Auto-Scaling-Mechanismus für Anwendungsherde (HPA)


Wenn die Aufgabe darin besteht, die Anzahl der Pods abhängig von der Ressourcennutzung (System-CPU / RAM oder Benutzer-RPS) automatisch zu erhöhen oder zu verringern, können k8s wie HPA (Horizontal Pod Autoscaler) Abhilfe schaffen. Der Algorithmus lautet wie folgt:


  1. Die aktuellen Messwerte der beobachteten Ressource (currentMetricValue) werden ermittelt
  2. Es werden die gewünschten Werte für die Ressource (wantedMetricValue) ermittelt, die per Request für Systemressourcen gesetzt werden
  3. Die aktuelle Anzahl der Replikate wird ermittelt (currentReplicas)
  4. Die folgende Formel berechnet die gewünschte Anzahl von Replikaten (desiredReplicas)
    desiredReplicas = [currentReplicas * (currentMetricValue / desiredMetricValue)]

Eine Skalierung findet jedoch nicht statt, wenn der Koeffizient (currentMetricValue / desiredMetricValue) in der Nähe von 1 liegt (wir können den zulässigen Fehler selbst festlegen, standardmäßig beträgt er 0,1).


Berücksichtigen Sie hpa mit der App-Testanwendung (als Bereitstellung bezeichnet), bei der die Anzahl der Replikate abhängig vom CPU-Verbrauch geändert werden muss:


  • Anwendungsmanifest


     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 

    Das heißt Wir sehen, dass es mit der Anwendung zunächst in zwei Instanzen gestartet wird, von denen jede zwei Container nginx und nginx-exporter enthält, für die jeweils Anforderungen an die CPU gestellt werden.


  • HPA-Manifest


     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 

    Das heißt Wir haben ein HPA erstellt, das den Deployment-App-Test überwacht und die Anzahl der Herde mit der Anwendung basierend auf der CPU-Anzeige anpasst (wir gehen davon aus, dass 30% der angeforderten CPU verbraucht werden), während die Anzahl der Replikate im Bereich von 2 bis 10 liegt.


    Nun betrachten wir den hpa-Betriebsmechanismus, wenn wir eine Last auf einen der Herde ausüben:


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


Insgesamt haben wir folgende:


  • Gewünschter Wert (desiredMetricValue) - gemäß den hpa-Einstellungen haben wir 30%
  • Aktueller Wert (currentMetricValue) - Zur Berechnung berechnet der Controller-Manager den Durchschnittswert des Ressourcenverbrauchs in%, d. H. bedingt das Folgende:
    1. Ruft die absoluten Werte der Herdmetriken vom Metrikserver ab, d. H. 101m und 4m
    2. Berechnet den durchschnittlichen Absolutwert, d.h. (101 m + 4 m) / 2 = 53 m
    3. Ermittelt den absoluten Wert für den gewünschten Ressourcenverbrauch (dazu werden die Anforderungen aller Container summiert) 60m + 30m = 90m
    4. Berechnet den durchschnittlichen Prozentsatz des CPU-Verbrauchs relativ zum Anforderungsherd, d. H. 53 m / 90 m * 100% = 59%

Jetzt haben wir alles Nötige, um festzustellen, ob die Anzahl der Replikate geändert werden muss. Dazu berechnen wir den Koeffizienten:


ratio = 59% / 30% = 1.96


Das heißt Die Anzahl der Replikate sollte um das ~ 2-fache erhöht werden und [2 * 1,96] = 4 betragen.


Fazit: Wie Sie sehen, ist es eine Grundvoraussetzung, dass Anforderungen für alle Container im beobachteten Herd verfügbar sind, damit dieser Mechanismus funktioniert.


Der Mechanismus der horizontalen automatischen Skalierung von Knoten (Cluster Autoscaler)


Um die negativen Auswirkungen auf das System während Lastspitzen zu neutralisieren, reicht das Vorhandensein eines abgestimmten hpa nicht aus. Beispielsweise entscheidet der hpa-Controller-Manager gemäß den Einstellungen, dass die Anzahl der Replikate um das Zweifache erhöht werden muss. Es sind jedoch keine Ressourcen auf den Knoten verfügbar, um eine solche Anzahl von Pods auszuführen (d. H. Der Knoten kann die angeforderten Ressourcen für die Pod-Anforderungen nicht bereitstellen) Geben Sie den Status Ausstehend ein.


In diesem Fall kann uns ein Tool wie Node Autoscaler helfen, wenn der Anbieter über das entsprechende IaaS / PaaS verfügt (z. B. GKE / GCE, AKS, EKS usw.). Sie können die maximale und minimale Anzahl von Knoten im Cluster festlegen und die aktuelle Anzahl von Knoten automatisch anpassen (indem Sie auf die Cloud-Provider-API zugreifen, um Knoten zu bestellen / zu löschen), wenn im Cluster ein Ressourcenmangel vorliegt und die Pods nicht geplant werden können (im Status Ausstehend).


Schlussfolgerung: Um die Knoten automatisch skalieren zu können, müssen Anforderungen in den Herdcontainern angegeben werden, damit k8s die Knotenlast korrekt auswerten und dementsprechend melden kann, dass sich keine Ressourcen im Cluster befinden, um den nächsten Herd zu starten.




Fazit


Es sollte beachtet werden, dass das Festlegen von Ressourcenlimits für den Container keine Voraussetzung für den erfolgreichen Start der Anwendung ist. Es ist jedoch aus den folgenden Gründen immer noch besser, dies zu tun:


  1. Für einen genaueren Scheduler-Betrieb im Hinblick auf den Lastausgleich zwischen k8s-Knoten
  2. Verringerung der Wahrscheinlichkeit einer Räumung des Herdes
  3. Für horizontale Anwendungsherde mit automatischer Skalierung (HPA)
  4. Zur horizontalen automatischen Skalierung von Knoten (Cluster Autoscaling) für Cloud-Anbieter

Lesen Sie auch andere Artikel in unserem Blog:


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


All Articles