
Beim ersten Arbeiten mit Kubernetes wird oft die Konfiguration der Containerressourcen vergessen. In diesem Stadium reicht es aus, sicherzustellen, dass das Docker-Image funktioniert und im Kubernetes-Cluster bereitgestellt werden kann.
Später muss die Anwendung jedoch zusammen mit anderen Anwendungen im Produktionscluster bereitgestellt werden. Dazu müssen Ressourcen für den Container bereitgestellt werden, und es muss sichergestellt werden, dass diese ausreichend sind, um die Anwendung zu starten und auszuführen, ohne dass es Probleme mit anderen laufenden Anwendungen gibt.
Team Ich habe einen Artikel über Containerressourcen (CPU & MEM), Anfragen und Ressourcenbeschränkungen übersetzt. Sie werden erfahren, welche Vorteile diese Einstellungen bieten und was passiert, wenn sie nicht festgelegt werden.
Rechenressourcen
Wir haben zwei Ressourcentypen mit folgenden Einheiten:
- Zentralprozessor (CPU) – Kerne;
- Speicher (MEM) – Bytes.
Ressourcen werden für jeden Container angegeben. In der folgenden YAML-Datei für den Pod sehen Sie den Ressourcenabschnitt, der die angeforderten und maximalen Ressourcen enthält:
- Angeforderte Ressourcen des Pods = Summe der angeforderten Ressourcen aller Container;
- Maximale Ressourcen des Pods = Summe der maximalen Ressourcen 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 # ANGEFRAGTE CPU: 200m Kerne
memory: "1Gi" # ANGEFRAGTER MEM: 1Gi
limits:
cpu: 1 # MAXIMALE CPU-NUTZUNG: 1 Kern
memory: "1Gi" # MAXIMALE MEM-NUTZUNG: 1Gi
- name: other-container
image: other-app
tag: v1
ports:
- containerPort: 8000
resources:
requests:
cpu: "200m" # ANGEFRAGTE CPU: 200m Kerne
memory: "0.5Gi" # ANGEFRAGTER MEM: 0.5Gi
limits:
cpu: 1 # MAXIMALE CPU-NUTZUNG: 1 Kern
memory: "1Gi" # MAXIMALE MEM-NUTZUNG: 1GiBeispiel für angeforderte und maximale Ressourcen
Feld resources.requested aus der Pod-Spezifikation – eines der Elemente, die verwendet werden, um den passenden Knoten zu finden. Darauf kann bereits die Bereitstellung des Pods geplant werden. Wie sucht man also den geeigneten Knoten?
Kubernetes besteht aus mehreren Komponenten, einschließlich eines Master-Knotens (Kubernetes Control Plane). Im Master-Knoten laufen mehrere Prozesse: kube-apiserver, kube-controller-manager und kube-scheduler.
Der Prozess kube-scheduler ist verantwortlich für die Überprüfung neu erstellter Pods und die Suche nach möglichen Arbeitsknoten, die allen Anforderungen der Pods entsprechen, einschließlich der Anzahl der angeforderten Ressourcen. Die Liste der Knoten, die kube-scheduler gefunden hat, wird bewertet. Der Pod wird auf dem Knoten mit den höchsten Punktzahlen eingeplant.
Wo wird der lila Pod platziert?
Auf dem Bild ist zu sehen, dass der kube-scheduler einen neuen lila Pod planen soll. Der Kubernetes-Cluster enthält zwei Knoten: A und B. Wie zu erkennen ist, kann der kube-scheduler den Pod nicht auf Knoten A planen — die verfügbaren (unangeforderten) Ressourcen entsprechen nicht den Anforderungen des lila Pods. So passt der vom lila Pod angeforderte 1 GB Speicher nicht auf Knoten A, da der verfügbare Speicher 0,5 GB beträgt. Aber Knoten B hat genügend Ressourcen. Letztendlich entscheidet der kube-scheduler, dass das Ziel des lila Pods Knoten B ist.
Jetzt wissen wir, wie die angeforderten Ressourcen die Auswahl des Knotens für den Pod-Start beeinflussen. Aber wie beeinflussen die Grenzwerte der Ressourcen?
Grenzwerte der Ressourcen sind das Limit, welches CPU/MEM nicht überschreiten darf. Dennoch ist die CPU-Ressource flexibel, daher führen Container, die die Grenzwerte der CPU erreicht haben, nicht zur Beendigung des Pods. Stattdessen wird eine Drosselung der CPU aktiviert. Wenn jedoch das Limit für die Nutzung von MEM erreicht wird, wird der Container vom OOM-Killer gestoppt und neu gestartet, wenn dies durch die RestartPolicy erlaubt ist.
Angeforderte und Grenzwerte der Ressourcen im Detail
Verhältnis der Ressourcen zwischen Docker und Kubernetes
Der beste Weg, um zu erklären, wie angeforderte und Grenzwerte der Ressourcen funktionieren, besteht darin, die Beziehung zwischen Kubernetes und Docker darzustellen. Im obigen Bild können Sie sehen, wie die Felder von Kubernetes mit den Docker-Startflags verbunden sind.
Speicher: Anfrage und Begrenzung
containers:
...
resources:
requests:
memory: "0.5Gi"
limits:
memory: "1Gi"
Wie bereits erwähnt, wird der Speicher in Bytes gemessen. Basierend auf , können wir den Speicher als Zahl angeben. Normalerweise handelt es sich um eine ganze Zahl, z.B. 2678 — also 2678 Bytes. Sie können auch Suffixe verwenden G und Gi, wichtig ist, dass sie nicht gleichwertig sind. Der erste ist dezimal und der zweite binär. Als Beispiel, wie in der k8s-Dokumentation erwähnt: 128974848, 129e6, 129M, 123Mi — sie sind praktisch gleichwertig.
Der Kubernetes-Parameter limits.memory entspricht dem Flag --memory von Docker. Im Fall von request.memory fehlt der Hinweis für Docker, da Docker dieses Feld nicht nutzt. Sie könnten fragen, ob das überhaupt notwendig ist? Ja, es ist nötig. Wie ich bereits sagte, ist das Feld für Kubernetes von Bedeutung. Basierend auf den Informationen daraus entscheidet der kube-scheduler, auf welchem Knoten der Pod geplant werden soll.
Was passiert, wenn für die Anfrage nicht genügend Speicher eingestellt wird?
Wenn der Container die Grenzen des angeforderten Speichers erreicht, wird der Pod in eine Gruppe von Pods versetzt, die bei unzureichendem Speicher im Knoten gestoppt werden.
Was passiert, wenn ein zu niedriger Grenzwert für den Arbeitsspeicher festgelegt wird?
Wenn der Container den Grenzwert für den Arbeitsspeicher überschreitet, wird er aus Gründen des OOM-Kill beendet. Er wird neu gestartet, wenn dies basierend auf der RestartPolicy möglich ist, wobei der Standardwert – Immer.
Was passiert, wenn kein angeforderter Arbeitsspeicher angegeben wird?
Kubernetes übernimmt den Grenzwert und setzt ihn als Standardwert fest.
Was kann passieren, wenn kein Grenzwert für den Arbeitsspeicher angegeben wird?
Der Container hat keine Einschränkungen und kann so viel Arbeitsspeicher verwenden, wie er möchte. Wenn er jedoch beginnt, den gesamten verfügbaren Arbeitsspeicher des Knotens zu verwenden, wird er vom OOM-Killer beendet. Der Container wird dann neu gestartet, wenn dies basierend auf der RestartPolicy möglich ist.
Was passiert, wenn keine Arbeitsspeicher-Limits angegeben werden?
Dies ist das schlimmste Szenario: Der Scheduler weiß nicht, wie viele Ressourcen der Container benötigt, und das kann ernsthafte Probleme auf dem Knoten verursachen. In diesem Fall wäre es gut, Standardlimits im Namensraum (festgelegt durch LimitRange) zu haben. Standardmäßig gibt es keine Limits – der Pod hat keine Einschränkungen, er kann so viel Arbeitsspeicher verwenden, wie er möchte.
Wenn der angeforderte Arbeitsspeicher größer ist als das, was der Knoten anbietet – wird der Pod nicht geplant. Es ist wichtig zu beachten, dass Requests.memory kein Minimum darstellt. Es beschreibt den Speicherbedarf, der ausreicht, um den Container stabil zu betreiben.
Es wird im Allgemeinen empfohlen, denselben Wert für request.memory und limit.memoryfestzulegen. Dadurch stellt Kubernetes sicher, dass der Pod nicht auf einem Knoten geplant wird, der über genügend Arbeitsspeicher verfügt, um den Pod zu starten, aber nicht genügend, um ihn auszuführen. Beachten Sie: Bei der Planung des Pods berücksichtigt Kubernetes nur requests.memory, und limits.memory nicht.
CPU: Anfrage und Limit
containers:
...
resources:
requests:
cpu: 1
limits:
cpu: "1200m"
Bei CPU ist es etwas komplizierter. Wenn man sich das Bild der Beziehung zwischen Kubernetes und Docker anschaut, fällt auf, dass request.cpu entspricht --cpu-shares, während limit.cpu entspricht dem Flag cpus in Docker.
Die von Kubernetes angeforderte CPU wird mit 1024 multipliziert – die Verteilung der CPU-Zyklen. Wenn Sie eine vollständige Kernanzahl anfordern möchten, müssen Sie hinzufügen cpu: 1, wie oben gezeigt.
Die Anfrage nach einem vollständigen Kern (Verhältnis = 1024) bedeutet nicht, dass Ihr Container diesen erhält. Wenn Ihr Host-Computer nur über einen Kern verfügt und Sie mehr als einen Container verwenden, müssen alle Container die verfügbare CPU gemeinsam nutzen. Wie funktioniert das? Schauen wir uns das Bild an.

CPU-Anfrage - System mit einem Kern
Stellen Sie sich vor, Sie haben ein Host-System mit einem Kern, auf dem Container laufen. Mama (Kubernetes) hat einen Kuchen (CPU) gebacken und möchte ihn mit den Kindern (Containern) teilen. Drei Kinder wollen einen ganzen Kuchen (Verhältnis = 1024), ein weiteres Kind möchte die Hälfte des Kuchens (512). Mama möchte 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%Laut Berechnung werden drei Kinder jeweils 28 % eines Kerns erhalten, und nicht einen ganzen Kern. Dem vierten Kind stehen 14 % eines vollständigen Kerns zu, nicht die Hälfte. Aber alles ist anders, wenn Sie ein Multi-Core-System haben.

CPU-Anfrage - Multi-Core (4) System
Im obigen Bild sieht man, dass drei Kinder einen ganzen Kuchen wollen und eines die Hälfte. Da Mama vier Kuchen gebacken hat, wird jedes ihrer Kinder so viel bekommen, wie es möchte. In einem Multi-Core-System sind die Prozessorressourcen auf alle verfügbaren Prozessorkerne verteilt. Wenn der Container auf weniger als einen vollen CPU-Kern beschränkt ist, kann er ihn trotzdem zu 100 % nutzen.
Die oben genannten Berechnungen sind vereinfacht, um zu verstehen, wie die CPU zwischen Containern aufgeteilt wird. Natürlich gibt es neben den Containern auch andere Prozesse, die CPU-Ressourcen nutzen. Wenn Prozesse in einem Container im Leerlauf sind, können andere deren Ressourcen benutzen. CPU: "200m" entspricht CPU: 0,2, was etwa 20 % eines Kerns entspricht.
Jetzt sprechen wir über limit.cpu. CPU, das Kubernetes begrenzt, wird mit 100 multipliziert. Das Ergebnis ist die Menge an Zeit, die der Container alle 100 µs nutzen kann (cpu-period).
limit.cpu entspricht dem Docker-Flag --cpus. Das ist eine neue Kombination aus den alten --cpu-period und --cpu-quota. Indem wir es festlegen, geben wir an, wie viel verfügbare CPU-Ressourcen der Container maximal nutzen kann, bis die Drosselung beginnt:
- cpus — Kombination
cpu-periodundcpu-quota. cpus = 1.5entspricht der Festlegung voncpu-period = 100000undcpu-quota = 150000; - cpu-period — die Periode , standardmäßig 100 Mikrosekunden;
- cpu-quota — die Anzahl der Mikrosekunden innerhalb von
cpu-period, die der Container begrenzt ist.
Was passiert, wenn nicht genügend angeforderte CPU bereitgestellt wird?
Wenn der Container mehr benötigt, als bereitgestellt ist, stiehlt er CPU von anderen Prozessen.
Was geschieht, wenn ein unzureichendes CPU-Limit festgelegt wird?
Da die CPU-Ressourcen reguliert sind, wird das Drosseln aktiviert.
Was passiert, wenn kein CPU-Anforderungswert angegeben wird?
Analog zur Speicheranfrage entspricht der Wert der Anfrage dem Limit.
Was passiert, wenn kein CPU-Limit angegeben wird?
Der Container verwendet so viel CPU, wie er benötigt. Wenn eine Standard-CPU-Richtlinie im Namespace definiert ist (LimitRange), wird dieses Limit auch für den Container verwendet.
Was geschieht, wenn weder eine Anfrage noch ein Limit für die CPU angegeben werden?
Ähnlich wie beim Speicher ist dies das schlechteste Szenario. Der Scheduler weiß nicht, wie viele Ressourcen Ihr Container benötigt, was zu schwerwiegenden Problemen auf dem Knoten führen kann. Um dies zu vermeiden, sollten Standardlimits für Namespaces (LimitRange) festgelegt werden.
Denken Sie daran: Wenn Sie mehr CPU anfordern, als die Knoten bereitstellen können, wird der Pod nicht geplant. Requests.cpu — kein Mindestwert, sondern ein Wert, der ausreicht, um den Pod zu starten und ohne Ausfälle zu betreiben. Wenn die Anwendung keine komplexen Berechnungen durchführt, ist es am besten, request.cpu <= 1 und so viele Replikate wie nötig zu starten.
Die ideale Anzahl an angeforderten Ressourcen oder Ressourcenlimits
Wir haben von der Begrenzung der Rechenressourcen erfahren. Jetzt ist es an der Zeit, die Frage zu beantworten: „Wie viele Ressourcen benötigt mein Pod, um die Anwendung reibungslos zu betreiben? Welche Anzahl ist ideal?“
Leider gibt es auf diese Fragen keine eindeutigen Antworten. Wenn Sie nicht wissen, wie Ihre Anwendung funktioniert und wie viel CPU oder Speicher sie benötigt, ist es am besten, der Anwendung viel Speicher und CPU zu geben und dann Leistungstests durchzuführen.
Neben den Leistungstests sollten Sie die Anwendung eine Woche lang im Monitoring beobachten. Wenn die Grafiken zeigen, dass Ihre Anwendung weniger Ressourcen verbraucht, als Sie angefordert haben, können Sie die angeforderte CPU oder den Speicher reduzieren.
Als Beispiel sehen Sie dieses . Es zeigt den Unterschied zwischen den angeforderten Ressourcen oder dem Ressourcenlimit und der aktuellen Ressourcennutzung.
Fazit
Anfragen und Ressourcensperren helfen, die Funktionsfähigkeit des Kubernetes-Clusters aufrechtzuerhalten. Eine richtige Konfiguration der Limits minimiert die Kosten und hält die Anwendungen ständig in einem funktionsfähigen Zustand.
Kurz gesagt, es gibt einige Punkte, die man beachten sollte:
- Die angeforderten Ressourcen sind die Konfiguration, die beim Start berücksichtigt wird (wenn Kubernetes plant, die Anwendung zu platzieren). Im Gegensatz dazu ist die Ressourcensperre während des Betriebs wichtig — wenn die Anwendung bereits auf einem Knoten läuft.
- Im Vergleich zu RAM ist die CPU eine regulierbare Ressource. Bei CPU-Mangel wird Ihr Pod nicht beendet; es tritt ein Drosselmechanismus in Kraft.
- Angeforderte Ressourcen und Ressourcensperren sind keine minimalen oder maximalen Werte! Durch die Festlegung angeforderter Ressourcen garantieren Sie, dass die Anwendung reibungslos funktioniert.
- Eine gute Praxis ist es, die angeforderte Speichermenge gleich dem Speicherrlimit zu setzen.
- Es ist gut, die angeforderte
CPU <=1, wenn die Anwendung keine komplexen Berechnungen durchführt. - Wenn Sie mehr Ressourcen anfordern, als auf dem Knoten verfügbar sind, wird der Pod niemals auf diesem Knoten geplant.
- Um die richtige Menge an angeforderten Ressourcen/Ressourcensperren zu bestimmen, verwenden Sie Lasttests und Überwachung.
Ich hoffe, dieser Artikel hilft Ihnen, das grundlegende Konzept der Ressourcensperren zu verstehen. Und Sie können dieses Wissen in Ihrer Arbeit anwenden.
Viel Erfolg!
Was Sie sonst noch lesen sollten:
- .
- .
- .
Quelle: habr.com
