
La scalabilità è un requisito fondamentale per le applicazioni cloud. Con Kubernetes, scalare un'applicazione è semplice quanto aumentare il numero di repliche per il deployment corrispondente o ReplicaSet — ma è un processo manuale.
Kubernetes consente di scalare automaticamente le applicazioni (cioè i Pod in un deployment o ReplicaSet) in modo dichiarativo utilizzando la specifica Horizontal Pod Autoscaler. Di default, il criterio per lo scaling automatico sono le metriche di utilizzo della CPU (metriche delle risorse), ma è possibile integrare metriche personalizzate e metriche fornite dall'esterno.
Team ha tradotto un articolo su come utilizzare metriche esterne per il auto-scaling dell'applicazione Kubernetes. Per illustrare il funzionamento, l'autore utilizza metriche di richieste HTTP, raccolte tramite Prometheus.
Invece della scalabilità automatica orizzontale dei pod, viene utilizzato Kubernetes Event Driven Autoscaling (KEDA) — un operatore Kubernetes open source. Si integra inizialmente con il Horizontal Pod Autoscaler per garantire una scalabilità fluida (incluso fino/a zero) per carichi di lavoro attivati da eventi. Il codice è disponibile su .
Panoramica del sistema

Nello schema, una breve descrizione di come funziona tutto:
- L'applicazione fornisce metriche sul numero di richieste HTTP nel formato Prometheus.
- Prometheus è configurato per raccogliere queste metriche.
- Il scalatore Prometheus in KEDA è impostato per scalare automaticamente l'applicazione in base al numero di richieste HTTP.
Ora spiegherò in dettaglio ogni elemento.
KEDA e Prometheus
Prometheus è un set di strumenti open source per il monitoraggio e la notifica dei sistemi, parte . Raccoglie metriche da diverse fonti e le memorizza come dati temporali. Per la visualizzazione dei dati è possibile utilizzare o altri strumenti di visualizzazione che lavorano con l'API di Kubernetes.
KEDA supporta il concetto di scaler: funge da ponte tra KEDA e un sistema esterno. L'implementazione dello scaler è specifica per ogni sistema di destinazione e ne estrae i dati. KEDA utilizza poi queste informazioni per gestire la scalabilità automatica.
Gli scaler supportano diverse fonti di dati, come Kafka, Redis, Prometheus. Questo significa che KEDA può essere utilizzato per la scalabilità automatica dei deployment Kubernetes, utilizzando come criteri le metriche di Prometheus.
Applicazione di test
L'applicazione di test in Golang fornisce accesso HTTP e svolge due funzioni importanti:
- Utilizza la libreria client Prometheus Go per strumentare l'app e fornire la metrica http_requests, che contiene un contatore degli accessi. Il punto finale dal quale le metriche di Prometheus sono accessibili si trova all'URI
/metrics.var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{ Name: "http_requests", Help: "numero di richieste http", }) - In risposta a una richiesta
GETl'applicazione incrementa il valore della chiave (access_count) in Redis. Questo è un modo semplice per eseguire l'operazione come parte del gestore HTTP e controllare anche le metriche di Prometheus. Il valore della metrica dovrebbe essere lo stesso del valoreaccess_countin 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("Impossibile incrementare il contatore Redis", err) os.Exit(1) } resp := "Accesso il " + time.Now().String() + " Conteggio accessi " + strconv.Itoa(int(count)) w.Write([]byte(resp)) }) http.ListenAndServe(":8080", nil) }
L'applicazione viene distribuita in Kubernetes tramite Deployment. Viene anche creato un servizio ClusterIP, che consente al server Prometheus di ricevere le metriche dell'applicazione.
Ecco .
Server Prometheus
Il manifesto di distribuzione di Prometheus è composto da:
ConfigMap— per la trasmissione della configurazione di Prometheus;Deployment— per la distribuzione di Prometheus nel cluster Kubernetes;ClusterIP— servizio per l'accesso all'interfaccia utente di Prometheus;ClusterRole,ClusterRoleBindingeServiceAccount— per il funzionamento dell'auto-scoperta dei servizi in Kubernetes (Auto-discovery).
Ecco .
KEDA Prometheus ScaledObject
Lo scaler funge da ponte tra KEDA e un sistema esterno da cui è necessario raccogliere metriche. ScaledObject — risorsa configurabile, deve essere distribuita per sincronizzare la distribuzione con la sorgente di eventi, in questo caso con Prometheus.
ScaledObject contiene informazioni sullo scaling del deployment, metadati sull'origine dell'evento (ad esempio, segreti per la connessione, nome della coda), intervallo di polling, periodo di raffreddamento e altri dati. Porta alla risorsa di auto-scaling corrispondente (definizione HPA) per scalare il deployment.
Quando l'oggetto ScaledObject viene rimosso, la relativa definizione HPA viene cancellata.
Ecco la definizione ScaledObject per il nostro esempio, in cui viene utilizzato lo 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]))
Tenere a mente i seguenti punti:
- Indica
Deploymentchiamatogo-prom-app. - Il tipo di trigger è
Prometheus. L'indirizzo del server Prometheus è menzionato insieme al nome della metrica, al valore soglia e , che verrà utilizzata. La query PromQL èsum(rate(http_requests[2m])). - Secondo
pollingInterval, KEDA interroga l'obiettivo da Prometheus ogni quindici secondi. È supportato un minimo di un pod (minReplicaCount), mentre il numero massimo di pod non superamaxReplicaCount(in questo esempio - dieci).
Puoi impostare minReplicaCount a zero. In questo caso, KEDA attiverà il deployment da zero a uno e poi fornirà HPA per ulteriore scalabilità automatica. È possibile anche l'ordine inverso, quindi scalare da uno a zero. Nell'esempio non abbiamo scelto zero, poiché si tratta di un servizio HTTP, non di un sistema on-demand.
La magia dell'autoscaling
Il valore di soglia viene utilizzato come attivatore per scalare il deployment. Nel nostro esempio, la richiesta PromQL sum(rate(http_requests[2m])) restituisce il valore aggregato della velocità delle richieste HTTP (numero di richieste al secondo), misurato nelle ultime due minuti.
Poiché il valore di soglia è tre, ci sarà un pod finché il valore è sum(rate(http_requests[2m])) inferiore a tre. Se il valore aumenta, viene aggiunto un pod ogni volta che sum(rate(http_requests[2m])) aumenta di tre. Ad esempio, se il valore va da 12 a 14, il numero di pod sarà quattro.
Adesso proviamo a configurarlo!
Configurazione preliminare
Tutto ciò di cui hai bisogno è un cluster Kubernetes e un'utilità configurata kubectl. In questo esempio si utilizza il cluster minikube, ma puoi prendere qualsiasi altro. Per installare il cluster, c'è .
Installa l'ultima versione su Mac:
curl -Lo minikube
https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64
&& chmod +x minikube
sudo mkdir -p /usr/local/bin/
sudo install minikube /usr/local/bin/
Installa , per accedere al cluster Kubernetes.
Installare 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 di KEDA
Puoi distribuire KEDA in diversi modi, elencati in . Io utilizzo un YAML monolitico:
kubectl apply -f
https://raw.githubusercontent.com/kedacore/keda/master/deploy/KedaScaleController.yaml
KEDA e i suoi componenti vengono installati nello spazio dei nomi keda. Comando per il controllo:
kubectl get pods -n keda
Aspetta che il pod del KEDA Operator avvii e passi a Running State. E poi continua.
Installazione di Redis con Helm
Se Helm non è installato, utilizza questa . Comando per l'installazione su Mac:
brew install kubernetes-helm
helm init --history-max 200
helm init inizializza l'interfaccia della riga di comando locale e installa Tiller nel cluster Kubernetes.
kubectl get pods -n kube-system | grep tiller
Aspetta che il pod di Tiller passi allo stato Running.
Nota del traduttore: L'autore utilizza Helm@2, che richiede l'installazione del componente server Tiller. Attualmente è in uso Helm@3, per il quale il server non è necessario.
Dopo aver installato Helm per avviare Redis, è sufficiente un comando:
helm install --name redis-server --set cluster.enabled=false --set
usePassword=false stable/redis
Assicurati che Redis sia stato avviato correttamente:
kubectl get pods/redis-server-master-0
Attendi che il pod Redis passi allo stato Esecuzione.
Distribuzione dell'applicazione
Comando per la distribuzione:
kubectl apply -f go-app.yaml
//output
department.apps/go-prom-app created
service/go-prom-app-service created
Verifica che tutto sia avviato:
kubectl get pods -l=app=go-prom-app
Attendi il cambiamento dello stato di Redis in Esecuzione.
Distribuzione del server Prometheus
Il manifesto di Prometheus utilizza . Questo consente di scoprire dinamicamente i 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 la distribuzione:
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
department.extensions/prometheus-deployment created
service/prometheus-service created
Verifica che tutto sia avviato:
kubectl get pods -l=app=prometheus-server
Attendere il passaggio di Prometheus allo stato Esecuzione.
Usa kubectl port-forward per accedere all'interfaccia utente di Prometheus (o al server API) all'indirizzo .
kubectl port-forward service/prometheus-service 9090
Distribuzione della configurazione di auto-scaling 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 dovrebbe apparire simile 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"
Controlla il pod delle applicazioni. Dovrebbe esserci un'istanza in esecuzione, poiché minReplicaCount è uguale a 1:
kubectl get pods -l=app=go-prom-app
Verifica che la risorsa HPA sia stata creata con successo:
kubectl get hpa
Dovresti vedere qualcosa di simile:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
keda-hpa-go-prom-app Deployment/go-prom-app 0/3 (avg) 1 10 1 45s
Verifica della funzionalità: accesso all'applicazione
Per accedere all'endpoint REST della nostra applicazione, esegui:
kubectl port-forward service/go-prom-app-service 8080
Ora puoi accedere all'applicazione Go utilizzando l'indirizzo . Per fare ciò, esegui il comando:
curl http://localhost:8080/test
Il risultato dovrebbe apparire simile a:
Accessed on 2019-10-21 11:29:10.560385986 +0000 UTC
m=+406004.817901246
Access count 1
In questo passaggio, controlla anche Redis. Vedrai che la chiave access_count è aumentata a 1:
kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
"1"
Assicurati che il valore della metrica http_requests sia lo stesso:
curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests numero di richieste http
# TYPE http_requests counter
http_requests 1
Creazione del carico
Utilizzeremo — un'utility per generare carico:
curl -o hey https://storage.googleapis.com/hey-release/hey_darwin_amd64
&& chmod a+x hey
Puoi anche scaricare l'utility per o .
Eseguila:
./hey http://localhost:8080/test
Per impostazione predefinita, l'utility invia 200 richieste. Puoi verificarlo utilizzando le metriche Prometheus e anche Redis.
curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests numero di richieste http
# TYPE http_requests counter
http_requests 201
kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
201
Verifica 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 scalare, poiché la soglia che abbiamo impostato è 3.
Maggiore carico!
Nel nuovo terminale, segui il numero di pod dell'app:
kubectl get pods -l=app=go-prom-app -w
Aumentiamo il carico con il comando:
./hey -n 2000 http://localhost:8080/test
Dopo un po' vedrai che HPA scala il deployment e avvia nuovi pod. Controlla l'HPA per verificarlo:
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 è irregolare, il deployment si ridurrà al punto in cui funziona solo un pod. Se vuoi controllare la metrica reale (restituita dalla query PromQL), usa 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 permette di scalare automaticamente i tuoi deployment Kubernetes (fino/da zero) in base ai dati provenienti da metriche esterne. Ad esempio, basato su metriche Prometheus, lunghezza della coda in Redis, latenza del consumatore nel topic Kafka.
KEDA effettua l'integrazione con una fonte esterna e fornisce anche le sue metriche attraverso il Metrics Server per il Horizontal Pod Autoscaler.
Buona fortuna!
Cosa altro leggere:
- .
- .
- .
Fonte: habr.com
