Preis: 9,80 €
Erhältlich ab: August 2024
Umfang: 100
Der Schwank „Hans im Glück“ in den Kinder- und Hausmärchen der Brüder Grimm dürfte bei den meisten Leserinnen und Lesern nicht nur Assoziationen zu Fleischpflanzerln und ähnlichem hervorrufen, sondern vor allem zurück in die Kindheit führen, in der die Geschichte vom „Tauschprofi“ und schlussendlichen Antimaterialisten Hans bei nicht wenigen zur abendlichen Märchenvorlesestunde gehört haben dürfte. Wer denkt nicht gerne ans einstimmende „Es war einmal …“, bevor man nach mehr oder weniger langem elterlichen Vortrag in Morpheus‘ Armen lag?
Doch Moment mal! „Hans im Glück“ beginnt – zumindest in der Grimmschen Fassung – überhaupt nicht mit denselben drei Worten, mit denen auch (so gut wie) jeder Star-Wars-Film anfängt, sondern mit dem Eingang „Hans hatte sieben Jahre bei seinem Herrn gedient …“. Doch eher eine Vorbereitung aufs spätere Arbeitsleben? Nun ja, Märchen sind unerschöpflich und das sind und bleiben sie auch ohne „Es war einmal …“.
Der Leitartikel unserer aktuellen Ausgabe beginnt zwar auch nicht mit „Es war einmal …“, aber schon der zweite Absatz setzt mit der allseits bekannten Phrase ein. Und ein Hans tritt wenig später auch noch auf! Um ein Märchen handelt es sich beim Text unserer Leitartikler jedoch ganz und gar nicht. Obwohl es natürlich schön wäre, wenn die eine oder der andere nach der Lektüre ganz hänsisch von sich sagen könnte: „So glücklich wie ich [...], gibt es keinen Menschen unter der Sonne.“
Doch worum geht es überhaupt? Ohne viel Geschwafel und Drumherum: Es geht um Platform Engineering. Angesichts des Versprechens dieses Ansatzes, nämlich eine zentrale Plattform aufzubauen, die Entwicklern alle notwendigen Werkzeuge, Dienste und Umgebungen bereitstellt, repetitive und zeitaufwändige Aufgaben minimiert und so die Zusammenarbeit zwischen Entwicklungs- und Betriebsteams verbessert und die Produktivität steigert, dürfte für manche ein Glückszustand nicht allzu weit entfernt sein. Ob unser Held Hans dann letztendlich im Glück „landet“? Dazu und zum Thema Platform Engineering erfahren Sie mehr im Leitartikel von Michael Johann, Marcus Greuel, Christian Hartung und Thomas Ganter und im korrespondierenden Schwerpunktartikel der vier Autoren über Spotify Backstage.
Ich bin mir sicher, dass auch die Artikel, Serienteile und Kolumnen abseits unseres aktuellen Schwerpunkts dazu beitragen werden, Sie (etwas) glücklicher zu machen und will deswegen dem Start der Lektüre nicht länger im Wege stehen – möge dieselbe wie immer erkenntnisreich und fruchtbar sein!
Marius Nied
Redakteur Java Magazin
Vielerorts hört und liest man den provokanten Satz: „DevOps is dead“. Dabei ist diese Behauptung nicht nur falsch, sondern will eigentlich nur die Aufmerksamkeit auf einen gegenwärtigen Trend, das Platform Engineering, lenken. In diesem Artikel beleuchten wir die aktuellen Probleme von DevOps und Entwickler:innen und unternehmen den Versuch, Platform Engineering als Lösungsweg zu beschreiben.
Es waren einmal … Entwickler:innen, die Businessfunktionalität entwickelten, und Systemoperator:innen, die die Software auslieferten. Dabei betrug die Zeitspanne von der Übergabe der „fertigen“ Software bis zur Auslieferung eines Release für die Anwender:innen oft mehrere Monate. Häufig definierten IT-Organisationen sogar zwei Hauptreleases pro Jahr sowie geplante Bugfix-Releases hier und da zwischendurch. Aus Anwendersicht war das mitunter unbefriedigend und zudem undenkbar bei Applikationen auf Basis von Software as a Service (SaaS). Zu spät kamen neue Features und Fehlerbereinigungen.
Aus Entwicklersicht bedeutete das eine hohe Parallelität von mehreren Dev-, Test-, Bugfix- und Releaseversionen. Aus Betriebssicht wiederum brachte diese Komplexität lange Bugfix-Zyklen und damit einhergehend Workaround- und „Frickel“-Lösungen sowie eine starke Bürokratisierung.
Zudem bestimmten Systemoperatoren maßgeblich, wie die Artefakte anzuliefern waren, was nicht immer die notwendige Flexibilität unterstützt und Innovationen oft behindert hat.
Mit der Etablierung von DevOps-Prinzipien in IT-Projekten gehörten diese starren Prozesse der Vergangenheit an, und heute stellt jeder Commit ein potenzielles Release dar. Continuous Delivery lautet die Devise. Entwickler:innen sind viel näher am Betrieb als früher. Das Motto lautet: „Entwickle es, wie du willst, wenn du es auch ausrollen kannst“. Damit genießen Entwickler:innen mehr Freiheiten bei der Auswahl von Programmiersprachen und Frameworks, solange sie die spezifischen Anforderungen von Deployment und Betrieb ebenfalls berücksichtigen und unterstützen.
So kommt es, dass es einen riesigen Wildwuchs an Sprachen, Frameworks und Tools gibt und das nicht nur zur Entwicklung von Software, sondern auch zum Betrieb von Anwendungen. Docker, Chef, Ansible, Terraform, Nix usw. sind im Umfeld von Infrastructure as Code längst keine Exoten mehr. Sie sorgen für reproduzierbare Laufzeitumgebungen und helfen beim „Verpacken“ von Applikationen. Mit dem Aufkommen von Docker und Containern wurde das Bereitstellen von Anwendungen in einheitlicher Form stark vereinfacht und das Ausrollen von Cloud-nativen Anwendungen und Services hat seinen Höhepunkt mit der Nutzung von Kubernetes gefunden.
Doch was bedeutet das für den Alltag von DevOps-Mitarbeiterinnen und Mitarbeitern? Grob gesagt, beschäftigen sich Entwickler:innen heutzutage zu einem Großteil der zur Verfügung stehenden Zeit nicht mehr mit der Softwareentwicklung an sich, sondern vielmehr mit der Bereitstellung von Infrastruktur und Querschnittfunktionalitäten wie Monitoring, Logging, Alerting etc.
Zur Verdeutlichung soll folgende Geschichte helfen:
Hans ist Softwareentwickler in einem großen Unternehmen. Dort gibt es Hunderte von Entwickler:innen, die sich mittlerweile immer mehr von der Rolle der Softwareentwicklerin oder des Softwareentwicklers entfernen und zum DevOps Engineer werden. Neben all den Meetings im agilen Umfeld kommen so immer mehr Aufgaben aus dem Operations-Bereich hinzu, und so stellt Hans fest, dass er eigentlich nur noch zu 20 Prozent mit der Entwicklung von Geschäftsfunktionalität beschäftigt ist. Der Rest der Zeit ist für Operations und Infrastruktur notwendig. Die Geschäftsführung hat vor einigen Jahren entschieden, dass sämtliche Altanwendungen cloudifiziert werden und in Zukunft in Amazon AWS laufen sollen. Hans hat sich nicht nur während der Arbeitszeit mit dem Erlernen der AWS-spezifischen Dienste beschäftigt, sondern auch in seiner Freizeit und ist mächtig stolz, dass er nun Anwendungen und Services in der Cloud ausrollen und betreiben kann. Andere Mitarbeiter:innen wollen und sollen das natürlich auch tun, und so wird mehr und mehr in die Weiterbildung investiert. Einheitliche Prozesse zum Roll-out gibt es allerdings dadurch noch nicht, und so entwickeln einige Teams Frameworks und Werkzeuge, um sich den Arbeitsalltag leichter zu machen und produktiver im Umgang mit Cloud-Diensten zu werden.
Inzwischen haben konkurrierende Cloud-Dienstleister wie Microsoft Azure und Google Cloud Platform teilweise für spezielle Anwendungen besser geeignete und oft preisgünstigere Dienste im Angebot, und die Geschäftsführung hat die Idee, dass man eine Multi-Cloud-Strategie fahren sollte. Je nach Anwendungsfall soll so möglichst an den Betriebskosten gespart werden. Blöd nur, wenn man rein auf AWS-spezifische Dienste gesetzt und keine Abstraktionen für Datenbankdienste, Dateiservices und andere Infrastrukturdienste entwickelt oder genutzt hat. Wer sich auf Kubernetes spezialisiert hat, kann seine Dienste unabhängig vom Hyperscaler deployen, nutzt kluge Abstraktionen und kann außerdem auf viele Informationen aus der Community zurückgreifen.
Die folgende Beschreibung ist an einen Produktservice angelehnt, und vielleicht erkennt der oder die eine oder andere geneigte Leser:in Teile dieses Beispiels aus dem eigenen Umfeld wieder. Falls dem so ist, lohnt sich das Weiterlesen in jedem Fall. Falls nicht? Trotzdem weiterlesen.
Ein paar Jahre später kommt Hans in eine Abteilung, die neue Entwickler:innen beim Onboarding unterstützen soll. Inzwischen gibt es für die vielen verschiedenen Cloud-Anbieter eigene Portale, um die DevOps-Leute nicht zu sehr alleinzulassen. Jedoch sieht der Onboarding-Prozess für neue Teams und Projekte inzwischen etwa wie folgt aus: Ein Team will einen Microservice auf Basis von Spring Boot entwickeln und in eine Produktionsumgebung ausrollen. Schön, dass man sich immerhin schon auf die Programmiersprache und entsprechende Frameworks einigen konnte. Jetzt kommen erst mal weitere Aufgaben auf das Team zu, bevor überhaupt eine Zeile Software entwickelt werden kann. Gerade wenn neue Teammitglieder hinzukommen, ist erst einmal unklar, wie hier weiter verfahren werden muss. Woher bekomme ich meine Accounts für AWS, GCP, Azure etc.? Wer ist Ansprechpartner für Securityfragen? Brauche ich eine Betriebsratsfreigabe? Welche Anforderungen zur Compliance gibt es? Nutzen wir Jira und brauchen wir für das Projekt entsprechende Zugänge bzw. Projektstrukturen? Okay, wir nutzen Git als Versionsverwaltung. Aber nehme ich da jetzt GitLab oder GitHub und in welche Unterstrukturen packen wir unseren Quellcode und unsere Artefakte? Gut, wir wissen, dass wir Cloud-nativ ausrollen wollen. Welche Container-Registry sollen wir da nehmen? Hat das Unternehmen eigene Standards? Welche Unterstrukturen für Container-Repositories müssen wir berücksichtigen?
Und wie ist das eigentlich bei den Pipelines zum automatisierten Build, Test und Deployment? Gibt es Vorgaben, welche Securityscans gemacht werden müssen? Wer kann mir das sagen? Wollen wir unseren eigenen Kubernetes-Cluster aufbauen und managen? Oder gibt es Teams im Unternehmen, die so etwas bereitstellen? Welche Kostenstellen müssen wir denn für all das angeben? Wie stellen wir während der Laufzeit die Compliance sicher, nachdem wir die Anwendung ausgerollt haben? Und was ist mit Observability, mit Monitoring, Logging und Tracing?
An dieser Stelle soll die Liste der Fragen ausreichen, um zu verdeutlichen, wie komplex ein Vorhaben noch vor der ersten Zeile Code aussehen kann. Wer all diese Fragen auch für zukünftige Projekte beantworten will, muss immer auf dem Laufenden sein und sich mit einer ganzen Menge Themen beschäftigen, die mit der eigentlichen Entwicklung, beispielsweise eines Produkt-Services, nicht mehr viel zu tun haben.
Abb. 1: Die Tool-Landschaft der CNCF
DevOps trat einst mit „Tools“ als eine der Kernsäulen an. Von „Werkzeugkästen“ war die Rede und das funktionierte gut, solange die Anzahl der zu beherrschenden Tools überschaubar blieb. Wer heute einmal einen Blick auf die Toollandkarte der Cloud Native Computing Foundation (CNCF) wirft, wird geradezu erschlagen (Abb. 1). Von Werkzeugkästen mit einer Handvoll Werkzeugen kann schon lange keine Rede mehr sein (vielleicht sogar noch nie). Wir haben Ökosysteme von Werkzeugen und das bedeutet, dass ein Softwareentwicklungsteam, das DevOps ernst nimmt und alle Wertschöpfungsschritte seiner Software abbilden möchte, um seine Software ganzheitlich bereitzustellen und zu betreiben, vor der Herausforderung einer immensen Anzahl an Werkzeugmöglichkeiten steht.
Natürlich kann man als Team versuchen, automatisch immer auf die De-facto-Standards zu setzen; für den Wildwuchs an Werkzeugen über das eigene Team hinaus kann der Ansatz jedoch keine Abhilfe schaffen. Gerade ist man zum Toolspezialisten ausgebildet, da ändert sich der Standard, werden andere oder neue Werkzeugfunktionalitäten gebraucht oder ein Open-Source-Projekt wird eingestellt. Regelmäßig tauchen neue Werkzeuge auf der Landkarte auf (was prinzipiell natürlich begrüßenswert ist, aber für die hier beschriebene Problematik immer größeren Lösungsbedarf aufweist). Jedes Team verwendet seinen eigenen Toolstack, und Teamwechsel in flexiblen Organisationen, in denen Projekteinsätze regelmäßiger stattfinden, führen zu Frustration, da das automatisch mit erneutem Erlernen anderer Werkzeuge einhergeht, die in den meisten Fällen nichts anderes tun als die alten. Kein:e Entwickler:in kann und will Spezialist:in in all diesen diversen sich überschneidenden Werkzeugen oder Diensten sein.
Dieser Wust an zusätzlichem Know-how und dessen Notwendigkeit wird in der Praxis auch als Cognitive Load oder bei zu viel davon auch als Cognitive Overload bezeichnet. Aus Unternehmenssicht ist das definitiv nicht die optimale Situation. Entwickler:innen sind üblicherweise viel mehr daran interessiert, Code zu schreiben, als sich mit Ticket-Ops, Chat-Ops oder E-Mail-Ops zu beschäftigen. Man kann sich leicht vorstellen, dass das Abschätzen von Sprints und Backlogs in so einem Umfeld einfach zu ungenau wird und nur wenigen Beteiligten Spaß macht.
Unternehmen und deren Teams versuchen bereits seit geraumer Zeit die oben gestellten typischen Fragen mit eigenen Orderportalen, Funktionsmailboxen, Ticketsystemen und Trainings zu beantworten, wobei mit immer mehr neuen Themen (z. B. künstliche Intelligenz) auch immer wieder neue strategische Wege beschritten werden, bevor andere Themen grundlegend geklärt werden konnten.
Platform Engineering soll hier endlich für Klarheit sorgen und viele Probleme lösen. Anstelle unzähliger Einstiegsportale und Ansprechpartner soll durch sinnvolle Abstraktionen und entsprechende Control Planes der Cognitive Load der DevOps-Mitarbeiter:innen signifikant reduziert werden. Ziel ist es, mit Hilfe von Self-Services und integrierten Views die Produktivität zu steigern, während bei der Softwareentwicklung der Spaß wieder an vorderer Stelle stehen soll.
Zunächst ist es wichtig, dass Best Practices und „goldene“ Pfade dafür identifiziert werden, wie effiziente Entwicklung funktionieren kann. Goldene Pfade können gut und gerne 80 Prozent der Anwendungsfälle der breiten Masse abdecken, um maximale Skalierungseffekte zu erreichen – und schon kommt die Frage nach Individuallösungen. Der hier beschriebene Ansatz unterstützt beides, weil jedes Team Dienste entwickeln und bereitstellen kann. Je individueller ein benötigter Dienst ist, umso weniger wahrscheinlich existiert er schon als von einem Spezialistenteam bereitgestellter Service, und umso eher muss der Dienst individuell implementiert werden, womit letztlich weniger Support aus der Inner-Source-Community kommt. Sprich: Die Individuallösung ist aufwendiger und das ist normal und okay, aber ebenso machbar und lohnenswert wie die Anwendungsfälle, die die Masse abdecken.
Zurück zu unserem Beispiel: Hans und sein Team sollen also einen Produkt-Service entwickeln. Idealerweise bietet das Unternehmen eine Internal Developer Platform (IDP) an, die alle Aktivitäten des kompletten Application Lifecycle unterstützt. Eine IDP ist ein zentralisiertes System innerhalb des Platform Engineerings, das darauf abzielt, Entwickler:innen die notwendigen Werkzeuge, Dienste und Automatisierungen bereitzustellen, um die Effizienz und Produktivität im Softwareentwicklungsprozess zu steigern. Sie fungiert als eine Abstraktionsschicht über der Infrastruktur und ermöglicht Entwickler:innen den einfachen Zugang zu Ressourcen, ohne tiefgehendes Wissen über die zugrunde liegende Infrastruktur zu benötigen. Eine IDP umfasst typischerweise Funktionen wie Developer Self-Services, kontinuierliche Integration und Bereitstellung (CI/CD), Infrastructure as Code (IaC), Monitoring, Logging, Tracing, Sicherheitsmechanismen sowie im besten Falle auch die Abrechnung von Kosten.
Abb. 2: Backstage als Einstieg in den Katalog
Hans setzt sich also an den Rechner und öffnet das Developer-Portal der IDP, um dort mit Hilfe eines Scaffolders ein Template für einen typischen Microservice auf Basis von Spring Boot zu erstellen. Beispiele für solche Developer-Portale sind Backstage [1] und Port [2]. Dort gibt Hans einige Parameter wie den Projektnamen, das zugehörige Team und die verwendeten Frameworks an. Der Scaffolder wandelt das zugehörige Template in ein Git-Projekt um, das von der Control Plane automatisch mit allen Konventionen zur Erstellung von Unterstrukturen in GitLab/GitHub generiert und entsprechend für das Team mit den jeweiligen Rollen angelegt wird. Damit ist Hans von den weiteren Aspekten wie Monitoring, Pipelines, Container-Images, Laufzeitumgebungen, Securitymaßnahmen usw. weitgehend befreit, da die IDP all diese Punkte abstrahiert und von seinem Team fernhält. Die Control Plane nimmt die gewünschten Parameter für das Projekt aus dem Developer-Portal entgegen und generiert alle Bestandteile selbstständig und stellt sie bereit. Dafür ist das Wissen der Platform Engineers in die Plattform eingeflossen, womit Hans und sein Team dieses Wissen nicht mehr im Detail benötigen. Somit bleibt automatisch mehr Zeit für die eigentliche Entwicklung des Produkt-Service.
Braucht der Produkt-Service eine Datenbank, wird diese automatisch provisioniert. Genauso verhält es sich mit dem Monitoring, den Container-Images und Logging-Schnittstellen bis hin zur Kostenverrechnung im internen Gebrauch. Die Platform Engineers der IDP haben sämtliche Konventionen und Best Practices im Unternehmen in Managed Services implementiert und entsprechend innerhalb der Control Plane abstrahiert und miteinander synchronisiert, sodass am Ende Hans und sein Team eine Nachricht erhalten, dass alle benötigten Funktionalitäten bereitstehen. Zur Erinnerung: Vorher mussten Dutzende von Kolleg:innen und Bestellportale identifiziert und aufgesucht werden, um in einem zeitraubenden Prozess alle benötigten Dienste zusammenzutragen. Dazu kam noch das breite Wissen zur Erstellung der Infrastruktur, die der Service benötigt.
Nach erfolgreichem Ablauf des Scaffoldings im Developer-Portal stehen nun ein Git-Repository, Pipelines, Container-Images, eine Laufzeitumgebung und weitere nicht funktionale Dienste wie Logging, Monitoring, Tracing und Compliance-Checks zur Verfügung. Im Developer-Portal wird das durch eine kumulierte Sicht unterschiedlicher Datenquellen visualisiert, sodass Hans und sein Team nur noch einen Browsertab im Developer-Portal benötigen, um sich über den aktuellen Stand des Projekts zu informieren und bei eventuellen Problemen zur Laufzeit handlungsfähig zu sein.
Durch die beschriebene Broker-Architektur wird zudem Konkurrenz unter den Dienstanbietern gefördert, was aus Unternehmenssicht durchaus gewünscht sein kann. Viele genutzte Dienste könnten so über die „natürliche Auslese“ aus Anwendersicht mit der Zeit stark verbessert werden, während abhängig von der Nutzung auch eher „exotischere“ Dienste bestehen bleiben, obwohl sie nicht dem goldenen Pfad entstammen, sondern vielleicht ein spezielles Compliance-Problem lösen.
Das sieht auf den ersten Blick zu schön aus, um wahr zu sein. Oder? Aber genauso kann jedes Unternehmen zukünftig Platform Engineering nutzen und damit die Produktivität im Unternehmen steigern und enorme Kosteneinsparungen erzielen. Fragen Sie einmal Ihre Teamkolleg:innen, ob sie schon mal bei einem Cloud-Anbieter Ressourcen zu Testzwecken erstellt haben. Wer dies bejaht, sollte gleich danach die Frage beantworten, ob diese Ressourcen auch wieder gelöscht wurden. Nur wenige werden das getan haben. Man kann sich schnell grob ausmalen, wie viel Geld so verschwendet wird. Platform Engineering kann ebenso wie das Erstellen von Ressourcen auch das Löschen übernehmen. Somit wird auf einfache Weise ein Lebenszyklus für Ressourcen verwendet.
Abb. 3: Managed Services als Kubernetes APIs
Die Autoren haben über ein Jahr damit verbracht, von der Vision über Prototypen bis zur aktuell festgelegten produktionstauglichen sowie skalier- und wartbaren Architektur eine solche Internal Developer Platform inklusive einer offenen Architektur zu entwickeln. Wie diese Architektur aussieht, beschreiben die folgenden Absätze.
Zunächst war die Idee, dass ein Team von Platform Engineers sämtliche zu integrierende Dienste abstrahiert und dann in der IDP bereitstellt. Das war allerdings mit zahlreichen Problemen behaftet. Hier ist primär der personelle Aufwand zu nennen. Ein doch eher kleines Team hätte sich intensiver Planung, Implementierung und Integration sämtlicher Dienste im Unternehmen widmen müssen. Bei einer IDP geht es primär nicht darum, neue Dienste zu entwickeln, sondern bestehende Dienste zu abstrahieren und dann in die Plattform zu integrieren. Bei Hunderten von Diensten ist das für ein kleines Team nicht zu leisten.
Ein weiteres Problem ist, dass nicht jedes Teammitglied über das tiefgreifende Know-how verfügt, das von den anderen Teams aufgebaut wurde, als die Dienste entwickelt wurden. Allein die Frage, wie sich komplexe dedizierte Kubernetes-Cluster provisionieren lassen, ist nicht einfach zu beantworten. Proprietäre Technologien und Konzepte hätten überdies dazu geführt, dass für weitere Mitarbeiter:innen im Platform Engineering mehr Weiterbildung nötig geworden wäre, sprich Spezialwissen, das nur für das eigene Unternehmen aufgebaut und genutzt werden müsste.
Nun gibt es für die Abstrahierung von Diensten Frameworks wie Crossplane [3], die es ermöglichen, die Provisionierung von Diensten zu abstrahieren, aber auch hier ist das kleine Platform-Team nicht in der Lage, alle notwendigen Dienste zu kapseln und an die Plattform anzubinden. Eine weitere Idee war es, eine eigene Domain Specific Language (DSL) auf Basis von YAML zu entwickeln, die gleichzeitig proprietär ist und zudem von anderen Entwicklern erst einmal erlernt werden müsste. Alles in allem ein Einsatz, der Zweifel an der Umsetzung aufkommen lässt und zum Nachdenken anregt.
So haben sich die Autoren intensiv mit dem Gedanken auseinandergesetzt, dass für die Vermeidung eines Vendor-Lock-ins, also der Bindung an einen Hersteller, wie beispielsweise Amazon AWS oder Microsoft Azure, bereits eine Abstraktionsebene existiert, die zudem noch von einer riesigen Community unterstützt wird: Kubernetes [4]. Kubernetes wird bei dieser Idee, wie auch von Crossplane, als generisches API verwendet und kann zudem im Vergleich zu klassischen REST APIs viel mehr. Beispielsweise ist das von Kubernetes bereitgestellte Reconciling beim Nutzen von Pods auch beim allgemeinen API-Handling, wie beispielsweise Retries, bei fehlgeschlagenen API-Aufrufen nutzbar. Zusätzlich kann die Kubernetes-Architektur sehr einfach erweitert werden, um neue Ressourcen bereitzustellen.
Unsere Operatortechnik ermöglicht im Gegensatz zu Crossplane nicht nur eine Flussrichtung. Crossplane synchronisiert Ressourcen von Kubernetes nach extern, egal ob in Richtung Amazon AWS oder GitLab. Aber es kann über einen Workaround auch von Kubernetes nach Kubernetes eingesetzt werden. Von GitLab nach Kubernetes wird es schon deutlich schwieriger. Crossplane kann dennoch genutzt werden, beispielsweise von unseren Service-Providern, denen wir eben nicht vorschreiben müssen, wie sie ihren Service implementieren sollen.
Die Autoren verwenden gern den Vergleich mit der Uber-Plattform für Fahrdienstleistungen, um die Sicht auf die IDP zu visualisieren. Dabei wird Uber als reiner Broker von Fahrdienstleistungen betrachtet. Für die Anbieter von Transportfahrten werden Mehrwertdienste wie Abrechnung, Vermittlung und Bewertungen sowie Marketing von Uber bereitgestellt. Bei der IDP, die von den Autoren konzipiert wurde, verhält es sich ähnlich. Das IDP-Team stellt einen Broker für Kubernetes-API-basierte Ressourcen bereit, der Mehrwerte zu den eigentlichen Diensten bietet.
Anbieter von sogenannten Managed Services können die Plattform nutzen, um ihre Dienste für andere Entwickler:innen bereitzustellen. Dabei werden Zusatzdienste wie Orchestrierung, interne Verrechnung und Kostenmanagement sowie die Visualisierung im Developer-Portal von der IDP zur Verfügung gestellt. Der Vorteil für die Service-Anbieter ist, dass diese ihre Dienste lediglich als Kuberntes Custom Resources (CR) bereitstellen müssen. Hierzu wird üblicherweise eine Custom Resource Definition (CRD), eine YAML-Datei mit einer Open-API-Spezifikation erstellt und von einem Controller und Operator implementiert, die die Fachlogik kapseln. Näheres hierzu unter [5]. Hauptaugenmerk ist hier, dass Dienste, die als Kubernetes-Ressourcen implementiert werden, unabhängig von einer IDP betrieben werden können, da sie lediglich dem Kubernetes-Standard entsprechen müssen. Die Notwendigkeit proprietärer Konzepte fällt damit weg. Das wiederum stärkt die Akzeptanz im Unternehmen und bei den Entwickler:innen, denn sie müssen keinesfalls proprietäres Wissen aufbauen, sondern können sich wie bei allen Kubernetes-APIs an die offenen Standards halten.
Teams, die ihre Dienste als Kubernetes-Ressourcen bereitstellen, profitieren auch davon, dass sie keine eigenen Bestellportale mehr umsetzen und pflegen müssen, da diese von der IDP im Portal generisch visualisiert werden können. Somit sind mehr Kapazitäten zur Optimierung bestehender Funktionalitäten und zur Entwicklung neuer Features vorhanden. Alle in der IDP registrierten Dienste können über das einheitliche Portal bestellt werden.
Kommen wir nun aber wieder mehr zur Architektur. Es werden im Prinzip grob drei Ebenen unterschieden:
Developer Plane
Control Plane
Managed Services
Als Developer Plane bezeichnen wir alle Aufgaben, die durch eine Weboberfläche gesteuert an die Control Plane weitergegeben werden. Das ist die Verwaltung von Ressourcen, bereitgestellt durch die Managed Services, sowie das Scaffolding/Order-Processing. In unserem Beispiel wird das sehr populäre Backstage verwendet.
Backstage ist ein Open-Source-Projekt, das ursprünglich von Spotify entwickelt wurde. Es spielt eine zentrale Rolle bei der Implementierung und Verwaltung einer IDP. Es dient als Entwicklerportal und ermöglicht es Teams, ihre Entwicklungsprozesse, Tools und Dienstleistungen zu konsolidieren und zu verwalten. Die wichtigsten Rollen von Backstage in Bezug auf eine IDP umfassen:
Zentralisierung und Standardisierung: Backstage bietet eine einheitliche Benutzeroberfläche, über die Entwickler:innen auf verschiedene Tools, Dienste und Dokumentationen zugreifen können. Das fördert die Standardisierung und vereinfacht die Nutzung und Verwaltung von Entwicklungsressourcen. Implementiert wird Backstage auf Basis von TypeScript und dem React Framework sowie Material UI.
Plug-in-Architektur: Mit seiner modularen Plug-in-Architektur ermöglicht Backstage die Integration verschiedener Tools und Dienste, die Entwickler:innen im Alltag nutzen. Das umfasst CI/CD Pipelines, Monitoring-Tools, Cloud-Dienste und vieles mehr. Diese Daten werden von der Control Plane bereitgestellt und Backstage nutzt sie zur Visualisierung.
Developer Experience: Backstage verbessert die Developer Experience durch eine intuitive Benutzeroberfläche und leicht zugängliche Informationen. Entwickler:innen können schnell auf benötigte Ressourcen zugreifen, Projekte erstellen und verwalten sowie Deployments durchführen.
Katalogisierung und Discovery: Backstage bietet einen Service-Katalog, in dem alle internen Dienste und Komponenten katalogisiert sind. Das erleichtert das Auffinden und Wiederverwenden vorhandener Services und fördert die Zusammenarbeit zwischen Teams.
Automatisierung und Self-Service: Backstage unterstützt die Automatisierung wiederkehrender Aufgaben und bietet Self-Service-Funktionen, sodass Entwickler:innen ohne die Unterstützung von Infrastruktur- oder DevOps-Teams arbeiten können. Das beschleunigt den Entwicklungszyklus und erhöht die Produktivität.
Dokumentation: Mit dem TechDocs-Plug-in kann eine zentrale Dokumentation aufgebaut werden. Dabei lassen sich pro Ressource im Katalog Dokumentationen pflegen, die dann global durchsucht werden können.
Wird ein Template von der Benutzerin oder dem Benutzer ausgefüllt und abgeschickt, sorgt eine entsprechende Action dafür, dass in der Control Plane weitere Aktionen ausgeführt und die gewünschten Ressourcen angelegt werden.
Abb. 4: Control Planes sind der Kern der IDP
Die eigentliche zentrale Control Plane sorgt für die Orchestrierung der gewünschten Dienste. Dabei ist die Spezifikation von Kubernetes APIs die Basis für alles. Die Control Plane selbst ist dabei eine Sammlung von Kubernetes APIs, die Mehrwertdienste für die Anbieter von Managed Services bereitstellt. Kernbestandteile der Control Plane sind Core APIs und Provider, die wiederum Kubernetes APIs sind.
Sogenannte Consumer können die angebotenen APIs der Provider nutzen. Jeder Provider, der im Grunde seine Managed Services als Kubernetes APIs anbietet, bekommt seine eigene Control Plane, was die Skalierbarkeit wesentlich vereinfacht. Die zentrale Control Plane dient damit im Wesentlichen als Broker für die Vermittlung von Diensten.
Die Provider werden von den Teams entwickelt und bereitgestellt, die auch die Managed Services bereitstellen. Praktisch betrachtet implementieren die Provider-Teams dann Kubernetes APIs anstelle von Rest APIs. Sollte ein Provider weitere Dienste integrieren wollen oder müssen, so lassen sich diese einfach konsumieren, womit komplexere Dienste auf Basis von atomaren Diensten entwickelt werden können.
Beim Onboarding neuer Dienste können die Teams über einen Self-Service im Developer-Portal selbst die notwendigen Schritte zur Registrierung vornehmen. Im Anschluss wird eine Kubeconfig geliefert, mit der die Provider ihre APIs bereitstellen und entsprechend andere Dienste abonnieren können.
Die Provider betreiben ihre eigenen Managed Services nach wie vor selbst und tauschen für einen funktionierenden Betrieb wiederum eine Kubeconfig mit der IDP aus. Die IDP kopiert dann die Custom Resource Definitions des Providers in die zentrale Control Plane. Somit besteht eine bidirektionale Kommunikation zwischen der IDP und der Control Plane des Providers.
Zugegeben, das liest sich alles relativ kompliziert. In der Implementierung ist das aber sehr schlank und geht mit einiger Routine zügig von der Hand. Wie erwähnt, ist ein Vorteil, dass die implementierten Kubernetes APIs/Provider auch unabhängig von einer IDP eingesetzt werden können.
Ein weiterer Dienst, der für die Entwickler:innen bereitgestellt wird, ist eine komplette Entwicklungsumgebung auf Basis von Coder [6]. Dabei handelt es sich im Wesentlichen um eine browserbasierte Umgebung mit Visual Studio Code sowie einem Terminal. Die gesamte Konfiguration der Workspaces, die ähnlich wie die GitHub Codespaces funktionieren, wird dabei durch eine Nix-Konfiguration [7] erreicht. Somit kann das Onboarding interner und externer Projektmitarbeiter:innen schnell und sicher erfolgen und der Einstieg in ein Projekt wesentlich beschleunigt werden.
Im aktuellen Stadium der IDP geht es darum, ein Minimum Viable Product (MVP) zu implementieren, das die IDP und das Developer-Portal bereitstellt. Dann werden etwa ein Dutzend Managed Services in die IDP integriert und für die Entwickler:innen zur Verfügung gestellt. Das Ganze soll dann organisch wachsen. Dabei müssen die Provider-Teams vom Kern-Plattform-Team mit Know-how und Best Practices versorgt werden. Grundsätzlich ist man gut beraten, die Umsetzung einer IDP wie bei einem kommerziellen Produkt zu betreiben. Also inklusive Marketing, Vertrieb und Communitypflege. Und nicht zuletzt auch mit entsprechenden Budgets.
Während der Forschungsphase hat es sich sehr bewährt, immer offen und proaktiv über alles, was aktuell „in der Mache“ ist, zu berichten. Die Autoren haben hierzu nicht nur intern die Werbetrommel gerührt und eine Roadshow veranstaltet. Auch externe Partner und Unternehmen wurden zur Diskussion über die Architektur eingeladen. Es ist geplant, die Architektur und die Komponenten der IDP Open Source zur Verfügung zu stellen, denn wir sehen hier das Potenzial, diesmal der Community etwas zurückzugeben. Auch andere Unternehmen machen sich nahezu die gleichen Gedanken, sodass am Ende vielleicht eine Community entsteht, die sich mit der konkreten Umsetzung mittels Kubernetes APIs identifiziert und weiter ausbaut. Die Leserschaft dieses Artikels ist somit aufgerufen, mit den Autoren in Kontakt zu treten.
[1] Backstage: https://backstage.io
[2] Port: https://getport.io
[3] Crossplane: https://crossplane.io
[4] Kubernetes: https://kubernetes.io
[5] Custom Resource Definitions: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/
[6] Coder: https://coder.com
[7] Nix: https://nixos.org, https://nix.dev
Im Bereich des Platform Engineering sind Developer-Portale ein zentraler Baustein, um die Effizienz und Produktivität im Unternehmen zu verbessern. Der Musikstreamingdienst Spotify hat das sehr früh erkannt und mit Backstage eine eigene Entwicklung an die Cloud Native Computing Foundation (CNCF) übergeben. Grund genug, sich einmal näher mit den Features des Frameworks zu befassen.
In der modernen Softwareentwicklung stehen Unternehmen vor der Herausforderung, ihre Entwicklungsprozesse effizient und skalierbar zu gestalten. Backstage, ursprünglich als internes Tool bei Spotify entwickelt und jetzt als Open-Source-Projekt verfügbar, bietet eine umfassende Lösung für diese Anforderungen. Backstage zentralisiert die Verwaltung von Softwareprojekten, erleichtert die Zusammenarbeit und steigert die Produktivität von Entwicklerteams. In diesem Artikel geben wir eine kurze Einführung in das Framework, beleuchten die Hauptfunktionen und zeigen, wie Plug-ins verwendet und Templates erstellt werden können, um die individuellen Bedürfnisse von Unternehmen und Benutzer:innen zu erfüllen.
Wer den ebenfalls in dieser Ausgabe erschienenen Artikel zum Platform Engineering gelesen hat, weiß bereits, dass Backstage als Bestandteil einer Internal Developer Platform (IDP) die Funktion eines Developer-Portals abdeckt.
Das Framework wurde entwickelt, um Entwicklerteams bei der Verwaltung und Organisation ihrer Projekte zu unterstützen. Seine Hauptmerkmale umfassen die zentrale Dokumentation, einen Service-Katalog, Unterstützung für Plug-ins und Softwaretemplates sowie die nahtlose Integration mit DevOps-Tools. Diese Funktionen tragen dazu bei, die Effizienz zu steigern und die Komplexität der Softwareentwicklung zu abstrahieren und vereinfacht darzustellen. Backstage fördert eine einheitliche und transparente Arbeitsweise, die es Teams ermöglicht, sich auf das Wesentliche zu konzentrieren: die Entwicklung hochqualitativer Software.
Die technologische Basis von Backstage sind TypeScript als Sprache und React mit MaterialUI für die Visualisierung. Aus unserer Sicht ist Backstage ein Framework für Plug-ins, das bereits seit einigen Jahren weiterentwickelt wird und hin und wieder neue Architekturansätze eingeführt hat, um beispielsweise die Integration verschiedenster Tools und deren Daten einfacher zu machen.
Sein Ziel ist es, dass Entwicklerinnen und Entwickler nur noch einen einzigen Browsertab brauchen, um sich in der internen IT-Landschaft eines Unternehmens zurechtzufinden und damit zielsicher durch einen sonst recht undurchsichtigen Dschungel an Informationen in Dutzenden verteilten Tools zu navigieren.
Im Folgenden stellen wir die Kernbestandteile und Konzepte vor.
Wir zeigen einige Beispiele dafür, wie mit Backstage ein Developer-Portal aufgebaut werden kann. Hierzu ist die Erstellung einer Instanz von Backstage die Grundlage. Empfohlen wird Node.js 18 oder 20:
npx @backstage/create-app@latest
yarn dev
Abb. 1: Die initial erstellte Instanz von Backstage
Das soll nur einen kleinen Eindruck davon vermitteln, wie eine neue Instanz erzeugt wird. Der eine oder die andere Lesende wird schnell erkennen, dass es sich hier wie bei React-Apps üblich um einen kleinen Generator handelt. Für weitergehende Instruktionen verweisen wir auf die Dokumentation [1].
Backstage wird regelmäßig aktualisiert, und das Team stellt stets eine ausführliche Dokumentation dazu bereit, was an welcher Stelle wie geändert werden muss, um ein Update zu implementieren. Aus unserer Erfahrung lohnt es sich definitiv, hier am Ball zu bleiben und nicht allzu lange mit dem Update der eigenen Codebasis zu warten. Neben Securitypatches werden zudem oft Breaking Changes ausgeliefert, die es mitunter etwas aufwendiger machen, die Code-Base anzupassen. Wenn das nur ab und an passiert, kann man schnell den Überblick verlieren. Eigene Plug-ins wurden bisher relativ aufwendig in den Code von Backstage integriert, aber nach einem radikalen Schnitt der Architektur wurde eine sehr große Vereinfachung zur Integration veröffentlicht. Das erleichterte das Handling von Plug-ins und der entsprechenden Backend-Systeme sehr. Meist kann man zuvor geschriebenen Code im Nachhinein auf einige wenige Zeilen reduzieren oder komplett entfernen.
Die zentrale Dokumentation ist ein Kernelement von Backstage und spielt eine entscheidende Rolle bei der Verbesserung der Effizienz von Entwicklerteams. Durch die Bündelung aller Dokumentationen an einem Ort können sie schnell und einfach auf die benötigten Informationen zugreifen, seien es technische Spezifikationen, API-Dokumentationen oder interne Richtlinien. Diese zentrale Verwaltung fördert nicht nur die Produktivität, sondern auch die Konsistenz und Qualität der Dokumentation, was wiederum die Zusammenarbeit und das Wissensmanagement innerhalb des Teams verbessert.
Hier ein Beispiel: Stellen Sie sich vor, ein Unternehmen hat mehrere Entwicklerteams, die an verschiedenen Projekten arbeiten. Jedes Team erstellt Dokumentationen für seine Projekte, jedoch sind sie oft über verschiedene Systeme verstreut und schwer zugänglich. Das führt zu Informationsverlust, ineffizientem Arbeiten und Schwierigkeiten bei der Zusammenarbeit. Mit Backstage kann das Unternehmen alle Dokumentationen zentralisieren und den Zugang zu diesen Informationen vereinfachen. Es können problemlos neue Dokumentationsseiten erstellt werden, die verschiedene Formate wie Markdown oder HTML umfassen. Diese Seiten lassen sich nach Projekten, Teams oder anderen Kriterien organisieren, was eine logische und leicht navigierbare Struktur schafft.
Backstage ermöglicht auch die Integration von Dokumentationen aus verschiedenen Quellen. Entwickler:innen können Dokumentationen aus Repositorys wie GitHub, Gitlab oder Bitbucket importieren, wobei Änderungen automatisch synchronisiert werden, um sicherzustellen, dass die Dokumentationen stets aktuell sind.
Die Plattform bietet verschiedene Plug-ins, die die Verwaltung und Darstellung von Dokumentationen erleichtern. Ein Beispiel ist das TechDocs-Plug-in, das speziell für technische Dokumentationen entwickelt wurde. Zudem verfügt Backstage über eine leistungsstarke Suchfunktion, die es ermöglicht, schnell die benötigten Informationen zu finden. Die Suchfunktion kann auf alle Dokumentationen zugreifen und relevante Ergebnisse anzeigen, unabhängig davon, in welchem Projekt oder Repository sie sich befinden. Weitere Plug-ins können ebenfalls in die Suche integriert werden. Beispielsweise können so Beiträge aus Stack Overflow in Suchergebnisse einfließen.
Der Catalog ist ein zentrales Element von Backstage, das die Verwaltung von und Übersicht über Softwarekomponenten, APIs, Bibliotheken und anderen Ressourcen innerhalb eines Unternehmens erleichtert. Er ermöglicht eine strukturierte und einheitliche Darstellung aller relevanten Informationen und bietet einen umfassenden Überblick über die vorhandenen Ressourcen. Seine Hauptmerkmale sind:
Zentrale Verwaltung: Der Katalog dient als zentraler Ort, an dem alle Softwarekomponenten und -ressourcen des Unternehmens aufgelistet und verwaltet werden. Das erleichtert die Auffindbarkeit und Nutzung bestehender Komponenten, APIs, Projekte etc.
Kategorisierung und Tagging: Komponenten können nach verschiedenen Kriterien wie Projekt, Team, Typ und Status kategorisiert werden. Das ermöglicht eine gezielte Suche und Filterung von Ressourcen sowie eine übersichtliche Darstellung.
Visuelle Darstellung: Der Katalog bietet eine benutzerfreundliche Oberfläche, die eine visuelle Darstellung der Komponenten und ihrer Abhängigkeiten ermöglicht. So wird das Verständnis der Gesamtarchitektur verbessert und die Navigation durch die Ressourcen erleichtert. Anpassungen der Darstellung lassen sich oft sehr schnell umsetzen, da der gesamte Quellcode von Backstage verfügbar ist.
Automatisierung und Synchronisierung: Durch die Verwendung von catalog-info.yaml-Dateien können Informationen zu den Komponenten automatisch synchronisiert und aktuell gehalten werden. So lassen sich beispielsweise innerhalb einer Control Plane in einer Internal Developer Platform komplexe Informationen in entsprechenden catalog-info.yaml-Dateien zusammenführen und von Backstage einlesen. Die catalog-info.yaml dient als zentrale Konfigurationsdatei, die die Metadaten und Spezifikationen einer Softwarekomponente definiert, mit Relationen anreichert und den Katalog navigierbar macht.
Um Daten aus Gitlab/GitHub in den Backstage Catalog zu synchronisieren, wird die catalog-info.yaml-Datei direkt in Gitlab-Repositorys abgelegt. Über die Integration von Backstage mit Gitlab kann das Framework periodisch bestimmte Quell-Repositorys nach diesen Dateien scannen und in die eigene Datenbank aufnehmen.
Abb. 2: Der Catalog Service von Backstage
Der Katalog ist wiederum aufgeteilt in Kategorien von Komponenten, APIs etc. Wer mit dem internen Katalog und seinen Entitäten nicht zufrieden ist, kann die Liste von Entitäten durch Plug-ins oder eigene Entity-Provider und Entity-Prozessoren erweitern. Dafür ist es allerdings immer notwendig, Quellcode zu schreiben, um Backstage zu erweitern. Neue Entitäten erfordern eine neue Version der eigenen Backstage-Instanz. Aus diesem Grund hat sich das Autorenteam überlegt, eigene Plug-ins zu entwickeln, die es erlauben, Backstage dynamisch mit neuen Entities, Providern und Prozessoren zu versorgen. Dabei gibt es einen Endpoint in Backstage, der die neuen Entitäten als CRDs im YAML-Format entgegennimmt und in einer Datenbank ablegt. Per Reflection wird dann jede neue Entität nach Validierung zu einer Catalog-Komponente gemacht und entsprechend verarbeitet.
Abb. 3: Der Overview zu einer Entität
In den letzten Absätzen war schon mehrfach von Plug-ins die Rede. Zeit, näher darauf einzugehen. Plug-ins sind ein zentraler Bestandteil von Backstage und erweitern die Funktionalität der Plattform, indem sie spezifische Bedürfnisse und Anforderungen von Entwicklerteams erfüllen.
Die meisten Kernfunktionen wurden ebenfalls in internen Plug-ins implementiert. Damit lassen sich fast alle APIs von Backstage auch in eigenen Plug-ins wiederverwenden.
Backstage-Plug-ins sind modular aufgebaut und basieren auf einer Architektur, die es ermöglicht, unabhängige und wiederverwendbare Komponenten zu erstellen. Jedes Plug-in besteht typischerweise aus den folgenden Elementen:
API-Definitionen: APIs, die das Plug-in bereitstellt oder konsumiert
UI-Komponenten: Benutzeroberflächenkomponenten, die in Backstage eingebettet werden
Backend-Komponenten: serverseitige Logik, die vom Plug-in benötigt wird
Backstage bietet verschiedene vorgefertigte Plug-ins, die direkt genutzt werden können. Zu den populärsten gehören das TechDocs-Plug-in für Dokumentationen, das Lighthouse-Plug-in für Performanceaudits und das Kubernetes-Plug-in für die Integration von Kubernetes-Clustern. Alle sind sofort einsatzbereit und können durch einfache Konfigurationen angepasst werden.
Unternehmen können eigene Plug-ins entwickeln, um spezifische Anforderungen zu erfüllen, oder bestehende Plug-ins anpassen. Das ermöglicht eine flexible und skalierbare Nutzung von Backstage.
In der Praxis haben sich diverse Plug-ins als nützlich erwiesen, um das Potenzial von Backstage in einem Proof of Concept zu evaluieren und weiteren Entscheidern zu präsentieren. Diese Plug-ins sind neben zahlreichen anderen im Plug-in-Katalog auf der Homepage von Backstage zu finden [2].
Plug-in-Name |
Zweck |
---|---|
GitLab |
visualisiert Pipelines, Merge Requests, Sprachen und Contributors |
Kubernetes |
Überblick zu Deployments von Projekten über die Grenzen von Clustern hinweg |
Architecture Decision Records |
Übersichtliche Darstellung von ADRs in Projekten |
Quay – Registry |
zeigt Details zu Images in der Quay-Registry inklusive Securityscans und deren Findings |
Todo – Plug-in |
listet alle TODO-Kommentare im Quellcode von Projekten auf |
Announcements |
Plug-in zur Darstellung von Bekanntmachungen im Portal |
Cost Insights |
Visualisierung von Projektkosten, die Teams betreffen |
Coder – Workspaces |
stellt fertige Workspaces als sogenannte Dev Containers bereit. |
Tabelle 1: Einige nützliche Plug-ins
Das letzte wichtige Feature von Backstage ist der Scaffolder mit seinen Templates und Actions. Templates in Backstage sind vorgefertigte Projektstrukturen, die Entwickler:innen helfen, neue Projekte schnell und konsistent aufzusetzen. Diese Templates stellen sicher, dass Best Practices und Unternehmensstandards eingehalten werden, was die Qualität und Wartbarkeit von Projekten erhöht.
Die Hauptmerkmale von Templates in Backstage sind:
Standardisierung: Templates bieten standardisierte Projektstrukturen, die sicherstellen, dass alle neuen Projekte nach denselben Vorgaben erstellt werden.
Automatisierung: Templates automatisieren den Erstellungsprozess neuer Projekte, was die Effizienz steigert und Fehler reduziert.
Konsistenz: Durch die Verwendung von Templates wird eine konsistente Struktur und Konfiguration über alle Projekte hinweg gewährleistet.
Templates werden in YAML-Dateien definiert und beinhalten die Struktur, Dateien und Konfigurationen, die für ein neues Projekt benötigt werden. Diese Templates werden in Backstage registriert und können von Entwicklern über das Backstage-Interface verwendet werden.
Das folgende Beispiel ist stark vereinfacht und erstellt keineswegs ein neues Projekt. Diese Art der Arbeit und Logik wird bei den Autoren im Team der Control Plane der Internal Developer Platform übernommen. Vielmehr nutzen wir im Beispiel die Templates als Formular zur Registrierung von neuen Benutzer:innen.
Diese können sich mittels eines Templates und unter Eingabe von Vor- und Nachname sowie einer E-Mail-Adresse im Katalog als user-entity registrieren. Zunächst wird eine Templatedatei namens user-entity-template.yaml erstellt, die die Definition der user-entity enthält.
Listing 1
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: user-entity
title: Create new user
description: An example template for the scaffolder that creates a new user
spec:
owner: backstage/idp
type: User
# Edit the template parameters below to see how they will render in the scaffolder form UI
parameters:
- title: Fill in some steps
required:
- firstName
- lastName
- email
properties:
firstName:
title: First Name
type: string
description: Your first name
lastName:
title: Last Name
type: string
description: Your last name
email:
title: E-Mail
type: string
description: Your email address like info@example.com
steps:
- id: register
name: Register User Entity
action: catalog:write
input:
entity:
apiVersion: backstage.io/v1alpha1
kind: User
metadata:
name: ${{ parameters.firstName }}-${{ parameters.lastName }}
annotations:
backstage.io/created-by: user-entity-template
spec:
profile:
displayName: ${{ parameters.firstName }} ${{ parameters.lastName }}
email: ${{ parameters.email }}
Im Wesentlichen sammelt das Template die drei Attribute firstName, lastName und Email der Benutzer:in ein und verarbeitet die Daten dann in der Sektion input im Attribut entity zu einer aus Kubernetes bekannten Manifest-Definition. Bestückt mit den Variablen gelangt dieses Manifest dann durch die Action catalog:write in das Backstage-System.
Das Template kann in einem Git-Repository abgelegt und automatisch von Backstage eingelesen werden. Danach wird es der Benutzer:in bei einem Klick auf Create… angezeigt und kann genutzt werden.
Abb. 4: Das Template im Browser
Backstage ist ein mächtiges Framework für die Erstellung von Developer-Portalen im Bereich des Platform Engineering. Die Mischung aus TypeScript und React bietet die notwendige Flexibilität, um einheitliche Oberflächen auch mit Hilfe von Plug-ins zu realisieren. Ein bedeutender Nachteil ist, dass neue Funktionalität immer in Code gegossen werden muss. Schön wäre eine Möglichkeit, dynamisch neue Entity-Typen ins System zu integrieren, wie das beispielsweise Port [3] anbietet. Allerdings bietet Backstage eine riesige Community, eine passable Dokumentation, ist zudem Open Source und lässt sich selbst hosten.
[1] Backstage-Dokumentation: https://backstage.io/docs/getting-started/
[2] Plug-in-Katalog: https://backstage.io/Plug-ins
[3] Port: https://getport.io
Java Core | New-Relic-Report
Wer populäre Technologien einsetzt, bekommt im Problemfall schneller Hilfe und hat auch bei der Entwicklerrekrutierung weniger Probleme. Die aktuelle Ausgabe des von dem SaaS-Anbieter New Relic veröffentlichten Status-quo-Reports zeigt, wie es um das Java-Ökosystem steht.
Der New-Relic-Report [1] speist sich überwiegend aus Daten, die das Unternehmen aus den hauseigenen Observability-Systemen erhält. Wir stellen die Ergebnisse vor und gehen kurz auf die Besonderheiten verschiedener GC-Algorithmen ein. Bei der Bewertung der Daten ist zu beachten, dass die Informationen auf im Einsatz befindlichen Systemen beruhen – Prototypen und nur auf der Workstation eines Entwicklers lebende Programme werden nur selten mit New Relic verbunden.
Oracles Entscheidung, die Auslieferung neuer Java-Releases zu beschleunigen, wirkt sich auf das gesamte Ökosystem aus. Java 21 war aufgrund der Inklusion diverser Preview-Technologien ein besonders interessantes Release, das rasch angenommen wurde. Genauer: Nach der Auslieferung wurden binnen sechs Monaten 1,4 Prozent der überwachten Applikationen umgestellt – die Vorgängervariante Java 17 erreichte in der entsprechenden Zeitspanne nur eine Umstellung von 0,37 Prozent.
Relevant ist auch, dass Nicht-LTS-Versionen in den Ergebnissen von New Relic eine untergeordnete Rolle spielen: Weniger als 2 Prozent der untersuchten Programme nutzen sie produktiv.
Mindestens ebenso relevant ist die Frage, welches JDK beziehungsweise welche Runtime zur Ausführung verwendet wird – Oracle hat in der Vergangenheit durch eigenwillige lizenzpolitische Entscheidungen einiges an Goodwill verspielt, was sich in den Zahlen widerspiegelt (Abb. 1).
Abb. 1: Das Wachstum anderer Anbieter erfolgt fast ausschließlich auf Oracles Kosten (Bildquelle: [1])
Der Höhenflug von Amazon war dabei von kurzer Dauer, mittlerweile liegt der Großteil des Wachstums im Bereich des von der Eclipse Foundation verwalteten Adoptium. Azul Systems ist mehr oder weniger konstant, auch Red Hat und BellSoft erfreuen sich einer loyalen Nutzerschaft. SAP und Ubuntu konnten ihre (minimalen) Mindshare-Anteile indes nicht wirklich halten.
Neue Designparadigmen wie Serverless und Microservices wurden von der Java-Community schnellstmöglich umgesetzt bzw. angenommen. Das geht mit interessanten Veränderungen hinsichtlich des Ressourcenbedarfs der individuellen Komponenten eines Systems einher.
Erstens hat sich der Trend zum Multi-Threading reduziert: Mit 68 Prozent entfällt der Löwenanteil der von New Relic überwachten Systeme auf Anwendungen, die einen bis vier Prozessorkerne verwenden. Die Nutzung von fünf bis acht Kernen stagniert, während noch stärker parallelisierte Anwendungen wie in Tabelle 1 gezeigt mehr oder weniger konstant bleiben. Andererseits kann es sich dabei auch um eine Konsolidierung handeln, da die Pro-Kern-Rechenleistung (in eingeschränktem Rahmen) weiter gestiegen ist.
Kernzahl |
2023 [%] |
2024 [%] |
---|---|---|
Kernzahl |
2023 [%] |
2024 [%] |
1 bis 4 |
57,7 |
68.0 |
5 bis 8 |
25 |
14.8 |
9 bis 16 |
8,2 |
9.8 |
17 bis 32 |
4,1 |
3.6 |
33 bis 64 |
3,0 |
2.8 |
Mehr als 64 |
2,0 |
1.1 |
Tabelle 1: Verfügbare logische Prozessoren nach Java-Anwendungen im Jahr 2023
Im Bereich der JVM-Speicherzuweisungen setzt sich dieser Trend dagegen nicht fort. Sehr kleine VMs sind nach wie vor sehr beliebt, während sehr große Speicherbereiche eine (eher geringe) Schrumpfung zeigen. Der Gutteil der Systeme kommt indes mit weniger als 2 GB aus, was die im Markt vorherrschende Meinung von Java als Speicherfresser relativiert.
Insbesondere im Embedded-Bereich wird Java wegen der durch den Garbage Collector (GC) systemimmanenten „Denkpausen“ kritisiert. Die diversen JVM-Anbieter begegnen diesem Problem seit einiger Zeit durch neuartige GC-Algorithmen, die insbesondere auf mehrkernigen Systemen die Minderung der Probleme ermöglichen (Abb. 2). Zu berücksichtigen ist dabei, dass die verschiedenen VMs unterschiedliche Standardeinstellungen mitbringen – die Umstellung von Java 11 auf G1 und der damit einhergehende Zuwachs an darauf basierenden Systemen belegt, dass viele Installationen nach dem Prinzip „defaults are fine“ agieren.
Abb. 2: Garbage Collectors, die von Java-LTS-Versionen genutzt werden (Bildquelle: [1])
Der Rückgang im Bereich des Klassikers Serial ist im Zusammenhang mit der oben besprochenen Änderung an der Konstruktion der Systeme interessant – er hält das Gesamtsystem an, ist aber auf ressourcenbeschränkten Systemen am effizientesten.
Im Fall von G1 gilt aufgrund des Aufräumens kleiner Speicherbereiche, dass das System insbesondere auf nebenläufigen Maschinen für weniger Ärger sorgt. Der Garbage Collector kann seine Stärken vor allem dann ausspielen, wenn die JVM mehr als 4 GB Speicher zugewiesen hat. Die feinere Unterteilung macht die Aufräumprozesse effizienter.
Die älteren Verfahren Parallel und CMS spielen in Java 17 und Java 21 keine nennenswerte Rolle mehr. Der von Oracle in Java 17 neu eingeführte ZGC hat – das dürfte sowohl der geringen Verbreitung der ihn implementierenden VMs als auch der Neuartigkeit geschuldet sein – bisher nur eine sehr geringe Verbreitung in praktischen Deployments erreicht. Seine Nutzung ist indes insbesondere für Systeme relevant, die „weiche“ Echtzeitkriterien erfüllen müssen. Gemäß den unter [2] beschriebenen Maßnahmen gilt nämlich, dass das Verfahren – je nach Literaturquelle – eine Worst-Case-Pausenzeit von einer oder zehn Millisekunden garantiert. Das mag sogar für manche Smart-Home-Anwendung ausreichen.
Die Verfügbarkeit von Modularisierungssystemen wie Maven oder die in Gradle integrierte Artefaktverwaltung animieren Entwickler dazu, Komponenten aus dem Ökosystem zur Erfüllung der anstehenden Aufgaben heranzuziehen.
Die erste in diesem Zusammenhang wichtige Frage betrifft die Art der Datenspeicherung: Schon aus dem Enterprise-Fokus folgt, dass Java-Applikationen häufig mit Datenbankservern aller Sorten interagieren. Die Herkunft von Java aus dem Sun- bzw. Oracle-Umfeld spiegelt sich in einer klaren Marktdominanz der Oracle Database wider, die in fast 20 Prozent der von New Relic überwachten Java-Applikationen zum Einsatz kommt (Tabelle 2).
Datenbank |
Nutzerschaft [%] |
---|---|
Oracle Database |
17,3 |
PostgreSQL |
14,4 |
MySQL |
12,5 |
MongoDB |
7,4 |
DynamoDB |
4,9 |
SQL Server |
4,4 |
Cassandra |
2,7 |
Elasticsearch |
2,5 |
MariaDB |
1,4 |
Redshift |
0,3 |
Tabelle 2: Die beliebtesten Datenbankserver [1]
Dabei dominieren klassische, auf SQL basierende Datenbanken: Werden die Anteile der drei Bestplatzierten addiert, erhält man einen Gesamtwert von 44,2 Prozent. An vierter Stelle folgt MongoDB; Java-Datenbanken wie die Graphdatenbank Neu4J sind überhaupt nicht auf den Rangplätzen anzutreffen.
Ein weiteres Thema betrifft den Verbreitungsgrad der Kryptographienutzung: Aus den von New Relic erhobenen Zahlen lässt sich ableiten, dass 41 Prozent der überwachten Applikationen auf die ein oder andere Weise auf eine Kryptographiebibliothek zurückgreifen. Das muss aber nicht unbedingt durch eine explizite Willensäußerung des Entwicklerteams bedingt sein, es ist genauso gut vorstellbar, dass die Bibliothek als Dependency einer anderen Bibliothek Eingang in die Build-Artefaktliste findet.
Jedenfalls zeigt die Verteilung der verwendeten Bibliotheken nur wenig Überraschendes (Abb. 3). Der erste Platz geht an den Klassiker Bouncy Castle, während die in diversen Spring-Frameworks inkludierte Spring Security den zweiten Platz einnimmt.
Abb. 3: Meistgenutzte Verschlüsselungsbibliotheken für Java-Anwendungen (Bildquelle: [1])
In seinem Report weist New Relic darauf hin, dass man ein baldiges deutliches Wachstum von Amazon Corretto erwartet. Ursache dafür ist demnach erstens die Vereinheitlichung der Software-Supply-Chain und zweitens die im Allgemeinen sehr gute Performance der diversen von Amazon implementierten Algorithmen.
Eine weitere im Report gestellte Frage betrifft die Art, wie Java-Applikationen Logging-Informationen sammeln. SLF4J wird dabei von 83 Prozent der Entwickler benutzt und damit ein Framework, das wie in Abbildung 4 schematisch dargestellt als Abstraktionsschicht zwischen der Applikation und dem jeweiligen Logging-Framework fungiert und zu einer Steigerung der Flexibilität beiträgt.
Abb. 4: SLF4J abstrahiert zwischen Applikationscode und dem jeweiligen Logging-Framework
Neben diesem genutzten Shortcut gilt, dass sich Log4j nach wie vor als absoluter Platzhirsch im Bereich der Logging-Frameworks etabliert hat: In 76,4 Prozent der von New Relic überwachten Applikationen findet sich eine Abhängigkeit auf diesen Universallogger. An zweiter Stelle steht JBoss (Abb. 5).
Abb. 5: Die beliebtesten Logging-Frameworks (Bildquelle: [1])
Dass die Anzahl der im Entwicklerfragedienst Stack Overflow zu bestimmten Technologien sichtbaren Interaktionen eine gute Benchmark für die Popularität der jeweiligen Technologie darstellt, soll in den folgenden Schritten als gegeben angenommen werden. Im Hause NewRelic bietet man mit GenAI seit einiger Zeit etwas Vergleichbares an, das auf Java-Entwickler fokussiert ist. Abbildung 6 zeigt, wie sich die Anfragen an diese KI über die verschiedenen Kategorien verteilen. Unter Learning versteht man dabei im Hause New Relic dabei nicht Machine Learning. Vielmehr handelt es sich um Fragen, die man auch als „How to“-Questions bezeichnen würde.
Abb. 6: Entwicklerfragen an die New-Relic-KI nach Themen (Bildquelle: [1])
Die von New Relic erhobenen Informationen geben Entwicklern und Nutzern einen Überblick über den Zustand der Java-Entwicklung als Ganzes. Die rasche Annahme neuer Technologien zeigt, dass Sorgen um das Ableben der Java-Entwicklung gelinde gesagt vollkommen übertrieben sind.
Im ersten Teil der Artikelserie ging es um Architekturtotalschäden. Im vorliegenden zweiten Teil wird ein weiterer Totalschaden, aber auch kleinere Pannen vorgestellt. Doch können Unfälle auch vermieden werden. Durch die Bildung von Architekturcommunitys können Risiken und Fehlentwicklungen erkannt und abgewendet werden.
Unfälle in der Softwarearchitektur passieren. Im ersten Teil der Serie haben wir Unfälle in der Serverentwicklung angesehen. Aber auch in der Frontend-Entwicklung kommen sie vor. Blinder Glaube an Richtlinien und Vorgaben kann ebenfalls zu Unfällen führen, obwohl die Regeln doch genau das verhindern sollen. Idealerweise werden Unfälle natürlich vermieden, einen Ansatz dafür sehen wir uns am Schluss an.
Benutzerfreundliche Oberflächen sind heute wichtiger denn je. Benutzer müssen auch durch komplexe Oberflächen geleitet werden, sodass sie schnell und unkompliziert ihr Ziel erreichen können. Angestrebt wird, dass Benutzerprozesse nicht vorzeitig abgebrochen werden und dass es zu Vertragsabschlüssen kommt.
Das folgende Beispiel stammt aus der Versicherungsbranche, kann aber so oder ähnlich in allen Branchen auftreten – die Erstellung einer TAA-Strecke (Abb. 1). TAA steht hierbei für „Tarifierung – Angebot – Antrag“.
Abb. 1: TAA-Strecke einer Versicherung
Im ersten Schritt wählt der Benutzer ein Produkt, z. B. eine Gebäudeversicherung. Anschließend werden in der Tarifierung aufgrund von persönlichen Angaben des Interessenten Tarife berechnet. Die Angaben können von der Größe der Wohnung für eine Hausratversicherung bis hin zu Gesundheitsdaten für eine Kranken- oder Lebensversicherung reichen. Sie können sehr umfangreich werden. Denken Sie z. B. an die Angaben für eine Gebäudeversicherung für ein denkmalgeschütztes Haus. Zusätzlich kann das Produkt auch Unterlagen erfordern, wie z. B. Grundbuchauszüge, die der Benutzer in das System hochladen kann. Auf dieser Basis kann ein automatisches System die Risiken bewerten und dem Interessenten bestimmte Tarife anbieten. Diese können sich z. B. in der Abdeckung der Risiken oder in den Laufzeiten unterscheiden. Das meint das T in TAA.
Wählt der Benutzer nun einen Tarif, erhält er ein Angebot – das erste A in TAA. Angebote sollten gespeichert werden, um sie später auch weiter bearbeiten zu können. Möchte der Benutzer das Angebot annehmen, muss er noch weitere Angaben, insbesondere auch zu seiner Bankverbindung machen. Damit kann der Antrag – das zweite A in TAA – gestellt werden. Der Antrag wird dann in der Versicherung in der Regel automatisch geprüft und die Police erstellt.
Bei komplexen Produkten, wie sie Versicherungen darstellen können, ist es wichtig, Benutzer an die Hand zu nehmen, um Abbrüche und Nichtabschlüsse zu vermeiden. Hierzu eignen sich sogenannte Wizards (Zauberer), die den Benutzer Schritt für Schritt durch die Anwendung leiten und falsche Eingaben und unnötige Wartezeiten verhindern.
Die Lösung für diese Aufgabe liegt nahe. Sie beinhaltet den clientseitigen Wizard und einen Backend-Service, der Angebote und Anträge speichern kann. Beide können über entsprechende APIs kommunizieren. Der Kunde kann seine Eingaben für eine Tarifierung am Ende speichern. Das entspricht den Empfehlungen der MACH-Architektur (Kasten: „MACH-Architektur“), die wiederum durch die Enterprise-Architektur vorgegeben wurde.
Unter MACH-Architektur wird ein Architekturstil verstanden, der sich aus M – Microservices, A – API-first, C – Cloud-native SaaS und H – Headless zusammensetzt [1]. Microservices sind hierbei kleine Services, die eine Geschäftsfunktion oder eine Geschäftsfähigkeit wie den Abschluss eines Antrags für eine Versicherung implementieren.
API-first steht für den Entwurfsansatz, APIs zuerst zu entwerfen und danach zu implementieren, wodurch eine hohe Parallelität zwischen Client- und Serverentwicklung ermöglicht wird. Zusätzlich lässt sich die gemeinsame Sprache von Geschäftsfähigkeiten und Implementierung von Client und Server gut etablieren, da die APIs diese publizieren. Cloud-native SaaS-Lösungen sind Anwendungen, die ausschließlich über die Cloud angeboten werden und keine zusätzliche On-Premise-Installation benötigen.
Mit Headless ist ein Architekturansatz gemeint, in dem Serveranwendungen ohne zusätzliche Oberfläche (kopflos) entworfen werden. Nachfolgende Prozesse wie die Policierung einer Versicherung können ohne weitere Benutzerinteraktionen ausgeführt werden. Eine solche Architektur verlangt, dass der Benutzerstatus im Client gespeichert wird [2].
Mit einer MACH-Architektur lassen sich hochflexible und gut wartbare Systeme bauen, die problemlos an sich ändernde Anforderungen und Technologieweiterentwicklungen angepasst werden können.
Die Vorgehensweise wurde zwar gut umgesetzt, ein Unfall passierte dennoch (Abb. 2). Denn es wurde angenommen, dass nur vollständige Angaben auf dem Server gespeichert werden können, um dem Headless-Prinzip zu entsprechen. Das führte aber dazu, dass Benutzer ihre zum Teil sehr umfangreichen Angaben bei komplexen Eingaben jedes Mal von vorn machen mussten. Diese Benutzererfahrung war nicht akzeptabel.
Abb. 2: Aufgabe zur Erstellung einer TAA-Strecke einer Versicherung
Die Lösung für dieses Problem liegt auf der Hand – Angebote müssen auch gespeichert werden können, wenn sie unvollständig sind. Insbesondere für Webanwendungen sind clientseitige Speicher in der Regel an die jeweilige Benutzersitzung gebunden und können bei Wiederaufnahme nicht verwendet werden (Abb. 3).
Abb. 3: Lösung für eine benutzerfreundliche TAA-Strecke
Um unfertige Angebote speichern zu können, muss ein Backend-für-Frontend-Service (BFF) implementiert werden, der die Benutzereingaben speichert und vom Benutzer bei Wiederaufnahme abgerufen werden kann. Dadurch wird ermöglicht, dass ein Benutzer zu jeder Zeit seine Angebote speichern und später wieder darauf zurückkommen kann.
Der hier geschilderte Unfall geschah, weil Vorgaben umgesetzt wurden, ohne sie zu hinterfragen. Architekturvorgaben sind nützlich und sinnvoll. Allerdings darf man sie nicht blind umsetzen, sondern sollte immer wieder den Zweck hinterfragen und eventuell eine andere Lösung finden. Ausschließlich theoretische Architekturmodellierungen führen zu benutzerunfreundlichem Verhalten. Manchmal muss man in der Zusammenarbeit auch bewusst gegen Regeln verstoßen.
Interaktive und kollaborative Modellierungstechniken wie Domain Storytelling [3] und Event Storming [4] führen zu besseren Lösungen. Allerdings helfen Architekturvorgaben, Entscheidungen bewusst zu treffen und komplizierte Probleme sinnvoll zu strukturieren.
Die bisher beschriebenen Unfälle waren in der Regel „Totalschäden“, die nur durch umfangreiche Refactoring-Maßnahmen oder sogar vollständigen Neuaufsatz des Entwicklungsprojekts behoben werden konnten. Es entstehen in der Architekturarbeit aber täglich auch kleinere Unfälle, die unsere Aufmerksamkeit verdienen. Ein paar von ihnen wollen wir beleuchten.
Eine unverständliche Sprache trifft man häufig in APIs, die schon längere Zeit existieren. Oft werden bestimmte Felder aus Kompatibilitäts- oder Aufwandsgründen einfach inhaltlich anders interpretiert, sodass kein neues Feld angelegt werden muss. Solche Felder heißen dann vielleicht Angebotsnummer, enthalten aber keine Angebotsnummer, sondern ein Identifikationskennzeichen, das frei durch einen Berater vergeben werden kann und nicht eindeutig sein muss.
Wir müssen in der Implementierung von Geschäftsanforderungen tagtäglich architekturelle Kompromisse eingehen und uns einer realen Welt stellen, aber diese Kompromisse dürfen nicht dazu führen, dass zukünftige Implementierungen wesentlich aufwendiger oder sogar unverständlich werden.
Ähnlich verhält es sich, wenn Architekturvorgaben einfach ignoriert werden. Das Beispiel „Nicht nur innere Werte zählen“ hat gezeigt, dass Architekturvorgaben nicht blind umgesetzt werden dürfen, aber genauso wenig dürfen sie einfach ignoriert werden, weil ein Einzelner denkt, er wisse es besser. Im Zweifelsfall müssen Architekturvorgaben und die damit zu implementierenden Lösungen diskutiert und verbessert werden. Architekturvorgaben zu ignorieren, führt häufig zu Doppelimplementierungen oder vermeidbaren Umbauten, weil die Gründe für die Vorgaben nicht vollständig bekannt waren. Dazu gehören z. B. Vorgaben zu Datenbanken oder auch Implementierungssprachen, die häufig nicht rein technisch, sondern auch organisatorisch und geschäftlich getrieben sind.
Schwierig sind auch veraltete Architekturvorgaben, die über größere Zeiträume nicht aktualisiert wurden. Diese führen dann zu veralteten Implementierungen, die wahrscheinlich innerhalb eines sehr kurzen Zeitraums erneut überarbeitet werden müssen, um sie aktuellen Geschäftsanforderungen anzupassen.
Wie kann man aber solche Unfälle vermeiden und eventuelle Gefahren frühzeitig erkennen? Um Unfälle vermeiden zu können, müssen Architekt:innen Skills erwerben, um Gefahren rechtzeitig erkennen und Risiken mitigieren zu können. Ähnlich wie beim Autofahren ein spezifisches Training hilft auch in der Softwarearchitektur der Aufbau von Skills dabei, Gefahren rechtzeitig zu erkennen.
Skills von Architekt:innen unterteilen sich in die großen Gruppen Technologie, Entwurf und Organisation (Abb. 4).
Abb. 4: Anforderungen an Architekt:innen
Im Bereich Technologie müssen Architekt:innen moderne Architekturstile kennen und vermitteln können. Dazu gehören unter anderen eventgetriebene und Microservices-Architekturen, aber auch sehr neue Architekturstile, die vielleicht noch nicht so gefestigt sind, aber zur jeweiligen Lösung beitragen könnten. Daher ist es unabdingbar, dass sich Architekt:innen ständig weiterbilden.
Im Bereich Entwurf müssen sie Kenntnisse im Domain-Driven Design haben. Sie müssen in der Lage sein, Architekturvorgaben zu machen, die sowohl evolutionär als auch kollaborativ sind. Und sie müssen interaktive Modellierungstechniken wie Event Storming und Domain Storytelling beherrschen.
Um solche Modellierungstechniken anwenden zu können, sind sogenannte Soft Skills wie Moderation und Visualisierung zwingend notwendig. Auch diese können in Trainings und durch Coachingprogramme erworben und konstant verbessert werden.
Im Bereich Organisation müssen Architekt:innen als Ansprechpartner:innen allen Stakeholdern des Softwareproduktes zur Verfügung stehen. Das sind nicht nur die Entwickler:innen in den Teams, sondern auch Projektmanagement, Product Owner und Business Analysts, aber auch das höhere Management, dem technologische und architektonische Herausforderungen erläutert werden müssen. Kommunikations- und Präsentationstrainings können hier unterstützen.
Sie müssen implizite Vorgaben des Managements erkennen und ansprechen. Sie müssen einen funktionierenden Governance-Prozess (Kasten: „Governance“) etablieren. Ein solcher Prozess ermöglicht auch Ausnahmeregelungen, die wohlbegründet sein müssen.
Unter Governance versteht man die Absicherung, dass Vorgänge und Prozesse sinnvoll durchgeführt werden. Eine Governance besteht nicht so sehr aus Kontrolle, vielmehr werden Regeln und Anleitung vermittelt. Für die Architektur bedeutet es, Architekturrichtlinien zu vermitteln und die Implementierungsteams in den entsprechenden Festlegungen zu trainieren.
Architekt:innen müssen auch Schätzungen für Implementierungsvorhaben abgeben. Hierbei können sie gut auf ihr Verständnis von Komplexität zurückgreifen, um grobe, aber trotzdem gute Schätzungen abgeben zu können. Dabei schließt die architektonische Komplexität auch die organisatorische Komplexität der Implementierungsteams ein. Entstehen hohe Abhängigkeiten der Implementierungsteams untereinander, ist in der Regel der Aufwand durch erhöhte Synchronisationsaufwände größer. Diese Abhängigkeiten müssen in eine architektonische Bewertung Eingang finden.
Abb. 5: Verantwortlichkeiten verschiedener Rollen in der Entwicklung
Da Architektur nie im luftleeren Raum stattfindet, müssen Architekt:innen und andere Beteiligte dafür sorgen, dass Informationen frei fließen können und dort ankommen, wo sie benötigt werden. Um dies zu erreichen, hat sich die Bildung von Communitys bewährt (Abb. 5). In den Communitys müssen die unterschiedlichen Beteiligten unterschiedliche Aufgaben übernehmen.
Architekt:innen bilden eine teamübergreifende Architekturcommunity. An dieser Community können nicht nur nominierte Architekt:innen teilnehmen, sondern alle Interessierten, wie z. B. Entwickler:innen, DevOps-Ingeneur:innen, aber auch Product Owner. Wichtig ist, dass aus jedem Team mindestens eine Vertretung teilnehmen kann. Architekt:innen übernehmen hierbei die Moderation von kollaborativen Modellierungstechniken und kommunizieren diese Modelle in alle Richtungen – also in die Teams und in das Management. Letztlich kann eine solche Community auch Schwierigkeiten und Herausforderungen in den Teams diskutieren und gemeinsam lösen.
Entwicklerteams können in regelmäßigen Face-to-face-Meetings mit der Architektur Implementierungsdetails diskutieren und gemeinsam Lösungsalternativen erarbeiten.
In der Organisation beraten Architekt:innen Product Owner, Business Analysts und die Projektleitung. Insbesondere in der Planung müssen Manager:innen hinsichtlich architektonischer Risiken und Komplexitäten eng beraten werden, um nicht scheinbar einfache Lösungen mit hoher Implementierungskomplexität einzukaufen.
Unfälle in der Architektur geschehen. In der Artikelserie wurden unterschiedliche Totalschäden und kleinere Unfälle vorgestellt. Diese Unfälle lassen sich manchmal nicht vermeiden, weil im Vorfeld vielleicht Wissen oder Fähigkeiten fehlen. Aber die meisten der hier vorgestellten Pannen lassen sich vermeiden, wenn in der Architektur auf kollaborative Modellierungstechniken gesetzt wird. Zusätzlich lassen sich Probleme frühzeitig identifizieren und beseitigen, wenn in einer Architekturcommunity gut zusammengearbeitet wird.
[1] MACH Alliance. „MACH Technology. MACH Alliance“: https://machalliance.org/mach-technology
[2] Ozkaya, Mehmet: „Headless Architecture with Separated UI for Backend and Frontend“: https://medium.com/design-microservices-architecture-with-patterns/headless-architecture-with-separated-ui-for-backend-and-frontend-f9789920e112
[3] Hofer, Stefan; Schwentner, Henning: „Domain Storytelling: A Collaborative, Visual, and Agile Way to Build Domain-Driven Software“; Pearson International, 2021
[4] Brandolini, Alberto: „EventStorming“: https://www.eventstorming.com