Αυτόματη κλιμάκωση εφαρμογών Kubernetes χρησιμοποιώντας Prometheus και KEDA

Αυτόματη κλιμάκωση εφαρμογών Kubernetes χρησιμοποιώντας Prometheus και KEDABalloon Man του Cimuanos

Η επεκτασιμότητα είναι βασική απαίτηση για εφαρμογές cloud. Με το Kubernetes, η κλιμάκωση μιας εφαρμογής είναι τόσο απλή όσο η αύξηση του αριθμού των αντιγράφων για την κατάλληλη ανάπτυξη ή ReplicaSet — αλλά είναι μια χειροκίνητη διαδικασία.

Το Kubernetes επιτρέπει στις εφαρμογές να κλιμακώνονται αυτόματα (δηλ. Pods σε μια ανάπτυξη ή ReplicaSet) με δηλωτικό τρόπο χρησιμοποιώντας την προδιαγραφή Horizontal Pod Autoscaler. Το προεπιλεγμένο κριτήριο για την αυτόματη κλιμάκωση είναι οι μετρήσεις χρήσης της CPU (μετρήσεις πόρων), αλλά μπορείτε να ενσωματώσετε προσαρμοσμένες και εξωτερικά παρεχόμενες μετρήσεις.

Ομάδα Kubernetes aaS από το Mail.ru μετέφρασε ένα άρθρο σχετικά με τον τρόπο χρήσης εξωτερικών μετρήσεων για την αυτόματη κλιμάκωση μιας εφαρμογής Kubernetes. Για να δείξει πώς λειτουργούν όλα, ο συγγραφέας χρησιμοποιεί μετρήσεις αιτημάτων πρόσβασης HTTP, οι οποίες συλλέγονται χρησιμοποιώντας το Prometheus.

Αντί της οριζόντιας αυτόματης κλιμάκωσης των pod, χρησιμοποιείται Kubernetes Event Driven Autoscaling (KEDA), ένας τελεστής Kubernetes ανοιχτού κώδικα. Ενσωματώνεται εγγενώς με το Horizontal Pod Autoscaler για να παρέχει απρόσκοπτη αυτόματη κλιμάκωση (συμπεριλαμβανομένων προς/από το μηδέν) για φόρτους εργασίας βάσει συμβάντων. Κωδικός διαθέσιμος στο GitHub.

Σύντομη επισκόπηση του συστήματος

Αυτόματη κλιμάκωση εφαρμογών Kubernetes χρησιμοποιώντας Prometheus και KEDA

Το διάγραμμα δείχνει μια σύντομη περιγραφή του πώς όλα λειτουργούν:

  1. Η εφαρμογή παρέχει μετρήσεις αριθμού επισκέψεων HTTP σε μορφή Prometheus.
  2. Ο Προμηθέας έχει διαμορφωθεί για να συλλέγει αυτές τις μετρήσεις.
  3. Ο scaler Prometheus στο KEDA έχει ρυθμιστεί ώστε να κλιμακώνει αυτόματα την εφαρμογή με βάση τον αριθμό των επισκέψεων HTTP.

Τώρα θα σας πω αναλυτικά για κάθε στοιχείο.

ΚΕΔΑ και Προμηθέας

Το Prometheus είναι ένα τμήμα εργαλείων παρακολούθησης και ειδοποίησης συστήματος ανοιχτού κώδικα Ίδρυμα Cloud Native Computing. Συλλέγει μετρήσεις από διάφορες πηγές και τις αποθηκεύει ως δεδομένα χρονοσειρών. Για να οπτικοποιήσετε δεδομένα μπορείτε να χρησιμοποιήσετε Γκράφανα ή άλλα εργαλεία οπτικοποίησης που λειτουργούν με το Kubernetes API.

Το KEDA υποστηρίζει την έννοια του scaler - λειτουργεί ως γέφυρα μεταξύ του KEDA και του εξωτερικού συστήματος. Η υλοποίηση του scaler είναι συγκεκριμένη για κάθε σύστημα στόχου και εξάγει δεδομένα από αυτό. Το KEDA στη συνέχεια τα χρησιμοποιεί για τον έλεγχο της αυτόματης κλιμάκωσης.

Οι Scalers υποστηρίζουν πολλαπλές πηγές δεδομένων, για παράδειγμα, Kafka, Redis, Prometheus. Δηλαδή, το KEDA μπορεί να χρησιμοποιηθεί για την αυτόματη κλιμάκωση των αναπτύξεων Kubernetes χρησιμοποιώντας τις μετρήσεις Prometheus ως κριτήρια.

Δοκιμαστική εφαρμογή

Η εφαρμογή δοκιμής Golang παρέχει πρόσβαση μέσω HTTP και εκτελεί δύο σημαντικές λειτουργίες:

  1. Χρησιμοποιεί τη βιβλιοθήκη πελατών Prometheus Go για να οργανώσει την εφαρμογή και να παρέχει τη μέτρηση http_requests, η οποία περιέχει έναν αριθμό επισκέψεων. Το τελικό σημείο όπου είναι διαθέσιμες οι μετρήσεις Prometheus βρίσκεται στο URI /metrics.
    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "number of http requests",
       })
    
  2. Σε απάντηση αιτήματος GET η εφαρμογή αυξάνει την τιμή του κλειδιού (access_count) στο Ρέντις. Αυτός είναι ένας εύκολος τρόπος για να κάνετε τη δουλειά ως μέρος ενός προγράμματος χειρισμού HTTP και επίσης να ελέγξετε τις μετρήσεις του Prometheus. Η μετρική τιμή πρέπει να είναι ίδια με την τιμή access_count στο Ρέντις.
    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)
       }
    

Η εφαρμογή αναπτύσσεται στο Kubernetes μέσω Deployment. Δημιουργείται επίσης μια υπηρεσία ClusterIP, επιτρέπει στον διακομιστή Prometheus να αποκτήσει μετρήσεις εφαρμογών.

Εδώ δηλωτικό ανάπτυξης για την εφαρμογή.

Διακομιστής Prometheus

Το μανιφέστο ανάπτυξης του Prometheus αποτελείται από:

  • ConfigMap — για μεταφορά της διαμόρφωσης Prometheus.
  • Deployment — για την ανάπτυξη του Prometheus σε ένα σύμπλεγμα Kubernetes.
  • ClusterIP — υπηρεσία πρόσβασης στο UI Prometheus·
  • ClusterRole, ClusterRoleBinding и ServiceAccount — για αυτόματη ανίχνευση υπηρεσιών στο Kubernetes (Αυτόματη ανακάλυψη).

Εδώ μανιφέστο για τη λειτουργία του Προμηθέα.

ΚΕΔΑ Προμηθέας ScaledObject

Ο κλιμακωτής λειτουργεί ως γέφυρα μεταξύ της ΚΕΔΑ και του εξωτερικού συστήματος από το οποίο πρέπει να λαμβάνονται μετρήσεις. ScaledObject είναι ένας προσαρμοσμένος πόρος που πρέπει να αναπτυχθεί για να συγχρονιστεί η ανάπτυξη με την πηγή συμβάντος, σε αυτήν την περίπτωση τον Prometheus.

ScaledObject περιέχει πληροφορίες κλιμάκωσης ανάπτυξης, μεταδεδομένα πηγής συμβάντων (όπως μυστικά σύνδεσης, όνομα ουράς), διάστημα ψηφοφορίας, περίοδο ανάκτησης και άλλα δεδομένα. Έχει ως αποτέλεσμα τον αντίστοιχο πόρο αυτόματης κλιμάκωσης (ορισμός HPA) για την κλίμακα της ανάπτυξης.

Όταν ένα αντικείμενο ScaledObject διαγράφεται, ο αντίστοιχος ορισμός HPA διαγράφεται.

Εδώ είναι ο ορισμός ScaledObject για το παράδειγμά μας, χρησιμοποιεί ένα 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]))

Σημειώστε τα ακόλουθα σημεία:

  1. Δείχνει σε Deployment Με όνομα go-prom-app.
  2. Τύπος σκανδάλης - Prometheus. Η διεύθυνση διακομιστή Prometheus αναφέρεται μαζί με το μετρικό όνομα, το όριο και Ερώτημα PromQL, το οποίο θα χρησιμοποιηθεί. Ερώτημα PromQL - sum(rate(http_requests[2m])).
  3. Σύμφωνα με pollingInterval,Η ΚΕΔΑ ζητά έναν στόχο από τον Προμηθέα κάθε δεκαπέντε δευτερόλεπτα. Τουλάχιστον ένα κάτω από (minReplicaCount), και ο μέγιστος αριθμός λοβών δεν υπερβαίνει maxReplicaCount (σε αυτό το παράδειγμα - δέκα).

Μπορεί να εγκατασταθεί minReplicaCount ίσο με μηδέν. Σε αυτήν την περίπτωση, το KEDA ενεργοποιεί την ανάπτυξη μηδέν προς ένα και στη συνέχεια εκθέτει το HPA για περαιτέρω αυτόματη κλιμάκωση. Είναι δυνατή και η αντίστροφη σειρά, δηλαδή η κλίμακα από το ένα στο μηδέν. Στο παράδειγμα, δεν επιλέξαμε το μηδέν επειδή πρόκειται για υπηρεσία HTTP και όχι για σύστημα κατ' απαίτηση.

Η μαγεία μέσα στην αυτόματη κλιμάκωση

Το κατώφλι χρησιμοποιείται ως έναυσμα για την κλιμάκωση της ανάπτυξης. Στο παράδειγμά μας, το ερώτημα PromQL sum(rate (http_requests [2m])) επιστρέφει το συγκεντρωτικό ρυθμό αιτημάτων HTTP (αιτήματα ανά δευτερόλεπτο), που μετρήθηκε τα τελευταία δύο λεπτά.

Δεδομένου ότι η τιμή κατωφλίου είναι τρία, σημαίνει ότι θα υπάρχει ένα κάτω ενώ η τιμή sum(rate (http_requests [2m])) λιγότερο από τρεις. Εάν η τιμή αυξάνεται, κάθε φορά προστίθεται ένα επιπλέον δευτερεύον sum(rate (http_requests [2m])) αυξάνεται κατά τρεις. Για παράδειγμα, εάν η τιμή είναι από 12 έως 14, τότε ο αριθμός των λοβών είναι τέσσερις.

Τώρα ας προσπαθήσουμε να το ρυθμίσουμε!

Προρύθμιση

Το μόνο που χρειάζεστε είναι ένα σύμπλεγμα Kubernetes και ένα διαμορφωμένο βοηθητικό πρόγραμμα kubectl. Αυτό το παράδειγμα χρησιμοποιεί ένα σύμπλεγμα minikube, αλλά μπορείτε να πάρετε οποιοδήποτε άλλο. Για να εγκαταστήσετε ένα σύμπλεγμα υπάρχει οδηγός.

Εγκαταστήστε την πιο πρόσφατη έκδοση σε 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/

Σετ kubectlγια πρόσβαση στο σύμπλεγμα Kubernetes.

Εγκαταστήστε την πιο πρόσφατη έκδοση σε 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

Εγκατάσταση ΚΕΔΑ

Μπορείτε να αναπτύξετε το KEDA με διάφορους τρόπους, αυτοί αναφέρονται τεκμηρίωση. Χρησιμοποιώ μονολιθικό YAML:

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

Το KEDA και τα στοιχεία του εγκαθίστανται στον χώρο ονομάτων keda. Εντολή για έλεγχο:

kubectl get pods -n keda

Περιμένετε να ξεκινήσει ο χειριστής KEDA και μεταβείτε στο Running State. Και μετά από αυτό, συνεχίστε.

Εγκατάσταση του Redis χρησιμοποιώντας Helm

Εάν δεν έχετε εγκατεστημένο το Helm, χρησιμοποιήστε αυτό ηγεσία. Εντολή για εγκατάσταση σε Mac:

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

helm init αρχικοποιεί τη διεπαφή τοπικής γραμμής εντολών και επίσης εγκαθιστά Tiller στο σύμπλεγμα Kubernetes.

kubectl get pods -n kube-system | grep tiller

Περιμένετε μέχρι το Tiller pod να εισέλθει σε κατάσταση λειτουργίας.

Σημείωμα μεταφραστή: Ο συγγραφέας χρησιμοποιεί το Helm@2, το οποίο απαιτεί την εγκατάσταση του στοιχείου διακομιστή Tiller. Τώρα το Helm@3 είναι σχετικό, δεν απαιτεί τμήμα διακομιστή.

Μετά την εγκατάσταση του Helm, αρκεί μία εντολή για να ξεκινήσει το Redis:

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

Βεβαιωθείτε ότι το Redis ξεκίνησε με επιτυχία:

kubectl get pods/redis-server-master-0

Περιμένετε να μπει ο Redis σε κατάσταση Running.

Ανάπτυξη Εφαρμογής

Εντολή ανάπτυξης:

kubectl apply -f go-app.yaml

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

Ελέγξτε ότι όλα έχουν ξεκινήσει:

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

Περιμένετε να εισέλθει ο Redis σε κατάσταση Running.

Ανάπτυξη διακομιστή Prometheus

Το μανιφέστο του Προμηθέα χρησιμοποιεί Kubernetes Service Discovery για τον Προμηθέα. Επιτρέπει τη δυναμική ανακάλυψη ομάδων εφαρμογών με βάση την ετικέτα υπηρεσίας.

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

Για ανάπτυξη:

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

Ελέγξτε ότι όλα έχουν ξεκινήσει:

kubectl get pods -l=app=prometheus-server

Περιμένετε να πάει ο Προμηθέας σε κατάσταση Running.

χρήση kubectl port-forward για πρόσβαση στη διεπαφή χρήστη Prometheus (ή διακομιστή API) στη διεύθυνση http://localhost:9090.

kubectl port-forward service/prometheus-service 9090

Ανάπτυξη της ρύθμισης παραμέτρων αυτόματης κλιμάκωσης KEDA

Εντολή για δημιουργία ScaledObject:

kubectl apply -f keda-prometheus-scaledobject.yaml

Ελέγξτε τα αρχεία καταγραφής χειριστή KEDA:

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

Το αποτέλεσμα μοιάζει κάπως έτσι:

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"

Ελέγξτε κάτω από τις εφαρμογές. Μια παρουσία πρέπει να εκτελείται επειδή minReplicaCount ισούται με 1:

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

Βεβαιωθείτε ότι ο πόρος HPA δημιουργήθηκε με επιτυχία:

kubectl get hpa

Θα πρέπει να δείτε κάτι σαν:

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

Έλεγχος υγείας: πρόσβαση στην εφαρμογή

Για πρόσβαση στο τελικό σημείο REST της εφαρμογής μας, εκτελέστε:

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

Μπορείτε πλέον να αποκτήσετε πρόσβαση στην εφαρμογή Go χρησιμοποιώντας τη διεύθυνση http://localhost:8080. Για να το κάνετε αυτό, εκτελέστε την εντολή:

curl http://localhost:8080/test

Το αποτέλεσμα μοιάζει κάπως έτσι:

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

Σε αυτό το σημείο ελέγξτε επίσης το Redis. Θα δείτε ότι το κλειδί access_count αυξήθηκε σε 1:

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

Βεβαιωθείτε ότι η μετρική τιμή είναι http_requests το ίδιο:

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

Φόρτωση Δημιουργίας

Θα το χρησιμοποιησουμε hey — βοηθητικό πρόγραμμα για τη δημιουργία φορτίου:

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

Μπορείτε επίσης να κάνετε λήψη του βοηθητικού προγράμματος για Linux ή Windows.

Τρέξε το:

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

Από προεπιλογή, το βοηθητικό πρόγραμμα στέλνει 200 ​​αιτήματα. Μπορείτε να το επαληθεύσετε χρησιμοποιώντας τις μετρήσεις Prometheus καθώς και το 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

Επικυρώστε την τιμή της πραγματικής μέτρησης (που επιστράφηκε από το ερώτημα 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"]}]}}

Σε αυτή την περίπτωση το πραγματικό αποτέλεσμα είναι 1,686057971014493 και εμφανίζεται στο πεδίο value. Αυτό δεν αρκεί για κλιμάκωση, αφού το όριο που ορίσαμε είναι 3.

Περισσότερο φορτίο!

Στο νέο τερματικό, παρακολουθήστε τον αριθμό των ομάδων εφαρμογών:

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

Ας αυξήσουμε το φορτίο χρησιμοποιώντας την εντολή:

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

Μετά από λίγο, θα δείτε το HPA να κλιμακώνει την ανάπτυξη και να εκκινεί νέα pods. Ελέγξτε το HPA σας για να βεβαιωθείτε:

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

Εάν το φορτίο είναι ασυνεπές, η ανάπτυξη θα μειωθεί στο σημείο όπου λειτουργεί μόνο ένα pod. Εάν θέλετε να ελέγξετε την πραγματική μέτρηση (που επιστράφηκε από το ερώτημα PromQL), χρησιμοποιήστε την εντολή:

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

Καθαρισμός

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

Συμπέρασμα

Το KEDA σάς επιτρέπει να κλιμακώνετε αυτόματα τις αναπτύξεις του Kubernetes (σε/από μηδέν) με βάση δεδομένα από εξωτερικές μετρήσεις. Για παράδειγμα, με βάση τις μετρήσεις του Προμηθέα, το μήκος ουράς στο Redis, τον λανθάνοντα χρόνο καταναλωτή στο θέμα Kafka.

Το KEDA ενσωματώνεται με μια εξωτερική πηγή και παρέχει επίσης τις μετρήσεις του μέσω του Metrics Server στο Horizontal Pod Autoscaler.

Καλή τύχη!

Τι άλλο να διαβάσετε:

  1. Βέλτιστες πρακτικές και βέλτιστες πρακτικές για τη λειτουργία κοντέινερ και Kubernetes σε περιβάλλοντα παραγωγής.
  2. 90+ Χρήσιμα εργαλεία για Kubernetes: Ανάπτυξη, Διαχείριση, Παρακολούθηση, Ασφάλεια και άλλα.
  3. Το κανάλι μας Around Kubernetes στο Telegram.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο