Ich lese und denke nun schon seit einiger Zeit über (interne) Entwicklungsplattformen (IDPs – Internal Developer Platforms) nach. Schnell habe ich den Zweck und den Nutzen verstanden: Ihr Ziel ist es, das Leben von Softwareingenieuren zu erleichtern. Es bleibt mehr Zeit für die tatsächliche Entwicklung von Software. Resultat: Steigerung der Produktivität und Zufriedenheit.
Ich lese oft, dass Entwicklungsplattformen eine Abstraktionsebene darstellen. Softwareingenieure sollten nicht mehr wissen müssen, wie die zugrunde liegende Infrastruktur funktioniert, um sie zu nutzen (z. B. um ihre Software darauf zu deployen).
So weit so gut.
Ich habe auch gelesen, dass
- Entwicklungsplattformen wie Produkte gehandhabt werden sollen und sich darauf konzentrieren sollten, ihren Kernanwenderinnen und -anwendern nützliche Dienste bereitzustellen.
- eine Entwicklungsplattform wirklich alles sein kann: Dokumentation, Vorlagen, APIs oder Portale. Eben alles, was eine Organisation als einen Ort identifiziert, an dem Entwickler:innen Informationen, Unterstützung und Ressourcen erhalten können, um mit Infrastruktur, Pipelines und Deployments umzugehen.
- sie für jede Organisation einzigartig sind. Wie eine spezifische Entwicklungsplattform aussieht, welche Komponenten sie hat und welche Funktionen sie bietet, hängt stark davon ab, was bereits in einer Organisation an Prozessen, Tools etc. vorhanden ist.
Einzeln betrachtet ergeben all diese Punkte Sinn. Aber ich hatte Schwierigkeiten, sie alle zusammenzufügen. In meinem Kopf wurde die Idee von „Entwicklungsplattformen“ zu einem großen, schwer zu beschreibenden Klumpen…und war noch schwerer anzuwenden.
Dann bin ich auf dieses Video von Victor Farcic gestoßen. Es war die erste Ressource, die mir geholfen hat, dieses Chaos in greifbare, anwendbare Kategorien aufzuteilen. Ich habe verstanden, wie man eine IDP aufbaut, wo man anfangen sollte und was wichtig ist.
In dem Video beschreibt Victor Farcic, wie man eine Entwicklungsplattform in 5 Schritten aufbaut: API, Zustandsverwaltung, Einmalige Aktionen / Workflows, RBAC & Richtlinien und Benutzeroberflächen (die er lustigerweise, als optional bezeichnet). Ich fand diese Schritte hilfreich. Sie beschreiben die Kernfähigkeiten, die eine Entwicklungsplattform haben sollte, um nützlich zu sein. Es wird nicht versucht zu beschreiben, wie ein Plattform aussehen sollte, sondern was eine Plattform können sollte. Wie man diese Funktionen erreicht, liegt ganz bei einem selbst.
Dieser Beitrag ist keine Zusammenfassung des Videos. Es ist meine Meinung über die Kernfunktionen von IDPs, die von dem Video inspiriert wurden. Ich formuliere sie aber anders und füge eine Funktion hinzu:
- API
- User Interfaces (nicht optional)
- Automatisierungen: One-Shot-Actions und State Management
- Einschränkungen
- Dokumentation und Auffindbarkeit
Sehen wir uns diese Funktionen an und warum sie wichtig sind.
#1 API
Eine API ist das Herzstück des Werteversprechens eines Entwicklungsportals. Sie ist die zentrale Abstraktionsebene, die Plattform-Nutzerinnen und -Nutzer Dienste auf einfache und sichere Weise zur Verfügung stellt.
- Einfach:
- API-Aufrufe sollten mit einem minimalen Satz an erforderlicher Parameter verfügbar sein, sodass eine Ressource so einfach wie möglich angefordert werden kann, z. B. durch die alleinige Angabe von „eine DB“, wobei alle zusätzlichen Konfigurationen standardmäßig auf Vorlagen zurückgreifen. Zusätzliche Parameter zur Anpassung sollten verfügbar, aber nicht erforderlich sein.
- API-Aufrufe sollten einem einfachen, standardisierten Schema folgen, das immer gleich bleibt, unabhängig von der spezifischen Anfrage.
- API-Aufrufe sollten unabhängig von der zugrunde liegenden Infrastruktur und dem Tech-Stack sein: Die API sollte nicht erfordern, dass Personen beispielsweise angeben müssen, ob die Datenbank auf AWS oder GCloud deployed werden soll. Außerdem sollten die Anfragestruktur sowie die Parameter von der zugrunde liegenden Infrastruktur unabhängig sein.
- Die API sollte sich selbst beschreiben, d. h. ihr eigenes Schema zurückgeben, damit darauf aufbauende Anwendungen oder Benutzer:innen einfach erkennen können, welche Funktionen verfügbar sind.
- Sicherheit:
- Die API ist der zentrale Ort, an dem Richtlinien angewendet und durchgesetzt werden. Das bedeutet, dass die API in der Lage sein sollte, Richtlinien durchzusetzen und nur Anfragen zu akzeptieren, die Authentifizierung und Validierung bestehen.
Die API ist das Kernstück der IDP. Wenn man versucht, eine IDP ohne eine zentrale API aufzubauen, endet man mit einem unüberschaubaren und schwer wartbaren System.
Falls eine zentrale Komponente zur Definition einer benutzerdefinierten API vorhanden ist – beispielsweise wenn die IDP auf Kubernetes basiert – sollte diese genutzt werden, um die Kern-API der Plattform zu definieren. Wenn die Entwicklungsplattform aber das Deployment in verschiedenen Cloud- oder Infrastruktur-Umgebungen unterstützen soll und/oder Dienste über die API bereitstellt, die nicht mit der Infrastruktur-Bereitstellung zusammenhängen, dann ist es sinnvoll, ein dediziertes API-Management-Tool einzusetzen oder eine eigene API-Schicht für die Entwicklungsplattform zu entwickeln.
#2 User Interfaces
Benutzeroberflächen (User Interfaces) werden auf der API aufgebaut und bieten Plattformnutzerinnen und -nutzern einfache Interaktionsmöglichkeiten mit der Plattform. Benutzeroberflächen können beispielsweise sein:
- Portale / Web-GUIs wie Backstage oder Port. Diese ermöglichen es beispielsweise, Ressourcen anzufordern. Dazu wird ein Formular ausgefüllt, das auf dem API-Schema basiert.
- CLIs (Command-Line Interfaces), die es ermöglichen, Funktionen über ein Terminal zu nutzen.
- IDE-Plugins, die Funktionen direkt aus einer IDE verfügbar machen.
- Integrationen mit anderen bestehenden GUIs.
- Benutzerdefinierte Web-UIs.
- Oder alles andere, das auf eine API zugreifen kann.
Angesichts der Tatsache, dass die Value Proposition eines Entwicklungsportals darin besteht, das Leben von Softwareingenieuren zu erleichtern, sind Benutzeroberflächen eine wesentliche Kernfunktion. Sie sollten mit größter Sorgfalt und in enger Zusammenarbeit mit den Kernnutzerinnen und -nutzern ausgewählt und gestaltet werden. So kann sichergestellt werden, dass die Funktionen auf eine sinnvolle Art und Weise nutzbar sind und zu den bestehenden Arbeitsabläufen passen. Eine falsche Gestaltung der Benutzeroberflächen kann einen Großteil des potenziellen Werts zerstören.
#3 Automatisierung: One-Shot-Actions und State Management
One-Shot-Actions oder Workflows sind wahrscheinlich der Teil, mit dem man bereits am vertrautesten ist. Es handelt sich dabei um Prozessautomatisierung, Skripterstellung, Pipelines und alles, was es ermöglicht, etwas einmalig automatisch zu tun.
One-Shot-Actions sind Dinge wie: Erstellen eines Snapshots, Erstellen eines Container-Images, Ausführen von Tests usw. Es handelt sich um alles, was automatisch ablaufen muss, aber für eine bestimmte Konstellation oder Konfiguration in der Regel nur einmal gemacht wird. Zum Beispiel wird ein Container-Image normalerweise nur einmal erstellt. Ändert sich etwas? Dann wird dieser Schritt wiederholt.
Was ist State Management? Wir sollen in der Lage sein zu definieren, wie etwas sein soll. Es geht also um einen bestimmten Zustand. Dafür müssen wir ein Werkzeug haben, das sicherstellt, dass dieser Zustand aufrechterhalten wird. Ein Beispiel für State Management ist ein zentrales Merkmal von Kubernetes. Wenn ein Cluster so konfiguriert ist, dass es drei Pods ausführt, sorgt Kubernetes dafür, dass immer drei Pods vorhanden sind. Wenn es nur zwei gibt, wird ein dritter hinzugefügt. Wenn es vier gibt, wird einer entfernt.
Werkzeuge für das State Management ermöglichen es, den Zustand zu definieren, ohne sich um die One-Shot-Actions kümmern zu müssen. Diese wären erforderlich, um das System von einem Zustand in einen anderen zu versetzen (zum Beispiel die One-Shot-Actions des Bereitstellens oder Löschens eines Kubernetes-Nodes). Als solche sind Tools für das State Management bereits eine Abstraktionsschicht. Sie enthalten die Logik für One-Shot-Actions innerhalb ihres Bereichs und ermöglichen es Benutzer:innen, diese auf eine konzeptionell andere und einfachere Weise zu verwenden: Indem nur der gewünschte Zustand beschrieben wird.
Daher sind Tools für das State Management immer domänenspezifisch. Sie enthalten Logik für das State Management innerhalb eines bestimmten Bereichs, zum Beispiel für ein Kubernetes-Cluster oder im Fall von Ansible für Infrastrukturmanagement im weiteren Sinne.
Um zu funktionieren, muss ein State-Management-Tool „wissen“, wie ein System von jedem möglichen Zustand in jeden anderen möglichen Zustand transformiert werden kann. Je nach Bereich kann das eine Menge Automatisierungslogik erfordern, um ein State Management bereitzustellen, das für den Benutzer einfach erscheint.
Es ist durchaus möglich, den Zustand mit jedem System zu verwalten, das in der Lage ist, One-Shot-Actions durchzuführen. Es ist jedoch schwieriger dies einzurichten und zu verwalten als mit einem dedizierten State-Management-System.
Zusammenfassend:
State Management erfordert:
- Eine Möglichkeit, einen Zustand zu definieren
- One-Shot-Aktionen, die flexibel kombiniert werden können, damit das System von jedem Zustand, zu jedem anderen Zustand übergehen kann
- Bewusstsein über den Zustand, d. h. eingebaute Funktionen, um zu wissen, was der aktuelle Zustand ist
Management transformiert jede Art von Eingabe (aktuelle Zustände) in dasselbe Ergebnis (den gewünschten Zustand). Daher ist State Management deterministisch: Man weißt genau, welches Ergebnis für jede Eingabe erhalten wird. Das System ist sich des Zustands bewusst und wird weiterhin versuchen, den gewünschten Zustand zu erreichen, unabhängig davon, welche One-Shot-Actions bereits durchgeführt wurden oder nicht.
One-Shot-Actions hingegen konzentrieren sich in der Regel stärker auf:
- Prozesslogik und
- Konfigurationsmanagement, d. h. die Eingaben, die eine One-Shot-Aktion erhält und die die Prozesslogik beeinflussen.
Eine One-Shot-Action transformiert einen spezifischen Satz von Eingaben in einen spezifischen Satz von Ausgaben. Da One-Shot-Aktionen typischerweise nicht zustandsbewusst sind (oder zumindest nicht vollständig), sind die Ausgaben einer One-Shot-Action nicht deterministisch. Die gleiche Eingabe kann zu einer unterschiedlichen Ausgabe führen, abhängig vom initialen Zustand des Systems.
Beispiel: Die One-Shot-Aktion zum Erstellen eines Kubernetes-Nodes kann dazu führen, dass ein, zehn oder hundert Kubernetes-Nodes erstellt werden – die One-Shot-Aktion weiß oder berücksichtigt nicht, wie viele Nodes vor der Ausführung existieren.
Du hast höchstwahrscheinlich bereits eine Menge One-Shot-Actions im Einsatz. Beim Aufbau einer Entwicklungsplattform kann es verlockend sein, bestehende Automatisierungslösungen wiederzuverwenden (oder missbrauchen), um Plattformdienste zu erstellen. Je nachdem, welche Automatisierungslösungen das sind, kann das eine gute oder eine sehr schlechte Idee sein. Bestehende, bewährte Pipelines und andere Automatisierungslösungen, die bereits in der Produktion eingesetzt werden, sollten selbstverständlich so viel wie möglich wiederverwendet werden. Die Erstellung plattformspezifischer Dienste mit bestehenden Automatisierungslösungen kann gut funktionieren, wenn diese Lösungen den Aufbau modularer, wartbarer Automatisierungen unterstützen. Und idealerweise, wenn sie Funktionen für das State Management bereitstellen.
#4 Einschränkungen
Die Plattform-API bietet eine Reihe von Diensten. Zu jedem Zeitpunkt werden nicht alle diese Dienste für Nuter:innen verfügbar sein. Die Regeln, die bestimmen, welche Dienste wann, warum und für wen verfügbar oder nicht verfügbar sind, nenne ich Einschränkungen.
Eine Plattform muss eine Möglichkeit unterstützen, solche Einschränkungen zu definieren, zu integrieren und durchzusetzen. Idealerweise ist dies eine Funktion der API, welche die Definition von Richtlinien ermöglichen sollte. Sie sollten festlegen können, welche Anfragen von welchen Benutzergruppen gestellt werden können.
In bestehenden Infrastruktureinstellungen und wahrscheinlich in den meisten, wenn nicht allen Entwicklungsplattformen werden Einschränkungen über ein Sammelsurium verschiedener Tools mit sehr unterschiedlichen Schwerpunkten implementiert. Die rollenbasierte Zugriffskontrolle (RBAC) ist ein solcher Schwerpunkt: Ihr Zweck ist es, Rollen zu definieren, die mit Berechtigungen verbunden sind. Diese Berechtigungen legen fest, welche Rechte eine bestimmte Rolle hat.
Im Kontext einer Entwicklungsplattform kann dies zum Beispiel bedeuten, dass Softwareingenieure mit einer bestimmten Rolle Ressourcen mit GPUs anfordern dürfen, während andere dies nicht können.
Ressourcen-Quoten sind ein weiteres Beispiel für eine Richtlinie oder Einschränkung.
Die API sollte sich all dieser Einschränkungen bewusst sein und die Anfragen, die sie erhält, validieren. Wenn eine Anfrage gegen eine Einschränkung verstößt, sollte sie mit einer hilfreichen Fehlermeldung abgelehnt werden.
Nebenbemerkung: Funktional eng damit verbunden ist die Schema-Validierung. Die API überprüft die Anfrage und validiert sie gegen ein Schema. Dieses definiert, welche Parameter erforderlich sind und ob alle erforderlichen Parameter in der Anfrage enthalten sind und im richtigen Format vorliegen. Wenn die Validierung fehlschlägt, wird die Anfrage mit einer hilfreichen Fehlermeldung abgelehnt.
Einschränkungen können auf die gleiche Weise modelliert werden: Damit eine Anfrage gültig ist, muss sie das richtige Set an Berechtigungen und anderen Parametern enthalten, die in das Einschränkungsframework passen.
#5 Dokumentation und Auffindbarkeit
Die API stellt Dienste basierend auf State Management und One-Shot-Actions bereit. Einschränkungen bestimmen, welche dieser Dienste in welcher Konfiguration zu welchem Zeitpunkt für welchen Nutzer oder welcher Nutzerin verfügbar sind.
Benutzeroberflächen ermöglichen es, diese Dienste zu verwenden. Damit all dies aber sinnvoll ist, müssen die Nutzer:innen wissen, welche Dienste verfügbar sind und verstehen, wie sie diese nutzen können. Ohne dieser Auffindbarkeit werden alle anderen Plattformfunktionen deutlich weniger wertvoll, da sie insgesamt weniger genutzt werden.
Die Auffindbarkeit ist ein Thema, das idealerweise von jeder Plattformkomponente bereitgestellt werden sollte: Die API sollte eine OpenAPI-Spezifikation haben, die die verfügbaren Aufrufe beschreibt, die Einschränkungen haben sollten, wo immer sie modelliert sind, transparent sein – zumindest in dem Maße, dass Nutzer:innen wissen, dass seine Anfrage aufgrund unzureichender Berechtigungen fehlgeschlagen ist – und Benutzeroberflächen sollten den Nutzerinnen und Nutzern Informationen über verfügbare Dienste bieten (z. B. Hilfe in der CLI oder eine gut strukturierte Webanwendung mit einer Suchfunktion).
Auffindbarkeit erstreckt sich aber auch auf ein Thema, das für viele IDPs zentral ist: Die Dokumentation. Die Auffindbarkeit von Funktionen, Diensten, aber auch von Infrastruktur, geistigem Eigentum (Softwarekomponenten, Repositories usw.) und anderen relevanten Aspekten der Arbeit eines Softwareingenieurs ist ein zentraler Wert, den IDPs bieten können. Tatsächlich beginnen viele IDPs als Dokumentationszentren wie Softwarekataloge oder lokale Deployment-Anleitungen mit Links zu Konfigurationstemplates usw.
Beim Aufbau von IDPs sollte die Auffindbarkeit frühzeitig berücksichtigt werden. Eine manuell gepflegte Dokumentation ist großartig und oft unverzichtbar. Allerdings ist eine manuell kuratierte Dokumentation auch sehr ressourcenintensiv zu pflegen. Jede Komponente der IDP, die sich selbst beschreibt und eingebaute Funktionen zur Unterstützung der Entdeckbarkeit bereitstellt, ist ein großer Vorteil und wird die langfristige Wartung des IDPs erheblich erleichtern.
Wie hilft mir das, eine Plattform zu bauen?
Wenn du über die Probleme nachdenkst, die du kürzlich als Plattform- oder DevOps-Ingenieur:in hattest, wirst du sie wahrscheinlich zu einer der beschriebenen Funktionen zuordnen können.
Einige Beispiele:
- Wenn du Probleme mit Ausfällen von Instanzen oder unbeabsichtigten hohen Kosten aufgrund von Cloud-Ressourcen hast, die ungenutzt herumliegen, hast du unzureichende State-Management-Fähigkeiten.
- Wenn du Schwierigkeiten damit hast, dass Softwareingenieure keinen Zugang zu den Infrastrukturen haben, die sie benötigen, oder dass Junior-Ingenieure mit Bereitstellungen herumhantieren, mit denen sie nicht arbeiten sollten, verwaltest du Einschränkungen nicht gut.
- Wenn deine Entwickler:innen nicht in der Lage sind, ein Feature-Branch-System selbst zu erstellen oder einen Build- und Testlauf für ein bestimmtes Commit auszulösen, musst du dir die Automatisierungsfähigkeiten für One-Shot-Actions anschauen.
- Wenn deine Softwareingenieure die APIs und Dienste einfach nicht nutzen, solltest du dir wahrscheinlich die Benutzeroberflächen ansehen, oder überprüfen, ob deine Dienste auffindbar / dokumentiert sind.
Wenn du beginnst, über Probleme – oder idealerweise die Dienste, die du deinen Softwareingenieuren anbieten möchtest – in diesen Kategorien nachzudenken, wird es dir helfen, zu identifizieren, was du tun musst und wie du es auf eine Weise angehen kannst, die dein Leben langfristig erleichtert.
Anstatt dein One-Shot-Automation-Tool für das State-Management zu missbrauchen und Workflows mit vielen „if“-Bedingungen zu basteln, solltest du vielleicht ein Tool finden, das speziell für das State-Management entwickelt wurde. Es wird dein Leben einfacher machen.
Du hast überall Richtlinien, aber keinen Überblick, wo welche Einschränkungen gelten? Du bist dir unsicher, ob sie überhaupt sinnvoll sind? Oder jeder hat einfach vollen Zugriff auf alles – obwohl du weißt, dass das nicht richtig ist? Wenn dir der Weg fehlt, das Prinzip der geringsten Privilegien nachhaltig über deine Infrastruktur und Benutzerbasis umzusetzen, brauchst du vielleicht ein Tool, das dir das Modellieren von Einschränkungen erleichtert.
Und so weiter.
Der Zweck dieser Kernfähigkeiten ist einfach: Sie helfen dir zu erkennen, warum du bei bestimmten Themen immer wieder scheiterst. Und sie zeigen dir, wie du beginnen kannst, Probleme so zu lösen, dass es dauerhaft funktioniert – und nachhaltig verwaltbar bleibt.
Abschließende Bemerkung
Wir denken nicht nur über Entwicklungsplattformen nach. Wir bauen ein Framework, um Entwicklungsplattformen zu schaffen, die sowohl nützlich als auch nachhaltig sind. Cloudomation ist ein Python-Framework zur Erstellung von Entwicklungsplattformen. Wir haben Cloudomation 2019 als ein allgemeines (One-Shot-Action) Automatisierungsframework auf den Markt gebracht und seitdem kontinuierlich weiterentwickelt. Mit Stolz können wir sagen, dass wir inzwischen ein breites, flexibles und leistungsstarkes Framework haben, das die in diesem Beitrag beschriebenen Kernfähigkeiten unterstützt:
- API: Cloudomation verfügt über einen integrierten API-Manager, der es ermöglicht, benutzerdefinierte APIs zu definieren.
- Benutzeroberflächen:
- Benutzerdefinierte Web-Apps basierend auf benutzerdefinierten APIs.
- Integration mit Portal-Lösungen wie Backstage.
- Eine grundlegende CLI.
- Schema-basierte Einzelformular-Web-UIs (nicht geeignet als vollständige Plattformlösungen, aber geeignet, um einzelne Dienste für spezifische Benutzergruppen bereitzustellen, z.B. das Bereitstellen einer Demo-Umgebung zu ermöglichen).
- Jede benutzerdefinierte Benutzeroberfläche, die auf den APIs basiert.
- One-Shot-Actions: Cloudomation wurde als Automatisierungsplattform konzipiert und ist besonders gut darin, komplexe Workflows zu verwalten. Dies ist eine der Hauptstärken der Plattform. Sowohl die Integration mit bestehenden Pipelines, Skripten, IaC und anderen Tools als auch native Automatisierungen in Python werden durch eine breite und erprobte Funktionsvielfalt unterstützt.
- State Management: Cloudomation ist das einzige Framework, von dem wir wissen, dass es ermöglicht, ein benutzerdefiniertes State-Management für eigene Domänen zu erstellen. Dies wird durch unseren einzigartigen objektorientierten Automatisierungsansatz ermöglicht. Objekte können modelliert werden, die den gewünschten Zustand beschreiben. Diese werden dann mit Lifecycle-Hooks verbunden, die Zustandsübergänge verwalten.
- Einschränkungen: Cloudomation unterstützt rollenbasierte Zugriffskontrolle (RBAC), die direkt über die Plattform modelliert werden kann sowie die Integration mit LDAP für die Authentifizierung. Darüber hinaus kann die Festlegung von Einschränkungen mit den Kernautomatisierungsfunktionen der Plattform durchgeführt werden.
- Dokumentation und Entdeckbarkeit: Unsere benutzerdefinierten APIs können sich selbst beschreiben und unser LLM-basierter Assistent kann Informationen bereitstellen und Dokumentation für benutzerdefinierte Automatisierungen, Dienste und APIs in Cloudomation schreiben. Was das Hosting und Bereitstellen von Dokumentationen betrifft, ist Cloudomation nicht das richtige Tool, aber es kann nahtlos in spezialisierte Dokumentationslösungen oder Entwicklerportale (wie Backstage) integriert werden, um automatisch generierte Dokumentation (z. B. für API-Schemata) kontinuierlich zu aktualisieren.