Django Hurricane

29. Dezember 2020
Wir haben uns erneut Gedanken gemacht, wie wir das Ausführen von Django-Anwendungen mehr cloud-native und ready for kubernetes gestalten können. Als Resultat ist django-hurricane herausgekommen, welches wir in diesem Blogpost vorstellen und als Open Source zur Verfügung stellen.

Wir bei Blueshoe sind schon immer Fans von Open Source. In sehr vielen unserer Projekten kommen Open Source Komponenten zum Einsatz, wir nutzen ja auch u.a. sehr stark das Django Framework und wir bemühen uns auch Open Source Projekte bei der Maintenance und Weiterentwicklung zu unterstützen. Seit einiger Zeit hat nun auch Kubernetes bei uns Einzug erhalten, wodurch wir uns mehr und mehr der Herausforderung stellen wie wir möglichst cloud native entwickeln können. Dazu haben wir ja auch schon Blog-Posts geschrieben, z.B. diesen hier:  Cloud native kubernetes development.

Die logische Konsequenz ist, dass wir uns nun Gedanken gemacht haben wie wir das Ausführen von Django-Anwendungen mehr cloud-native gestalten können. Als Resultat ist django-hurricane herausgekommen, welches wir in diesem Blogpost vorstellen und als Open Source zur Verfügung stellen.

 

“Klassisches” Deployment

Zunächst wollen wir uns kurz betrachten wie Django oftmals auf einem Server, bzw. einer VM ausgeführt wird. Üblicherweise verwenden wir dazu einen Stack mit nginx  als Web Server, sowie uwsgi als Application Server, welcher den Django-Code ausführt. Appserver wie uwsgi  haben ein hochgradig optimiertes Prozess Modell für diese Art von Deployments mit vielen CPUs, mehreren Threads, usw. Mit genügend Wissen über die Anwendung und genügend Erfahrung im Betrieb von Django-Anwendungen lässt sich der Application Server nun möglichst optimal konfigurieren, wofür i.d.R. genügend Optionen zur Verfügung stehen.

Kubernetes Deployment von django Anwendungen

pexels-pixabay-163811.jpg In Kubernetes sieht das nun etwas anders aus. Auch dort lässt sich unsere Django-Anwendung in einem Container mittels uwsgi ausführen. Allerdings ist eine auf die Hardware abgestimmte Optimierung des Application Servers im Container eher fehl am Platze. Schon allein da sich ja nicht direkt beeinflussen lässt auf welcher Node im Cluster der Container nun tatsächlich ausgeführt wird. In Kubernetes kann weiterhin mit dem Replication-Wert die horizontale Skalierung der Anwendung konfiguriert werden. Zusätzlich kann mit dem Horizontal Pod Autoscaler eine Mindest- und Maximalanzahl an Pods spezifiziert werden. Kommt die App beispielsweise mit den Requests nicht mehr zurecht, kann Kubernetes einfach einen neuen Container parallel starten.

Es gibt noch weitere Punkte die wir in unserer Django-Anwendung beachten müssen wenn sie mit Kubernetes ausgeführt wird. Hier sind z.B. die Liveness-, Readiness und Startup-Probes genannt. Unsere django Anwendung muss Endpunkte für die Probes zur Verfügung stellen, die regelmäßig von Kubernetes abgefragt werden um zu beurteilen ob ein Container z.B. neu gestartet werden muss, oder ob er gerade Traffic empfangen kann. Das kann dann doch zu etwas Boilerplate-Code führen, oder auch dazu dass die Django-Anwendung u.U. Funktionalität einfach nur für das Hosting bereitstellen muss.

All das wollen wir eigentlich nicht, wir wollen einen Application Server der direkter mit Kubernetes verzahnt ist.
 

Django Hurricane

django hurricane kubernetes Aus diesem Grund haben wir Django Hurricane entwickelt. Dabei bauen wir auf dem Tornado Web Server auf. Hurricane lässt sich als einfacher Django Management-Command ausführen und mittels Flags auch konfigurieren. Es sind keine weiteren Konfigurationsdateien nötig.

Die Installation kann einfach mittels pip erfolgen:

pip install hurricane

Hurricane muss daraufhin in die INSTALLED_APPS des Django Projekts hinzugefügt werden. Weiterhin sollte auch ein Logger konfiguriert werden, damit Log-Nachrichten angezeigt werden:

 INSTALLED_APPS += (
    'hurricane',
)

LOGGING = {
    # [...]
    “loggers”: {
        # [...]
        “hurricane:”: {
            "handlers": ["console"],
            "level": os.getenv("HURRICANE_LOG_LEVEL", "INFO"),
            "propagate": False,
        },
    },
    # [...]
}
 

Starten lässt sich Hurricane mit dem Management-Command:

python manage.py serve

Auch die Konfiguration findet komplett mit Optionen des Management-Commands statt. Hier ist eine Auflistung der momentan vorhandenen Optionen:
 

--static

Ausliefern von Static-Files
--mediaAusliefern von Media-Files

--autoreload

Code-Änderungen dynamisch laden

--debugDebug Flag von Tornado setzen
(nicht mit Djangos DEBUG=True zu verwechseln)
--portDer Port auf dem Tornado laufen soll (default: 8000)
--probeDer Pfad für die Liveness- und Readiness-Probes (default: /alive)
--probe-port

Der Port unter welchem die Probes zu erreichen sind
default: ein Port nach --port)

--no-probeProbe Endpunkt deaktivieren

 

Mit diesen grundlegenden Konfigurationsmöglichkeiten lassen sich bereits einige Szenarien abdecken und wir können Hurricane damit bereits auf Produktivsystemen einsetzen.

Damit die Probes auch ihren Sinn erfüllen können, muss gewährleistet sein, dass sie tatsächlich eine Aussage über die Erreichbarkeit und Verfügbarkeit der Anwendung treffen und es nicht einfach nur ein Endpunkt ist, der eher unabhängig von der Anwendung zu erreichen ist. Bei Hurricane werden der Django Code und der Probe-Endpunkt zwar auf zwei verschiedenen Ports ausgeliefert, da die komplette Code-Basis in der gleichen asyncio-Loop ausgeführt wird, lässt sich aber implizit ein Rückschluss auf die Erreichbarkeit und Verfügbarkeit der Anwendung treffen.


Es kann durchaus nötig sein, dass es mehr Logik benötigt, um die Liveness oder Readiness einer Anwendung zu ermitteln, als einfach nur einen Endpunkt der eine 200 zurückliefert. Hurricanes Probe Endpunkt ruft Djangos Check Framework  auf. Dadurch ist es möglich die benötigte zusätzliche Logik für die Anwendung in Django Checks abzubilden. 

Roadmap und weitere Entwicklung

map-455769_1280.jpg Auch wenn Hurricane bereits für Produktiv-Systeme verwendet werden kann, steht die Entwicklung erst ganz am Anfang. Uns schweben noch einige weitere Features vor, die Todo-Liste im GitHub Repository bietet noch einige freie Checkboxen an. Unterstützung bei der Weiterentwicklung ist natürlich wie bei allen Open Source Projekten immer willkommen. Wir bleiben auf jeden Fall weiter am Ball, es wird künftig sicherlich auch noch den ein oder anderen Blogpost, z.B. über neue Hurricane Features oder auch Anwendungsszenarien geben.