OCI-Queue-Consumer in Kubernetes skalieren

Dieses Playbook zeigt, wie die Features der Oracle Cloud Infrastructure-(OCI-)Queue verwendet werden. Es enthält ein Rezept, das den meisten Anwendungsfällen entspricht, die eine dynamische Skalierung erfordern, basierend auf der Menge des Clientbedarfs, ohne dass Back-Druck oder Performanceengpässe auftreten.

Sie können einen Microservice in der Oracle Kubernetes Engine (OKE) bereitstellen, die Nachrichten aus einer OCI-Queue verarbeitet und dann die Queuetiefe nutzt, um Microservice-Instanzen, die in einem OKE-Cluster ausgeführt werden, horizontal zu skalieren. Das Beispiel enthält einen Nachrichtengenerator, den Sie von überall aus ausführen können, beispielsweise von Ihrem lokalen Rechner aus oder als Teil eines anderen Containers oder einer VM.

Dieses Playbook enthält auch Code- und detaillierte Setupanweisungen, die Sie im Repository Oracle-DevRel GitHub, oci-arch-queue-oke-demo, finden können (auf die Sie über den Abschnitt "Mehr entdecken" dieses Playbooks zugreifen können). Diese Lösung enthält alle Java-Codes, Skripte und Konfigurationsdateien sowie detaillierte Schritte zum Erstellen, Bereitstellen und Ausführen der Bausteine. Dieses Dokument bietet eine Architekturansicht und untersucht wichtige Elemente der Implementierung, einschließlich der Identifizierung der Teile des Codes, die Sie ändern müssen, um die Lösung an Ihre eigenen Anforderungen anzupassen.

Informationen zu OCI-Queue-APIs

Lösungen adressieren selten einzelne Prozesse. Die Kommunikation zwischen Anwendungen muss oft asynchron sein, um zu vermeiden, dass die Lösung durch den begrenztsten Teil einer Lösung eingeschränkt wird (z. B. CPU, Latenz usw.). Sie können diese Probleme lösen, indem Sie eine Kommunikation herstellen, bei der Hersteller und Verbraucher nicht voneinander abhängig sind. Das unterstützt OCI Queue bei sehr hoher Performance.

Während Queue Anwendungen von Bedarfsschwankungen abfedern kann, sollten Sie bei Benutzern nicht viel Zeit zwischen der Nachrichtenerstellung und der Nachrichtenverarbeitung übertragen. Daher muss das Backend je nach Bedarf dynamisch skalieren können. Dieser Bedarf wird durch die Anzahl der in der Queue sitzenden Nachrichten bestimmt; mehr Nachrichten bedeuten mehr Nachfrage und damit mehr Rechenaufwand. Umgekehrt stellt eine leere Queue keinen Bedarf dar und erfordert daher minimale Backend-Ressourcen. Bei der dynamischen Skalierung werden diese konstanten Variationen berücksichtigt.

Architektur

Diese Architektur erfordert eine Warteschlange für die Nachrichten, die sich außerhalb unserer sichtbaren Faultdomains befinden, da es sich um einen vollständig verwalteten Service handelt.

In OCI können Sie Kubernetes mit vom Client verwalteten Knoten oder mit von Oracle verwalteten Knoten ausführen. In diesem Szenario wird der ältere Ansatz von Clientknoten verwendet. Daher müssen Compute Nodes an das Cluster angehängt werden. Diese Knoten sind am besten über die Faultdomains innerhalb einer Availability-Zone verteilt.

Hinweis:

In diesem Playbook kommt die Bedarfsgenerierung von Ihrem lokalen Rechner und somit außerhalb der OCI-Umgebung.

Die letzten beiden Schlüsselelemente steuern die Skalierung. Zunächst wird eine OCI-Funktion regelmäßig aufgerufen und ruft Details zur Queue-Tiefe ab. Um die Art und Weise, wie die Queue-Tiefe ermittelt wird, zu abstrahieren, wird ein API-Gateway verwendet, das den Aufruf von OCI Functions erleichtert.

Schließlich benötigen wir zusätzliche Services wie Vault, um Zugangsdaten für den Zugriff auf die Queue, die Überwachung für allgemeine Zustandsbeobachtung usw. zu speichern.


Beschreibung von queue-scaling-oke-arch.png folgt
Beschreibung der Abbildung Queue-scaling-oke-arch.png

Queue-Skalierung-oke-arch-oracle.zip

Die Zahlen im vorherigen Diagramm stellen diese Ereignisfolge dar:
  1. Der lokal gehostete Producer stellt Nachrichten in die OCI-Queue.
  2. Unsere OCI Consumer-Instanzen rufen Nachrichten aus der Queue ab. Innerhalb des Codes wird die Verbrauchsrate durch eine Verzögerung eingeschränkt. Dadurch wird sichergestellt, dass der Provider mehr Nachrichten generiert, als ein einzelner Consumer aus der Queue entfernen kann. Dadurch funktionieren die Skalierungsmechanismen.
  3. In regelmäßigen Abständen unterstützt ein von Kubernetes geplanter Job KEDA beim Aufrufen der veröffentlichten API, um die Anzahl der Nachrichten in der Queue abzurufen.
  4. Das API-Gateway leitet die Anforderung an eine Instanz der OCI-Funktion weiter.
  5. Die OCI-Funktion fragt die OCI-Queue ab.
  6. Die Antwort wird zurückgegeben, was dazu führt, dass KEDA die Instanzen des Microservice erhöht oder verringert.
Außerdem (a) ermöglicht diese Implementierung dem Benutzer, jederzeit den Status der Queuetiefe abzufragen.
Diese Architektur enthält folgende Komponenten:
  • Region

    Eine OCI-Region ist ein lokalisierter geografischer Bereich, der mindestens ein Data Center enthält, das als Availability-Domains bezeichnet wird. Regionen sind unabhängig von anderen Regionen, und große Entfernungen können sie voneinander trennen (über Länder oder sogar Kontinente).

  • Availability-Domains

    Availability-Domains sind eigenständige, unabhängige Data Center innerhalb einer Region. Die physischen Ressourcen in jeder Availability-Domain sind von den Ressourcen in den anderen Availability-Domains isoliert, was Fehlertoleranz bietet. Availability-Domains haben keine gemeinsamen Infrastrukturservices wie Stromversorgung, Kühlung oder internes Availability-Domainnetzwerk. Es ist daher unwahrscheinlich, dass der Ausfall einer Availability-Domain Auswirkungen auf die anderen Availability-Domains in der Region hat.

  • Faultdomains

    Eine Faultdomain ist eine Gruppierung aus Hardware und Infrastruktur innerhalb einer Availability-Domain. Jede Availability-Domain verfügt über drei Faultdomains mit unabhängiger Stromversorgung und Hardware. Wenn Sie Ressourcen auf mehrere Faultdomains verteilen, können Ihre Anwendungen physische Serverausfälle, Systemwartungen und Stromausfälle innerhalb einer Faultdomain tolerieren.

  • Compartment

    Compartments sind regionsübergreifende logische Partitionen in einem OCI-Mandanten. Mit Compartments können Sie Ihre Ressourcen in Oracle Cloud organisieren, den Zugriff auf die Ressourcen kontrollieren und Nutzungsquoten festlegen. Um den Zugriff auf die Ressourcen in jedem Compartment zu kontrollieren, definieren Sie Policys, die angeben, wer auf die Ressourcen zugreifen kann und welche Aktionen sie ausführen können.

  • Virtuelles Cloud-Netzwerk (VCN) und Subnetze

    Ein VCN ist ein anpassbares, softwaredefiniertes Netzwerk, das Sie in einer OCI-Region einrichten. Wie herkömmliche Data-Center-Netzwerke erhalten Sie von VCNs vollständige Kontrolle über Ihre Netzwerkumgebung. Ein VCN kann mehrere sich nicht überschneidende CIDR-Blöcke aufweisen, die Sie nach dem Erstellen des VCN ändern können. Sie können ein VCN in Subnetze segmentieren, die für eine Region oder eine Availability-Domain gelten können. Jedes Subnetz besteht aus einem zusammenhängenden Adressbereich, der sich nicht mit den anderen Subnetzen im VCN überschneidet. Sie können die Größe eines Subnetzes nach der Erstellung ändern. Ein Subnetz kann öffentlich oder privat sein.

  • Compute-Instanzen

    Mit OCI Compute können Sie Compute-Hosts bereitstellen und verwalten. Sie können Compute-Instanzen mit Ausprägungen starten, die Ihren Ressourcenanforderungen (CPU, Arbeitsspeicher, Netzwerkbandbreite und Speicher) entsprechen. Nach dem Erstellen einer Compute-Instanz können Sie sicher auf die Compute-Instanz zugreifen, sie neu starten, Datenträger anhängen und die Zuordnung aufheben und sie beenden, wenn Sie sie nicht benötigen.

  • Funktionen

    Oracle Functions ist eine vollständig verwaltete, mehrmandantenfähige, skalierbare, bedarfsgesteuerte Functions-as-a-Service-(FaaS-)Plattform. Es basiert auf der Open-Source-Engine des Fn-Projekts. Mit Funktionen können Sie Ihren Code bereitstellen und ihn entweder direkt aufrufen oder als Reaktion auf Ereignisse auslösen. Oracle Functions verwendet Docker-Container, die in OCI Registry gehostet werden.

  • Container Registry

    OCI Registry ist eine von Oracle verwaltete Registry, mit der Sie Ihren Workflow von der Entwicklung bis zur Produktion vereinfachen können. Mit Registry können Sie Entwicklungsartefakte, wie Docker-Images, einfach speichern, freigeben und verwalten. Die hochverfügbare und skalierbare OCI-Architektur stellt sicher, dass Sie Ihre Anwendungen zuverlässig bereitstellen und verwalten können.

  • Container Engine for Kubernetes

    OCI Container Engine for Kubernetes ist ein vollständig verwalteter, skalierbarer und hochverfügbarer Service, mit dem Sie Ihre containerisierten Anwendungen in der Cloud bereitstellen können. Sie geben die Compute-Ressourcen an, die Ihre Anwendungen benötigen, und Container Engine for Kubernetes stellt sie in OCI in einem vorhandenen Mandanten bereit. Container Engine for Kubernetes verwendet Kubernetes, um das Deployment, die Skalierung und die Verwaltung containerisierter Anwendungen auf mehreren Hostclustern zu automatisieren.

  • API Gateway

    Mit Oracle API Gateway können Sie APIs mit Endpunkten veröffentlichen, um die Sichtbarkeit von Funktionen wie Functions, Microservices und anderen Anwendungsschnittstellen zu verwalten. Die Endpunkte bieten feingranulierte Sicherheitskontrollen für Backend-Lösungen sowie abstrakte Implementierung einer API.

  • Queue

    Queue ist ein serverloser, hoch skalierbarer asynchroner Kommunikationsmechanismus. Es ist ideal für die Entkopplung von Services und der Nachrichtenzustellung.

Aspekte

Wenn Sie einen Microservice in Kubernetes bereitstellen, um Nachrichten aus der OCI-Queue zu verarbeiten, sollten Sie Folgendes berücksichtigen:

  • Überlegungen zu Policys für Queues

    Policys zum Steuern und Konfigurieren von OCI-Queues und Policys zum Erstellen und Konsumieren von Nachrichten werden getrennt. Dadurch erhalten Sie genaue Kontrolle über Vorgänge, die über die APIs verfügbar sind. Das bedeutet, dass Sie die Anforderungen und Sicherheitsanforderungen Ihrer Anwendung berücksichtigen müssen. Für die Produktion werden strenge Kontrollen empfohlen. Bei dieser Implementierung werden entspannte Konfigurationseinstellungen verwendet, um die Wahrscheinlichkeit eines Konfigurationsfehlers zu minimieren, der verhindert, dass die Demo funktioniert.

  • Überlegungen zu Kubernetes-Skalierungslimits

    Sie müssen die Rate und Limits für die Backend-Skalierung berücksichtigen. Sie müssen Faktoren berücksichtigen, wie tief die Warteschlange stehen kann, bevor weitere Instanzen des Microservice gestartet werden. Die maximale Anzahl zusätzlicher Instanzen eines Microservice muss ausgeführt werden. Obwohl es verlockend wäre, dies nicht zu binden, in der realen Welt, praktische Begriffe, wenn jemand (versehentlich oder unbeabsichtigt) beginnt, überflutet Ihre Warteschlange mit falschen Nachrichten, Sie wollen nicht die Kosten der zusätzlichen Rechenleistung, die benötigt, um wegzufahren. Außerdem müssen Sie überlegen, wie schnell Sie die zusätzlichen Instanzen Ihres Microservice herunterfahren. Wenn Sie zu schnell herunterfahren, werden Sie feststellen, dass Ihre Umgebung ständig Services startet und stoppt. Unabhängig davon, wie effizient der Microservice ist, entstehen immer Gemeinkosten für das Starten und Stoppen von Serviceinstanzen, die letztendlich Kosten verursachen.

  • Überlegungen zur Skalierungskontrolle

    Der letzte Aspekt bei der Kontrolle der Skalierung besteht darin, ob Sie die Skalierung anwenden und wie sie kontrolliert werden soll. Dieses Szenario nutzt ein CNCF-Projekt namens KEDA (Kubernetes Event Driven Autoscaler). Neben der Ausführung der Backend-Skalierung müssen Sie überlegen, wie die API aufgerufen wird. In diesem Fall können Sie einen geplanten Kubernetes-Job konfigurieren (da der Job von einem Worker-Knoten ausgeführt wird, das Diagramm diesen Ablauf wiedergibt), um die API aufzurufen.

Voraussetzungen

Bevor Sie beginnen, müssen Sie die Umgebung vorbereiten, indem Sie die hier beschriebenen Voraussetzungen erfüllen.

  • Zur Nachrichtengenerierung benötigen Sie Java 8 oder höher (Java 8 zusammen mit Apache Maven installiert).
  • Die Interaktion mit der OCI-Queue erfordert Benutzer und zugehörige Zugangsdaten, um den Zugriff zu ermöglichen. Legen Sie die folgenden Policys fest:
    • Legen Sie diese Policy so fest, dass das zu verwendende Compartment (compartment-name) identifiziert wird:
      allow any-user to manage queues in compartment compartment-name 
    • Um das Lesen oder Schreiben von Benutzern in die OCI-Queue einzuschränken, erstellen Sie OCI-Gruppen mit dem Namen MessageConsumers und MessageProducers, und weisen Sie diesen Gruppen die entsprechenden Benutzer zu. Verwenden Sie die folgenden Policys:
      allow group MessageConsumers to use queues in compartment compartment-name 
      allow group MessageProducers to use queues in compartment compartment-name
    • Stellen Sie dem Producer-Client die OCI-Standardkonfigurationsattribute zur Verfügung, damit sie sich bei OCI authentifizieren und die API verwenden können.
    • Sie müssen Policys zur Unterstützung des dynamischen Verhaltens festlegen, da neue Ressourcen verfügbar sind und Zugriff auf die Queue benötigen. Legen Sie diese Policys fest, indem Sie eine dynamische Gruppe mit den Ressourcen erstellen, die Sie zur elastischen Kontrolle benötigen. Da diese Kontrolle in OCI erfolgt, verwenden Sie einen Instanz-Principal. Rufen Sie diese Gruppe queue_dg auf. Verwenden Sie die folgenden Policy-Anweisungen:
      ALL {instance.compartment.id='instance Compartment id (OCID)'} 
      allow dynamic-group queue_dg to use queues in compartment queue_parent_compartment 
      Dabei ist instance Compartment id (OCID) das Compartment, das die Worker-Knoten enthält.

Informationen zum Java-SDK

Die drei Codekomponenten (Produzent, Consumer und Funktion) verwenden alle OCI-APIs. Die einfachste Möglichkeit zur Interaktion mit den APIs ist das Java-SDK. Die von OCI bereitgestellten SDKs bieten eine Reihe von Überzeugungsfunktionen, die Informationen abrufen, die für die Authentifizierung und Autorisierung der Aufrufe von OCI-Services erforderlich sind. Die SDKs übernehmen Joshua Blochs Variante des Builder-Musters. Weitere Informationen zum SDK finden Sie unter Java-SDK. Das Oracle-Repository DevRel GitHub enthält weitere Beispiele für die hier verwendeten SDKs, z.B. unter https://github.com/oracle-devrel/oci-arch-queue-demo.