Applicazioni Kubernetes con scalabilità automatica utilizzando Prometheus e KEDA

Applicazioni Kubernetes con scalabilità automatica utilizzando Prometheus e KEDAL'Uomo dei Palloncini di Cimuanos

La scalabilità è un requisito fondamentale per le applicazioni cloud. Con Kubernetes, scalare un'applicazione è semplice come aumentare il numero di repliche per la distribuzione appropriata o ReplicaSet - ma è un processo manuale.

Kubernetes consente il dimensionamento automatico delle applicazioni (ad esempio i pod in una distribuzione o ReplicaSet) in modo dichiarativo utilizzando la specifica orizzontale Pod Autoscaler. Il criterio predefinito per il dimensionamento automatico sono i parametri di utilizzo della CPU (parametri delle risorse), ma è possibile integrare parametri personalizzati e forniti esternamente.

Squadra Kubernetes aaS da Mail.ru tradotto un articolo su come utilizzare le metriche esterne per ridimensionare automaticamente un'applicazione Kubernetes. Per mostrare come funziona il tutto, l'autore utilizza le metriche delle richieste di accesso HTTP, che vengono raccolte utilizzando Prometheus.

Invece della scalabilità automatica orizzontale dei pod, viene utilizzato Kubernetes Event Driven Autoscaling (KEDA), un operatore Kubernetes open source. Si integra in modo nativo con Vertical Pod Autoscaler per fornire una scalabilità automatica continua (incluso da/verso zero) per carichi di lavoro basati su eventi. Codice disponibile su GitHub.

Breve panoramica del sistema

Applicazioni Kubernetes con scalabilità automatica utilizzando Prometheus e KEDA

Il diagramma mostra una breve descrizione di come funziona il tutto:

  1. L'applicazione fornisce metriche sul conteggio delle visite HTTP in formato Prometheus.
  2. Prometheus è configurato per raccogliere queste metriche.
  3. Lo scaler Prometheus in KEDA è configurato per ridimensionare automaticamente l'applicazione in base al numero di accessi HTTP.

Ora ti parlerò in dettaglio di ogni elemento.

KEDA e Prometeo

Prometheus è un toolkit di monitoraggio e avviso del sistema open source, part Fondamenta del cloud nativo per il computing. Raccoglie parametri da varie fonti e li archivia come dati di serie temporali. Per visualizzare i dati è possibile utilizzare graminacee o altri strumenti di visualizzazione che funzionano con l'API Kubernetes.

KEDA supporta il concetto di scaler: funge da ponte tra KEDA e il sistema esterno. L'implementazione dello scaler è specifica per ciascun sistema di destinazione e ne estrae i dati. KEDA li utilizza quindi per controllare il ridimensionamento automatico.

Gli scaler supportano più origini dati, ad esempio Kafka, Redis, Prometheus. Ciò significa che KEDA può essere utilizzato per ridimensionare automaticamente le distribuzioni Kubernetes utilizzando le metriche Prometheus come criteri.

Applicazione di prova

L'applicazione di test Golang fornisce l'accesso tramite HTTP e svolge due importanti funzioni:

  1. Utilizza la libreria client Prometheus Go per strumentare l'applicazione e fornire la metrica http_requests, che contiene un conteggio degli accessi. L'endpoint in cui sono disponibili le metriche Prometheus si trova nell'URI /metrics.
    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "number of http requests",
       })
    
  2. In risposta ad una richiesta GET l'applicazione incrementa il valore della chiave (access_count) a Redis. Questo è un modo semplice per svolgere il lavoro come parte di un gestore HTTP e controllare anche le metriche Prometheus. Il valore della metrica deve essere uguale al valore access_count a 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)
       }
    

L'applicazione viene distribuita a Kubernetes tramite Deployment. Viene creato anche un servizio ClusterIP, consente al server Prometheus di ottenere le metriche dell'applicazione.

Qui manifesto di distribuzione per l'applicazione.

Server Prometeo

Il manifesto di distribuzione di Prometheus è costituito da:

  • ConfigMap — per trasferire la configurazione di Prometheus;
  • Deployment — per l'implementazione di Prometheus in un cluster Kubernetes;
  • ClusterIP — servizio per l'accesso all'UI Prometheus;
  • ClusterRole, ClusterRoleBinding и ServiceAccount — per il rilevamento automatico dei servizi in Kubernetes (rilevamento automatico).

Qui manifest per l'esecuzione di Prometeo.

KEDA Prometheus ScaledObject

Lo scaler funge da ponte tra KEDA e il sistema esterno da cui è necessario ottenere le metriche. ScaledObject è una risorsa personalizzata che deve essere distribuita per sincronizzare la distribuzione con l'origine dell'evento, in questo caso Prometheus.

ScaledObject contiene informazioni sulla scalabilità della distribuzione, metadati dell'origine evento (come segreti di connessione, nome della coda), intervallo di polling, periodo di ripristino e altri dati. Il risultato è la corrispondente risorsa di scalabilità automatica (definizione HPA) per ridimensionare la distribuzione.

Quando un oggetto ScaledObject viene cancellato, la definizione HPA corrispondente viene cancellata.

Ecco la definizione ScaledObject per il nostro esempio, utilizza uno 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]))

Considera i seguenti punti:

  1. Indica Deployment Con nome go-prom-app.
  2. Tipo di trigger - Prometheus. L'indirizzo del server Prometheus viene menzionato insieme al nome della metrica, alla soglia e Interrogazione PromQL, che verrà utilizzato. Interrogazione PromQL - sum(rate(http_requests[2m])).
  3. Secondo pollingInterval,KEDA richiede un bersaglio a Prometeo ogni quindici secondi. Almeno uno sotto (minReplicaCount) e il numero massimo di pod non deve essere superato maxReplicaCount (in questo esempio - dieci).

Può installare minReplicaCount uguale a zero. In questo caso, KEDA attiva la distribuzione zero-to-one e quindi espone l'HPA per un ulteriore dimensionamento automatico. È possibile anche l'ordine inverso, ovvero scalare da uno a zero. Nell'esempio non abbiamo selezionato zero perché si tratta di un servizio HTTP e non di un sistema on-demand.

La magia della scalabilità automatica

La soglia viene utilizzata come trigger per ridimensionare la distribuzione. Nel nostro esempio, la query PromQL sum(rate (http_requests [2m])) restituisce la frequenza di richieste HTTP aggregata (richieste al secondo), misurata negli ultimi due minuti.

Poiché il valore di soglia è tre, significa che ce ne sarà uno al di sotto del valore sum(rate (http_requests [2m])) meno di tre. Se il valore aumenta, viene aggiunto ogni volta un ulteriore sottotitolo sum(rate (http_requests [2m])) aumenta di tre. Ad esempio, se il valore è compreso tra 12 e 14, il numero di pod è quattro.

Ora proviamo a configurarlo!

preimpostazione

Tutto ciò di cui hai bisogno è un cluster Kubernetes e un'utilità configurata kubectl. Questo esempio utilizza un cluster minikube, ma puoi prenderne un altro. Per installare un cluster c'è guida.

Installa l'ultima versione su 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/

Set kubectlper accedere al cluster Kubernetes.

Installa l'ultima versione su 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

Installazione KEDA

Puoi distribuire KEDA in diversi modi, elencati in documentazione. Sto usando YAML monolitico:

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

KEDA e i suoi componenti sono installati nello spazio dei nomi keda. Comando da verificare:

kubectl get pods -n keda

Attendere l'avvio di KEDA Operator e andare su Running State. E dopo, continua.

Installazione di Redis utilizzando Helm

Se non hai installato Helm, usa questo guida. Comando da installare su Mac:

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

helm init inizializza l'interfaccia della riga di comando locale e installa anche Tiller al cluster Kubernetes.

kubectl get pods -n kube-system | grep tiller

Attendi che il pod Tiller entri nello stato In esecuzione.

Nota del traduttore: L'autore utilizza Helm@2, che richiede l'installazione del componente server Tiller. Ora Helm@3 è rilevante, non richiede una parte server.

Dopo aver installato Helm, è sufficiente un comando per avviare Redis:

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

Verifica che Redis sia stato avviato correttamente:

kubectl get pods/redis-server-master-0

Attendi che Redis entri nello stato Running.

Distribuzione dell'applicazione

Comando di distribuzione:

kubectl apply -f go-app.yaml

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

Verifica che tutto sia iniziato:

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

Attendi che Redis entri nello stato Running.

Distribuzione di un server Prometheus

Il manifesto di Prometeo utilizza Individuazione del servizio Kubernetes per Prometheus. Consente il rilevamento dinamico dei pod dell'applicazione in base all'etichetta del servizio.

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

Per distribuire:

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 che tutto sia iniziato:

kubectl get pods -l=app=prometheus-server

Aspetta che Prometeo entri nello stato Running.

Utilizzare kubectl port-forward per accedere all'interfaccia utente di Prometheus (o al server API) su http://localhost:9090.

kubectl port-forward service/prometheus-service 9090

Distribuzione della configurazione di scalabilità automatica KEDA

Comando per creare ScaledObject:

kubectl apply -f keda-prometheus-scaledobject.yaml

Controlla i log dell'operatore KEDA:

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

Il risultato è simile a questo:

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"

Controlla sotto le applicazioni. Un'istanza deve essere in esecuzione perché minReplicaCount è uguale a 1:

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

Verificare che la risorsa HPA sia stata creata correttamente:

kubectl get hpa

Dovresti vedere qualcosa come:

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

Controllo dello stato: accesso all'applicazione

Per accedere all'endpoint REST della nostra applicazione, esegui:

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

Ora puoi accedere alla tua app Go utilizzando l'indirizzo http://localhost:8080. Per fare ciò, esegui il comando:

curl http://localhost:8080/test

Il risultato è simile a questo:

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

A questo punto controlla anche Redis. Vedrai che è la chiave access_count aumentato a 1:

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

Assicurati che il valore della metrica sia http_requests lo stesso:

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

Carica creazione

Noi useremo ehi — utilità per la generazione del carico:

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

Puoi anche scaricare l'utilità per Linux o Windows.

Eseguirlo:

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

Per impostazione predefinita, l'utilità invia 200 richieste. Puoi verificarlo utilizzando le metriche Prometheus e 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

Convalidare il valore della metrica effettiva (restituita dalla query 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"]}]}}

In questo caso il risultato effettivo è 1,686057971014493 e viene visualizzato nel campo value. Questo non è sufficiente per il ridimensionamento, poiché la soglia che abbiamo impostato è 3.

Più carico!

Nel nuovo terminale, monitora il numero di pod dell'applicazione:

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

Aumentiamo il carico utilizzando il comando:

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

Dopo un po', vedrai HPA ridimensionare la distribuzione e lanciare nuovi pod. Controlla il tuo HPA per assicurarti:

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

Se il carico non è coerente, la distribuzione verrà ridotta al punto in cui è in esecuzione un solo pod. Se desideri verificare la metrica effettiva (restituita dalla query PromQL), utilizza il comando:

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

pulizia

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

conclusione

KEDA ti consente di ridimensionare automaticamente le tue distribuzioni Kubernetes (da/a zero) in base ai dati provenienti da parametri esterni. Ad esempio, in base alle metriche Prometheus, lunghezza della coda in Redis, latenza del consumatore nell'argomento Kafka.

KEDA si integra con una fonte esterna e fornisce inoltre le proprie metriche tramite Metrics Server all'Horizontal Pod Autoscaler.

Buona fortuna!

Cos'altro leggere:

  1. Best practice e best practice per l'esecuzione di contenitori e Kubernetes negli ambienti di produzione.
  2. Oltre 90 strumenti utili per Kubernetes: distribuzione, gestione, monitoraggio, sicurezza e altro ancora.
  3. Il nostro canale Around Kubernetes in Telegram.

Fonte: habr.com

Aggiungi un commento