
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ół 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 .
Krótki przegląd działania systemu

Na diagramie znajduje się krótki opis tego, jak wszystko działa:
- Aplikacja dostarcza metryki liczby żądań HTTP w formacie Prometheus.
- Prometheus jest skonfigurowany do zbierania tych danych.
- 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ęść . Zbiera metryki z różnych źródeł i przechowuje je w postaci danych szeregów czasowych. Do wizualizacji danych można wykorzystać 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:
- 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", }) - 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_countw 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 .
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,ClusterRoleBindingiServiceAccount— do obsługi automatycznego wykrywania usług w Kubernetes (Auto-discovery).
Oto .
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:
- Odnosi się do
Deploymentz nazwągo-prom-app. - Typ wyzwalacza to —
Prometheus. Adres serwera Prometheus wymieniony jest wraz z nazwą metryki, wartością progową i , które będzie używane. Zapytanie PromQL to —sum(rate(http_requests[2m])). - 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ą .
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 , 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 . 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 . 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 . 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 .
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 . 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ć — 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 lub .
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ć:
- .
- .
- .
Źródło: habr.com
