Verteilte Lasttests mit Kubernetes

Belastungstests sind der Schlüssel zur Entwicklung einer Back-End-Infrastruktur, da diese zeigen, wie gut das System funktioniert, wenn es um reale Anforderungen geht. Ein wichtiger Aspekt der Belastungstests ist die richtige Simulation von Nutzer- und Geräteverhalten, um mögliche Systemengpässe zu identifizieren und zu verstehen, und zwar weit vor dem Einsatz von Applikationen zur Produktion.

Allerdings kann eine dedizierte Testinfrastruktur teuer und schwer zu pflegen sein, da sie nicht kontinuierlich benötigt wird. Darüber hinaus ist sie oftmals ein einmaliger Investitionsaufwand mit einer festen Kapazität, was es schwierig macht, Belastungstests über die Anfangsinvestition hinaus zu skalieren. Außerdem werden Tests unter Umständen begrenzt. Dies kann zu Produktivitätsverlangsamungen für Entwicklungsteams und zu Anwendungen führen, die vor der Implementierung in einer Produktionsumgebung nicht ordnungsgemäß getestet werden.

Lösungsüberblick

Verteilte Belastungstests mit Cloud Computing sind eine attraktive Option für eine Vielzahl von Testszenarien. Cloudplattformen bieten ein hohes Maß an Infrastruktur-Elastizität, was das Testen von Anwendungen und Diensten mit einer großen Anzahl von simulierten Clients erleichtert. Dabei wird jeweils Traffic generiert, der nach Nutzern oder Geräten gestaltet ist. Darüber hinaus passt das Preismodell von Cloud Computing sehr gut zur elastischen Natur der Belastungstests.

Container, die eine einfache Alternative zum Ausführen von kompletten VM-Instanzen für Anwendungen bieten, eignen sich hervorragend für die schnelle Skalierung von simulierten Clients. Container sind eine hervorragende Abstraktion für den Betrieb von Test-Clients, weil sie einfach, leicht zu implementieren, sofort verfügbar und gut geeignet für einzelne Aufgaben sind.

Die Google Cloud Platform ist eine hervorragende Umgebung für verteilte Belastungstests mit Containern. Die Plattform unterstützt Container als Entitäten erster Klasse und verwendet dafür Google Kubernetes Engine (GKE) auf Basis von Kubernetes, dem Open-Source-System zur Verwaltung von Container-Clustern. GKE ermöglicht die schnelle Bereitstellung von Container-Infrastruktur und -Tools für die Verwaltung implementierter Anwendungen und Ressourcen.

Diese Lösung zeigt, wie GKE zur Bereitstellung eines Frameworks für verteilte Belastungstest verwendet wird. Das Framework verwendet mehrere Container, um Traffic für Belastungstests für eine einfache REST-basierte API zu erzeugen. Obwohl diese Lösung eine einfache Webanwendung testet, kann das gleiche Muster verwendet werden, um komplexere Belastungstestszenarien wie Spiele oder IdD-Anwendungen zu erstellen. Diese Lösung behandelt die allgemeine Architektur eines containerbasierten Frameworks für Belastungstests. Eine Anleitung mit Anweisungen zum Einrichten eines Beispiel-Frameworks finden Sie im Abschnitt "Anleitung" am Ende dieses Dokuments.

In dieser Lösung wird GKE in erster Linie verwendet, um Traffic für Belastungstests zu erzeugen. Das zu prüfende System ist eine einfache Webanwendung, die eine REST API verwendet. Die Lösung nutzt ein bestehendes Framework für Belastungstests, um die API-Interaktionen zu modellieren, die in den folgenden Abschnitten näher erläutert werden. Nach der Bereitstellung des zu prüfenden Systems nutzt die Lösung Kubernetes Engine, um die Aufgaben für die verteilten Belastungstests bereitzustellen.

System Under Test

Gemäß der Software-Test-Terminologie ist das System Under Test das System, das Ihre Tests bewerten sollen. Bei dieser Lösung ist das System Under Test eine kleine Webanwendung, die auf Google App Engine bereitgestellt wird. Die Anwendung stellt grundlegende REST-artige Endpunkte dar, um eingehende HTTP-POST-Anforderungen zu erfassen (eingehende Daten werden nicht beibehalten). In einem realistischen Szenario können Webanwendungen komplex sein und eine Vielzahl von zusätzlichen Komponenten und Diensten wie Caching, Textnachrichten und Persistenz umfassen. Diese Komplexität übersteigt den Umfang dieser Lösung. Weitere Informationen zum Erstellen skalierbarer Webanwendungen auf der Google Cloud Platform finden Sie in der Lösung Skalierbare und stabile Webanwendungen entwickeln.

Der Quellcode für die Beispielanwendung steht als Teil der Anleitung am Ende dieses Dokuments zur Verfügung.

Beispielarbeitslasten

Die Beispielanwendung wird in Anlehnung an die Komponente des Back-End-Dienstes modelliert, die in vielen IdD-Deployments zu finden ist. Geräte werden zuerst bei dem Dienst registriert und melden dann Mess- oder Sensorwerte. Gleichzeitig werden die Geräte regelmäßig neu beim Dienst registriert.

Das folgende Diagramm zeigt eine häufig vorkommende Interaktion der Komponenten eines Back-End-Dienstes.

Ein Diagramm, das eine übliche Interaktion von Back-End-Dienst-Komponenten zeigt

Um diese Interaktion zu modellieren, können Sie Locust nutzen, ein verteiltes, Python-basiertes Belastungstest-Tool, das in der Lage ist, Anfragen an mehrere Zielpfade zu verteilen. Locust kann zum Beispiel Anfragen an die Zielpfade /login und /metrics senden. Es gibt viele Softwarepakete zur Lastgenerierung, darunter JMeter, Gatling und Tsung, von denen eines möglicherweise noch besser auf die Anforderungen Ihres Projekts abgestimmt ist.

Die Arbeitslasten basieren auf der oben beschriebenen Interaktion und sind in Locust als eine Reihe von Aufgaben modelliert. Um konkrete Clients anzugleichen, wird jede Locust-Aufgabe gewichtet. Eine Registrierung erfolgt zum Beispiel bei tausend Client-Anfragen einmal.

Container-basiertes Computing

Aus architektonischer Sicht gibt es zwei Hauptkomponenten, die bei der Bereitstellung dieser Lösungen für verteilte Belastungstests beteiligt sind: das Locust-Container-Image und der Container-Orchestrierungs- und Management-Mechanismus.

Das Locust-Container-Image ist ein Docker-Image, das die Locust-Software enthält. Das Dockerfile befindet sich im zugehörigen Github-Repository (siehe nachstehende Anleitung). Die Docker-Datei verwendet ein Basis-Python-Image und enthält Skripte, um den Locust-Dienst zu starten und die Aufgaben auszuführen.

Diese Lösung verwendet GKE als Mechanismus zur Container-Orchestrierung und -verwaltung. Die auf dem Open-Source-Framework Kubernetes basierende GKE ist das Produkt jahrelanger Erfahrung in der Ausführung, Orchestrierung und Verwaltung von Container-Bereitstellungen bei Google. Container-basiertes Computing ermöglicht es Entwicklern, sich auf ihre Anwendungen zu konzentrieren, anstatt auf Bereitstellungen und Integrationen in Hosting-Umgebungen. Container erleichtern auch die Portabilität von Belastungstests, sodass Container-Anwendungen in mehreren Cloudumgebungen ausgeführt werden können. GKE und Kubernetes führen mehrere spezifische Konzepte für die Containerorchestrierung und -verwaltung ein.

Container-Cluster

Ein Container-Cluster ist eine Gruppe von Compute Engine-Instanzen, die die Grundlage für Ihre gesamte Anwendung bilden. In der GKE- und Kubernetes-Dokumentation werden diese Instanzen als Knoten bezeichnet. Ein Cluster besteht aus einem einzigen Masterknoten und einem oder mehreren Worker-Knoten. Der Master und die Worker laufen alle auf Kubernetes, weshalb Container-Cluster manchmal Kubernetes-Cluster genannt werden. Weitere Informationen zu Clustern finden Sie in der Kubernetes Engine-Dokumentation.

Pods

Ein Pod ist eine eng gekoppelte Gruppe von Containern, die zusammen bereitgestellt werden sollen. Einige Pods enthalten nur einen einzigen Container. Bei dieser Lösung läuft jeder der Locust-Container zum Beispiel in seinem eigenen Pod. Oft enthalten Pods jedoch mehrere Container, die in irgendeiner Weise zusammenarbeiten. Bei dieser Lösung verwendet Kubernetes zum Beispiel einen Pod mit drei Containern, um DNS-Dienste bereitzustellen. In einem Container bietet SkyDNS DNS-Server-Funktionalität. SkyDNS stützt sich auf einen Schlüssel-Werte-Speicher namens etcd, der sich in einem anderen Container befindet. Im dritten Pod-Container fungiert kube2sky als eine Brücke zwischen Kubernetes und SkyDNS.

Replikations-Controller

Ein Replikations-Controller stellt sicher, dass eine bestimmte Anzahl von Pod-Replikaten zu einem beliebigen Zeitpunkt ausgeführt wird. Wenn es zu viele gibt, beendet der Replikations-Controller einige Pods. Wenn es zu wenige gibt, startet er mehr. Diese Lösung hat drei Replikations-Controller: Einer sichert die Existenz eines einzigen DNS-Server-Pods, ein anderer unterhält einen einzigen Locust-Master-Pod und der dritte sichert die Funktion von genau zehn Locust-Worker-Pods.

Dienste

Ein bestimmter Pod kann aus einer Vielzahl von Gründen verschwinden. Dazu zählen Knotenfehler und absichtliche Knotenunterbrechung aufgrund von Updates oder Wartung. Das bedeutet, dass die IP-Adresse eines Pods keine zuverlässige Schnittstelle für diesen Pod zur Verfügung stellt. Ein zuverlässigerer Ansatz würde eine abstrakte Darstellung dieser Schnittstelle verwenden, die unverändert bleibt, selbst wenn der zugrunde liegende Pod verschwindet und durch einen neuen Pod mit einer anderen IP-Adresse ersetzt wird. Ein GKE-Dienst bietet eine solche abstrakte Schnittstelle durch das Definieren einer logischen Reihe von Pods und einer Richtlinie für den Zugriff auf diese Pods. Diese Lösung enthält mehrere Dienste, die Pods oder Reihen von Pods darstellen. Es gibt zum Beispiel einen Dienst für den DNS-Server-Pod, einen weiteren Dienst für den Locust-Master-Pod und einen Dienst, der alle zehn Locust-Worker-Pods darstellt.

Das folgende Diagramm zeigt den Inhalt der Master- und Worker-Knoten.

Ein Diagramm, das den Inhalt der Master- und Worker-Knoten zeigt

Getestetes System bereitstellen

Die Lösung nutzt App Engine zum Ausführen des zu testenden Systems. Um das zu testende System bereitzustellen, benötigen Sie ein aktives Google Cloud Platform-Konto, mit dem Sie das Cloud SDK installieren und ausführen können. Wenn das SDK installiert ist, können Sie die Beispielwebanwendung mit einem einzigen Befehl bereitstellen. Der Quellcode für die Webanwendung steht als Teil der Anleitung am Ende dieses Dokuments zur Verfügung.

Belastungstestaufgaben bereitstellen

Um die Belastungstestaufgaben bereitzustellen, stellen Sie zuerst einen Belastungstest-Master und dann eine Gruppe von zehn Belastungstest-Workern bereit. Mit dieser Menge an Test-Workern können Sie eine erhebliche Menge an Traffic für Testzwecke schaffen. Beachten Sie jedoch, dass die Erzeugung von übermäßigem Traffic an externe Systeme einem Denial-of-Service-Angriff ähneln kann. Lesen Sie die Nutzungsbedingungen der Google Cloud Platform und die Richtlinien zur fairen Nutzung der Google Cloud Platform.

Belastungstest-Master

Die erste Komponente für die Bereitstellung ist der Locust-Master, welcher der Einstiegspunkt zur Ausführung der oben beschriebenen Belastungstestaufgaben ist. Der Locust-Master wird als Replikations-Controller mit einer einzigen Replik eingesetzt, weil wir nur einen Master benötigen. Ein Replikations-Controller ist auch bei der Bereitstellung eines einzelnen Pods nützlich, da er eine hohe Verfügbarkeit gewährleistet.

Die Konfiguration für den Replikations-Controller gibt mehrere Elemente an, einschließlich des Namens des Controllers (locust-master), der Labels für die Organisation (name: locust, role: master) und der Ports, die vom Container ausgesetzt werden müssen (8089 für die Weboberfläche, 5557 und 5558 für die Kommunikation mit den Workern). Diese Informationen werden später verwendet, um den Locust-Worker-Controller zu konfigurieren. Das folgende Snippet enthält die Konfiguration für die Ports:

...
ports:
  - name: locust-master-web
    containerPort: 8089
    protocol: TCP
  - name: locust-master-port-1
    containerPort: 5557
    protocol: TCP
  - name: locust-master-port-2
    containerPort: 5558
    protocol: TCP

Als Nächstes stellen wir einen Dienst bereit, um sicherzustellen, dass die freigegebenen Ports für andere Pods über den hostname:port innerhalb des Clusters zugänglich und über einen beschreibenden Portnamen referenzierbar sind. Die Verwendung eines Dienstes ermöglicht es den Locust-Workern, den Master einfach zu entdecken und zuverlässig mit ihm zu kommunizieren, auch wenn der Master ausfällt und vom Replikations-Controller durch einen neuen Pod ersetzt wird. Der Locust-Master-Dienst enthält auch eine Richtlinie, um eine externe Weiterleitungsregel auf Cluster-Ebene zu erstellen, welche es ermöglicht, dass der externe Traffic auf die Cluster-Ressourcen zugreifen kann. Beachten Sie, dass Sie trotzdem Firewallregeln erstellen müssen, um einen vollständigen Zugriff auf Zielinstanzen zu ermöglichen.

Nachdem Sie den Locust-Master bereitgestellt haben, können Sie über die öffentliche IP-Adresse der externen Weiterleitungsregel auf die Weboberfläche zugreifen. Nachdem Sie die Locust-Worker bereitgestellt haben, können Sie die Simulation starten und die Gesamtstatistik über die Locust-Weboberfläche betrachten.

Belastungstest-Worker

Die nächste Komponente der Bereitstellung umfasst die Locust-Worker, welche die oben beschriebenen Belastungstestaufgaben ausführen. Die Locust-Worker werden von einem einzigen Replikations-Controller bereitgestellt, der zehn Pods erzeugt. Die Pods sind über die Kubernetes-Cluster verteilt. Jeder Pod verwendet Umgebungsvariablen, um wichtige Konfigurationsinformationen wie den Hostnamen des zu testenden Systems und den Hostnamen des Locust-Masters zu steuern. Die Konfiguration des Replikations-Controllers des Workers finden Sie in der unten stehenden Anleitung. Die Konfiguration enthält den Namen des Controllers, locust-worker, Labels für die Organisation, name: locust, role: worker, und die zuvor beschriebenen Umgebungsvariablen. Das folgende Snippet enthält die Konfiguration für den Namen, die Labels und die Anzahl der Repliken:

kind: ReplicationController
  apiVersion: v1
  metadata:
    name: locust-worker
    labels:
      name: locust
      role: worker
  spec:
    replicas: 10
    selector:
      name: locust
      role: worker
...

Für die Locust-Worker muss kein zusätzlicher Dienst bereitgestellt werden, da die Worker-Pods selbst keine eingehende Kommunikation unterstützen müssen – sie verbinden sich direkt mit dem Locust-Master-Pod.

Das folgende Diagramm zeigt die Beziehung zwischen dem Locust-Master und den Locust-Workern.

Diagramm, das Kubernetes-Pods mit Locust-Master- und Worker-Knoten zeigt

Nachdem der Replikations-Controller die Locust-Worker bereitgestellt hat, können Sie zur Weboberfläche des Locust-Masters zurückkehren und sehen, dass die Anzahl der Slaves der Anzahl der bereitgestellten Worker entspricht.

Belastungstestaufgaben ausführen

Belastungstest beginnen

Mit der Locust-Master-Weboberfläche können Sie die Belastungstestaufgaben auf dem zu testenden System auszuführen, wie in der folgenden Abbildung dargestellt:

Ein Screenshot der anfänglichen Locust-Weboberfläche

Geben Sie zu Beginn die Gesamtzahl der zu simulierenden Nutzer und eine Rate an, mit der jeder Nutzer erzeugt werden soll. Klicken Sie anschließend auf Swarm beginnen, um die Simulation zu starten. Im Laufe der Zeit und wenn Nutzer erzeugt werden, sehen Sie, dass die Statistiken nach und nach zu Simulationsmetriken zusammengefasst werden, z. B. die Anzahl der Anfragen pro Sekunde, wie in der folgenden Abbildung gezeigt:

Ein Screenshot der Locust-Weboberfläche während Swarming

Um die Simulation anzuhalten, klicken Sie auf Stopp und der Test wird beendet. Die vollständigen Ergebnisse können in eine Tabelle heruntergeladen werden.

Clients skalieren

Um die Anzahl der simulierten Nutzer zu skalieren, muss die Anzahl der Locust-Worker-Pods erhöht werden. Wie im Locust-Worker-Controller angegeben, stellt der Replikations-Controller zehn Locust-Worker-Pods bereit. Um die Anzahl der Pods zu erhöhen, die vom Replikations-Controller bereitgestellt werden, bietet Kubernetes die Möglichkeit, die Größe der Controller anzupassen, ohne sie neu bereitzustellen. Sie können zum Beispiel die Anzahl der Worker-Pods ändern, indem Sie das Befehlszeilentool kubectl verwenden. Der folgende Befehl skaliert den Pool von Locust-Worker-Pods auf 20:

$ kubectl scale --replicas=20 replicationcontrollers locust-worker

Nachdem Sie den Skalierbefehl erteilt haben, warten Sie ein paar Minuten, bis alle Pods bereitgestellt und gestartet werden. Nachdem alle Pods gestartet sind, kehren Sie zur Weboberfläche des Locust-Masters zurück und starten den Belastungstest noch einmal.

Ressourcen und Kosten

Diese Lösung verwendet vier GKE-Knoten, die jeweils von einer Compute Engine-VM-Standardinstanz des Typs n1-standard-1 unterstützt werden. Mit dem Preisrechner von GCP können Sie eine Schätzung der monatlichen Kosten für die Ausführung des Container-Clusters abrufen. Wie bereits erwähnt, können Sie die Größe des Container-Clusters anpassen und gemäß Ihren Anforderungen skalieren. Mit dem Preisrechner können Sie die Cluster-Properties anpassen, um eine Schätzung der Kosten für eine Skalierung nach oben oder unten zu erhalten.

Tipp

Sie haben gesehen, wie Sie mit GKE ein Belastungstest-Framework für eine einfache Webanwendung erstellen können. Mit GKE können Sie die Anzahl der Containerknoten angeben, die die Grundlage Ihres Belastungstest-Frameworks bilden. Sie können darüber hinaus Ihre Belastungstest-Worker in Pods organisieren und angeben, wie viele Pods von GKE weiterhin ausgeführt werden sollen.

Sie können dieses Muster verwenden, um Belastungstest-Frameworks für eine Vielzahl von Szenarien und Anwendungen zu erstellen. Sie können dieses Muster zum Beispiel nutzen, um Belastungstest-Frameworks für Nachrichtensysteme, Datenstrom-Managementsysteme und Datenbanksysteme zu erstellen. Sie können neue Locust-Aufgaben erstellen oder sogar zu einem anderen Belastungstest-Framework wechseln.

Eine weitere Möglichkeit, das in dieser Lösung präsentierte Framework zu erweitern, besteht darin, die erfassten Metriken anzupassen. So können Sie zum Beispiel die Anfragen pro Sekunde messen, die Antwortlatenz bei Erhöhung der Belastung überwachen oder die Ausfallraten und Fehlerarten bei Antworten überprüfen. Verschiedene Überwachungsoptionen stehen zur Verfügung, unter anderem Stackdriver Monitoring.

Anleitung

Die vollständige Anleitung, einschließlich Vorgehensweise und Quellcode, steht in GitHub unter https://github.com/GoogleCloudPlatform/distributed-load-testing-using-kubernetes zur Verfügung.

Hat Ihnen diese Seite weitergeholfen? Teilen Sie uns Ihr Feedback mit:

Feedback geben zu...