Automatische Skalierung von Kubernetes-Anwendungen mit Prometheus und KEDA

Automatische Skalierung von Kubernetes-Anwendungen mit Prometheus und KEDABallonmann von Cimuanos

Skalierbarkeit ist eine zentrale Voraussetzung für Cloud-Anwendungen. Mit Kubernetes ist die Skalierung einer Anwendung so einfach wie die Erhöhung der Anzahl der Replikate für die entsprechende Bereitstellung oder ReplicaSet – aber es ist ein manueller Prozess.

Kubernetes ermöglicht die automatische Skalierung von Anwendungen (d. h. Pods in einer Bereitstellung oder ReplicaSet) auf deklarative Weise mithilfe der Horizontal Pod Autoscaler-Spezifikation. Das Standardkriterium für die automatische Skalierung sind CPU-Nutzungsmetriken (Ressourcenmetriken). Sie können jedoch benutzerdefinierte und extern bereitgestellte Metriken integrieren.

Team Kubernetes aaS von Mail.ru hat einen Artikel über die Verwendung externer Metriken zur automatischen Skalierung einer Kubernetes-Anwendung übersetzt. Um zu zeigen, wie alles funktioniert, verwendet der Autor HTTP-Zugriffsanfragemetriken, die mithilfe von Prometheus erfasst werden.

Anstelle der horizontalen Autoskalierung von Pods wird Kubernetes Event Driven Autoscaling (KEDA) verwendet, ein Open-Source-Kubernetes-Operator. Es lässt sich nativ in Horizontal Pod Autoscaler integrieren, um eine nahtlose automatische Skalierung (einschließlich auf/von Null) für ereignisgesteuerte Workloads zu ermöglichen. Code verfügbar unter GitHub.

Kurzer Überblick über das System

Automatische Skalierung von Kubernetes-Anwendungen mit Prometheus und KEDA

Das Diagramm zeigt eine kurze Beschreibung, wie alles funktioniert:

  1. Die Anwendung stellt Metriken zur Anzahl der HTTP-Treffer im Prometheus-Format bereit.
  2. Prometheus ist für die Erfassung dieser Metriken konfiguriert.
  3. Der Prometheus-Skalierer in KEDA ist so konfiguriert, dass die Anwendung automatisch basierend auf der Anzahl der HTTP-Treffer skaliert wird.

Jetzt erzähle ich Ihnen ausführlich über jedes Element.

KEDA und Prometheus

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

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

Scaler unterstützen mehrere Datenquellen, zum Beispiel Kafka, Redis, Prometheus. Das heißt, KEDA kann verwendet werden, um Kubernetes-Bereitstellungen automatisch zu skalieren, indem Prometheus-Metriken als Kriterien verwendet werden.

Testanwendung

Die Golang-Testanwendung bietet Zugriff über HTTP und führt zwei wichtige Funktionen aus:

  1. Verwendet die Prometheus Go-Clientbibliothek, um die Anwendung zu instrumentieren und die http_requests-Metrik bereitzustellen, die eine Trefferanzahl enthält. Der Endpunkt, an dem Prometheus-Metriken verfügbar sind, befindet sich am URI /metrics.
    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "number of http requests",
       })
    
  2. Als Antwort auf eine Anfrage GET Die Anwendung erhöht den Wert des Schlüssels (access_count) in Redis. Dies ist eine einfache Möglichkeit, die Arbeit als Teil eines HTTP-Handlers zu erledigen und auch Prometheus-Metriken zu überprüfen. Der Metrikwert muss mit dem Wert übereinstimmen access_count in Redis.
    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 Anwendung wird über Kubernetes bereitgestellt Deployment. Außerdem wird ein Dienst erstellt ClusterIPermöglicht es dem Prometheus-Server, Anwendungsmetriken abzurufen.

Hier 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 die Benutzeroberfläche Prometheus;
  • ClusterRole, ClusterRoleBinding и ServiceAccount – zur automatischen Erkennung von Diensten in Kubernetes (Auto-Discovery).

Hier Manifest zum Ausführen von Prometheus.

KEDA Prometheus ScaledObject

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

ScaledObject Enthält Informationen zur Bereitstellungsskalierung, Metadaten der Ereignisquelle (z. B. Verbindungsgeheimnisse, Warteschlangenname), Abfrageintervall, Wiederherstellungszeitraum und andere Daten. Dies führt zur entsprechenden Autoscaling-Ressource (HPA-Definition) zur Skalierung der Bereitstellung.

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

Hier ist die Definition ScaledObject In unserem Beispiel wird ein Scaler verwendet 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]))

Bitte beachten Sie folgende Punkte:

  1. Er zeigt darauf Deployment Mit Namen go-prom-app.
  2. Triggertyp - Prometheus. Die Prometheus-Serveradresse wird zusammen mit dem Metriknamen, dem Schwellenwert usw. erwähnt PromQL-Abfrage, die verwendet wird. PromQL-Abfrage – sum(rate(http_requests[2m])).
  3. Согласно pollingInterval,KEDA fordert alle fünfzehn Sekunden ein Ziel von Prometheus an. Mindestens einer unter (minReplicaCount), und die maximale Anzahl von Pods überschreitet nicht maxReplicaCount (in diesem Beispiel - zehn).

Kann installiert werden minReplicaCount gleich Null. In diesem Fall aktiviert KEDA die Null-zu-Eins-Bereitstellung und stellt dann die HPA für eine weitere automatische Skalierung bereit. Auch die umgekehrte Reihenfolge ist möglich, also eine Skalierung von eins auf null. Im Beispiel haben wir nicht Null ausgewählt, da es sich um einen HTTP-Dienst und nicht um ein On-Demand-System handelt.

Die Magie der automatischen Skalierung

Der Schwellenwert wird als Auslöser für die Skalierung der Bereitstellung verwendet. In unserem Beispiel die PromQL-Abfrage sum(rate (http_requests [2m])) gibt die aggregierte HTTP-Anfragerate (Anfragen pro Sekunde) zurück, gemessen in den letzten zwei Minuten.

Da der Schwellenwert drei beträgt, bedeutet dies, dass der Wert um eins unterschritten wird sum(rate (http_requests [2m])) weniger als drei. Steigt der Wert, kommt jedes Mal ein weiterer Sub hinzu sum(rate (http_requests [2m])) erhöht sich um drei. Wenn der Wert beispielsweise zwischen 12 und 14 liegt, beträgt die Anzahl der Pods vier.

Jetzt versuchen wir es einzurichten!

Voreinstellung

Sie benötigen lediglich einen Kubernetes-Cluster und ein konfiguriertes Dienstprogramm kubectl. In diesem Beispiel wird ein Cluster verwendet minikube, aber Sie können auch jedes andere nehmen. Um einen Cluster zu installieren, gibt es руководство.

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/

Setzen kubectlum auf den 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-Installation

Sie können KEDA auf verschiedene Arten bereitstellen, diese sind in aufgeführt Dokumentation. Ich verwende monolithisches YAML:

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

KEDA und seine Komponenten werden im Namespace installiert keda. Befehl zur Überprüfung:

kubectl get pods -n keda

Warten Sie, bis KEDA Operator gestartet ist, und gehen Sie zu Running State. Und danach geht es weiter.

Redis mit Helm installieren

Wenn Sie Helm nicht installiert haben, verwenden Sie dies Führung. Befehl zur Installation auf dem Mac:

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

helm init Initialisiert die lokale Befehlszeilenschnittstelle und installiert sie auch Tiller zum Kubernetes-Cluster.

kubectl get pods -n kube-system | grep tiller

Warten Sie, bis der Tiller-Pod in den Betriebszustand übergeht.

Anmerkung des Übersetzers: Der Autor verwendet Helm@2, was die Installation der Tiller-Serverkomponente erfordert. Jetzt ist Helm@3 relevant, es erfordert keinen Serverteil.

Nach der Installation von Helm genügt ein Befehl, um Redis zu starten:

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

Stellen Sie sicher, dass Redis erfolgreich gestartet wurde:

kubectl get pods/redis-server-master-0

Warten Sie, bis Redis in den Status wechselt Running.

Anwendungsbereitstellung

Bereitstellungsbefehl:

kubectl apply -f go-app.yaml

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

Überprüfen Sie, ob alles begonnen hat:

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

Warten Sie, bis Redis in den Status wechselt Running.

Bereitstellen eines Prometheus-Servers

Das Prometheus-Manifest verwendet Kubernetes Service Discovery für Prometheus. Es ermöglicht die dynamische Erkennung von Anwendungs-Pods basierend auf dem Service-Label.

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

Bereitstellen:

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 begonnen hat:

kubectl get pods -l=app=prometheus-server

Warten Sie, bis Prometheus in den Staat geht Running.

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

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 KEDA-Betreiberprotokolle:

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

Das Ergebnis sieht in etwa 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"

Schauen Sie unter Bewerbungen nach. Eine Instanz muss ausgeführt werden, weil minReplicaCount gleich 1:

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

Überprüfen Sie, ob die HPA-Ressource erfolgreich erstellt wurde:

kubectl get hpa

Sie sollten etwa Folgendes sehen:

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

Gesundheitscheck: Anwendungszugriff

Um auf den REST-Endpunkt unserer Anwendung zuzugreifen, führen Sie Folgendes aus:

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

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

curl http://localhost:8080/test

Das Ergebnis sieht in etwa so aus:

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

Überprüfen Sie an dieser Stelle auch Redis. Sie werden sehen, dass der Schlüssel access_count auf 1 erhöht:

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

Stellen Sie sicher, dass der Metrikwert lautet http_requests das gleiche:

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

Erstellung laden

Wir werden verwenden Hallo — Dienstprogramm zur Lasterzeugung:

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

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

Starte es:

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

Standardmäßig sendet das Dienstprogramm 200 Anfragen. Sie können dies mithilfe von Prometheus-Metriken sowie 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

Validieren Sie den Wert der tatsächlichen Metrik (zurückgegeben von der PromQL-Abfrage):

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 1,686057971014493 und wird im Feld angezeigt value. Dies reicht für die Skalierung nicht aus, da der von uns festgelegte Schwellenwert 3 beträgt.

Mehr Ladung!

Überwachen 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 werden Sie sehen, wie HPA die Bereitstellung skaliert und neue Pods startet. Überprüfen Sie Ihr 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 inkonsistent ist, wird die Bereitstellung so weit reduziert, dass nur noch ein Pod ausgeführt wird. Wenn Sie die tatsächliche Metrik (die von der PromQL-Abfrage zurückgegeben wird) überprüfen möchten, verwenden Sie den folgenden Befehl:

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

Очистка

//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

Abschluss

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 seine Metriken auch über den Metrics Server dem Horizontal Pod Autoscaler zur Verfügung.

Good Luck!

Was es sonst noch zu lesen gibt:

  1. Best Practices und Best Practices für die Ausführung 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 in Telegram.

Source: habr.com

Kommentar hinzufügen