Autoscalarea aplicațiilor Kubernetes cu ajutorul Prometheus și KEDA

Autoscalarea aplicațiilor Kubernetes cu ajutorul Prometheus și KEDABalloon Man de Cimuanos

Scalabilitatea este o cerință cheie pentru aplicațiile cloud. Cu Kubernetes, scalarea unei aplicații este la fel de simplă ca și creșterea numărului de replici pentru un deployment corespunzător sau ReplicaSet — dar este un proces manual.

Kubernetes permite scalarea automată a aplicațiilor (adică a Pod-urilor dintr-un deployment sau ReplicaSet) într-un mod declarativ utilizând specificația Horizontal Pod Autoscaler. În mod implicit, criteriile pentru scalarea automată sunt metricile de utilizare a CPU-ului (metricile resurselor), dar se pot integra metrici personalizate și metrici furnizate din externe.

Comanda Kubernetes aaS de la Mail.ru a tradus un articol despre cum să utilizezi metricile externe pentru scalarea automată a aplicației Kubernetes. Pentru a ilustra cum funcționează totul, autorul folosește metricile de cereri pentru accesul HTTP, care sunt colectate cu ajutorul Prometheus.

În loc de scalarea automată orizontală a Pod-urilor, se aplică Kubernetes Event Driven Autoscaling (KEDA) — un operator Kubernetes cu sursă deschisă. Acesta se integrează inițial cu Horizontal Pod Autoscaler pentru a asigura scalarea automată fluidă (inclusiv până la/de la zero) pentru sarcinile de lucru bazate pe evenimente. Codul este disponibil pe GitHub.

O prezentare generală a funcționării sistemului

Autoscalarea aplicațiilor Kubernetes cu ajutorul Prometheus și KEDA

În diagramă — o descriere succintă a modului în care funcționează totul:

  1. Aplicația oferă metrici privind numărul de cereri HTTP în format Prometheus.
  2. Prometheus este configurat pentru a colecta aceste date.
  3. Scalatorul Prometheus în KEDA este configurat pentru a scala automat aplicația pe baza numărului de cereri HTTP.

Acum voi detalia fiecare element.

KEDA și Prometheus

Prometheus este un set de instrumente pentru monitorizare și alertare a sistemelor cu sursă deschisă, parte din Cloud Native Computing Foundation. Colectează metrici din diferite surse și le stochează sub formă de date de tip time series. Pentru vizualizarea datelor, se pot folosi Grafana sau alte instrumente de vizualizare care funcționează cu API-ul Kubernetes.

KEDA sprijină conceptul de scalator — acesta acționează ca un pod între KEDA și un sistem extern. Implementarea scalatorului este specifică fiecărui sistem țintă și extrage date din acesta. Apoi, KEDA le utilizează pentru a gestiona scalarea automată.

Scalerii suportă mai multe surse de date, cum ar fi Kafka, Redis, Prometheus. Asta înseamnă că KEDA poate fi utilizat pentru scalarea automată a desfășurărilor Kubernetes, folosind ca criterii metricile Prometheus.

Aplicație de testare

Aplicația de testare Golang oferă acces prin HTTP și îndeplinește două funcții importante:

  1. Folosește biblioteca clientului Prometheus Go pentru a instrumenta aplicația și a oferi metrică http_requests, care conține un contor al accesărilor. Endpointul prin care sunt disponibile metricile Prometheus se află la URI /metrics.
    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "numărul cererilor http",
       })
    
  2. Ca răspuns la cerere metoda GET. aplicația crește valoarea cheii (access_count) în Redis. Aceasta este o modalitate simplă de a realiza această acțiune ca parte a handlerului HTTP și de asemenea de a verifica metricile Prometheus. Valoarea metricii ar trebui să fie aceeași cu valoarea access_count din 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("Imposibil de incrementat contorul redis", err)
                   os.Exit(1)
               }
               resp := "Accesat pe " + time.Now().String() + "nNumărul de accesări " + strconv.Itoa(int(count))
               w.Write([]byte(resp))
           })
           http.ListenAndServe(":8080", nil)
       }
    

Aplicația este desfășurată în Kubernetes prin Deployment. De asemenea, se creează un serviciu ClusterIP, care permite serverului Prometheus să primească metricile aplicației.

Iată manifestul de desfășurare pentru aplicație.

Serverul Prometheus

Manifestul de desfășurare Prometheus constă din:

  • ConfigMap — pentru transmiterea configurației Prometheus;
  • Deployment — pentru desfășurarea Prometheus în clusterul Kubernetes;
  • ClusterIP — serviciu pentru accesarea interfeței UI Prometheus;
  • ClusterRole, ClusterRoleBinding și ServiceAccount — pentru funcționarea auto-descoperirii serviciilor în Kubernetes (Auto-discovery).

Iată manifest pentru lansarea Prometheus.

KEDA Prometheus ScaledObject

Scalerul acționează ca un pod între KEDA și un sistem extern, din care trebuie să se obțină metricile. ScaledObject — un resursă configurabilă, care trebuie desfășurată pentru a sincroniza desfășurarea cu sursa de evenimente, în acest caz cu Prometheus.

ScaledObject conține informații despre scalarea desfășurării, metadate despre sursa evenimentului (de exemplu, secrete pentru conectare, nume coadă), intervalul de polling, perioada de recuperare și alte date. Acesta conduce la resursa corespunzătoare de scalare automată (definiția HPA) pentru scalarea desfășurării.

Când obiectul ScaledObject se șterge, definiția HPA corespunzătoare este eliberată.

Iată definiția ScaledObject pentru exemplul nostru, în care este utilizat un scaler 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]))

Rețineți următoarele aspecte:

  1. Acesta indică către Deployment cu numele go-prom-app.
  2. Tipul trigger-ului este Prometheus. Adresa serverului Prometheus este menționată împreună cu numele metrcii, valoarea de prag și interogarea PromQL, care va fi utilizată. Interogarea PromQL este sum(rate(http_requests[2m])).
  3. Conform pollingInterval, KEDA interoghează obiectivul de la Prometheus la fiecare cincisprezece secunde. Se acceptă un minim de un pod (minReplicaCount), iar numărul maxim de pod-uri nu depășește maxReplicaCount în acest exemplu — zece.

Se poate seta minReplicaCount la zero. În acest caz, KEDA activează desfășurarea de la zero la unu și apoi oferă HPA pentru scalarea automată ulterioară. Este posibilă și inversarea ordinii, adică scalarea de la unu la zero. În exemplul nostru nu am ales zero, deoarece acest lucru este un serviciu HTTP, nu un sistem pe cerere.

Magia din interiorul auto-scalării

Valoarea de prag este utilizată ca trigger pentru scalarea desfășurării. În exemplul nostru, interogarea PromQL sum(rate (http_requests [2m])) returnează valoarea agregată a vitezei solicitărilor HTTP (numărul de solicitări pe secundă), măsurată în ultimele două minute.

Deoarece valoarea de prag este trei, va exista un pod atât timp cât valoarea sum(rate (http_requests [2m])) este mai mică decât trei. Dacă valoarea crește, se adaugă un pod suplimentar de fiecare dată când sum(rate (http_requests [2m])) crește cu trei. De exemplu, dacă valoarea variază de la 12 la 14, numărul de pod-uri va fi patru.

Acum să încercăm să configurăm!

Configurare preliminară

Tot ce aveți nevoie este un cluster Kubernetes și un utilitar configurat kubectl. În acest exemplu se utilizează un cluster minikube, dar puteți lua orice altul. Pentru instalarea cluster-ului există ghid.

Instalare cea mai recentă versiune pe 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/

Instalați kubectl, pentru a accesa cluster-ul Kubernetes.

Instalare cea mai recentă versiune pe 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

Instalarea KEDA

Puteți desfășura KEDA în mai multe moduri, acestea sunt enumerate în documentation. Folosesc YAML monolit:

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

KEDA și componentele sale sunt instalate în spațiul de nume keda. Comanda pentru verificare:

kubectl get pods -n keda

Așteptați ca pod-ul KEDA Operator să pornească — să treacă în Starea de rulare. Și apoi continuați.

Instalarea Redis folosind Helm

Dacă nu aveți Helm instalat, utilizați acest ghid. Comanda pentru instalare pe Mac:

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

helm init inițializează interfața de linie de comandă locală și, de asemenea, instalează Tiller în clusterul Kubernetes.

kubectl get pods -n kube-system | grep tiller

Așteptați ca pod-ul Tiller să treacă în starea de rulare.

Nota traducătorului: Autorul folosește Helm@2, care necesită instalarea componentei server Tiller. Acum este relevant Helm@3, pentru care partea de server nu este necesară.

După instalarea Helm, pentru a lansa Redis, este suficientă o singură comandă:

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

Asigurați-vă că Redis s-a lansat cu succes:

kubectl get pods/redis-server-master-0

Așteptați ca pod-ul Redis să treacă în starea de Running.

Desfășurarea aplicației

Comanda pentru desfășurare:

kubectl apply -f go-app.yaml

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

Verificați că totul a fost lansat:

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

Așteptați ca Redis să treacă în starea Running.

Desfășurarea serverului Prometheus

Manifestul Prometheus folosește Descoperirea serviciului Kubernetes pentru Prometheus. Acesta permite descoperirea dinamică a pod-urilor de aplicație pe baza etichetei serviciului.

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

Pentru desfășurare:

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

Verificați că totul a fost lansat:

kubectl get pods -l=app=prometheus-server

Așteptați ca pod-ul Prometheus să treacă în starea Running.

Windows VPS pentru lucru la distanță kubectl port-forward pentru accesarea interfeței de utilizator Prometheus (sau a serverului API) la adresa http://localhost:9090.

kubectl port-forward service/prometheus-service 9090

Desfășurarea configurației de scalare automată KEDA

Comanda pentru crearea ScaledObject:

kubectl apply -f keda-prometheus-scaledobject.yaml

Verificați jurnalele operatorului KEDA:

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

Rezultatul arată aproximativ așa:

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"

Verificați pod-ul aplicației. Ar trebui să fie activ un singur exemplar, deoarece minReplicaCount este egal cu 1:

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

Verificați dacă resursa HPA a fost creată cu succes:

kubectl get hpa

Ar trebui să vedeți ceva de genul:

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

Verificare funcționalitate: acces la aplicație

Pentru a accesa endpoint-ul REST al aplicației noastre, rulați:

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

Acum puteți accesa aplicația Go folosind adresa http://localhost:8080. Pentru aceasta, executați comanda:

curl http://localhost:8080/test

Rezultatul arată aproximativ așa:

Accesat pe 2019-10-21 11:29:10.560385986 +0000 UTC 
m=+406004.817901246
Număr de acces 1

În această etapă, verificați și Redis. Veți observa că cheia access_count a fost crescută la 1:

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

Asigurați-vă că valoarea metricii http_requests este aceeași:

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

Generarea de sarcină

Vom folosi hey — o utilitară pentru generarea de sarcini:

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

De asemenea, puteți descărca utilitarul pentru Linux sau Windows.

Rulați-l:

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

Implicit, utilitarul trimite 200 de cereri. Puteți verifica acest lucru folosind metricile Prometheus, precum ș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

Confirmați valoarea metricii reale (returnată de interogarea 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"]}]}}

În acest caz, rezultatul real este 1,686057971014493 și este afișat în câmpul valoare. Acesta nu este suficient pentru scalare, deoarece pragul stabilit de noi este de 3.

Mai multă sarcină!

Într-un nou terminal, urmăriți numărul de poduri ale aplicației:

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

Să creștem sarcina folosind comanda:

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

După un timp, veți observa că HPA scalează desfășurarea și pornește noi poduri. Verificați HPA pentru a vă asigura de acest lucru:

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

Dacă sarcina este variabilă, desfășurarea se va reduce la un punct în care funcționează doar un singur pod. Dacă doriți să verificați metrica reală (returnată de interogarea PromQL), utilizați comanda:

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

Curățare

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

Concluzie

KEDA permite scalarea automată a desfășurărilor Kubernetes (de la/să) în funcție de datele din metrici externe. De exemplu, pe baza metricilor Prometheus, lungimea cozii în Redis, întârzierile consumatorului în topicul Kafka.

KEDA integrează o sursă externă și, de asemenea, furnizează metricile sale prin Metrics Server pentru Horizontal Pod Autoscaler.

Good luck!

Ce altceva să citești:

  1. Cele mai bune practici și recomandări pentru lansarea containerelor și Kubernetes în medii de producție.
  2. 90+ instrumente utile pentru Kubernetes: desfășurare, gestionare, monitorizare, securitate și altele.
  3. Our Around Kubernetes channel on Telegram.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster