Blog

Skillbyte Podcast #30: Die Zwölf Faktoren des Cloud Native Development (Teil 2)

Willkommen zum Skillbyte-Podcast! Skillbyte ist ihr Partner für digitale Exzellenz.

In diesem Podcast geht es um das Thema: Die Zwölf Faktoren des Cloud Native Development (Teil 2)

// Inhalt //
01:16 – Faktor 7: Bindung an Ports / Port binding
06:36 – Faktor 8: Nebenläufigkeit / Concurrency
14:31 – Faktor 9: Einweggebrauch / Disposability
19:34 – Faktor 10: Dev&Prod Vergleichbarkeit / Dev&prod parity
25:05 – Faktor 11: Logs
29:37 – Faktor 12: Administrationsprozesse / Admin processes

Twelve Factor App: https://12factor.net/

Abonnieren Sie diesen Podcast und besuchen Sie uns auf https://www.skillbyte.de

Feedback und Fragen gerne an podcast@skillbyte.de

TRANSKRIPT der Folge Skillbyte Podcast #30: Die Zwölf Faktoren des Cloud Native Development (Teil 2)

[00:00:00.950] – Oliver
Dass ist wirklich heiß, weil das ist das, weshalb man in die Cloud geht, vielleicht. Möglicherweise ist das der primäre Grund, damit ich eben nicht mir Wochen oder Monate im Voraus überlegen muss. Wieviel Hardware brauche ich, die dann noch installiert werden muss, sondern ich kann das innerhalb kürzester Zeit alles hoch und runterfahren, wie ich es brauche. Und vielleicht kann meine Anwendung das sogar von selber kontrollieren, wenn ich das irgendwie realisieren kann. Und da gibt es durchaus viele Möglichkeiten, das zu tun.

[00:00:36.650] – Maurice
Herzlich willkommen zu unserer aktuellen skillbyte Podcast Episode Nummer 30. Die zwölf Faktoren des Cloud Native Development Teil 2. Abonniert unseren Kanal für mehr spannende Themen aus dem Technologie Umfeld. Wenn Ihr Hörer-Fragen hat, sendet uns gerne eine E-Mail an podcast@skillbyte.de. Gerne könnt ihr auch eine Fünf-Sterne-Bewegung hinterlassen und ganz wichtig den Podcast an eure Freunde weiterempfehlen, die sich ebenfalls für die Themen interessieren. Ich bin heute wieder mit Oliver. Hi Oliver!

[00:01:05.210] – Oliver
Hallo Maurice. Schön wieder dabei sein zu dürfen.

[00:01:06.770] – Maurice
Gerne gerne. Und wir besprechen heute in unserem zweiten Teil die Faktoren sieben bis zwölf von der 12 Factor App oder Twelve Factor App. Der siebte Faktor ist die sogenannte Bindung an Ports englisch: Port Binding. Was meint das genau? 12 Factor Apps sollen self contained sein, das heißt, sie sollen alles mitbringen, was sie benötigen. Da es Micro Services sind, sollen sie auch ihren eigenen kleinen Webserver mitbringen oder ihren Container mitbringen, der dann eben startet und die Anwendung verfügbar macht, indem er Ports öffnet und auf HTTP Requests lauscht. So wird quasi ein Service exposed. Java Webserver könnten Jetty sein oder Tomcat. Das Falcon Framework kann man für Python benutzen. Ich weiß nicht, welchen Webserver du benutzt für deine Projekte?

[00:01:59.600] – Oliver
Ich habe am Anfang das erste Mal für Entwicklungszwecke, der Einfachheit halber, noch tatsächlich den von Flask selber benutzt. Das bringt einen eigenen Webserver mit. Ich habe nachher dann auf Gunicorn upgegraded. Wenn man so will, weil der einfach ein bisschen mehr Last aushält und unter Last zuverlässiger Arbeit. Nginx wäre natürlich auch noch gegangen.

[00:02:20.500] – Maurice
Okay, ich kenne Nginx noch als Alternative zum Apache Webserver, aber da war es, glaube ich, noch ein C Programm. Auf jeden Fall starten diese Webservices, öffnen einen oder mehrere Ports. Oft öffnen sie mindestens zwei Ports, also einen Nutzlast Port 8080 zum Beispiel für HTTP Requests. Und es gibt noch einen Port, entweder einen eigenen Port 8090, wo man dann heath, Informationen zu dem Service abrufen kann. Manchmal läuft das aber auch über den gleichen Port und wird einfach nur unter einer URL /health, zum Beispiel, registriert und dann kann man dann sehen, ob der Dienst lebt und ordnungsgemäß funktioniert.

[00:02:59.900] – Oliver
Das kann man an der Stelle vielleicht noch dazusagen, dann jetzt gerade die Ports. Wir reden hier über Web-Server, die nach außen auch sichtbar sein sollen, also sprich die durch Loadbalancer oder ähnliche Kontrollgruppen von meinem Container Cluster zum Beispiel nach außen durchlässig sind. Ich habe natürlich auch innerhalb meiner verschiedenen zum Beispiel Container, die ich für meinen Micro Service brauche, auch noch mein Netzwerk Traffic, der aber komplett weg gekapselt von der Außenwelt ist. Wo nochmal eigene Port bindings dann innerhalb funktionieren und notwendig sind.

[00:03:35.810] – Maurice
Genau. Also, ich glaube, das muss man sich so vorstellen: Man hat diese Landkarte von den Diensten, die öffnen ihre Ports, um untereinander zu kommunizieren. Aber nur ganz wenige kommunizieren wirklich mit der Außenwelt oder dem Internet. Nämlich die, die dann noch mal hinter einer gesonderten Firewall oder hinter einem Loadbalancer sitzen und die halt auch nur für die Web Request zuständig sind. Aber die ganzen Suchen, Bild Transformationen, Daten Transformationen. Die sprechen zwar auch über Ports miteinander, diese Services. Aber das geschieht halt alles im Hintergrund.

[00:04:05.750] – Oliver
Genau. Und auch die Anbindung an ausgelagerte Services, wie wenn man sich an die Episode vom letzten Mal erinnert, die Datenbank zum Beispiel. Oder externe Persistenzschichten. Auch die Kommunikation über Ports ist eben weggekapselt von der Öffentlichkeit. Damit ich da nicht über HTTP Request direkt an meine Datenstruktur im Backend komme, damit man sowas eben nicht ausnutzen kann.

[00:04:29.090] – Maurice
Ich finde es immer ganz erstaunlich, da steht ja dann so eine Landschaft von Micro Services, die alle untereinander sprechen können und man kann die sehr dynamisch eben über diese Ports Verbindungen miteinander verknüpfen. Und es kann durchaus auch sein, dass ein Service, der autark war, dann ein Backing Service von einem weiteren Service wird. Also zum Beispiel ein Service, der ein Bild croppt oder Bilder bearbeitet und der für sich funktioniert mit einem Bild könnte dann ein Backing Service werden für eine Fotobuch Applikation, die eben viele, viele Bilder croppen muss und also beschneiden muss und die Farben vielleicht verbessern, indem man einfach mehrfach aufgerufen wird und an der Anwendung müsste dafür nichts geändert werden. Es müsste nur eine Anwendung davor vorgestellt werden, die mehrere Bilder verwalten kann.

[00:05:17.690] – Oliver
Ja absolut. Wenn man das mit mit Programmier-Paradigmen vergleichen will, ist das vergleichbar mit objektorientierte Programmierung. Ich erzeuge mir quasi diesen Service, der Bildbearbeitung macht. Den kann ich in mehreren Instanzen theoretisch aufrufen. Und ich kann auch Applikationen haben, die den dann wiederrum selber benutzen. Ich kann das wirklich alles schön klein und kompakt halten, deswegen heißt es am Ende ja auch Microservice.

[00:05:41.650] – Maurice
Wie Legosteine die zusammengesteckt werden.

[00:05:45.320] – Oliver
Ja, zum Beispiel.

[00:05:46.180] – Maurice
Genau, und die ganzen Requests, das sollte man vielleicht auch noch sagen, die werden halt im Cluster selber. Können Sie eben mit Kubernetes Loadbalancern oder weiteren Routing Services im Grunde wie bei einem Hardware Router können halt dann auch diese Requests geoutet werden. Man ist dann sehr flexibel.

[00:06:03.070] – Oliver
Genau. In einer Cloud Umgebung würde dieser Service dann vom Provider zur Verfügung gestellt werden, weil dann ja alle initialen Anfragen der User gegen diesen Loadbalancer vor der Cloud quasi laufen müssen und der würde dann eben den Traffic in mein persönliches, weggekapseltes Netzwerk rein führen. Genau.

[00:06:23.490] – Maurice
Das stimmt. Das ist eine sehr elegante Methode mit den Ports und auch Betriebssystem übergreifend. Also alle modernen Betriebssysteme können natürlich Netzwerk Ports öffnen und verwalten, von daher ein sehr verbreiteter Standard. Kommen wir zum achten Punkt, der Nebenläufigkeit, Englisch Concurrency. Das ist ein ganz heißes Thema nicht nur für 12 Factor Apps, sondern generell für die ganzen Cloud Umgebungen und das DevOps Entwicklungsmodell. Hier geht es nämlich um die Skalierbarkeit einer Anwendung.

[00:06:58.120] – Oliver
Das ist wirklich heiß, weil das ist das weshalb man in die Cloud geht. Vielleicht. Möglicherweise ist das der primäre Grund, damit ich eben nicht mir Wochen oder Monate im Voraus überlegen muss. Wieviel Hardware brauche ich, die dann erst noch installiert werden muss, sondern ich kann das innerhalb kürzester Zeit alles hoch und runterfahren, wie ich es brauche. Und vielleicht kann meine Anwendung das sogar von selber kontrollieren, wenn ich das irgendwie realisieren kann. Und da gibt es durchaus viele Möglichkeiten, das zu tun.

[00:07:28.580] – Maurice
Genau. Die Anwendung muss etwas anders entwickelt werden, damit es in der Cloud. Damit man diese… Von diesem Benefit profitieren kann. Aber wenn ich das getan habe, dann macht es für eine Anwendung wenig Unterschied, ob es 10 Requests pro Sekunde sind oder 10000 Requests pro Sekunde. Also auch bei hoch lãst Szenarien ist man da relativ safe. Wie erreichen 12 Faktur Apps oder wie? Wie kann man das schaffen? 12 Faktor Apps achten darauf, dass die einzelnen Arbeitsschritte, man könnte auch Requests dazu sagen, in parallelen Prozessen und Threads durchgeführt werden können und keine Abhängigkeiten zueinander haben. Wir haben ja schon in der ersten, im ersten Teil gesagt, dass Prozesse dem Share-nothing Ansatz folgen. Das heißt, dass sie nicht aufeinander warten müssen, weil es keine Abhängigkeiten gibt. Jetzt kann man sich vorstellen, wenn ein Bild hochgeladen wird auf einem Server könnten natürlich auch 100 Bilder parallel hochgeladen werden, auf 100 Servern. Wenn man dieses Paradigma einhält, funktioniert das ganz genauso. Und da kommt dann diese Elastizität einer Cloud Anwendung her. Meistens gibt es noch eine Aufteilung. Es gibt die kurzlebigen Requests. Also ein Nutzer ruft eine Website auf, speichert ein Bild ab und es gibt die langlebigen Hintergrund Prozesse also clean up Jobs, Migrationsjobs. Die meisten zyklisch laufen und zu gewissen Zeiten angestoßen werden und die sehr, sehr lange laufen.

[00:08:53.440] – Oliver
Und du hast eben den Rückverweis auf das share-nothing Prinzip gemacht. Das ist hier, das sollten wir auch nochmal betonen: wirklich wichtig. Wenn ich einen stateful Prozess habe, der angefragt wird, ist das natürlich für die Parallelisierbarkeit gerne mal einen Bottle-Neck, den ich nicht umgehen kann. Man kann natürlich hochgradig parallel aus der Datenbank lesen, aber in die Datenbank rein, schreiben parallel, das ist dann eben schwierig bis unmöglich. Und da muss man dann eben aufpassen, wie man seine Anwendung entwickelt bzw. wie man eben diese Persistenzschichten gestaltet, damit diese Sachen möglich sind, die man gerne hätte.

[00:09:33.100] – Maurice
Genau das meine ich mit Programmier-Paradigma. Also das Kern-Leistungsversprechen der Cloud ist ja in Niedriglast Zeiten zahlst du nur für einen Server oder für zwei Server, weil du wenig Last hast. Jetzt ist dein Produkt super erfolgreich. Du hast Fernsehwerbung geschaltet zum Beispiel hast eine Last-Spitze: dann fährt das System automatisch zu den zwei Servern noch 48 weitere hoch. Du hast jetzt 50 Server, aber eben nur für eine halbe Stunde oder Stunde für den Zeitraum, in dem die Last anfällt. Und dann baut sich diese Überkapazität wieder ab und du landest wieder bei deinen 2 Servern, die du immer hast, sodass du quasi sehr elastisch deine Anwendung skalieren kannst, ohne das du physikalisch irgendwas bestellen müsstest.

[00:10:15.550] – Oliver
Und das Beispiel… Wir haben es jetzt an Requests erläutert. Das kann man auch, als Grundlage für die Skalierbarkeit, auf physische Ressourcen ausdehnen. Also zum Beispiel CPU Last oder konsumierter Arbeitsspeicher als Grundlage dafür, wann eine App mehr Instanzen erzeugt, weil mehr nötig sind. Oder eben wieder zurückgebaut, weil sie nicht mehr gebraucht werden? Ich kann da ganz kurz ein Beispiel aus meiner unmittelbaren Vergangenheit einbringen: ich habe ja schon bei der Airflow Episode unseres Podcasts einen Beitrag geleistet, und ich habe als eines der letzten Projekte eine Airflow Installation in Kubernetes aufgesetzt. Und da haben wir dann die Möglichkeit mit eingebaut, dass das Kubernetes eigene Horizintal Pod Autoscaling funktioniert, sodass automatisch mehr Airflow Worker, also die theoretisch Server, die die Last der ausgeführten Prozesse tragen, erzeugt werden können wenn z.B. die User sehr rechenintensive Anwendungen gerne laufen lassen, sei es ein Spark Job, der unglaublich viel Memory braucht. Dann können andere Leute nichts mehr machen, und das merkt das System und erzeugt dann neue Instanzen von Airflow Workern, die, wenn dann weniger Last auf dem Gesamtsystem ist, auch wieder abgebaut werden. Das kann man eben mit CPU oder eben auch eigens konzipierten Metriken zum Vermessen von Last auch ganz anders gestalten.

[00:11:42.650] – Maurice
Man ist da sehr flexibel. Das stimmt. Also ist auf jeden Fall nicht alle 12 Faktoren würde ich vielleicht gleich gewichten von der Wichtigkeit. Aber eine Anwendung, die neben Häufigkeit unterstützt, das sollte auf jeden Fall hohe Priorität haben. Einfach um den Scale out zu ermöglichen. Also was heißt scale out? Es gibt den Scale out und das Scale up Prinzip Scale out bedeutet: Ich habe einen Standard Server und stelle dem jetzt noch vier weitere Server, die identisch sind, an die Seite oder 10 oder 20. Also ich nehme die gleiche Hardware und stelle nebeneinander horizontal mehrere Geräte, die exakt gleich sind, auf. Durch diese Parallel-Verteilung erreiche ich dann eine Lastverteilung. Das wäre der Scale out. Scale up wäre: ich habe drei Standard Server, und die Last steigt. Und jetzt beginne ich, diese Standard Server aufzurüsten mehr CPUs, mehr Arbeitsspeicher, mehr SSD Platz und so weiter. Aber der Scale up funktioniert nur bis zu einem gewissen Grad, und dann wird es sehr, sehr teuer. Irgendwann gibt es einfach nicht den einen Server mehr, der die Last der Anwendung verarbeiten kann oder ist extrem teuer. Man denkt an Supercomputer, die nur von Universitäten betrieben werden können, oder Regierungsinstitutionen, die immense Kosten verursachen. Das wären Scale up Maschinen oder das Scale up Prinzip. Aber man möchte natürlich das Scale out sich zunutze machen. Günstige Standard Hardware, Server Grade STANDARD Hardware nebeneinander stellen, um endlos seitlich mal zu skalieren.

[00:13:13.850] – Oliver
Und das ist dann natürlich auch nochmal einfacher, wenn man bereits eine laufende aktive Anwendung hat. Es ist natürlich viel einfacher, gleichwertige Instanzen meiner Applikationen und Ressourcen Konsum oder Ressourcen insgesamt einfach zu erzeugen, als bestehende nach oben zu skalieren. Das muss in den meisten Fällen, würde das bedeuten, ich muss die Instanz abschalten und eine andere dafür hochfahren. Das heißt, ich kann das nicht, während dort Prozesse laufen, machen wenn ich feststelle, der Prozess braucht mehr Ressourcen, da bin ich an die Limitierung, die ich beim Erzeugen dieser Instanz eingegangen bin. Daran bin ich gebunden. Das heißt dieses Scale out Prinzip setzt auch voraus, dass meine meine Anfragen parallel eintreffen und ich vor allem darüber die Last habe und nicht durch einzelne Prozesse. Weil wenn der einmal gestartet ist, kann ich da auch nichts mehr dran machen.

[00:14:04.940] – Maurice
Beim Scale out kannst du dann auch Hardware leichter tauschen. Wenn was kaputt geht, ist das nicht so schlimm. Von den fünf Servern geht einer kaputt. Okay, den kann man dann ersetzen. Und dann merkt das hoffentlich keiner. Und du kannst auch Hardware Upgrades einfacher machen. Du kaufst dann immer neue Server, um die alten dann doch mal ab zu erlösen, wenn du es im eigenen Rechenzentrum machst. In der Cloud kaufst du natürlich keine neuen Server, sondern provisionierst einfach neue Server und kannst dann nach und nach die Anwendung umschwenken auf die neuen Maschinen. Der neunte der zwölf Faktoren ist die sogenannte Disposability oder zu Deutsch der Einweg-Gebrauch. Ein sperriges deutsches Wort. Was bedeutet das konkret? 12 Factor App Dienste oder die Prozesse dieser Dienste sind disposable. Das heißt, sie sind für den Einweg Gebrauch gemacht und können gestartet und gestoppt werden zu einem beliebigen Zeitpunkt. Wir haben uns dieses Beispiel vor Augen geführt. Wir haben zwei Server: Jetzt haben wir ein Last-Szenario. Das skaliert auf 50 Server. Wir fangen die Last ab, und irgendwann haben wir wieder die normale Ausgangslage. Das heißt, diese 50 Maschinen werden nach und nach abgebaut, bis wir wieder bei den zwei Servern der Ausgangssituation sind. Das heißt, es sind in der Zwischenzeit viele Prozesse gestartet worden. Beim Scale Out. Und als wir dann später wieder zurück zu den zwei Maschinen zurückgekehrt sind, sind viele Prozesse wieder gestoppt worden. Das kann man dadurch, ist deshalb kein Problem, weil wir ja den State in Backing Services halten, in Key Value Stores oder in Datenbanken. Deshalb können wir die Prozesse zügig starten und stoppen. Heißt aber auch, dass die Prozesse möglichst klein sein sollten oder die 12 Factor Apps möglichst klein sein sollten, damit die Start up Zeit eines einzelnen Prozesses minimal ist, also im Bereich von Sekunden.

[00:15:50.890] – Oliver
Je nachdem, was man da jetzt gerade betreiben will, als 12 Faktor App, um auf das Beispiel von Airflow eben zurückzukommen, kann man dem Ganzen natürlich noch eine gewisse Zeit einräumen bis die App eben terminiert wird und der Prozess wirklich beendet wird, weil zum Beispiel noch Prozesse laufen, die man nicht, ich sage mal fast böswillig terminieren will. Wenn man z.B. das Umfeld von einem Airflow Cluster hat oder einem Cluster, der mit Airflow betrieben wird, wo verschiedene User drauf arbeiten, dann möchte man nicht laufende User Prozesse killen und hart abschalten, sondern möchte denen vielleicht noch fünf Minuten Laufzeit geben. Aber dass diese Instanz der Applikation keine neuen Requests mehr annimmt, sondern wenn der Prozess durch ist, dann runterfährt. Das kann man unter Umständen dann auch ein bisschen netter designen, dass es ist nicht ganz so hart ist. Aber prinzipiell sollte es natürlich möglich sein, sofort abschalten zu können, ohne große Verluste in Kauf nehmen zu müssen.

[00:16:47.740] – Maurice
Genau. Also normalerweise würde der Prozess Manager, wenn man ihn so nennen will oder Kubernetes so bezeichnen möchte, würde sagen OK, Dienst, ich möchte dich stoppen. Dann würde das SIGTERM Signal an den Prozess gesendet werden. Dann bekommt die App eine sogenannte Grace-Period eingeräumt. Sagen wir mal 10 Sekunden. Was passiert mit der App? Die App schließt die Ports, also schließt ihren Port, nimmt keine neuen Requests mehr an. Die, die sie aber noch hat und verarbeitet, die werden noch zu Ende verarbeitet. Das Zwischenergebnis wird zu Ende verarbeitet. Irgendwann sind diese Requests aber abgearbeitet, und dann würde die App sich von selber terminieren, wenn sie disposable ist. Das wäre der nette Fall, den man anstreben sollte. Dennoch müssten oder sollten die Prozesse auch möglichst robust entwickelt werden gegenüber einem plötzlichen Kill oder wenn die Hardware kaputt geht da drunter oder sonst irgendwie jemand auf „terminate virutal Machine“ klickt, dann stirbt der Prozess natürlich sofort. Und auch das sollte keine katastrophalen ungültigen Zustände in der Datenbank hinterlassen, den man dann mühsam Debuggen muss. Und das sind die Anforderungen hier bei disposability. Ist auch im Sinne des Entwicklers und des DevOps Menschen auf jeden Fall also, wenn Prozesse höflich gestoppt werden können oder auch nicht so höflich, das beschleunigt die Entwicklung, das Testen von Konfigurationswechseln und einfach die generelle Robustheit der Anwendung auch in Produktion.

[00:18:16.000] – Oliver
Genau. Das heißt wenn ich entwickle, sollte ich darauf achten, dass Schreib Zugriffe auf Persistenzschichten im Optimalfall atomar erfolgen können. Also das ich in einem Prozess nicht viele kleine Schreibzugriffe auf z.B. eine Datenbank habe, sondern das im Optimalfall als ein Request gegen die Datenbank abfeuern kann und die das dann eben atomar wegschreibt, sodass ich keine undefinierten Zustände, die zu einzelnen Prozessen gehören, dann per Hand aufräumen muss, genau wie du es gerade gesagt hast. Ist also auch wieder eine Anforderung an die Entwicklung der App. Da muss man eventuell ein bisschen anders rangehen, als wenn man das in einem Mainframe Umfeld machen würde.

[00:18:56.510] – Maurice
Ist meiner Ansicht nach auch ein sehr wichtiger Punkt „Disposability“. Fast so wichtig wie die Nebenläufigkeit, weil es eben auf die, ja das Kernleistungsversprechen dieser schnellen Skalierbarkeit nach oben einzahlt. Und man hat schon, wenn man sich die anderen Faktoren zu Herz nimmt, so viel Vorarbeit geleistet dadurch, dass man den State in Backing Service hält, das man hier nicht mehr so viel Arbeit hat. Die Disposability sicherzustellen, einfach ein Handler schreiben, der auf SIGTERM reagiert, den Port dicht macht und die vorhandenen Transaktionen noch ausführt. Und dann.. Also es kommt natürlich auch die Komplexität der Anwendung an, aber generell sollte es nicht so kompliziert sein. Der zehnte Faktor bedeutet einfach die Vergleichbarkeit der Entwicklungsumgebung und der Produktionsumgebung. Die Angleichbarkeit / DevProd Parity. Die Entwicklungsumgebung und die Produktionsumgebung sollte sich möglichst wenig unterscheiden. Warum, ist ganz klar: Damit Fehler, die in der Produktionsumgebung auftreten können, schon möglichst früh im Entwicklungszyklus auftreten und dort behoben werden können und gar nicht die anderen Stufen durchlaufen. Ideal wäre es natürlich, wenn es gar keine Unterschiede geben würde. Aber in der Praxis Oli, das weißt du auch, man entwickelt auf einem schicken MacBook mit SQLite und in der Produktion hat man meistens eine Linux Umgebung, wo dann meist MySQL oder Maria DB oder production grade Datenbanken eingesetzt werden.

[00:20:24.010] – Oliver
Ja, das Problem kann man sich auf jeden Fall vorstellen, und wir haben ja in der ersten Episode zu dem Thema schon über Umgebungsvariablen gesprochen, dass man die Konfiguration seines Setups dahin auslagert, dass man eben auch, was die Umgebung in die meine Applikationen dann deployed, wird da schon berücksichtigt. Und dann… Das sorgt dafür, dass das auch mehr aneinander angeglichen wird, weil eben alles über die gleichen Umgebungsvariablen läuft, die nur nach System anders besetzt sind, was dann den Entwickler eigentlich gar nichts mehr angehen muss. Da funktioniert es dann automatisch richtig, und das ist, denke ich, ein ganz gutes Beispiel dafür, wie diese Annäherung der Umgebungen dann auch aussehen kann.

[00:21:06.210] – Maurice
Das Manifest der zwölf Faktoren kümmert sich oder spricht von den drei Gaps, dem sogenannten Time Gap: ein Entwickler schreibt heute Code, der erst in einigen Tagen, Wochen oder gar Monaten es in die Produktion schafft. Dann gibt es den Personal Gap oder Personell Gap: das ist der Entwickler schreibt den Code, und der Ops Engineer rollt ihn aus, oder der Systemadministrator rollt ihn aus und betreibt ihn, ist für diesen verantwortlich, dann in der Produktion. Und das dritte ist das so genannte Tools Gap: Den haben wir ja eingangs schon erwähnt, da geht es darum, dass der Entwickler beispielsweise auf OS X mit einem MacBook entwickelt, aber das Produktionssystem mit Linux bestückt ist. Und zwölf Faktoren Apps sollten eben diese drei Gaps minimieren. Also das Time Gap würde man mit Continuous Deployment reduzieren können, wenn der Code direkt getestet oder in einer automatischen Build-Pipeline getestet, paketiert, ausgerollt wird und sei es auch nur auf einem Testsystem, würde man sehr schnell Fehler bemerken und der Entwickler ist hoffentlich noch geistig dann in den Änderungen drin, die er zuletzt gemacht hat, und kann die schnell beheben. Der Personal Gap der weicht sich ja auf: also, es gibt nicht mehr den Entwickler und den Systemadministrator, und beide rangeln. Der eine baut Features, der andere will eine möglichst stabile Anwendung haben, damit sie nicht crasht und er nachts aufstehen muss. Das DevOps Mindset und Infrastructure as a Service verlagern ja schon die Verantwortung für den Betrieb der Anwendung auf den Entwickler, der das natürlich auch dann beherrschen muss und können muss. Und den Tools Gap, da zähle ich jetzt auch die Verwendung der System Variablen dazu sowie Software tools wie Docker und Kubernetes kann man auch lokal benutzen, mit Minicube vereinheitlichen und auch die Werkzeuge von der Produktions- und der Entwicklungsumgebung. Und machen diese so ähnlich wie möglich. Gleich bekommt man es natürlich nicht hin, aber sehr sehr ähnlich. Gerade Docker leistet hier gute Dienste, um nicht in unvorhergesehene Effekte zu laufen.

[00:23:03.720] – Oliver
Genau da würde ich an der Stelle kurz noch eine weitere Lanze für Docker brechen. Es ist wirklich toll. Ich habe die letzten Projekte, auch das Airflow Projekt, von dem ich erzählt habe, auf Windows Geräten entwickelt. Ich hatte zwar eine IDE, die prinzipiell in der Lage ist, überall zu laufen. Und mit dem Windows Subsystem Linux hat man ja auch eine quasi native, zum Beispiel, Ubuntu Shell auf seinem System. Aber es ist natürlich schon was anderes, wenn meine Komponenten auf einem Windows-System laufen würden. Als jetzt in dieser WSL oder auf einem Linux Server. Aber man kann natürlich durch Docker hingehen und diese Umgebung, in der das laufen soll, das Betriebssystem, was da quasi drunter liegt, das kann ich in Docker mehr alles zusammen stöpseln, wie ich möchte. Dann kann ich eben in Windows einen Docker Container betreiben, der auf einem Ubuntu oder auf einem anderen Linux flavour basiert oder auf etwas ganz anderem. Und das macht es dann eben möglich, über die ganzen normalen und gebräuchlichen Entwicklerplattformen hinweg gleiche Software zu entwickeln. Das ist wirklich toll. Da ist es dann auch egal, in welchem Gerät ich sitze.

[00:24:10.320] – Maurice
Hauptsache es ist schön schnell.

[00:24:12.930] – Oliver
Das kann nicht schaden, genau. Docker braucht dann auch Ressourcen aber mittlerweile haben ja auch viele Kunden eingesehen, dass Hardware für Software-Entwickler gut investiertes Geld ist.

[00:24:24.300] – Maurice
Ja, es ist auch so: Docker Container – das hat es ich auch in der ersten Episode zumindest angerissen, sind ja auch wesentlich schlanker als virtuelle Maschinen, die eben ein komplettes Betriebssystem hochfahren, wie das halt vor einigen Jahren oft der Fall war, dass man da seinen Entwicklungs Laptop sehr gequält hat, weil man im Grunde die Produktionsumgebung hochgefahren hat.

[00:24:43.260] – Oliver
Genau das ist eine völlig andere Hausnummer, salopp gesagt, als wenn ich mir mein Redhat System in Virtualbox nachbauen würde. Das ist überhaupt nicht vergleichbar, wenn ich es nicht ohnehin brauchen würde: ich kann natürlich auch eine komplette Linux VM vom Betriebssystem-Umfang in einem Docker Container realisieren. Aber das muss ich eben nicht.

[00:25:05.310] – Maurice
Der elfte Faktor: Da geht es um die Logs – treat Logs as event streams.

[00:25:11.790] – Maurice
Da haben wir in der Vorbereitung kurz überlegt und gedacht: Hm stimmt, das macht total Sinn, dass 12 Factor Manifest besagt, nämlich dass die 12 Faktor Apps selbst sich niemals um irgendetwas um das Login kümmern sollen, sondern alle Logausgaben plump auf Stdout raus schreiben. Also keine Logdatei schreiben, nichts verwalten, einfach alle Logs und den Logger so konfigurieren, dass alle Meldungen auf Stdout ausgegeben werden. Okay, was bedeutet das? Wenn ich lokal entwickele, sehe ich die Meldungen in meinem Terminal, weil sie einfach ausgegeben werden. Okay! Auf dem Server allerdings oder in der Produktionsumgebung werden die Log-Events auch einfach ausgegeben. Das heißt, ich brauche noch eine Instanz einer Software, die die Logs von den ganzen 12 Factor Apps einsammelt, aggregiert und persistiert und an einer sicheren Stelle weg speichert, die man dann aufsuchen kann. Macht aber total Sinn, weil Stichwort Einweggebrauch oder Disposability: die Dienste können ja gestartet, gestoppt werden zu beliebigen Zeitpunkten. Wenn sie jetzt Logfiles schreiben würden und die, die müssten ja irgendwo persistiert werden auf einem Volume, würde ja ein riesen Chaos entstehen. Also man hat im Grunde nur die Chance, dass man den Logstream rausschreibt auf Stdout und sich dann eine andere Instanz darum kümmert, diese Logs einzusammeln und entsprechend zu aggregieren und wegzuschreiben.

[00:26:40.140] – Oliver
Genau, dieses Ephemerale von meinen Pods oder von meinen Containern oder je nach Umgebung mags‘ dann nochmal anders heißen, ist eben der absolute Tod jeder Persistenz. Und ich kann es mir im Produktionsumfeld nicht erlauben, Logs zu verlieren, weshalb sich da gezielt drum gekümmert werden muss. Und da gibts dann diverseste Möglichkeiten: wenn ich eher auf der Systemadministrator Seite unterwegs bin, dann kann mir z.B. Rancher als Tool zur Verwaltung von Clustern eben wie einem Kubernetes Cluster oder auch einem Cloud Cluster in der Cloud zum Beispiel AWS oder so. Das kann mir dann sowas zur Verfügung stellen. Da kann ich Logs auch noch ein bisschen mehr History von bereits heruntergefahren Instanzen immer noch nachhalten. Ich kann sie durchsuchen und so weiter. Oder man könnte so einen klassischen Elastic Search Stack (ELK) mit Kibana und Logstash und einem Log Parser noch dafür benutzen. Da gibts diverse Möglichkeiten.

[00:27:38.900] – Maurice
Der muss dann auch sozusagen auf kritische Meldungen reagieren und wirklich Alarm schlagen, also eine SMS verschicken oder eine Push Notification dann an den zuständigen DevOps Menschen. Es gibt so OpenSource Log-Router wie Logplex, fluentd oder Splunk wird in der letzten Zeit immer verbreiteter, die genau das machen, das im Grunde von den Services die Logs einsammeln und die für spezifische Analysen weg speichern.

[00:28:06.560] – Oliver
Ich hab noch einen ganz kleinen weiteren Vorteil, es ist mir gerade eingefallen, man kann dadurch, dass ich die gesamte Log-Management nochmal weg abstrahierte, einfach aus deiner Notwendigkeit heraus, hab ich auch noch mal die Möglichkeit, das Rechtemanagement auf den Logs komplett anders zu machen, weil eigentlich sollten in solchen containerisierten Umgebungen nicht unbedingt User Accounts angelegt werden und das Rechtemanagement für die User nicht in diesen Applikationen selbst stattfinden und wenn ich das Log-Management komplett nach außen verlagert wird, dann kann ich zum Beispiel zwischen Logs-Sichtbarkeit für Systemadministratoren, für DevOps Engineers oder für die eigentlichen Softwareentwickler oder für wirkliche Nutzer nachher noch irgendwie machen, das die vielleicht nur bestimmte Informationen sehen dürfen oder sollen.

[00:28:54.860] – Maurice
Ich denke, Metriken und Dashboard sind hier auch wichtig, dass man im Operations Leitstand erkennt: alles grün oder gabs rote Events am Wochenende?Müsse wir da was angucken?

[00:29:06.200] – Oliver
Und das ist natürlich so viel einfacher, als wenn ich das über Stdout machen würde. Das wäre auch möglich aber die Gymnastik möchte man sich vielleicht doch sparen.

[00:29:14.060] – Maurice
Aber du würdest es auch nicht mitbekommen, wenn du aus den zwei Servern zu den 48 hoch skalierst und auf Server 36 fliegt ein Fehler den speichert er in sein Logfile. Aber er wird dann hinterher wieder abgebaut. Ist das Logfile weg und keiner weiß das es je ein Problem gab an dieser Stelle.

[00:29:31.410] – Oliver
Stimmt. Absolut richtig.

[00:29:33.500] – Maurice
Das geht eigentlich. Wenn man drüber nachdenkt, ist es ziemlich logisch. Geht es nur so. Der zwölfte und letzte Faktor bezieht sich auf Administrationsprozesse / Adminprocesses oder On-off Processes. Das sind Prozesse oder Jobs, die nur einmal ausgeführt werden für eine Anwendung, also beispielsweise ein Version Upgrade. Eine Datenbank Migration. Ein Job, der bestimmte Einträge in der Datenbank löscht, weil sich die rechtlichen Rahmenbedingungen geändert haben. Sowas würde mir einfallen. Was besagt das 12 Factor Manifest in diesem Fall? Es besagt, dass diese Skripte in der gleichen Umgebung ausgeführt werden wie lang laufende Prozesse, die wir angesprochen haben. Das bedeutet, dass ich das Skript mit der Anwendung mit releasen soll. Es ist quasi Teil der gleichen Codebase und nutzt, wenn es ausgeführt wird, die gleiche Konfiguration wie die Anwendung selbst, um beispielsweise auf die Datenbank zuzugreifen. Dieses Vorgehen soll eben Synchronisationsschwierigkeiten verhindern, die durch Abweichung von diesen Einmal-Skripten und der normalen App entstehen könnten.

[00:30:43.320] – Oliver
Wir reden ja immer über Dinge, die man eigentlich einmalig und vor allem manuell ausführen würde. Und wenn man das dann gegen mehrere Systeme machen möchte, ist das natürlich wieder so eine gewisse menschliche Schwachstelle, die dann unter Umständen zu Problemen führen kann oder aber auch deren Dokumentation dann eventuell nicht erfolgt.

[00:31:04.170] – Maurice
Das, denke ich, ist der Knackpunkt hier. Keiner möchte das auf der Kommandozeile, also per SSH, irgendwie ein Befehl abgesetzt wird, der die Struktur der Datenbank ändert. Kann ja richtig sein, aber dann ist es nicht versioniert.

[00:31:16.980] – Oliver
Und man kann es auch unter Umständen nicht mehr. Also nicht nur nicht versioniert, sondern man kann es auch überhaupt nicht mehr nachvollziehen und findet es einfach nicht mehr wieder. Genau. Wann ist die History meiner Command Line dann auch mal zu Ende. Und vielleicht ist die betreffende Person auch gerade nicht da und man möchte sowas eigentlich sinnvoll dokumentieren und nachhalten.

[00:31:33.900] – Maurice
Ich glaube, das ist der Punkt hier, diese Dokumentation und das Nachhalten. Man kann mit Kubernetes Befehlen ja den ganzen Kubernetes-Cluster einrichten. Das möchte man aber eigentlich nicht, sondern man möchte mit Helm Charts Pakete bauen, die eben quasi jeden frischen, Kubernetes Cluster immer in den gewünschten Zustand versetzen würden. Und damit ist es eben dokumentiert. Dadurch, dass man es durch Sourcecode beschreibt, kann es auch versioniert werden, und es ist für jeden nachvollziehbar, was da passiert ist oder welche Version da gerade aktuell ist. Ich denke, das ist hier im Grunde das gleiche Prinzip.

[00:32:06.180] – Oliver
Genau. Oder wenn man auch mal beim Stichwort Datenbank, was wir hier öfters mal als Beispiel heranziehen, ein Backup einspielen möchte. Ja, es ist was schiefgegangen, und man muss eine größere Datenmenge, die nicht über diese User getriebenen und request-basierten Service reinkommt machen, was dann meinetwegen one-liner auf der Command Line wäre, der ein riesiges JSON File in die Datenbank schreibt und sowas könnte man dann eben auch über so ein versioniertes Setup machen, wenn man das denn bei der Entwicklung berücksichtigt.

[00:32:38.080] – Maurice
Wow, das war intensiv. 12 Faktoren von Faktor Apps für Cloud Native Software Development. Wenn unsere Zuhörer eine Frage haben, können Sie gerne diese Frage oder Feedback an podcast@skillbyte.de senden. Lasst uns gerne eine fünf Sterne Bewertung da und empfehlt diesen Podcast an Freunde und Familie weiter. Wenn ihr euch für weitere spannende Technologie-Themen interessiert, schaut gerne auf skillbyte.de/blog vorbei. Oli Ich bedanke mich für deine Zeit und für die zweite Session. Es hat wahnsinnig Spaß gemacht.

[00:33:11.100] – Oliver
Ich finde es auch mal wieder cool. Und das war jetzt schon der dritte Podcast, wo ich mitwirken konnte und durfte. Ich bin gespannt. Da kommt demnächst bestimmt nochmal was, wo wir zusammenarbeiten werden.

[00:33:21.150] – Maurice
Ich bin mir da auch ganz sicher. Du hast schon eine kleine Serie gestartet hier.

[00:33:26.250] – Oliver
Wenn auch mit größerer Lücke und jetzt haben wir ja schon fast ein Jubiläumspodcast hinter uns mit Folge 30.

[00:33:32.220] – Maurice
Woah, Folge 30 unglaublich. Ich kann es noch gar nicht glauben. Vielen Dank dir Oli!

[00:33:37.830] – Oliver
Gerne Maurice. Dann bis bald!

[00:33:41.130] – Maurice
Bis bald!

Maurice KnoppSkillbyte Podcast #30: Die Zwölf Faktoren des Cloud Native Development (Teil 2)

Related Posts