In Zeiten agiler Märkte und der damit verbundenen Notwendigkeit zur Flexibilität, gilt es Software nicht mehr nur als statisches Produkt, sondern vielmehr als Kombination sich permanent weiterentwickelnder Services zu verstehen. Angefangen beim modularen Design der Software, über deren partielle, vollautomatisierte Bereitstellung in der Cloud bis hin zur Generierung von Mehrwerten zur Laufzeit durch die Kombination eigener Services mit 3rd Party Diensten, wie AI & Co, zieht sich der Service-Gedanke durch den gesamten Software-Lifecycle und ermöglicht so die Erschließung völlig neue Geschäftsmodelle.
Die eigene Anwendung als Choreografie lose gekoppelter Services zu verstehen, bringt Unabhängigkeit in allen Phasen des Software-Lifecycles. Im Rahmen unserer diesjährigen Online-Konferenz OPEN THANX haben wir gezeigt, wie es geht.
In modernen Software-Landschaften werden die Fachlichkeiten mit Hilfe von DDD sauber voneinander abgegrenzt und als eigenständige Services umgesetzt. Was muss in der Entwicklung eines solchen Services beachtet werden, um diese Eigenständigkeit zu gewährleisten und gleichzeitig sicherzustellen, dass alle Services gemeinsam als ein großes Ganzes funktionieren?
Service-Konsumenten sollen Schnittstellen nach Möglichkeit nutzen können, ohne Aufwand beim Anbieter der Schnittstelle zu verursachen. Das Ziel ist es, Features schnell und unabhängig umsetzen zu können.
In dem Vortrag wird vorgestellt, wie man eine hohe Nutzerzufriedenheit durch Consumer-Centric API Design und regelmäßige Produktiv-Deployments erzielt. Möglich wird das durch ein sauberes API-Design, eine schlanke Microarchitektur und eine hohe Testautomatisierung. An praktischen Beispielen wird gezeigt, wie das erreicht werden kann.
„Kleine Services” gilt wohl nur, wenn sehr wenig domain-logic vorhanden ist, oder?Sonst wäre doch die Kapselung der domain über Abstraktionen sinnvoll, oder?
Eine Kapselung der Domänenlogik ist immer sinnvoll. Dies muss aber nicht über eine Abstraktion und eine Mapping-Schicht geschehen. Es reicht, dass nur erlaubte Zugriffe erfolgen. Das kann über Tools wie ArchUnit sichergestellt werden. Ein lesender Zugriff kann häufig an der Domänen-Logik vorbei passieren, weil diese in der Regel eh nur durchleiten würde.
Ich sehe sehr häufig „kleine“ Architektur-Bilder. Für größere Micro-Service Architekturen (>50 Micro-Services) habe ich noch keine praxisbrauchbaren Diagramme gesehen… Auch ARC42 oder C4 finde ich nicht brauchbar, da es keine Übersicht gibt.Könnt ihr dazu etwas sagen?
Wichtig ist eine automatisierte Dokumentation der Architektur. Die Informationen dafür lassen sich aus dem Tracing-Server, dem Service-Mesh oder dem Consumer-Driven-Contract-Broker extrahieren. Alle diese Tools haben in der Regel eigene Ansichten, um die Service-Kommunikation zu visualisieren. Leider gibt es am Markt Out-Of-The-Box kein Tool, was diese Daten alle sammeln und auch (z.B. nach Bounded Context) aggregieren kann. Ein solches Tool müsste man selber entwickeln.
Wie prüfen wir mit dem Vorgehen die Testabdeckung?
Die Testabdeckung, die durch Integrationstests erzielt wird, fließt in die Gesamtbewertung mit ein. Die bekannten Tools zum Messen der Testabdeckung können durch geeignete Konfiguration auch bei Integrationstests verwendet werden.
Wir spalten unsere Integrationstests auf, so dass wir Module in getrennten Containern im CI parallel testen können. Gibt es für Integrationstests Ansätze der Parallelität für ein Modul?
Die Tests sollten entsprechend gruppiert werden. Dies kann in JUnit 5 z.B. durch Tags erfolgen. Alle Tests mit demselben Tag können dann in einer VM ausgeführt werden. Wenn pro Testdurchlauf nur ein Datenbank-Container und nur ein Application-Container gestartet wird, ist eine parallele Ausführung aus Performance-Gründen ggf. aber auch gar nicht mehr notwendig.
Jeder Service für sich kann unabhängig deployed und skaliert werden. Gerade Cloud Computing erleichtert in vielen Unternehmen die Verwaltung der IT-Infrastruktur. Weil die für die Software benötigte Plattformen so einfach anzumieten sind, werden Developer deshalb immer mehr in die Rolle des DevOps gedrängt — die Software, die sie entwickeln, soll auch selbst betrieben werden — You build it, you run it.
Doch diese Strukturierung ist nicht ganz kostenlos – Developer müssen dadurch immer mehr Verantwortung übernehmen. Um dieser Verantwortung gerecht zu werden, muss eine Schwachstelle ausgeschaltet werden: der Mensch. Im Talk gehe ich auf Prozesse der klassischen Softwareentwicklung ein und lege dar, wie diese in dem “You build it, you run it”-Modell verbessert werden.
Könnte der operator ein backup einspielen und wer schreibt den operator sinnvollerweise?
Natürlich ist denkbar, dass der Operator sich auch um Datenbank Backups und Recovery Strategien kümmert. Die Möglichkeiten sind natürlich unbegrenzt. Klassischerweise sind solche „Automatisierten“ Operatoren, grade im Kubernetes Umfeld, bereits vorhanden. Bekannte Beispiele dafür sind FluxCD und ArgoCD.
Wie läuft das Sequenzdiagramm, wenn ich mehrere Feature-Branches parallel habe?
Bei verschiedenen Parallelen Feature-Branches sieht das Sequenzdigramm genauso aus. Hier muss man natürlich nur darauf achten, dass keine Konflikte durch die PullRequests entstehen (oder diese eben per Hand auflösen). Angenommen ich stelle aus meinem CI-Syste, einen PullRequest an das Cluster-Repository mit dem folgendem Inhalt ein:
Dann sorgt der Operator für die entsprechende Aktualisierung des Clusters. Das spannende bei parallelen PullRequests ist dann lediglich der infrastrukturelle Merge-Konflikt, das heißt, eventuell wollen verschiedene PRs automatisch gemergt und entsprechend durch den Operator deployed werden.
Dazu kann es helfen, für die Feature-Branches eigene Naming Konventions zu finden. Beispielsweise könnte der CI-Job vom Branch my-foo-feature eben „my-foo-feature.yaml“ einchecken, während der branch „my-bar-feature“ eben auf dieser Datei hantiert. Dadurch werden durch entsprechende Konventionen im vornherein merge Konflikte des Infrastruktur-Repository vermieden.
Geht der Ansatz davon aus, dass es nur ein produktives Gesamtsystem gibt? Bei uns liegt die Konfiguration auf Betriebsseite und können nicht durch Dev modifiziert werden. Basis Images und Basis Helm Charts liegen auf Dev Seite für Dev Testumgebungen für das Test k8s. Ops übernimmt bei Änderungen entsprechende Teile für Prod. Einen automatisierten Operator sehe ich da als Risiko an, da viele Umgebungen betroffen sind.
Ich denke der Ansatz ist erstmal nur: Alles ist versioniert im Git. Die Idee ist aber schon, dass Entwickler, die das Produkt Ende-zu-Ende betreiben den Zustand des Clusters durch PullRequests und einem entsprechenden CodeReiew des OPs Teams beeinflussen können. Der automatisierte Operator selbst soll natürlich nur die ausführende Kraft sein, die dafür sorgt, dass das Git-Repository auch den Zustand des Clusters widerspiegelt.
Versteht man seine Anwendung als Kombination (fast) unabhängiger Services, so ergeben sich nicht nur für Entwicklung und Deployment neue Perspektiven. Denn nicht nur die eigenen Services können internen oder externen Dritten zur Verfügung gestellt werden, sondern auch der umgekehrte Weg ist denkbar. Eine entsprechend flexible Architektur vorausgesetzt, lässt sich die eigene Fachlichkeit durch 3rd Party Services sinnvoll und gewinnbringend ergänzen, ohne dabei das Rad neu erfinden zu müssen.
Besonders interessant scheint hier das Feld der künstlichen Intelligenz zu sein. Egal ob automatische Texerkennung, Retourenvorhersagen, Qualitätsicherung in der Produktion oder die Vorhersage von Terminen zur Maschinenwartung; die Möglichkeiten scheinen nahezu unbegrenzt. Die Session zeigt, welche Möglichkeiten heute bereits Out-of-the-Box AI Services bieten und für welche Aufgaben man doch besser einen ML Experten mit ins Boot holen sollte.
Ist aus deiner Sicht AI schon bereit für produktiven/effizienten Einsatz in unserer Domäne, nämlich im Software-Engineering (also in allen Phasen, um die es heute geht – dev bis prod)?
AI zieht sich mittlerweile durch alle Phasen des Software-Lifecycles. Angefangen bei der Entwicklungsunterstützung durch „intelligente“ Code-Block Vorschläge (siehe z.B. Copilot von GitHub – Technical Preview – oder DeepDev – Early Preview – von Microsoft) oder AI gesteuerte Tests und Reviews in den Pre-Release Phasen, über AI gestützte Deployment-/Rollout-Szenarien via IoC (Infrastructure of Code) bis hin zu AI basierten Monitoring inkl. Anomalien-Erkennung, intelligentem Alerting und automatischer Skalierung aufgrund von Lastvorhersagen. Und auf der Schutz der eigenen Anwendungswelt gegenüber Angriffen ist in stark verteilten (Cloud-)Systemen kaum noch ohne eine gewisse Form von künstlicher Intelligenz denkbar.
Aus meiner Erfahrung heraus, sind insbesondere die typischerweise den DevOps zugeschriebenen Aufgaben heute schon sehr weit AI gestützt möglich, was natürlich u.a. daran liegt, dass zur Laufzeit hinreichend viele Daten (Metriken etc.) herangezogen und mit historischen Daten verglichen werden können. Beim Coding dagegen wäre ich persönlich ein wenig vorsichtig, was aber daran liegen mag, dass ich aus der Entwicklung komme und daher nicht durch künstliche Intelligenz ersetzt werden möchte ;-)
Die eigene Anwendung als Choreografie lose gekoppelter Services zu verstehen, bringt Unabhängigkeit in allen Phasen des Software-Lifecycles. Im Rahmen unserer diesjährigen Online-Konferenz OPEN THANX haben wir gezeigt, wie es geht.
In modernen Software-Landschaften werden die Fachlichkeiten mit Hilfe von DDD sauber voneinander abgegrenzt und als eigenständige Services umgesetzt. Was muss in der Entwicklung eines solchen Services beachtet werden, um diese Eigenständigkeit zu gewährleisten und gleichzeitig sicherzustellen, dass alle Services gemeinsam als ein großes Ganzes funktionieren?
Service-Konsumenten sollen Schnittstellen nach Möglichkeit nutzen können, ohne Aufwand beim Anbieter der Schnittstelle zu verursachen. Das Ziel ist es, Features schnell und unabhängig umsetzen zu können.
In dem Vortrag wird vorgestellt, wie man eine hohe Nutzerzufriedenheit durch Consumer-Centric API Design und regelmäßige Produktiv-Deployments erzielt. Möglich wird das durch ein sauberes API-Design, eine schlanke Microarchitektur und eine hohe Testautomatisierung. An praktischen Beispielen wird gezeigt, wie das erreicht werden kann.
„Kleine Services” gilt wohl nur, wenn sehr wenig domain-logic vorhanden ist, oder?Sonst wäre doch die Kapselung der domain über Abstraktionen sinnvoll, oder?
Eine Kapselung der Domänenlogik ist immer sinnvoll. Dies muss aber nicht über eine Abstraktion und eine Mapping-Schicht geschehen. Es reicht, dass nur erlaubte Zugriffe erfolgen. Das kann über Tools wie ArchUnit sichergestellt werden. Ein lesender Zugriff kann häufig an der Domänen-Logik vorbei passieren, weil diese in der Regel eh nur durchleiten würde.
Ich sehe sehr häufig „kleine“ Architektur-Bilder. Für größere Micro-Service Architekturen (>50 Micro-Services) habe ich noch keine praxisbrauchbaren Diagramme gesehen… Auch ARC42 oder C4 finde ich nicht brauchbar, da es keine Übersicht gibt.Könnt ihr dazu etwas sagen?
Wichtig ist eine automatisierte Dokumentation der Architektur. Die Informationen dafür lassen sich aus dem Tracing-Server, dem Service-Mesh oder dem Consumer-Driven-Contract-Broker extrahieren. Alle diese Tools haben in der Regel eigene Ansichten, um die Service-Kommunikation zu visualisieren. Leider gibt es am Markt Out-Of-The-Box kein Tool, was diese Daten alle sammeln und auch (z.B. nach Bounded Context) aggregieren kann. Ein solches Tool müsste man selber entwickeln.
Wie prüfen wir mit dem Vorgehen die Testabdeckung?
Die Testabdeckung, die durch Integrationstests erzielt wird, fließt in die Gesamtbewertung mit ein. Die bekannten Tools zum Messen der Testabdeckung können durch geeignete Konfiguration auch bei Integrationstests verwendet werden.
Wir spalten unsere Integrationstests auf, so dass wir Module in getrennten Containern im CI parallel testen können. Gibt es für Integrationstests Ansätze der Parallelität für ein Modul?
Die Tests sollten entsprechend gruppiert werden. Dies kann in JUnit 5 z.B. durch Tags erfolgen. Alle Tests mit demselben Tag können dann in einer VM ausgeführt werden. Wenn pro Testdurchlauf nur ein Datenbank-Container und nur ein Application-Container gestartet wird, ist eine parallele Ausführung aus Performance-Gründen ggf. aber auch gar nicht mehr notwendig.
Jeder Service für sich kann unabhängig deployed und skaliert werden. Gerade Cloud Computing erleichtert in vielen Unternehmen die Verwaltung der IT-Infrastruktur. Weil die für die Software benötigte Plattformen so einfach anzumieten sind, werden Developer deshalb immer mehr in die Rolle des DevOps gedrängt — die Software, die sie entwickeln, soll auch selbst betrieben werden — You build it, you run it.
Doch diese Strukturierung ist nicht ganz kostenlos – Developer müssen dadurch immer mehr Verantwortung übernehmen. Um dieser Verantwortung gerecht zu werden, muss eine Schwachstelle ausgeschaltet werden: der Mensch. Im Talk gehe ich auf Prozesse der klassischen Softwareentwicklung ein und lege dar, wie diese in dem “You build it, you run it”-Modell verbessert werden.
Könnte der operator ein backup einspielen und wer schreibt den operator sinnvollerweise?
Natürlich ist denkbar, dass der Operator sich auch um Datenbank Backups und Recovery Strategien kümmert. Die Möglichkeiten sind natürlich unbegrenzt. Klassischerweise sind solche „Automatisierten“ Operatoren, grade im Kubernetes Umfeld, bereits vorhanden. Bekannte Beispiele dafür sind FluxCD und ArgoCD.
Wie läuft das Sequenzdiagramm, wenn ich mehrere Feature-Branches parallel habe?
Bei verschiedenen Parallelen Feature-Branches sieht das Sequenzdigramm genauso aus. Hier muss man natürlich nur darauf achten, dass keine Konflikte durch die PullRequests entstehen (oder diese eben per Hand auflösen). Angenommen ich stelle aus meinem CI-Syste, einen PullRequest an das Cluster-Repository mit dem folgendem Inhalt ein:
Dann sorgt der Operator für die entsprechende Aktualisierung des Clusters. Das spannende bei parallelen PullRequests ist dann lediglich der infrastrukturelle Merge-Konflikt, das heißt, eventuell wollen verschiedene PRs automatisch gemergt und entsprechend durch den Operator deployed werden.
Dazu kann es helfen, für die Feature-Branches eigene Naming Konventions zu finden. Beispielsweise könnte der CI-Job vom Branch my-foo-feature eben „my-foo-feature.yaml“ einchecken, während der branch „my-bar-feature“ eben auf dieser Datei hantiert. Dadurch werden durch entsprechende Konventionen im vornherein merge Konflikte des Infrastruktur-Repository vermieden.
Geht der Ansatz davon aus, dass es nur ein produktives Gesamtsystem gibt? Bei uns liegt die Konfiguration auf Betriebsseite und können nicht durch Dev modifiziert werden. Basis Images und Basis Helm Charts liegen auf Dev Seite für Dev Testumgebungen für das Test k8s. Ops übernimmt bei Änderungen entsprechende Teile für Prod. Einen automatisierten Operator sehe ich da als Risiko an, da viele Umgebungen betroffen sind.
Ich denke der Ansatz ist erstmal nur: Alles ist versioniert im Git. Die Idee ist aber schon, dass Entwickler, die das Produkt Ende-zu-Ende betreiben den Zustand des Clusters durch PullRequests und einem entsprechenden CodeReiew des OPs Teams beeinflussen können. Der automatisierte Operator selbst soll natürlich nur die ausführende Kraft sein, die dafür sorgt, dass das Git-Repository auch den Zustand des Clusters widerspiegelt.
Versteht man seine Anwendung als Kombination (fast) unabhängiger Services, so ergeben sich nicht nur für Entwicklung und Deployment neue Perspektiven. Denn nicht nur die eigenen Services können internen oder externen Dritten zur Verfügung gestellt werden, sondern auch der umgekehrte Weg ist denkbar. Eine entsprechend flexible Architektur vorausgesetzt, lässt sich die eigene Fachlichkeit durch 3rd Party Services sinnvoll und gewinnbringend ergänzen, ohne dabei das Rad neu erfinden zu müssen.
Besonders interessant scheint hier das Feld der künstlichen Intelligenz zu sein. Egal ob automatische Texerkennung, Retourenvorhersagen, Qualitätsicherung in der Produktion oder die Vorhersage von Terminen zur Maschinenwartung; die Möglichkeiten scheinen nahezu unbegrenzt. Die Session zeigt, welche Möglichkeiten heute bereits Out-of-the-Box AI Services bieten und für welche Aufgaben man doch besser einen ML Experten mit ins Boot holen sollte.
Ist aus deiner Sicht AI schon bereit für produktiven/effizienten Einsatz in unserer Domäne, nämlich im Software-Engineering (also in allen Phasen, um die es heute geht – dev bis prod)?
AI zieht sich mittlerweile durch alle Phasen des Software-Lifecycles. Angefangen bei der Entwicklungsunterstützung durch „intelligente“ Code-Block Vorschläge (siehe z.B. Copilot von GitHub – Technical Preview – oder DeepDev – Early Preview – von Microsoft) oder AI gesteuerte Tests und Reviews in den Pre-Release Phasen, über AI gestützte Deployment-/Rollout-Szenarien via IoC (Infrastructure of Code) bis hin zu AI basierten Monitoring inkl. Anomalien-Erkennung, intelligentem Alerting und automatischer Skalierung aufgrund von Lastvorhersagen. Und auf der Schutz der eigenen Anwendungswelt gegenüber Angriffen ist in stark verteilten (Cloud-)Systemen kaum noch ohne eine gewisse Form von künstlicher Intelligenz denkbar.
Aus meiner Erfahrung heraus, sind insbesondere die typischerweise den DevOps zugeschriebenen Aufgaben heute schon sehr weit AI gestützt möglich, was natürlich u.a. daran liegt, dass zur Laufzeit hinreichend viele Daten (Metriken etc.) herangezogen und mit historischen Daten verglichen werden können. Beim Coding dagegen wäre ich persönlich ein wenig vorsichtig, was aber daran liegen mag, dass ich aus der Entwicklung komme und daher nicht durch künstliche Intelligenz ersetzt werden möchte ;-)