Automatische Skalierung von Kubernetes-Anwendungen mit Prometheus und KEDA

Balloon Man von Cimuanos



Skalierbarkeit ist eine wichtige Voraussetzung für Cloud-Anwendungen. Mit Kubernetes ist das Skalieren einer Anwendung so einfach wie das Erhöhen der Anzahl von Replikaten für eine geeignete Bereitstellung oderReplicaSet- aber es ist ein manueller Prozess.



Mit Kubernetes können AnwendungenReplicaSetmithilfe der Horizontal Pod Autoscaler-Spezifikation deklarativautomatisch skaliert werden (d. H. Pods in Bereitstellung oder). Das Standardkriterium für die automatische Skalierung sind CPU-Auslastungsmetriken (Ressourcenmetriken). Benutzerdefinierte Metriken und extern bereitgestellte Metriken können jedoch integriert werden. Kubernetes aaS



Team von Mail.ruübersetzte einen Artikel über die Verwendung externer Metriken zum automatischen Skalieren einer Kubernetes-Anwendung. Um zu zeigen, wie alles funktioniert, verwendet der Autor HTTP-Zugriffsanforderungsmetriken, die mit Prometheus erfasst werden.



Kubernetes Event Driven Autoscaling (KEDA) ist ein Open-Source-Kubernetes-Operator, anstatt horizontal Pods automatisch zu skalieren. Es lässt sich nativ in den Horizontal Pod Autoscaler integrieren, um eine reibungslose automatische Skalierung (einschließlich von / nach Null) für ereignisgesteuerte Workloads zu ermöglichen. Der Code ist auf GitHub verfügbar .



Kurzbeschreibung des Systembetriebs







Das Diagramm zeigt eine kurze Beschreibung, wie alles funktioniert:



  1. Die Anwendung bietet Metriken für die Anzahl der HTTP-Anforderungen im Prometheus-Format.
  2. Prometheus soll diese Metriken sammeln.
  3. Der Prometheus-Skalierer in KEDA ist so konfiguriert, dass die Anwendung automatisch basierend auf der Anzahl der HTTP-Anforderungen skaliert wird.


Jetzt werde ich Ihnen detailliert über jedes Element berichten.



KEDA und Prometheus



Prometheus ist ein Open-Source-Toolkit zur Systemüberwachung und -warnung, das Teil der Cloud Native Computing Foundation ist . Sammelt Metriken aus verschiedenen Quellen und speichert sie als Zeitreihendaten. Zur Visualisierung von Daten können Sie Grafana oder andere Visualisierungstools verwenden, die mit der Kubernetes-API arbeiten.



KEDA unterstützt das Scaler-Konzept - es fungiert als Brücke zwischen KEDA und dem externen System. Die Scaler-Implementierung ist für jedes Zielsystem spezifisch und extrahiert Daten daraus. KEDA verwendet sie dann zur Steuerung der automatischen Skalierung.



Skalierer unterstützen mehrere Datenquellen wie Kafka, Redis, Prometheus. Das heißt, KEDA kann verwendet werden, um Kubernetes-Bereitstellungen automatisch anhand von Prometheus-Metriken als Kriterien zu skalieren.



Anwendung testen



Die Golang-Testanwendung bietet HTTP-Zugriff und erfüllt zwei wichtige Funktionen:



  1. Verwendet die Prometheus Go-Clientbibliothek, um die Anwendung zu instrumentieren und die Metrik http_requests bereitzustellen, die einen Trefferzähler enthält. Der Endpunkt, an dem Prometheus-Metriken verfügbar sind, befindet sich nach URI /metrics.



    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "number of http requests",
       })
    
  2. Als Antwort auf die Anforderung GETerhöht die Anwendung den Wert key ( access_count) in Redis. Dies ist eine einfache Möglichkeit, die Aufgabe als Teil eines HTTP-Handlers zu erledigen und Prometheus-Metriken zu überprüfen. Der Metrikwert muss mit dem Wert access_countin Redis übereinstimmen .



    func main() {
           http.Handle("/metrics", promhttp.Handler())
           http.HandleFunc("/test", func(w http.ResponseWriter, r 
    *http.Request) {
               defer httpRequestsCounter.Inc()
               count, err := client.Incr(redisCounterName).Result()
               if err != nil {
                   fmt.Println("Unable to increment redis counter", err)
                   os.Exit(1)
               }
               resp := "Accessed on " + time.Now().String() + "\nAccess count " + strconv.Itoa(int(count))
               w.Write([]byte(resp))
           })
           http.ListenAndServe(":8080", nil)
       }
    


Die App wird über über Kubernetes bereitgestellt Deployment. Außerdem wird ein Dienst erstellt ClusterIP, mit dem der Prometheus-Server Anwendungsmetriken empfangen kann.



Hier ist das Bereitstellungsmanifest für die Anwendung .



Prometheus Server



Das Prometheus-Bereitstellungsmanifest besteht aus:



  • ConfigMap - um die Prometheus-Konfiguration zu übertragen;
  • Deployment - für die Bereitstellung von Prometheus in einem Kubernetes-Cluster;
  • ClusterIP - Dienst für den Zugriff auf UI Prometheus;
  • ClusterRole, ClusterRoleBindingUnd ServiceAccount- für die automatische Erkennung von Diensten in Kubernetes (Auto-Discovery).


Hier ist das Manifest zum Ausführen von Prometheus .



KEDA Prometheus ScaledObject



Der Skalierer fungiert als Brücke zwischen KEDA und dem externen System, von dem aus die Metriken abgerufen werden. ScaledObjectIst eine benutzerdefinierte Ressource, muss sie bereitgestellt werden, um die Bereitstellung mit der Ereignisquelle zu synchronisieren, in diesem Fall Prometheus.



ScaledObjectEnthält Informationen zur Skalierung der Bereitstellung, Metadaten der Ereignisquelle (z. B. Verbindungsgeheimnisse, Warteschlangenname), Abfrageintervall, Wiederherstellungszeitraum und andere Informationen. Daraus ergibt sich die entsprechende Ressource für die automatische Skalierung (HPA-Definition) zur Skalierung der Bereitstellung.



Wenn ein Objekt ScaledObjectgelöscht wird, wird die entsprechende HPA-Definition gelöscht.



Hier ist die Definition ScaledObjectfür unser Beispiel, es verwendet einen Skalierer Prometheus:



apiVersion: keda.k8s.io/v1alpha1
kind: ScaledObject
metadata:
 name: prometheus-scaledobject
 namespace: default
 labels:
   deploymentName: go-prom-app
spec:
 scaleTargetRef:
   deploymentName: go-prom-app
 pollingInterval: 15
 cooldownPeriod:  30
 minReplicaCount: 1
 maxReplicaCount: 10
 triggers:
 - type: prometheus
   metadata:
     serverAddress: 
http://prometheus-service.default.svc.cluster.local:9090
     metricName: access_frequency
     threshold: '3'
     query: sum(rate(http_requests[2m]))


Beachten Sie die folgenden Punkte:



  1. Er zeigt Deploymentmit einem Namen darauf go-prom-app.
  2. Auslösertyp - Prometheus. Die Prometheus-Serveradresse wird zusammen mit dem Metriknamen , dem Schwellenwert und der zu verwendenden PromQL-Anforderung angegeben . PromQL-Anfrage - sum(rate(http_requests[2m])).
  3. Laut pollingIntervalKEDA fordert Prometheus alle fünfzehn Sekunden ein Ziel an. Es wird mindestens ein Pod ( minReplicaCount) unterstützt , und die maximale Anzahl von Pods wird nicht überschritten maxReplicaCount(in diesem Beispiel zehn).


Kann minReplicaCountauf Null gesetzt werden. In diesem Fall aktiviert KEDA die Null-zu-Eins-Bereitstellung und stellt dann HPA für die weitere automatische Skalierung bereit. Die umgekehrte Reihenfolge ist auch möglich, dh eine Skalierung von eins auf null. Im Beispiel haben wir nicht Null ausgewählt, da dies ein HTTP-Dienst und kein System on Demand ist.



Die Magie in der automatischen Skalierung



Der Schwellenwert wird als Auslöser zum Skalieren der Bereitstellung verwendet. In unserem Beispiel gibt die PromQL-Abfrage sum(rate (http_requests [2m]))den aggregierten Wert der HTTP-Anforderungsrate (Anforderungen pro Sekunde) zurück, der in den letzten zwei Minuten gemessen wurde.



Da der Schwellenwert drei ist, gibt es einen unter, solange der Wert sum(rate (http_requests [2m]))kleiner als drei ist. Wenn sich der Wert erhöht, wird jedes Mal, wenn er sum(rate (http_requests [2m]))um drei erhöht wird, ein zusätzliches Unter hinzugefügt . Wenn der Wert beispielsweise zwischen 12 und 14 liegt, beträgt die Anzahl der Pods vier.



Versuchen wir nun zu konfigurieren!



Voreinstellung



Sie benötigen lediglich einen Kubernetes-Cluster und ein benutzerdefiniertes Dienstprogramm kubectl. In diesem Beispiel wird ein Cluster verwendet minikube, Sie können jedoch auch einen anderen verwenden. Es gibt eine Anleitung zur Installation des Clusters .



Installieren Sie die neueste Version auf dem Mac:



curl -Lo minikube 
https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 \
&& chmod +x minikube
sudo mkdir -p /usr/local/bin/
sudo install minikube /usr/local/bin/


Installieren Sie kubectl, um auf Ihren Kubernetes-Cluster zuzugreifen.



Installieren Sie die neueste Version auf dem Mac:



curl -LO 
"https://storage.googleapis.com/kubernetes-release/release/$(curl -s
https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
kubectl version


KEDA installieren



Sie können KEDA auf verschiedene Arten bereitstellen. Diese sind in der Dokumentation aufgeführt . Ich benutze monolithische YAML:



kubectl apply -f
https://raw.githubusercontent.com/kedacore/keda/master/deploy/KedaScaleController.yaml


KEDA und seine Komponenten werden im Namespace installiert keda. Zu überprüfender Befehl:



kubectl get pods -n keda


Warten Sie, wenn unter KEDA Operator startet - geht zu Running State. Und dann weiter.



Redis mit Helm installieren



Wenn Sie Helm nicht installiert haben, verwenden Sie dieses Tutorial . Befehl zur Installation auf dem Mac:



brew install kubernetes-helm
helm init --history-max 200


helm initInitialisiert die lokale CLI und wird auch Tillerim Kubernetes-Cluster installiert .



kubectl get pods -n kube-system | grep tiller


Warten Sie, bis der Pinnen-Pod in den Betriebszustand wechselt.



Anmerkung des Übersetzers : Der Autor verwendet Helm @ 2, für das die Tiller-Serverkomponente installiert sein muss. Helm @ 3 ist derzeit relevant, es wird kein Serverteil benötigt.



Nach der Installation von Helm reicht ein Befehl aus, um Redis zu starten:



helm install --name redis-server --set cluster.enabled=false --set 
usePassword=false stable/redis


Überprüfen Sie, ob Redis erfolgreich gestartet wurde:



kubectl get pods/redis-server-master-0


Warten Sie, bis unter Redis der Status aktiviert ist Running.



Stellen Sie die Anwendung bereit



Befehl zur Bereitstellung:



kubectl apply -f go-app.yaml

//output
deployment.apps/go-prom-app created
service/go-prom-app-service created


Überprüfen Sie, ob alles gestartet ist:



kubectl get pods -l=app=go-prom-app


Warten Sie, bis Redis in den Status übergeht Running.



Bereitstellen von Prometheus Server



Das Prometheus-Manifest verwendet Kubernetes Service Discovery für Prometheus . Sie können damit Anwendungs-Pods basierend auf einem Service-Label dynamisch erkennen.



kubernetes_sd_configs:
   - role: service
   relabel_configs:
   - source_labels: [__meta_kubernetes_service_label_run]
     regex: go-prom-app-service
     action: keep


Für die Bereitstellung:



kubectl apply -f prometheus.yaml

//output
clusterrole.rbac.authorization.k8s.io/prometheus created
serviceaccount/default configured
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
configmap/prom-conf created
deployment.extensions/prometheus-deployment created
service/prometheus-service created


Überprüfen Sie, ob alles gestartet ist:



kubectl get pods -l=app=prometheus-server


Warten Sie, bis unter Prometheus der Zustand erreicht ist Running.



Verwenden Sie kubectl port-forwarddiese Option, um auf die Prometheus-Benutzeroberfläche (oder den API-Server) unter http: // localhost: 9090 zuzugreifen .



kubectl port-forward service/prometheus-service 9090


Bereitstellen der KEDA-Autoscaling-Konfiguration



Befehl zum Erstellen ScaledObject:



kubectl apply -f keda-prometheus-scaledobject.yaml


Überprüfen Sie die Protokolle des KEDA-Betreibers:



KEDA_POD_NAME=$(kubectl get pods -n keda 
-o=jsonpath='{.items[0].metadata.name}')
kubectl logs $KEDA_POD_NAME -n keda


Das Ergebnis sieht ungefähr so ​​aus:



time="2019-10-15T09:38:28Z" level=info msg="Watching ScaledObject:
default/prometheus-scaledobject"
time="2019-10-15T09:38:28Z" level=info msg="Created HPA with 
namespace default and name keda-hpa-go-prom-app"


Überprüfen Sie unter Anwendungen. Eine Instanz sollte ausgeführt werden, da es minReplicaCount1 ist:



kubectl get pods -l=app=go-prom-app


Stellen Sie sicher, dass die HPA-Ressource erfolgreich erstellt wurde:



kubectl get hpa


Sie sollten etwas sehen wie:



NAME                   REFERENCE                TARGETS     MINPODS   MAXPODS   REPLICAS   AGE
keda-hpa-go-prom-app   Deployment/go-prom-app   0/3 (avg)   1         10        1          45s


Integritätsprüfung: Zugriff auf die Anwendung



Führen Sie Folgendes aus, um auf den REST-Endpunkt unserer Anwendung zuzugreifen:



kubectl port-forward service/go-prom-app-service 8080


Sie können jetzt über die Adresse http: // localhost: 8080 auf die Go-App zugreifen . Führen Sie dazu den folgenden Befehl aus:



curl http://localhost:8080/test


Das Ergebnis sieht ungefähr so ​​aus:



Accessed on 2019-10-21 11:29:10.560385986 +0000 UTC 
m=+406004.817901246
Access count 1


Schauen Sie sich an dieser Stelle auch Redis an. Sie werden sehen, dass der Schlüssel access_countauf 1 erhöht wird:



kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
"1"


Stellen Sie sicher, dass der Metrikwert gleich http_requestsist:



curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests number of http requests
# TYPE http_requests counter
http_requests 1


Ladeerstellung



Wir werden hey verwenden , ein Dienstprogramm, um die Last zu erzeugen:



curl -o hey https://storage.googleapis.com/hey-release/hey_darwin_amd64 
&& chmod a+x hey


Sie können das Dienstprogramm auch für Linux oder Windows herunterladen .



Starte es:



./hey http://localhost:8080/test


Standardmäßig sendet das Dienstprogramm 200 Anforderungen. Sie können dies sowohl mit Prometheus-Metriken als auch mit Redis überprüfen.



curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests number of http requests
# TYPE http_requests counter
http_requests 201
kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
201


Bestätigen Sie den tatsächlichen Metrikwert (von der PromQL-Abfrage zurückgegeben):



curl -g 
'http://localhost:9090/api/v1/query?query=sum(rate(http_requests[2m]))'
//output
{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1571734214.228,"1.686057971014493"]}]}}


In diesem Fall ist das tatsächliche Ergebnis gleich 1,686057971014493und wird im Feld angezeigt value. Dies reicht für die Skalierung nicht aus, da der von uns festgelegte Schwellenwert 3 ist.



Mehr Ladung!



Verfolgen Sie im neuen Terminal die Anzahl der Anwendungs-Pods:



kubectl get pods -l=app=go-prom-app -w


Erhöhen wir die Last mit dem Befehl:



./hey -n 2000 http://localhost:8080/test


Nach einer Weile wird HPA die Bereitstellung skalieren und neue Pods starten. Überprüfen Sie die HPA, um sicherzustellen, dass:



kubectl get hpa
NAME                   REFERENCE                TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
keda-hpa-go-prom-app   Deployment/go-prom-app   1830m/3 (avg)   1         10        6          4m22s


Wenn die Last nicht konstant ist, wird die Bereitstellung so weit reduziert, dass nur noch ein Pod funktioniert. Wenn Sie die tatsächliche Metrik überprüfen möchten (von der PromQL-Abfrage zurückgegeben), verwenden Sie den folgenden Befehl:



curl -g 
'http://localhost:9090/api/v1/query?query=sum(rate(http_requests[2m]))'


Reinigung



//Delete KEDA
kubectl delete namespace keda
//Delete the app, Prometheus server and KEDA scaled object
kubectl delete -f .
//Delete Redis
helm del --purge redis-server


Fazit



Mit KEDA können Sie Ihre Kubernetes-Bereitstellungen automatisch (auf / von Null) basierend auf Daten aus externen Metriken skalieren. Zum Beispiel basierend auf Prometheus-Metriken, Warteschlangenlänge in Redis, Verbraucherlatenz im Kafka-Thema.



KEDA lässt sich in eine externe Quelle integrieren und stellt über den Metrics Server auch Metriken für den Horizontal Pod Autoscaler bereit.



Viel Glück!



Was noch zu lesen:



  1. Best Practices und Richtlinien zum Ausführen von Containern und Kubernetes in Produktionsumgebungen .
  2. Über 90 nützliche Tools für Kubernetes: Bereitstellung, Verwaltung, Überwachung, Sicherheit und mehr .
  3. Unser Kanal Rund um Kubernetes im Telegramm .



All Articles