
Wenn Sie mit Kubernetes beginnen, vergessen Sie häufig die Konfiguration von Containerressourcen. Zu diesem Zeitpunkt müssen Sie nur sicherstellen, dass das Docker-Image funktioniert und in Ihrem Kubernetes-Cluster bereitgestellt werden kann.
Später muss die Anwendung jedoch zusammen mit anderen Anwendungen im Produktionscluster bereitgestellt werden. Dazu müssen Sie Ressourcen für den Container zuweisen und sicherstellen, dass genügend Ressourcen zum Starten und Ausführen der Anwendung vorhanden sind. In anderen laufenden Anwendungen treten keine Probleme auf.
Das aaS- Team von Kubernetes von Mail.ru hat einen Artikel über Containerressourcen (CPU & MEM), Anforderungen und Ressourcenlimits übersetzt. Sie erfahren, welche Vorteile diese Einstellungen haben und was passiert, wenn Sie sie nicht installieren.
Rechenressourcen
Wir haben zwei Arten von Ressourcen mit den folgenden Einheiten:
- Zentraleinheit (CPU) - Kerne;
- Speicher (MEM) - Bytes.
Für jeden Container werden Ressourcen angegeben. In der folgenden YAML-Pod-Datei sehen Sie einen Ressourcenabschnitt, der die angeforderten und begrenzten Ressourcen enthält:
- Angeforderte Pod-Ressourcen = die Summe der angeforderten Ressourcen aller Pods;
- Limit Pod Resources = Die Summe der Grenzressourcen aller Container.
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 # REQUESTED CPU: 200m cores
memory: "1Gi" # REQUESTED MEM: 1Gi
limits:
cpu: 1 # MAX CPU USAGE: 1 core
memory: "1Gi" # MAX MEM USAGE: 1Gi
— name: other-container
image: other-app
tag: v1
ports:
— containerPort: 8000
resources:
requests:
cpu: "200m" # REQUESTED CPU: 200m cores
memory: "0.5Gi" # REQUESTED MEM: 0.5Gi
limits:
cpu: 1 # MAX CPU USAGE: 1 core
memory: "1Gi" # MAX MEM USAGE: 1GiBeispiel für angeforderte und begrenzte Ressourcen Ein
Feld
resources.requestedaus der Pod-Spezifikation ist eines der Elemente, mit denen der erforderliche Knoten gefunden wird. Bereits darauf können Sie eine Pod-Bereitstellung planen. Wie suchen sie nach einem geeigneten Knoten?
Kubernetes besteht aus mehreren Komponenten, einschließlich des Masterknotens oder Masterknotens (Kubernetes Control Plane). Im Masterknoten gibt es mehrere Prozesse: kube-apiserver, kube-controller-manager und kube-scheduler.
Der Kube-Scheduler-Prozess ist dafür verantwortlich, die neu erstellten Module und mögliche Worker-Knoten zu suchen, die allen Modulanforderungen entsprechen, einschließlich der Anzahl der angeforderten Ressourcen. Die Liste der vom kube-scheduler gefundenen Knoten ist geordnet. Der Pod ist für den Standort mit den höchsten Punktzahlen geplant.

Das Bild zeigt, dass der Kube-Scheduler einen neuen lila Pod planen sollte. Der Kubernetes-Cluster enthält zwei Knoten: A und B. Wie Sie sehen, kann der Kube-Scheduler keinen Pod für Knoten A planen - die verfügbaren (nicht angeforderten) Ressourcen stimmen nicht mit den Anforderungen für den lila Pod überein. Beispielsweise passt die vom lila Pod angeforderte 1 GB Speicher nicht auf Knoten A, da der verfügbare Speicher 0,5 GB beträgt. Knoten B verfügt jedoch über genügend Ressourcen. Infolgedessen entscheidet der Kube-Scheduler, dass das Ziel des lila Pods Knoten B ist.
Jetzt wissen wir, wie sich die angeforderten Ressourcen auf die Auswahl des Knotens zum Starten des Pods auswirken. Aber wie wirken sich marginale Ressourcen aus?
Grenzressourcen sind eine Grenze, die die CPU / das MEM nicht überschreiten kann. Die CPU ist jedoch flexibel, sodass Container, die das CPU-Limit erreichen, den Pod nicht herunterfahren. Stattdessen wird die CPU-Drosselung gestartet. Wenn das MEM-Nutzungslimit erreicht ist, wird der Container aufgrund von OOM-Killer gestoppt und neu gestartet, sofern die Einstellung RestartPolicy dies zulässt.
Angeforderte und begrenzte Ressourcen im Detail

beste Weg, um zu erklären, wie angeforderte und begrenzte Ressourcen funktionieren, besteht darin, die Beziehung zwischen Kubernetes und Docker darzustellen. In der Abbildung oben sehen Sie, wie Kubernetes-Felder und Docker-Startflags zusammenhängen.
Speicher: Anforderung und Begrenzung
containers:
...
resources:
requests:
memory: "0.5Gi"
limits:
memory: "1Gi"
Wie oben erwähnt, wird der Speicher in Bytes gemessen. Basierend auf der Kubernetes-Dokumentation können wir den Speicher als Zahl angeben. Normalerweise ist es eine Ganzzahl, zum Beispiel 2678 - also 2678 Bytes. Sie können auch Suffixe verwenden
Gund Givor allem daran denken, dass diese nicht gleichwertig sind. Die erste ist dezimal und die zweite binär. Als Beispiel in der Dokumentation K8S erwähnt: 128974848, 129e6, 129M, 123Mi- sie sind praktisch gleichwertig.
Der Parameter Kubernetes
limits.memoryentspricht dem Flag --memoryvon Docker. Im Falle vonrequest.memoryEs gibt keinen Pfeil für Docker, da Docker dieses Feld nicht verwendet. Sie fragen sich vielleicht, ob dies überhaupt notwendig ist? Ja brauchen. Wie ich bereits sagte, ist das Feld für Kubernetes wichtig. Basierend auf den Informationen daraus entscheidet der Kube-Scheduler, für welchen Knoten der Pod geplant werden soll.
Was passiert, wenn nicht genügend Speicher für eine Abfrage installiert ist?
Wenn der Container die Grenzen des angeforderten Speichers erreicht, wird der Pod in die Pod-Gruppe eingefügt, die angehalten wird, wenn sich kein Speicher im Knoten befindet.
Was passiert, wenn Sie das Speicherlimit zu niedrig einstellen?
Wenn der Container das Speicherlimit überschreitet, wird er aufgrund von OOM-Killed beendet. Und wird nach Möglichkeit basierend auf RestartPolicy neu gestartet, wobei der Standardwert ist
Always.
Was passiert, wenn Sie den angeforderten Speicher nicht angeben?
Kubernetes nimmt das Limit und legt es als Standard fest.
Was kann passieren, wenn Sie das Speicherlimit nicht angeben?
Der Container kennt keine Grenzen, er kann so viel Speicher belegen, wie er möchte. Wenn er den gesamten verfügbaren Speicher des Knotens verwendet, wird er von OOM getötet. Der Container wird dann nach Möglichkeit basierend auf RestartPolicy neu gestartet.
Was passiert, wenn Sie keine Speicherbeschränkungen angeben?
Dies ist das Worst-Case-Szenario: Der Scheduler weiß nicht, wie viel Ressourcen der Container benötigt, und dies kann schwerwiegende Probleme auf dem Knoten verursachen. In diesem Fall wäre es schön, Standard-Namespace-Einschränkungen zu haben (von LimitRange festgelegt). Standardmäßig gibt es keine Grenzen - der Pod hat keine Grenzen, er kann so viel Speicher verwenden, wie er möchte.
Wenn der angeforderte Speicher mehr ist, als der Knoten bieten kann, wird der Pod nicht geplant. Es ist wichtig zu bedenken, dass dies
Requests.memorykein Mindestwert ist. Dies ist eine Beschreibung der Speichermenge, die ausreicht, damit der Container kontinuierlich ausgeführt werden kann.
Es wird normalerweise empfohlen, den gleichen Wert für
request.memoryund einzustellenlimit.memory... Dies verhindert, dass Kubernetes einen Pod auf einem Knoten plant, der über genügend Speicher verfügt, um den Pod auszuführen, aber nicht genug, um ausgeführt zu werden. Beachten Sie: Bei der Planung eines Pods zählt Kubernetes nur requests.memory, limits.memorynicht.
CPU: Anfrage und Limit
containers:
...
resources:
requests:
cpu: 1
limits:
cpu: "1200m"
Mit der CPU ist alles etwas komplizierter. Wenn Sie zum Bild der Beziehung zwischen Kubernetes und Docker zurückkehren, können Sie sehen, dass sie
request.cpuübereinstimmt --cpu-shares, während sie limit.cpumit der Flagge cpusin Docker übereinstimmt .
Die von Kubernetes angeforderte CPU wird mit 1024 multipliziert, dem Anteil der CPU-Zyklen. Wenn Sie 1 vollständigen Kern anfordern möchten, müssen Sie
cpu: 1wie oben gezeigt hinzufügen .
Das Anfordern eines vollständigen Kernels (Anteil = 1024) bedeutet nicht, dass Ihr Container ihn erhält. Wenn Ihr Hostcomputer nur einen Kern hat und Sie mehr als einen Container verwenden, müssen sich alle Container die verfügbare CPU untereinander teilen. Wie kommt es dazu? Schauen wir uns das Bild an.

CPU-Anforderung - Single Core-System
Angenommen, Sie haben ein Single Core-Hostsystem, auf dem Container ausgeführt werden. Mama (Kubernetes) hat einen Kuchen (CPU) gebacken und möchte ihn unter Kindern (Containern) teilen. Drei Kinder wollen einen ganzen Kuchen (Anteil = 1024), ein anderes Kind will die Hälfte des Kuchens (512). Mama will fair sein und macht eine einfache Berechnung.
# ?
# 3
cakesNumberKidsWant = (3 * 1) + (1 * 0.5) = 3.5
# :
3 (/) * 1 ( / ) + 1 (/) * 0.5 ( / )
# ?
availableCakesNumber = 1
# () ?
newMaxRequest = 1 / 3.5 =~ 28%
Basierend auf der Berechnung erhalten drei Kinder 28% des Kernels und nicht den gesamten Kernel. Das vierte Kind erhält 14% des gesamten Kernels, nicht die Hälfte. Bei einem Multi-Core-System sieht es jedoch anders aus.

CPU-Anforderung - Multi-Core (4) -System
In der Abbildung oben sehen Sie, dass drei Kinder einen ganzen Kuchen und eines die Hälfte wollen. Da Mama vier Kuchen gebacken hat, bekommt jedes ihrer Kinder so viel, wie sie wollen. In einem Mehrkernsystem sind die Prozessorressourcen auf alle verfügbaren Prozessorkerne verteilt. Wenn ein Container auf weniger als einen vollen CPU-Kern beschränkt ist, kann er ihn dennoch zu 100% nutzen.
Die obigen Berechnungen werden vereinfacht, um zu verstehen, wie die CPU zwischen Containern aufgeteilt wird. Natürlich gibt es neben den Containern selbst auch andere Prozesse, die ebenfalls CPU-Ressourcen verwenden. Wenn Prozesse in einem Container inaktiv sind, können andere seine Ressource verwenden.
CPU: "200m"entspricht CPU: 0,2, was etwa 20% eines Kerns bedeutet.
Jetzt lass uns darüber reden
limit.cpu... Die CPU, die Kubernetes begrenzt, wird mit 100 multipliziert. Das Ergebnis ist die Zeit, die der Container alle 100 μs ( cpu-period) verwenden kann.
limit.cpuentspricht der Docker-Flagge --cpus. Dies ist eine neue Kombination aus alten --cpu-periodund --cpu-quota. Durch Festlegen geben wir an, wie viele verfügbare CPU-Ressourcen der Container maximal nutzen kann, bis er mit der Drosselung beginnt:
- cpus ist eine Kombination aus
cpu-periodundcpu-quota. cpus = 1.5entspricht der Einstellungcpu-period = 100000undcpu-quota = 150000; - CPU-Periode - CPU-CFS-Scheduler- Periode , standardmäßig 100 Mikrosekunden;
- CPU-Quote - Die Anzahl der Mikrosekunden
cpu-period, auf die der Container begrenzt ist.
Was passiert, wenn die angeforderte CPU nicht ausreicht?
Wenn der Container mehr benötigt als installiert ist, stiehlt er die CPU von anderen Prozessen.
Was passiert, wenn Sie ein unzureichendes CPU-Limit festlegen?
Da die CPU-Ressource einstellbar ist, wird die Drosselung aktiviert.
Was passiert, wenn Sie keine CPU-Anforderung angeben?
Wie beim Speicher entspricht der Anforderungswert dem Grenzwert.
Was passiert, wenn Sie das CPU-Limit nicht angeben?
Der Container verbraucht so viel CPU wie er benötigt. Wenn im Namespace eine Standard-CPU-Richtlinie (LimitRange) definiert ist, wird diese Grenze auch für den Container verwendet.
Was passiert, wenn Sie weder die Anforderung noch das CPU-Limit angeben?
Wie beim Speicher ist dies das Worst-Case-Szenario. Der Scheduler weiß nicht, wie viel Ressourcen Ihr Container benötigt, und dies kann schwerwiegende Probleme auf dem Knoten verursachen. Um dies zu vermeiden, müssen Sie die Standardgrenzwerte für Namespaces (LimitRange) festlegen.
Denken Sie daran, wenn Sie mehr CPU anfordern, als die Knoten liefern können, wird der Pod nicht geplant.
Requests.cpu- kein Mindestwert, aber ein Wert, der ausreicht, um den Pod zu starten und reibungslos zu laufen. Wenn Ihre Anwendung keine komplexen Berechnungen durchführt, ist es am besten request.cpu <= 1, so viele Replikate wie nötig zu installieren und auszuführen.
Ideale Menge der angeforderten Ressourcen oder Ressourcenlimit
Wir haben etwas über die Begrenzung der Rechenressourcen gelernt. Jetzt ist es Zeit, die Frage zu beantworten: „Wie viele Ressourcen benötigt mein Pod, um die Anwendung ohne Probleme auszuführen? Was ist die ideale Menge? "
Leider gibt es keine eindeutigen Antworten auf diese Fragen. Wenn Sie nicht wissen, wie Ihre Anwendung funktioniert, wie viel CPU oder Speicher sie benötigt, können Sie der Anwendung am besten viel Speicher und CPU zur Verfügung stellen und dann Benchmarks ausführen.
Beobachten Sie zusätzlich zu Leistungstests eine Woche lang das Überwachungsverhalten der Anwendung. Wenn die Grafiken zeigen, dass Ihre Anwendung weniger Ressourcen verbraucht als Sie angefordert haben, können Sie die Menge der angeforderten CPU oder des angeforderten Speichers reduzieren.
Sehen Sie sich dieses Grafana-Dashboard als Beispiel an .... Es zeigt den Unterschied zwischen den angeforderten Ressourcen oder dem Ressourcenlimit und der aktuellen Ressourcennutzung an.
Fazit
Durch das Abfragen und Begrenzen von Ressourcen bleibt Ihr Kubernetes-Cluster funktionsfähig. Durch die korrekte Konfiguration von Grenzwerten werden die Kosten minimiert und Anwendungen können jederzeit ausgeführt werden.
Kurz gesagt, es gibt einige Dinge zu beachten:
- Angeforderte Ressourcen sind die Konfiguration, die beim Start berücksichtigt wird (wenn Kubernetes plant, die Anwendung zu hosten). Im Gegensatz dazu ist die Begrenzung der Ressourcen zur Laufzeit wichtig - wenn die Anwendung bereits auf dem Knoten ausgeführt wird.
- Im Vergleich zum Speicher ist die CPU eine regulierte Ressource. Bei unzureichender CPU wird Ihr Pod nicht heruntergefahren, sondern gedrosselt.
- Angeforderte Ressourcen und Ressourcenlimit sind keine Minimal- und Maximalwerte! Indem Sie die angeforderten Ressourcen identifizieren, stellen Sie sicher, dass die Anwendung reibungslos ausgeführt wird.
- Es wird empfohlen, die Speicheranforderung gleich dem Speicherlimit zu setzen.
- Es ist gut, wie gewünscht festzulegen,
CPU <=1wenn die Anwendung keine komplexen Berechnungen durchführt. - Wenn Sie mehr Ressourcen anfordern als der Knoten hat, wird der Pod niemals für diesen Knoten geplant.
- Verwenden Sie Lasttests und Überwachung, um die richtige Menge an angeforderten Ressourcen / Ressourcenlimits zu ermitteln.
Ich hoffe, dieser Artikel hilft Ihnen, das Grundkonzept der Ressourcenbegrenzung zu verstehen. Und dieses Wissen können Sie in Ihrer Arbeit anwenden.
Viel Glück!
Was noch zu lesen: