Ich habe einen GKE Kubernetes-Cluster und eine Bereitstellung.
Ich habe die Ressourcenstrophe für die Bereitstellung auf
resources.requests.memory: 4G
resources.requests.cpu: 2
resources.limits.memory: 4G
CPU-Limit ist nicht festgelegt
Ich stelle den Pod (eine Django-Webanwendung) bereit und unterziehe ihn einem Belastungstest. Bei Sättigung steigt die CPU-Auslastung des Pods auf 1 CPU – weigert sich aber im Wesentlichen, über 1 CPU hinauszugehen.
Irgendwelche Ideen, was ich hier beheben sollte?
Antwort1
Ich habe diesen Beitrag offen gelassen, also schließen wir ihn.
In meinem konkreten Fall stellte sich heraus, dass der Engpass tatsächlich vor dem K8S Pod in der Datenbank lag. Die Postgres-Instanz war einfach nicht groß genug und erreichte Spitzenwerte bei 100 % CPU-Auslastung und verursachte Downstream-Timeouts.
Ich vermute, bin mir aber nicht sicher, dass die CPU-Auslastung auf den Pods einfach deshalb ausgeglichen wurde, weil die Pods auf eine Antwort vom Upstream warteten und nicht über die CPU-Auslastung von 1 hinausgehen konnten, weil sie nichts anderes zu tun hatten.
Darüber hinaus verwenden die Django-Instanzen Django-Kanäle und das asynchrone ASGI-Modell, das einfädig ist und nicht über dasselbe „Child-Thread“-Modell wie UWSGI verfügt. Dies ist ein weiterer Grund – oder vielleicht der eigentliche Grund – dafür, dass die CPU-Auslastung auf dem Pod bei 1 CPU ihr Maximum erreicht.
Ich bin mir also ziemlich sicher, dass der richtige Weg, dies zu skalieren, darin besteht,
- Postgres vertikal skalieren
- Erhöhen Sie die Basisanzahl der Pods
- Senken Sie den Autoscaler-Schwellenwert (HPA), um zu skalieren und neue Pods hinzuzufügen
EDIT: Zusätzliche Informationen
Das Problem hat auch mit der Art und Weise zu tun, wie die App selbst entworfen wurde. Wir versuchen, Django Channels asynchrones Python zu verwenden und es in einem Daphne ASGI-Container auszuführen; allerdings ist nicht die gesamte App asynchron, und das ist anscheinend schlecht. Ich habe viel zu diesem Problem von asynchronen vs. synchronisierten Anwendungen und den daraus resultierenden Deadlocks recherchiert und während ich das Entwicklerteam die App neu entwerfen lasse, habe ich auch die Bereitstellung neu gestaltet.
- Fügen Sie der Bereitstellung einen uWSGI-Server hinzu
- Stellen Sie die Codebasis in zwei Bereitstellungen/Pods bereit
- Man hat den ASGI Pod
- Man hat den uWSGI Pod
- Leiten Sie alle ASGI-Endpunkte (es gibt nur einen) in den Ingress-Pfad-Regeln zum ASGI-Pod weiter.
- Leiten Sie alle uWSGI-Endpunkte in den Ingress-Pfad-Regeln zum Sync-Pod weiter.
Dies funktioniert, ich habe jedoch noch keinen Volllasttest durchgeführt.