Automatyczne skalowanie aplikacji Kubernetes za pomocą Prometheus i KEDA

Automatyczne skalowanie aplikacji Kubernetes za pomocą Prometheus i KEDABalloon Man autorstwa Cimuanos

Skalowalność to kluczowy wymóg dla aplikacji chmurowych. Z Kubernetes skalowanie aplikacji jest tak proste, jak zwiększenie liczby replik dla danego wdrożenia lub ReplicaSet — ale to żmudny proces.

Kubernetes umożliwia automatyczne skalowanie aplikacji (to znaczy Pod w wdrożeniu lub ReplicaSet) w sposób deklaratywny, korzystając ze specyfikacji Horizontal Pod Autoscaler. Domyślnym kryterium automatycznego skalowania są metryki wykorzystania CPU (metryki zasobów), ale można zintegrować metryki użytkownika oraz metryki dostarczane z zewnątrz.

Zespół Kubernetes aaS od Mail.ru przetłumaczyła artykuł o tym, jak wykorzystać zewnętrzne metryki do automatycznego skalowania aplikacji Kubernetes. Aby pokazać, jak to działa, autor korzysta z metryk żądań HTTP, które są zbierane za pomocą Prometheus.

Zamiast poziomego automatycznego skalowania podów, stosuje się Kubernetes Event Driven Autoscaling (KEDA) — operator Kubernetes z otwartym źródłem. Na początku integruje się z Horizontal Pod Autoscaler, aby umożliwić płynne automatyczne skalowanie (w tym do/od zera) dla obciążeń sterowanych zdarzeniami. Kod jest dostępny pod adresem GitHub.

Krótki przegląd działania systemu

Automatyczne skalowanie aplikacji Kubernetes za pomocą Prometheus i KEDA

Na diagramie znajduje się krótki opis tego, jak wszystko działa:

  1. Aplikacja dostarcza metryki liczby żądań HTTP w formacie Prometheus.
  2. Prometheus jest skonfigurowany do zbierania tych danych.
  3. Skalownik Prometheus w KEDA jest skonfigurowany do automatycznego skalowania aplikacji na podstawie liczby żądań HTTP.

Teraz szczegółowo omówię każdy element.

KEDA i Prometheus

Prometheus to zestaw narzędzi do monitorowania i powiadamiania systemów z otwartym źródłem, część Cloud Native Computing Foundation. Zbiera metryki z różnych źródeł i przechowuje je w postaci danych szeregów czasowych. Do wizualizacji danych można wykorzystać Grafana lub inne narzędzia wizualizacyjne współpracujące z API Kubernetes.

KEDA wspiera koncepcję skalownika — działa jako pomost między KEDA a zewnętrznym systemem. Realizacja skalownika jest specyficzna dla każdego docelowego systemu i pobiera z niego dane. Następnie KEDA wykorzystuje je do zarządzania automatycznym skalowaniem.

Skalery obsługują kilka źródeł danych, takich jak Kafka, Redis, Prometheus. Oznacza to, że KEDA może być używana do automatycznego skalowania wdrożeń Kubernetes, wykorzystując jako kryteria metryki Prometheus.

Aplikacja testowa

Testowa aplikacja w języku Golang zapewnia dostęp przez HTTP i wykonuje dwie istotne funkcje:

  1. Wykorzystuje klientską bibliotekę Prometheus Go do instrumentowania aplikacji i dostarczania metryki http_requests, która zawiera licznik wywołań. Punkt końcowy, w którym dostępne są metryki Prometheus, znajduje się pod URI /metrics.
    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "liczba zapytań http",
       })
    
  2. W odpowiedzi na żądanie i login/hasło: admin/admin. aplikacja zwiększa wartość klucza (access_count) w Redis. To prosty sposób wykonania pracy jako część handlera HTTP, a także sprawdzenie metryk Prometheus. Wartość metryki powinna być taka sama, jak wartość access_count w 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("Nie można zwiększyć licznika Redis", err)
                   os.Exit(1)
               }
               resp := "Dostęp był na " + time.Now().String() + "nLiczba dostępów " + strconv.Itoa(int(count))
               w.Write([]byte(resp))
           })
           http.ListenAndServe(":8080", nil)
       }
    

Aplikacja jest wdrażana w Kubernetes za pomocą Deployment. Tworzona jest również usługa ClusterIP, pozwala to serwerowi Prometheus na odbieranie metryk aplikacji.

Oto manifest wdrożeniowy dla aplikacji.

Serwer Prometheus

Manifest wdrożeniowy Prometheus składa się z:

  • ConfigMap — do przesłania konfiguracji Prometheus;
  • Deployment — do wdrożenia Prometheus w klastrze Kubernetes;
  • ClusterIP — usługa do uzyskania dostępu do UI Prometheus;
  • ClusterRole, ClusterRoleBinding i ServiceAccount — do obsługi automatycznego wykrywania usług w Kubernetes (Auto-discovery).

Oto manifest do uruchomienia Prometheus.

KEDA Prometheus ScaledObject

Skaler działa jako most między KEDA a zewnętrznym systemem, z którego należy pobierać metryki. ScaledObject — konfigurowalny zasób, który należy wdrożyć w celu synchronizacji wdrożenia z źródłem zdarzeń, w tym przypadku z Prometheus.

ScaledObject zawiera informacje o skalowaniu wdrożenia, metadane o źródle zdarzenia (np. tajne klucze do połączenia, nazwa kolejki), interwał zapytań, okres przywracania i inne dane. Prowadzi to do odpowiedniego zasobu automatycznego skalowania (definicja HPA) dla skalowania wdrożenia.

Gdy obiekt ScaledObject usunięte, odpowiadająca definicja HPA jest usuwana.

Oto definicja ScaledObject dla naszego przykładu, używany jest skaler 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]))

Zwróć uwagę na następujące kwestie:

  1. Odnosi się do Deployment z nazwą go-prom-app.
  2. Typ wyzwalacza to — Prometheus. Adres serwera Prometheus wymieniony jest wraz z nazwą metryki, wartością progową i zapytaniem PromQL, które będzie używane. Zapytanie PromQL to — sum(rate(http_requests[2m])).
  3. Zgodnie z pollingInterval, KEDA sprawdza cel u Prometheus co piętnaście sekund. Wspierane jest co najmniej jedno pod (minReplicaCount), a maksymalna liczba podów to nie więcej niż maxReplicaCount (w tym przykładzie — dziesięć).

Można ustawić minReplicaCount na zero. W takim przypadku KEDA aktywuje wdrożenie od zera do jednego, a następnie dostarcza HPA do dalszego automatycznego skalowania. Możliwe jest także odwrotne działanie, tj. skalowanie od jednego do zera. W przykładzie nie wybraliśmy zera, ponieważ to serwis HTTP, a nie system na żądanie.

Magia w automatycznym skalowaniu

Wartość progowa używana jest jako wyzwalacz do skalowania wdrożenia. W naszym przykładzie zapytanie PromQL sum(rate(http_requests[2m])) zwraca zagregowaną wartość szybkości HTTP-żądań (liczba żądań na sekundę), mierzono ją przez ostatnie dwie minuty.

Ponieważ wartość progowa wynosi trzy, będzie jeden pod, dopóki wartość sum(rate(http_requests[2m])) jest mniejsza niż trzy. Jeśli wartość wzrasta, dodawany jest dodatkowy pod za każdym razem, gdy sum(rate(http_requests[2m])) wzrasta o trzy. Na przykład, jeśli wartość wynosi od 12 do 14, to liczba podów wynosi cztery.

Teraz spróbujmy skonfigurować!

Wstępna konfiguracja

Wszystko, czego potrzebujesz, to klaster Kubernetes i skonfigurowane narzędzie kubectl. W tym przykładzie używany jest klaster minikube, ale możesz wziąć jakikolwiek inny. Aby zainstalować klaster, dostępne są przewodnik.

Zainstaluj najnowszą wersję na Macu:

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/

Zainstaluj kubectl, aby uzyskać dostęp do klastra Kubernetes.

Zainstaluj najnowszą wersję na Macu:

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

Instalacja KEDA

Możesz zainstalować KEDA na kilka sposobów, które są wymienione w dokumentacji. Używam monolitycznego pliku YAML:

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

KEDA i jej komponenty są instalowane w przestrzeni nazw keda. Polecenie do sprawdzenia:

kubectl get pods -n keda

Poczekaj, aż pod KEDA Operator wystartuje — przejdzie do stanu Running State. A następnie kontynuuj.

Instalacja Redis za pomocą Helm

Jeśli nie masz zainstalowanego Helma, skorzystaj z tego poradnika. Komenda do instalacji na Macu:

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

helm init inicjuje lokalny interfejs wiersza poleceń i instaluje Tiller w klastrze Kubernetes.

kubectl get pods -n kube-system | grep tiller

Poczekaj, aż pod Tiller przejdzie do stanu Running.

Nota tłumacza: Autor korzysta z Helm@2, która wymaga instalacji komponentu serwerowego Tiller. Obecnie aktualny jest Helm@3, który nie wymaga części serwerowej.

Po zainstalowaniu Helma, aby uruchomić Redis, wystarczy jedna komenda:

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

Sprawdź, czy Redis uruchomił się pomyślnie:

kubectl get pods/redis-server-master-0

Poczekaj, aż pod Redis przejdzie do stanu Running.

Rozwój aplikacji

Polecenie do wdrożenia:

kubectl apply -f go-app.yaml

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

Sprawdź, czy wszystko się uruchomiło:

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

Poczekaj na przejście Redis do stanu Running.

Wdrożenie serwera Prometheus

Manifest Prometheus korzysta z Kubernetes Service Discovery dla Prometheus. Umożliwia to dynamiczne odkrywanie podów aplikacji na podstawie etykiety usługi.

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

Do wdrożenia:

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

Sprawdź, czy wszystko się uruchomiło:

kubectl get pods -l=app=prometheus-server

Poczekaj, aż pod Prometheus przejdzie do stanu Running.

Użyj kubectl port-forward aby uzyskać dostęp do interfejsu użytkownika Prometheus (lub serwera API) pod adresem http://localhost:9090.

kubectl port-forward service/prometheus-service 9090

Wdrażanie konfiguracji skalowania KEDA

Polecenie do utworzenia ScaledObject:

kubectl apply -f keda-prometheus-scaledobject.yaml

Sprawdź dzienniki operatora KEDA:

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

Wynik wygląda mniej więcej tak:

time="2019-10-15T09:38:28Z" level=info msg="Obserwowanie ScaledObject:
default/prometheus-scaledobject"
time="2019-10-15T09:38:28Z" level=info msg="Utworzono HPA z 
namespaces default i nazwą keda-hpa-go-prom-app"

Sprawdź pod aplikacji. Powinien działać jeden egzemplarz, ponieważ minReplicaCount wynosi 1:

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

Sprawdź, czy zasób HPA został pomyślnie utworzony:

kubectl get hpa

Powinieneś zobaczyć coś w rodzaju:

NAZWA                   REFERENCJA                CELE     MINPODS   MAXPODS   REPLIKI   WIEK
keda-hpa-go-prom-app   Deployment/go-prom-app   0/3 (średnio)   1         10        1          45s

Sprawdzanie dostępności: dostęp do aplikacji

Aby uzyskać dostęp do punktu końcowego REST naszej aplikacji, uruchom:

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

Teraz możesz uzyskać dostęp do aplikacji Go, używając adresu http://localhost:8080. W tym celu wykonaj polecenie:

curl http://localhost:8080/test

Wynik wygląda mniej więcej tak:

Dostępne w 2019-10-21 11:29:10.560385986 +0000 UTC 
m=+406004.817901246
Liczba dostępów 1

Na tym etapie również sprawdź Redis. Zobaczysz, że klucz access_count został zwiększony do 1:

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

Upewnij się, że wartość metryki http_requests jest taka sama:

curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests liczba żądań HTTP
# TYPE http_requests licznik
http_requests 1

Generowanie obciążenia

Będziemy używać hey — narzędzia do generowania obciążenia:

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

Możesz również pobrać narzędzie do Linuxa lub Windows.

Uruchom je:

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

Domyślnie narzędzie wysyła 200 żądań. Możesz to potwierdzić, korzystając z metryk Prometheus oraz Redis.

curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests liczba żądań HTTP
# TYPE http_requests licznik
http_requests 201
kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
201

Potwierdź wartość faktycznej metryki (zwróconej przez zapytanie PromQL):

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"]}]}}

W takim przypadku faktyczny wynik wynosi 1,686057971014493 i pojawia się w polu value. To nie wystarczy do skalowania, ponieważ ustalony przez nas próg wynosi 3.

Więcej obciążenia!

W nowym terminalu obserwuj liczbę podów aplikacji:

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

Zwiększmy obciążenie za pomocą polecenia:

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

Po chwili zobaczysz, że HPA skalowało wdrożenie i uruchomiło nowe pody. Sprawdź HPA, aby się o tym przekonać:

kubectl get hpa
NAZWA                   ODWOŁANIE                CEL             MINPODS   MAXPODS   REPLIKI   WIEK
keda-hpa-go-prom-app   Deployment/go-prom-app   1830m/3 (średnia)   1         10        6          4m22s

Jeśli obciążenie jest nieregularne, wdrożenie zredukuje się do punktu, w którym działa tylko jeden pod. Jeśli chcesz sprawdzić rzeczywistą metrykę (zwróconą przez zapytanie PromQL), użyj polecenia:

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

Wyczyść

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

Podsumowanie

KEDA umożliwia automatyczne skalowanie twoich wdrożeń Kubernetes (do/zera) w oparciu o dane z zewnętrznych metryk. Na przykład, na podstawie metryk Prometheus, długości kolejki w Redis, opóźnienia konsumenta w temacie Kafka.

KEDA integruje się z zewnętrznym źródłem i dostarcza jego metryki przez Metrics Server do Horizontal Pod Autoscaler.

Powodzenia!

Co jeszcze przeczytać:

  1. Najlepsze praktyki i zalecenia dla uruchamiania kontenerów oraz Kubernetes w środowiskach produkcyjnych.
  2. 90+ przydatnych narzędzi dla Kubernetes: wdrożenie, zarządzanie, monitorowanie, bezpieczeństwo i nie tylko.
  3. Nasz kanał Wokół Kubernetes na Telegramie.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster