Freigeben über


Nutzen von Containern und Orchestratoren

Tipp

Dieser Inhalt ist ein Auszug aus dem eBook, Architecting Cloud Native .NET Applications for Azure, verfügbar auf .NET Docs oder als kostenlose herunterladbare PDF, die offline gelesen werden kann.

Miniaturansicht des E-Books „Architecting Cloud Native .NET Applications for Azure“.

Container und Orchestratoren sind dafür konzipiert, Probleme zu lösen, die bei monolithischen Bereitstellungsansätzen häufig auftreten.

Herausforderungen bei monolithischen Bereitstellungen

Traditionell wurden die meisten Anwendungen als einzelne Einheit bereitgestellt. Solche Anwendungen werden als Monolith bezeichnet. Dieser allgemeine Ansatz für die Bereitstellung von Anwendungen als einzelne Einheiten, auch wenn sie aus mehreren Modulen oder Assemblys bestehen, wird als monolithische Architektur bezeichnet, wie in Abbildung 3-1 dargestellt.

Monolithische Architektur.

Abbildung 3-1. Monolithische Architektur.

Obwohl sie den Vorteil der Einfachheit haben, stehen monolithische Architekturen vielen Herausforderungen gegenüber:

Einsatz

Darüber hinaus ist ein Neustart der Anwendung erforderlich, was sich vorübergehend auf die Verfügbarkeit auswirken kann, wenn während der Bereitstellung keine Techniken zur Vermeidung von Ausfallzeiten angewendet werden.

Skalierung

Eine monolithische Anwendung wird vollständig auf einer einzelnen Computerinstanz gehostet, die häufig hochfähige Hardware erfordert. Wenn ein Teil des Monolithen eine Skalierung erfordert, muss eine andere Kopie der gesamten Anwendung auf einem anderen Computer bereitgestellt werden. Mit einem Monolithen können Sie Anwendungskomponenten nicht einzeln skalieren – es ist alles oder nichts. Skalierungskomponenten, die keine Skalierung erfordern, führen zu einer ineffizienten und kostspieligen Ressourcennutzung.

Umwelt

Monolithische Anwendungen werden in der Regel in einer Hostingumgebung mit vorinstallierten Betriebssystem-, Laufzeit- und Bibliotheksabhängigkeiten bereitgestellt. Diese Umgebung entspricht möglicherweise nicht derjenigen, auf der die Anwendung entwickelt oder getestet wurde. Inkonsistenzen in anwendungsübergreifenden Umgebungen sind eine häufige Ursache von Problemen für monolithische Bereitstellungen.

Kopplung

Eine monolithische Anwendung wird wahrscheinlich eine hohe Kopplung über ihre funktionalen Komponenten hinweg erleben. Ohne harte Grenzen führen Systemänderungen häufig zu unbeabsichtigten und kostspieligen Nebenwirkungen. Neue Features/Fixes werden schwierig, zeitaufwendig und teuer zu implementieren. Updates erfordern umfangreiche Tests. Die Kopplung erschwert auch das Umgestalten von Komponenten oder das Austauschen alternativer Implementierungen. Selbst bei einer Konstruktion mit strikter Trennung der Zuständigkeiten setzt die Architekturerosion ein, wenn sich die monolithische Codebasis durch niemals endende "Sonderfälle" verschlechtert.

Plattformsperre

Eine monolithische Anwendung wird mit einem einzigen Technologiestapel konstruiert. Diese Verpflichtung kann zwar einheitlich sein, aber sie kann zu einer Barriere für Innovationen werden. Neue Features und Komponenten werden mithilfe des aktuellen Stapels der Anwendung erstellt – auch wenn modernere Technologien möglicherweise eine bessere Wahl sind. Ein langfristiges Risiko besteht darin, dass Ihr Technologie-Stack veraltet und obsolet wird. Die Neuanordnung einer gesamten Anwendung auf eine neue, modernere Plattform ist am besten teuer und riskant.

Was sind die Vorteile von Containern und Orchestratoren?

Wir haben Container in Kapitel 1 eingeführt. Wir haben hervorgehoben, wie die Cloud Native Computing Foundation (CNCF) containerisierung als erster Schritt in ihrem Cloud-Native Trail Map bewertet – Anleitungen für Unternehmen, die ihre cloudeigene Reise beginnen. In diesem Abschnitt erläutern wir die Vorteile von Containern.

Docker ist die beliebteste Containerverwaltungsplattform. Es funktioniert mit Containern sowohl unter Linux als auch unter Windows. Container stellen separate, aber reproduzierbare Anwendungsumgebungen bereit, die auf die gleiche Weise auf jedem System ausgeführt werden. Dieser Aspekt macht sie perfekt für die Entwicklung und Das Hosting von Cloud-nativen Diensten. Container sind voneinander isoliert. Zwei Container auf derselben Hosthardware können unterschiedliche Softwareversionen aufweisen, ohne dass Konflikte auftreten.

Container werden durch einfache textbasierte Dateien definiert, die zu Projektartefakten werden und in die Quellcodeverwaltung eingecheckt werden. Während vollständige Server und virtuelle Computer manuelle Aktualisierungen erfordern, sind Container einfach versionsgesteuert. Apps, die in Containern ausgeführt werden können, können mithilfe automatisierter Tools als Teil einer Buildpipeline entwickelt, getestet und bereitgestellt werden.

Container sind unveränderlich. Nachdem Sie einen Container definiert haben, können Sie ihn auf die gleiche Weise neu erstellen und ausführen. Diese Unveränderlichkeit eignet sich für komponentenbasiertes Design. Wenn sich einige Teile einer Anwendung anders entwickeln als andere, warum sollten Sie die gesamte App erneut bereitstellen, wenn Sie nur die Am häufigsten geänderten Teile bereitstellen können? Verschiedene Features und grenzüberschreitende Bedenken einer App können in separate Einheiten unterteilt werden. Abbildung 3-2 zeigt, wie eine monolithische App Container und Microservices nutzen kann, indem bestimmte Features oder Funktionen delegiert werden. Die verbleibenden Funktionen in der App selbst wurden ebenfalls containerisiert.

Aufteilen einer monolithischen App zur Verwendung von Microservices im Back-End.

Abbildung 3-2. Dekompilieren einer monolithischen App, um Microservices zu nutzen.

Jeder cloudeigene Dienst wird in einem separaten Container erstellt und bereitgestellt. Jede kann bei Bedarf aktualisiert werden. Einzelne Dienste können auf Knoten gehostet werden, deren Ressourcen für jeden Dienst geeignet sind. Die Umgebung, in der jeder Dienst ausgeführt wird, ist unveränderlich, über Entwicklungs-, Test- und Produktionsumgebungen hinweg freigegeben und einfach versioniert. Die Kopplung zwischen verschiedenen Bereichen der Anwendung erfolgt explizit als Aufrufe oder Nachrichten zwischen Diensten, nicht kompilierungszeitabhängigkeiten innerhalb des Monolithen. Sie können auch die Technologie auswählen, die eine bestimmte Funktion am besten bietet, ohne dass Änderungen an den restlichen Apps erforderlich sind.

Containerisierte Dienste erfordern eine automatisierte Verwaltung. Es wäre nicht möglich, eine große Gruppe von unabhängig bereitgestellten Containern manuell zu verwalten. Betrachten Sie beispielsweise die folgenden Aufgaben:

  • Wie werden Containerinstanzen in einem Cluster vieler Computer bereitgestellt?
  • Nach der Bereitstellung, wie erkennen und kommunizieren Container miteinander?
  • Wie können Container bei Bedarf hoch- oder herunterskaliert werden?
  • Wie überwachen Sie den Status jedes Containers?
  • Wie schützen Sie einen Container vor Hardware- und Softwarefehlern?
  • Wie lässt sich eine Live-Anwendung ohne Ausfallzeiten mit neueren Containern aktualisieren?

Container-Orchestratoren behandeln und automatisieren diese und andere Bedenken.

Im cloudeigenen Ökosystem ist Kubernetes zum de facto Container Orchestrator geworden. Es ist eine Open-Source-Plattform, die von der Cloud Native Computing Foundation (CNCF) verwaltet wird. Kubernetes automatisiert die Bereitstellungs-, Skalierungs- und Betriebsbedenken von containerisierten Workloads in einem Computercluster. Die Installation und Verwaltung von Kubernetes ist jedoch berüchtigt komplex.

Ein viel besserer Ansatz besteht darin, Kubernetes als verwalteter Dienst von einem Cloudanbieter zu nutzen. Die Azure-Cloud verfügt über eine vollständig verwaltete Kubernetes-Plattform mit dem Titel Azure Kubernetes Service (AKS). AKS abstrahiert die Komplexität und den betriebstechnischen Aufwand der Verwaltung von Kubernetes. Sie nutzen Kubernetes als Clouddienst; Microsoft übernimmt die Verantwortung für die Verwaltung und Unterstützung. AKS lässt sich auch eng in andere Azure-Dienste und Entwicklertools integrieren.

AKS ist eine clusterbasierte Technologie. Ein Pool mit virtuellen Verbundcomputern oder Knoten wird in der Azure-Cloud bereitgestellt. Zusammen bilden sie eine hoch verfügbare Umgebung oder einen Cluster. Der Cluster wird als nahtlose, einzelne Entität für Ihre cloudeigene Anwendung angezeigt. Im Hintergrund stellt AKS Ihre containerisierten Dienste auf diesen Knoten nach einer vordefinierten Strategie bereit, die die Last gleichmäßig verteilt.

Was sind die Vorteile der Skalierung?

Auf Containern basierende Dienste können Skalierungsvorteile nutzen, die von Orchestrierungstools wie Kubernetes bereitgestellt werden. Container wissen nur über sich selbst Bescheid. Sobald Sie mehrere Container haben, die zusammenarbeiten müssen, sollten Sie sie auf einer höheren Ebene organisieren. Das Organisieren einer großen Anzahl von Containern und deren gemeinsamen Abhängigkeiten, wie z. B. die Netzwerkkonfiguration, ist der Punkt, an dem Orchestrierungstools zum Einsatz kommen, um den Tag zu retten! Kubernetes erstellt eine Abstraktionsebene über Gruppen von Containern und organisiert sie in Pods. Pods werden auf Workercomputern ausgeführt, die als Knoten bezeichnet werden. Diese organisierte Struktur wird als Cluster bezeichnet. Abbildung 3-3 zeigt die verschiedenen Komponenten eines Kubernetes-Clusters.

Kubernetes-Clusterkomponenten. Abbildung 3-3. Kubernetes-Clusterkomponenten.

Die Skalierung containerisierter Workloads ist ein wichtiges Feature von Container-Orchestratoren. AKS unterstützt die automatische Skalierung über zwei Dimensionen: Containerinstanzen und Computeknoten. Gemeinsam bieten sie AKS die Möglichkeit, schnell und effizient auf Spitzen der Nachfrage zu reagieren und zusätzliche Ressourcen hinzuzufügen. Wir besprechen die Skalierung in AKS weiter unten in diesem Kapitel.

Deklarativ versus imperativ

Kubernetes unterstützt sowohl deklarative als auch imperative Konfiguration. Der imperative Ansatz umfasst das Ausführen verschiedener Befehle, die Kubernetes mitteilen, was jeder Schritt des Weges zu tun hat. Dieses Image ausführen. Diesen Pod löschen. Diesen Port verfügbar machen. Mit dem deklarativen Ansatz erstellen Sie eine Konfigurationsdatei, die als Manifest bezeichnet wird, um den gewünschten Zustand zu beschreiben, anstatt wie er erreicht werden soll. Kubernetes liest das Manifest und wandelt den gewünschten Endzustand in den tatsächlichen Endzustand um.

Imperative Befehle eignen sich hervorragend zum Lernen und interaktiven Experimentieren. Sie sollten jedoch Kubernetes-Manifestdateien deklarativ erstellen, um eine Infrastruktur als Codeansatz zu nutzen, die zuverlässige und wiederholbare Bereitstellungen bereitstellt. Die Manifestdatei wird zu einem Projektartefakt und wird in Ihrer CI/CD-Pipeline zum Automatisieren von Kubernetes-Bereitstellungen verwendet.

Wenn Sie Ihren Cluster bereits konfiguriert haben, indem Sie imperative Befehle verwendet haben, können Sie ein deklaratives Manifest mithilfe von kubectl get svc SERVICENAME -o yaml > service.yaml exportieren. Dieser Befehl erzeugt ein Manifest ähnlich wie unten gezeigt:

apiVersion: v1
kind: Service
metadata:
  creationTimestamp: "2019-09-13T13:58:47Z"
  labels:
    component: apiserver
    provider: kubernetes
  name: kubernetes
  namespace: default
  resourceVersion: "153"
  selfLink: /api/v1/namespaces/default/services/kubernetes
  uid: 9b1fac62-d62e-11e9-8968-00155d38010d
spec:
  clusterIP: 10.96.0.1
  ports:
  - name: https
    port: 443
    protocol: TCP
    targetPort: 6443
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}

Wenn Sie deklarative Konfiguration verwenden, können Sie eine Vorschau der Änderungen anzeigen, die vorgenommen werden, bevor Sie sie festschreiben, indem Sie kubectl diff -f FOLDERNAME für den Ordner verwenden, in dem sich Ihre Konfigurationsdateien befinden. Sobald Sie sicher sind, dass Sie die Änderungen anwenden möchten, führen Sie kubectl apply -f FOLDERNAME aus. Fügen Sie -R hinzu, um eine Ordnerhierarchie rekursiv zu verarbeiten.

Sie können auch deklarative Konfiguration mit anderen Kubernetes-Features verwenden, einschließlich Bereitstellungen. Deklarative Bereitstellungen helfen beim Verwalten von Versionen, Updates und Skalierung. Sie weisen den Kubernetes-Bereitstellungscontroller an, wie neue Änderungen bereitgestellt, die Auslastung skaliert oder ein Rollback auf eine vorherige Revision durchgeführt werden kann. Wenn ein Cluster instabil ist, gibt eine deklarative Bereitstellung den Cluster automatisch wieder in einen gewünschten Zustand zurück. Wenn beispielsweise ein Knoten abstürzt, stellt der Bereitstellungsmechanismus einen Ersatz erneut bereit, um den gewünschten Zustand zu erreichen.

Durch die Verwendung deklarativer Konfiguration kann die Infrastruktur als Code dargestellt werden, der zusammen mit dem Anwendungscode eingecheckt und versioniert werden kann. Dadurch wird die Änderungssteuerung verbessert und Continuous Deployment mithilfe einer Build- und Bereitstellungspipeline besser unterstützt.

Welche Szenarien sind ideal für Container und Orchestratoren?

Die folgenden Szenarien eignen sich ideal für die Verwendung von Containern und Orchestratoren.

Anwendungen, die hohe Betriebszeit und Skalierbarkeit erfordern

Individuelle Anwendungen mit hohen Anforderungen an Die Verfügbarkeit und Skalierbarkeit eignen sich ideal für cloudeigene Architekturen mit Microservices, Containern und Orchestratoren. Sie können in Containern entwickelt, in versionsierten Umgebungen getestet und in der Produktion ohne Ausfallzeiten bereitgestellt werden. Durch die Verwendung von Kubernetes-Clustern wird sichergestellt, dass solche Apps auch bei Bedarf skaliert und von Knotenfehlern automatisch wiederhergestellt werden können.

Große Anzahl von Anwendungen

Organisationen, die eine große Anzahl von Anwendungen bereitstellen und verwalten, profitieren von Containern und Orchestratoren. Der anfängliche Aufwand für die Einrichtung von containerisierten Umgebungen und Kubernetes-Clustern ist in erster Linie Fixkosten. Das Bereitstellen, Warten und Aktualisieren einzelner Anwendungen hat einen Kostenaufwand, der sich je nach Anzahl der Anwendungen unterscheidet. Über einige Anwendungen hinaus überschreitet die Komplexität der Verwaltung von benutzerdefinierten Anwendungen manuell die Kosten für die Implementierung einer Lösung mit Containern und Orchestratoren.

Wann sollten Sie die Verwendung von Containern und Orchestratoren vermeiden?

Wenn Sie Ihre Anwendung nicht nach den Twelve-Factor App-Prinzipien erstellen können, sollten Sie container und Orchestratoren vermeiden. In diesen Fällen sollten Sie eine VM-basierte Hostingplattform oder möglicherweise ein hybrides System in Betracht ziehen. Damit können Sie bestimmte Funktionen immer in separate Container oder sogar serverlose Funktionen umwandeln.

Entwicklungsressourcen

Dieser Abschnitt enthält eine kurze Liste der Entwicklungsressourcen, die Ihnen bei den ersten Schritten mit Containern und Orchestratoren für Ihre nächste Anwendung helfen können. Wenn Sie nach Anleitungen zum Entwerfen Ihrer cloudeigenen Microservices-Architektur-App suchen, lesen Sie den Begleittitel .NET Microservices: Architecture for Containerized .NET Applications.

Lokale Kubernetes-Entwicklung

Kubernetes-Bereitstellungen bieten einen großen Wert in Produktionsumgebungen, können aber auch lokal auf Ihrem Entwicklungscomputer ausgeführt werden. Sie können zwar unabhängig von einzelnen Microservices arbeiten, aber es kann vorkommen, dass Sie das gesamte System lokal ausführen müssen – genau wie es beim Einsatz in der Produktion ausgeführt wird. Es gibt mehrere Tools, die Ihnen helfen können: Minikube und Docker Desktop. Visual Studio bietet auch Tools für die Docker-Entwicklung.

Minikube

Was ist Minikube? Das Minikube-Projekt sagt: "Minikube implementiert einen lokalen Kubernetes-Cluster unter macOS, Linux und Windows.". Seine Hauptziele sind "das beste Tool für die lokale Kubernetes-Anwendungsentwicklung und die Unterstützung aller Kubernetes-Features, die passen." Die Installation von Minikube ist von Docker getrennt, aber Minikube unterstützt unterschiedliche Hypervisoren als Docker Desktop. Die folgenden Kubernetes-Features werden derzeit von Minikube unterstützt:

  • Domain Name System (DNS)
  • NodePorts
  • ConfigMaps und Geheimnisse
  • Armaturenbretter
  • Containerruntimes: Docker, rkt, CRI-O und containerd
  • Aktivieren der Containernetzwerkschnittstelle (Container Network Interface, CNI)
  • Eingang

Nach der Installation von Minikube können Sie schnell mit der Verwendung beginnen, indem Sie den minikube start Befehl ausführen, der ein Image herunterlädt und den lokalen Kubernetes-Cluster startet. Nachdem der Cluster gestartet wurde, interagieren Sie mit dem Cluster mit den standardmäßigen Kubernetes-Befehlen kubectl .

Docker Desktop

Sie können auch direkt über Docker Desktop unter Windows mit Kubernetes arbeiten. Es ist Ihre einzige Option, wenn Sie Windows-Container verwenden und auch für Nicht-Windows-Container eine gute Wahl ist. Abbildung 3-4 zeigt, wie lokale Kubernetes-Unterstützung beim Ausführen von Docker Desktop aktiviert wird.

Konfigurieren von Kubernetes in Docker Desktop

Abbildung 3-4. Konfigurieren von Kubernetes in Docker Desktop.

Docker Desktop ist das beliebteste Tool zum konfigurieren und ausführen von containerisierten Apps lokal. Wenn Sie mit Docker Desktop arbeiten, können Sie lokal für die gleiche Gruppe von Docker-Containerimages entwickeln, die Sie für die Produktion bereitstellen. Docker Desktop wurde entwickelt, um containerisierte Apps lokal zu erstellen, zu testen und zu versenden. Sie unterstützt sowohl Linux- als auch Windows-Container. Sobald Sie Ihre Images in eine Imageregistrierung übertragen haben, z. B. Azure Container Registry oder Docker Hub, kann AKS sie in der Produktion abrufen und bereitstellen.

Visual Studio Docker Tooling

Visual Studio unterstützt die Docker-Entwicklung für webbasierte Anwendungen. Wenn Sie eine neue ASP.NET Core-Anwendung erstellen, haben Sie die Möglichkeit, sie mit Docker-Unterstützung zu konfigurieren, wie in Abbildung 3-5 dargestellt.

Aktivieren der Docker-Unterstützung in Visual Studio

Abbildung 3-5. Aktivieren der Docker-Unterstützung in Visual Studio

Wenn diese Option ausgewählt ist, wird das Projekt mit einem Dockerfile im Stammverzeichnis erstellt, das zum Erstellen und Hosten der App in einem Docker-Container verwendet werden kann. Ein Beispiel für Dockerfile ist in Abbildung 3-6 dargestellt.

FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["eShopWeb/eShopWeb.csproj", "eShopWeb/"]
RUN dotnet restore "eShopWeb/eShopWeb.csproj"
COPY . .
WORKDIR "/src/eShopWeb"
RUN dotnet build "eShopWeb.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "eShopWeb.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "eShopWeb.dll"]

Abbildung 3-6. Visual Studio generierte das Dockerfile

Nachdem die Unterstützung hinzugefügt wurde, können Sie Ihre Anwendung in einem Docker-Container in Visual Studio ausführen. Abbildung 3-7 zeigt die verschiedenen Ausführungsoptionen, die in einem neuen ASP.NET Core-Projekt verfügbar sind, das mit hinzugefügter Docker-Unterstützung erstellt wurde.

Visual Studio-Docker-Ausführungsoptionen

Abbildung 3-7. Visual Studio-Docker-Ausführungsoptionen

Außerdem können Sie jederzeit Docker-Unterstützung zu einer vorhandenen ASP.NET Core-Anwendung hinzufügen. Klicken Sie im Visual Studio-Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie"Docker-Support>" aus, wie in Abbildung 3-8 dargestellt.

Visual Studio: Hinzufügen der Docker-Unterstützung

Abbildung 3-8. Hinzufügen von Docker-Unterstützung zu Visual Studio

Visual Studio Code: Docker-Tools

Es stehen viele Erweiterungen für Visual Studio Code zur Verfügung, die die Docker-Entwicklung unterstützen.

Microsoft stellt die Docker für Visual Studio Code-Erweiterung bereit. Diese Erweiterung vereinfacht den Prozess des Hinzufügens von Containerunterstützung zu Anwendungen. Es erstellt erforderliche Dateien, erstellt Docker-Images und ermöglicht es Ihnen, Ihre App in einem Container zu debuggen. Die Erweiterung verfügt über einen visuellen Explorer, der das Ausführen von Aktionen für Container und Bilder erleichtert, z. B. "Start", "Beenden", "Überprüfen", "Entfernen" und vieles mehr. Die Erweiterung unterstützt auch Docker Compose, mit dem Sie mehrere ausgeführte Container als einzelne Einheit verwalten können.