Wiederverwendbare Muster zum Erstellen von Cloud-nativen Anwendungen
E-Book, Deutsch, 260 Seiten
ISBN: 978-3-96010-366-0
Verlag: O'Reilly
Format: EPUB
Kopierschutz: 6 - ePub Watermark
Bilgin Ibryam (@bibryam) ist leitender Architekt bei Red Hat und trägt zu vielen Projekten der Apache Software Foundation bei. Roland Huß (@ro14nd) ist leitender Softwareentwickler bei Red Hat und Mitglied des Serverless-Teams, das an Knative arbeitet.
Weitere Infos & Material
KAPITEL 1
Einführung
In diesem einführenden Kapitel legen wir die Grundlagen für den Rest des Buches, indem wir ein paar der zentralen Kubernetes-Konzepte erklären, die zum Designen und Implementieren von Container-basierten Cloud-nativen Anwendungen genutzt werden. Es ist ausgesprochen wichtig, diese neuen Abstraktionen und die dazugehörigen Prinzipien und Patterns aus diesem Buch zu verstehen, um verteilte Anwendungen zu bauen, die automatisiert von Cloud-nativen Plattformen verteilt werden. Dieses Kapitel ist keine Voraussetzung für das Verstehen der später beschriebenen Patterns. Leserinnen und Leser, die mit den Konzepten von Kubernetes vertraut sind, können es überspringen und direkt zu den für sie interessanten Patterns-Kategorien springen. Der Weg nach Cloud-native
Die beliebteste Anwendungs-Architektur auf Cloud-nativen Plattformen wie Kubernetes ist der Microservice-Stil. Diese Technik der Softwareentwicklung geht die Komplexität von Software an, indem sie die einzelnen Aspekte der Geschäftsvorgänge modularisiert und Entwicklungs-Komplexität gegen operative Komplexität eintauscht. In der Microservice-Bewegung gibt es einen deutlichen Anteil an Theorie und unterstützenden Techniken zum Erstellen neuer Microservices oder für das Aufteilen von Monolithen in Microservices. Die meisten dieser Praktiken basieren auf dem Buch Domain-Driven Design von Eric Evans (Addison-Wesley, https://dddcommunity.org/book/evans_2003) und den Konzepten der Bounded Contexts und Aggregate. Bounded Contexts kümmern sich um große Modelle, indem sie sie in unterschiedliche Komponenten unterteilen, während Aggregate dabei helfen, die Bounded Contexts in Module mit definierten Transaktionsgrenzen zu unterteilen. Aber neben diesen Überlegungen aus Business-Sicht gibt es für jedes verteilte System – ob es nun auf Microservices basiert oder nicht – eine Reihe technischer Aspekte rund um seine Organisation, Struktur und das Laufzeitverhalten. Container und Container-Orchestrierer wie Kubernetes stellen viele neue Primitive und Abstraktionen bereit, um die Probleme mit verteilten Anwendungen anzugehen, und hier beschreiben wir die verschiedenen Möglichkeiten, über die Sie nachdenken sollten, wenn Sie ein verteiltes System auf Kubernetes bringen wollen. Im Buch gehen wir Container- und Plattform-Interaktionen an, indem wir die Container als Blackboxes behandeln. Aber wir haben diesen Abschnitt geschrieben, um hervorzuheben, wie wichtig es ist, was in diesen Containern ist. Container und Cloud-native Plattformen bieten Ihren verteilten Anwendungen unglaubliche Vorteile, aber wenn Sie in Ihre Container nur Müll stecken, werden Sie auch nur Müll skalieren. In Abbildung 1-1 sehen Sie die verschiedenen Fähigkeiten, die erforderlich sind, um gute Cloud-native Anwendungen zu schreiben. Abbildung 1-1: Der Weg nach Cloud-native Aus der Vogelperspektive betrachtet gibt es in einer Cloud-nativen Anwendung eine Reihe von Abstraktionsschichten, für die unterschiedliche Design-Überlegungen erforderlich sind: Auf unterster Codeebene spielt jede von Ihnen definierte Variable, jede Methode und jede instanziierte Klasse in der langfristigen Wartung der Anwendung eine Rolle. Es ist egal, welche Container-Technologie oder welche Orchestrierungs-Plattform Sie nutzen – das Entwicklungs-Team und die von ihm erzeugten Artefakte haben den größten Einfluss. Es ist wichtig, Entwickler aufzubauen, deren Ziel es ist, Clean Code zu schreiben, die richtige Menge an automatisierten Tests einzusetzen, fortlaufend zu refaktorieren, um die Qualität des Codes zu verbessern, und die in ihrem Herzen Code-Handwerker sind. Beim Domain-Driven Design geht es darum, ein Software-Design aus Business-Perspektive mit der Intention anzugehen, die Architektur so nahe wie möglich an der Realität zu orientieren. Dieser Ansatz funktioniert am besten für objektorientierte Programmiersprachen, aber es gibt auch andere gute Wege, Software für Probleme aus der realen Welt zu modellieren und zu entwerfen. Ein Modell mit den richtigen Business- und Transaktions-Grenzen, einfach zu nutzenden Schnittstellen und umfangreichen APIs ist die Grundlage für ein späteres erfolgreiches Containerisieren und Automatisieren. Der Microservices-Architekturstil hat sich sehr schnell zum Standardvorgehen entwickelt und er bietet wertvolle Prinzipien und Praktiken für das Designen von sich ändernden verteilten Applikationen. Das Anwenden dieser Prinzipien ermöglicht es Ihnen, Implementierungen zu schaffen, die auf Skalierbarkeit, Resilienz und Änderbarkeit optimiert sind, was für heutige, moderne Software übliche Anforderungen sind. Container wurden sehr schnell als der Standardweg zum Verpacken und Ausführen verteilter Anwendungen akzeptiert. Das Erstellen modularer, wiederverwendbarer Container, die gute Cloud-native Mitbürger sind, ist eine weitere grundlegende Voraussetzung. Mit einer wachsenden Zahl von Containern entsteht in jeder Organisation die Notwendigkeit, sie mit effektiveren Methoden und Werkzeugen zu managen. Cloud-native ist ein recht neuer Begriff, mit dem die Prinzipien, Patterns und Tools zum Automatisieren von containerisierten Microservices im großen Maßstab beschrieben werden. Wir nutzen Cloud-native parallel zu Kubernetes – der beliebtesten aktuell verfügbaren Cloud-nativen Open-Source-Plattform. In diesem Buch gehen wir nicht weiter auf Clean Code, Domain-Driven Design oder Microservices ein. Wir konzentrieren uns nur auf die Patterns und Praktiken rund um das Orchestrieren von Containern. Aber damit diese Patterns effektiv eingesetzt werden können, muss Ihre Anwendung aus dem Inneren heraus gut entworfen sein, indem Clean-Code-Praktiken, Domain-Driven Design, Microservices-Patterns und andere relevante Design-Techniken angewendet werden. Verteilte Primitive
Um zu erläutern, was wir mit neuen Abstraktionen und Primitiven meinen, vergleichen wir sie hier mit der wohlbekannten objektorientierten Programmierung (OOP) und insbesondere Java. Im OOP-Universum haben wir Konzepte wie Klasse, Objekt, Paket, Vererbung, Kapselung und Polymorphismus. Dann liefert die Java-Runtime spezifische Features und Garantien zum Managen des Lebenszyklus unserer Objekte und der Anwendung im Ganzen. Die Java-Sprache und die Java Virtual Machine (JVM) bieten lokale In-Process-Bausteine für das Erstellen von Anwendungen. Kubernetes fügt dieser bekannten Denkweise eine ganz neue Dimension hinzu, indem es einen neuen Satz an verteilten Primitiven und eine weitere Runtime für das Bauen verteilter Systeme anbietet, die über viele Knoten und Prozesse verteilt sind. Mit Kubernetes sind Sie nicht mehr nur auf lokale Primitive angewiesen, um das gesamte Anwendungsverhalten zu implementieren. Sie müssen immer noch die objektorientierten Bausteine nutzen, um die Komponenten der verteilten Anwendung zu bauen, aber Sie können auch Kubernetes-Primitive für manche der Anwendungsaspekte einsetzen. Tabelle 1-1 zeigt, wie verschiedene Entwicklungs-Konzepte mit lokalen und verteilten Primitiven unterschiedlich umgesetzt werden. Tabelle 1-1: Lokale und verteilte Primitive Konzept Lokales Primitiv Verteiltes Primitiv Verhalten kapseln Klasse Container-Image Verhaltens-Instanz Objekt Container Wiederverwendbare Einheit .jar Container-Image Komposition Klasse A enthält Klasse B Sidecar-Pattern Vererbung Klasse A erweitert Klasse B FROM Super-Image eines Containers Deployment-Einheit .jar/.war/.ear Pod Buildtime/Runtime-Isolierung Modul, Paket, Klasse Namespace, Pod, Container Initialisierungs-Vorbedingungen Konstruktor Init Container Postinitialisierungs-Trigger Init-Methode postStart Pre-Destroy-Trigger Destroy-Methode preStop Cleanup-Prozedur finalize(),...