Digital Transformation
Stabilität im Kubernetes Nodepool: Die Herausforderung mit Cronjobs
Cronjobs in Kubernetes können Nodepools destabilisieren. Optimierungsstrategien werden angewandt, doch bleiben offene Probleme bestehen. Wie geht man damit um?
11.05.2023
In einer Kubernetes-Umgebung erlaubt uns das Container-Prinzip nicht mehr den crontab für wiederkehrende Prozesse zu nutzen. Dafür gibt es eigens dafür geschaffene Cronjob Deployments. Das funktioniert gut. Aber nur solange, wie man wenige Cronjobs hat, die gleichzeitig starten wollen. Wir aber haben Cronjobs im zweistelligen Bereich, die alle gleichzeitig starten wollen, und das jede Minute! Das führt dazu, dass Nodes instabil werden können. Also wie können wir Abhilfe schaffen?
Ausgangssituation
Unser SaaS Produkt läuft in einem Kubernetes Cluster. Wir haben für jeden unserer Kunden separate Deployments (wir nennen sie Workspaces) und jeder dieser Workspaces hat drei Cronjobs:
Einen in der Nacht
einen am Mittag und
einen zu jeder Minute
Das sind in der Summe > 100 Deployments in einem Nodepool. Unser PROD-Nodepool hat drei Nodes. Per se sollte das kein Problem sein, denn unsere Deployments verbrauchen nicht viel Ressourcen. Weder in der CPU, noch im RAM. Die Cronjobs zu jeder Minute aber sorgen für Unruhe auf den Nodes. Wenn eine Anzahl von Cronjobs im zweistelligen Bereich zur selben Zeit hochfahren, um ihre Arbeit zu verrichten, dann bringt das einen Node schon mal durcheinander und beeinflusst die anderen Container, die auch darauf laufen. Der minütliche Cronjob sieht erst einmal harmlos aus:
Optimierung 1: Eigener Nodepool nur für Cronjobs
Also haben wir den Cronjobs einen eigenen Nodepool gegeben und sie somit von allen anderen Anwendungen separiert. Das haben wir mit NodeSelectors gemacht. NodeSelectors sorgen dafür, dass Container nur dort deployed werden, wo sie dürfen. Sie reagieren auf die Labels der Nodepools. Also haben wir ein Label “Cronjob: allowed” auf einen neuen Nodepool gesetzt. Und die Cronjobs haben folgenden NodeSelector erhalten.
Somit werden die Cronjobs nur auf Nodes erstellt, die das Label “cronjob: allowed” haben. Ansonsten läuft dort nichts. Warum? Weil wir alle unsere Anwendungen mit NodeSelectors versehen haben und sie somit zwingen auf ihren zugewiesenen Nodepools zu laufen. Ein Nodepool für die Cronjobs, ein Nodepool für die Kunden und ein Nodepool für die Anwendungen, die alle brauchen, wie IAM etc.
Das hat erst einmal geholfen und das Gewissen beruhigt. Aber schnell war zu erkennen, dass dies nicht wirklich geholfen hat. Die Nodes im Nodepool für die Cronjobs hatten immer noch dieselben Probleme und wurden instabil. Es half nur diese Nodes zu bereinigen, zu löschen und den Nodepool automatisch neue Nodes generieren zu lassen.
Um manuelle Arbeit zu vermeiden, mussten wir uns etwas anderes überlegen. Es lag auf der Hand. Wir müssen diese Cronjobs abschaffen!
Optimierung 2: Keine Cronjobs mehr!
Keine Cronjobs mehr wäre schön. Leider haben wir keine Lösung gefunden, die die Cronjobs abgeschafft hätten. Ich hätte Euch gerne gesagt, dass es ein Cronjob “” “ ” “ ”" nicht mehr braucht. Aber für uns braucht es den noch. Wir haben für uns eine Lösung gefunden, dass die Cronjobs nicht mehr vom Cluster verwaltet werden müssen und dass es somit keine Instabilität mehr gibt.
Wir haben eine zentrale Anwendung, welche alle Workspaces kennt. Von Anfang an hatten wir diese zentrale Verwaltung. Diese Verwaltung lassen wir nun alle Workspaces notifizieren, dass ein Cronjob ausgeführt werden soll. Dazu hat jeder Workspace eine API, die dann den genannten Cronjob in der Shell startet. Wir haben dadurch mehr Last auf dem Workspace, aber meistens passiert nichts, weil nichts zu tun ist.
Somit haben wir denselben Effekt, wie mit separaten Cronjob-Deployments. So vermeiden wir zu viel Last auf unserem Cluster durch dauerndes Hochfahren von Cronjobs.
Noch mehr Optimierungspotential
Leider hat auch diese Lösung einen Haken. Sie funktioniert nur solange, solange wir weniger als 300 Kunden haben: Ein Request an einen Workspace zum Starten eines Cronjobs dauert ca. 200ms. Innerhalb einer Minute können wir somit bis zu 300 Cronjobs starten. Danach dauert die Aktion alle Cronjobs zu starten länger als eine Minute und wir haben einen Versatz und ein Cronjob läuft nicht mehr jede Minute, sondern etwas seltener.
Aber auch das bekommt man in den Griff… man kann die Requests an die Workspaces in parallelen Prozessen ausführen lassen. Aber darüber schreiben wir ein andermal.
Sind wir alleine mit instabilen Nodes aufgrund von Cronjobs?
Wie geht Ihr mit Cronjobs um, wenn ganz viele Anwendungen zur selben Zeit einen Cronjob starten wollen?
Latest articles
Bleiben wir in Kontakt