Autoskalowanie aplikacji Kubernetes przy użyciu Prometheusa i KEDA

Autoskalowanie aplikacji Kubernetes przy użyciu Prometheusa i KEDABalonowy Człowiek od Cimuanos

Skalowalność jest kluczowym wymaganiem w przypadku aplikacji w chmurze. Dzięki Kubernetes skalowanie aplikacji jest tak proste, jak zwiększenie liczby replik w celu odpowiedniego wdrożenia lub ReplicaSet — ale jest to proces ręczny.

Kubernetes umożliwia automatyczne skalowanie aplikacji (tj. Podów we wdrożeniu lub ReplicaSet) w sposób deklaratywny przy użyciu specyfikacji autoskalera poziomego podu. Domyślnym kryterium automatycznego skalowania są metryki użycia procesora (metryki zasobów), ale można zintegrować metryki niestandardowe i dostarczone zewnętrznie.

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

Zamiast poziomego automatycznego skalowania podów używany jest Kubernetes Event Driven Autoscaling (KEDA), operator Kubernetes typu open source. Integruje się natywnie z modułem automatycznego skalowania podów poziomych, aby zapewnić płynne automatyczne skalowanie (w tym do/od zera) w przypadku obciążeń sterowanych zdarzeniami. Kod dostępny pod adresem GitHub.

Krótki przegląd systemu

Autoskalowanie aplikacji Kubernetes przy użyciu Prometheusa i KEDA

Diagram przedstawia krótki opis działania wszystkiego:

  1. Aplikacja udostępnia metryki liczby trafień HTTP w formacie Prometheus.
  2. Prometheus jest skonfigurowany do zbierania tych metryk.
  3. Skaler Prometheus w KEDA jest skonfigurowany tak, aby automatycznie skalować aplikację na podstawie liczby trafień HTTP.

Teraz opowiem szczegółowo o każdym elemencie.

KEDA i Prometeusz

Prometheus to zestaw narzędzi do monitorowania i ostrzegania systemu typu open source, część Fundacja Cloud Native Computing. Zbiera metryki z różnych źródeł i przechowuje je jako dane szeregów czasowych. Aby zwizualizować dane, których możesz użyć grafana lub inne narzędzia do wizualizacji współpracujące z Kubernetes API.

KEDA wspiera koncepcję skalera - pełni rolę pomostu pomiędzy KEDA a systemem zewnętrznym. Implementacja skalera jest specyficzna dla każdego systemu docelowego i wydobywa z niego dane. Następnie KEDA wykorzystuje je do kontrolowania automatycznego skalowania.

Skalery obsługują wiele źródeł danych, na przykład Kafka, Redis, Prometheus. Oznacza to, że KEDA może służyć do automatycznego skalowania wdrożeń Kubernetes przy użyciu metryk Prometheusa jako kryteriów.

Aplikacja testowa

Aplikacja testowa Golang zapewnia dostęp poprzez HTTP i spełnia dwie ważne funkcje:

  1. Używa biblioteki klienta Prometheus Go do instrumentowania aplikacji i udostępniania metryki http_requests, która zawiera liczbę trafień. Punkt końcowy, w którym dostępne są metryki Prometheus, znajduje się w identyfikatorze URI /metrics.
    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "number of http requests",
       })
    
  2. W odpowiedzi na prośbę GET aplikacja zwiększa wartość klucza (access_count) w Redisie. Jest to prosty sposób na wykonanie pracy w ramach procedury obsługi HTTP i sprawdzenie metryk Prometheusa. Wartość metryki musi być taka sama jak wartość access_count w Redisie.
    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)
       }
    

Aplikacja jest wdrażana w Kubernetes za pośrednictwem Deployment. Tworzony jest także serwis ClusterIPumożliwia serwerowi Prometheus uzyskanie metryk aplikacji.

tutaj jest manifest wdrożenia aplikacji.

Serwer Prometeusz

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

  • ConfigMap — aby przenieść konfigurację Prometheusa;
  • Deployment — za wdrożenie Prometheusa w klastrze Kubernetes;
  • ClusterIP — usługa dostępu do UI Prometheus;
  • ClusterRole, ClusterRoleBinding и ServiceAccount — do automatycznego wykrywania usług w Kubernetesie (Auto-discovery).

tutaj jest manifest do uruchamiania Prometeusza.

Obiekt skalowany KEDA Prometheus

Skaler pełni rolę pomostu pomiędzy KEDA a systemem zewnętrznym, z którego należy uzyskać metryki. ScaledObject to zasób niestandardowy, który należy wdrożyć, aby zsynchronizować wdrożenie ze źródłem zdarzenia, w tym przypadku Prometheusem.

ScaledObject zawiera informacje o skalowaniu wdrożenia, metadane źródła zdarzeń (takie jak klucze tajne połączenia, nazwa kolejki), interwał odpytywania, okres przywracania i inne dane. Powoduje to odpowiedni zasób automatycznego skalowania (definicja HPA) umożliwiający skalowanie wdrożenia.

Kiedy obiekt ScaledObject zostanie usunięty, odpowiednia definicja HPA zostanie wyczyszczona.

Oto definicja ScaledObject w naszym przykładzie używa skalera 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]))

Proszę zwrócić uwagę na następujące punkty:

  1. Wskazuje na Deployment Z imieniem go-prom-app.
  2. Typ wyzwalacza - Prometheus. Adres serwera Prometheus jest wymieniony wraz z nazwą metryki, progiem i Zapytanie PromQL, który będzie używany. Zapytanie PromQL — sum(rate(http_requests[2m])).
  3. Według pollingInterval,KEDA żąda od Prometeusza celu co piętnaście sekund. Przynajmniej jeden poniżej (minReplicaCount), a maksymalna liczba strąków nie przekracza maxReplicaCount (w tym przykładzie - dziesięć).

Można zainstalować minReplicaCount równy zeru. W tym przypadku KEDA aktywuje wdrożenie „zero do jednego”, a następnie udostępnia HPA do dalszego automatycznego skalowania. Możliwa jest także kolejność odwrotna, czyli skalowanie od jednego do zera. W przykładzie nie wybraliśmy zera, ponieważ jest to usługa HTTP, a nie system na żądanie.

Magia automatycznego skalowania

Próg służy jako wyzwalacz skalowania wdrożenia. W naszym przykładzie zapytanie PromQL sum(rate (http_requests [2m])) zwraca zagregowaną liczbę żądań HTTP (żądań na sekundę) mierzoną w ciągu ostatnich dwóch minut.

Ponieważ wartość progowa wynosi trzy, oznacza to, że wartość będzie poniżej wartości sum(rate (http_requests [2m])) mniej niż trzy. Jeśli wartość wzrasta, za każdym razem dodawany jest dodatkowy sub sum(rate (http_requests [2m])) wzrasta o trzy. Na przykład, jeśli wartość wynosi od 12 do 14, liczba strąków wynosi cztery.

Teraz spróbujmy to skonfigurować!

Wstępne ustawienie

Wszystko czego potrzebujesz to klaster Kubernetes i skonfigurowane narzędzie kubectl. W tym przykładzie zastosowano klaster minikube, ale możesz wziąć dowolny inny. Aby zainstalować klaster, istnieje руководство.

Zainstaluj najnowszą wersję na komputerze 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/

Zestaw kubectlaby uzyskać dostęp do klastra Kubernetes.

Zainstaluj najnowszą wersję na komputerze 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

Instalacja KEDA

Możesz wdrożyć KEDA na kilka sposobów, są one wymienione w dokumentacja. Używam monolitycznego YAML:

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

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

kubectl get pods -n keda

Poczekaj, aż KEDA Operator uruchomi się i przejdź do Running State. A potem kontynuuj.

Instalowanie Redis przy użyciu Helma

Jeśli nie masz zainstalowanego Helma, użyj tego przywództwo. Polecenie instalacji na komputerze Mac:

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

helm init inicjuje lokalny interfejs wiersza poleceń, a także instaluje Tiller do klastra Kubernetes.

kubectl get pods -n kube-system | grep tiller

Poczekaj, aż moduł Tiller przejdzie w stan Uruchomiony.

Notatka tłumacza: Autor używa Helm@2, który wymaga zainstalowania komponentu serwera Tiller. Teraz Helm@3 jest istotny, nie wymaga części serwerowej.

Po zainstalowaniu Helma wystarczy jedno polecenie, aby uruchomić Redis:

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ż Redis przejdzie do stanu Running.

Wdrożenie aplikacji

Polecenie 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ę rozpoczęło:

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

Poczekaj, aż Redis wejdzie w stan Running.

Wdrażanie serwera Prometheus

Manifest Prometeusza używa Wykrywanie usług Kubernetes dla Prometheusa. Umożliwia dynamiczne wykrywanie podów aplikacji w oparciu o etykietę usługi.

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

Rozmieścić:

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ę rozpoczęło:

kubectl get pods -l=app=prometheus-server

Poczekaj, aż Prometeusz przejdzie do stanu Running.

Stosowanie 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 automatycznego skalowania KEDA

Polecenie utworzenia ScaledObject:

kubectl apply -f keda-prometheus-scaledobject.yaml

Sprawdź logi 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="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"

Sprawdź w aplikacjach. Jedna instancja musi być uruchomiona, ponieważ minReplicaCount równa się 1:

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

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

kubectl get hpa

Powinieneś zobaczyć coś takiego:

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

Kontrola stanu: 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

Możesz teraz uzyskać dostęp do aplikacji Go, korzystając z adresu http://localhost:8080. Aby to zrobić, uruchom polecenie:

curl http://localhost:8080/test

Wynik wygląda mniej więcej tak:

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

W tym momencie sprawdź także Redis. Zobaczysz, że to klucz access_count zwiększono do 1:

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

Upewnij się, że wartość metryki to http_requests ten sam:

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

Załaduj tworzenie

Użyjemy hej — narzędzie do generowania obciążenia:

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

Możesz także pobrać narzędzie dla Linux lub Windows.

Uruchom:

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

Domyślnie narzędzie wysyła 200 żądań. Możesz to zweryfikować za pomocą metryk Prometheus i Redis.

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

Sprawdź wartość rzeczywistej 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 tym przypadku faktyczny wynik jest taki 1,686057971014493 i jest wyświetlany w polu value. To nie wystarczy do skalowania, ponieważ próg, który ustaliliśmy, wynosi 3.

Więcej obciążenia!

W nowym terminalu monitoruj liczbę podów aplikacyjnych:

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, jak HPA skaluje wdrożenie i uruchamia nowe pody. Sprawdź swój HPA, aby upewnić się, że:

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

Jeśli obciążenie jest niespójne, wdrożenie zostanie ograniczone do punktu, w którym działa tylko jeden zasobnik. 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]))'

Czyszczenie

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

wniosek

KEDA umożliwia automatyczne skalowanie wdrożeń Kubernetes (do/od zera) w oparciu o dane z metryk zewnętrznych. Na przykład w oparciu o metryki Prometheusa, długość kolejki w Redis, opóźnienia konsumenckie w temacie Kafka.

KEDA integruje się ze źródłem zewnętrznym, a także udostępnia swoje metryki poprzez serwer metryk do automatycznego skalowania podów poziomych.

Good Luck!

Co jeszcze przeczytać:

  1. Najlepsze praktyki i najlepsze praktyki dotyczące uruchamiania kontenerów i Kubernetes w środowiskach produkcyjnych.
  2. Ponad 90 przydatnych narzędzi dla Kubernetes: wdrażanie, zarządzanie, monitorowanie, bezpieczeństwo i nie tylko.
  3. Nasz kanał Around Kubernetes w Telegramie.

Źródło: www.habr.com

Dodaj komentarz