Autoscaling des applications Kubernetes avec Prometheus et KEDA

Autoscaling des applications Kubernetes avec Prometheus et KEDABalloon Man par Cimuanos

La scalabilitĂ© est une exigence clĂ© pour les applications cloud. Avec Kubernetes, il est aussi simple de mettre Ă  l'Ă©chelle une application que d'augmenter le nombre de rĂ©pliques pour le dĂ©ploiement correspondant ou ReplicaSet — mais cela reste un processus manuel.

Kubernetes permet de mettre automatiquement à l'échelle les applications (c'est-à-dire les Pods dans un déploiement ou ReplicaSet) de maniÚre déclarative en utilisant la spécification Horizontal Pod Autoscaler. Par défaut, le critÚre pour la mise à l'échelle automatique repose sur les métriques d'utilisation du CPU (métriques des ressources), mais il est possible d'intégrer des métriques personnalisées ainsi que des métriques fournies de l'extérieur.

Commande Kubernetes aaS de Mail.ru a traduit un article sur la maniĂšre d'utiliser des mĂ©triques externes pour mettre automatiquement Ă  l'Ă©chelle une application Kubernetes. Pour illustrer son fonctionnement, l'auteur utilise les mĂ©triques des requĂȘtes HTTP, qui sont collectĂ©es via Prometheus.

Au lieu de la mise Ă  l'Ă©chelle horizontale des Pods, Kubernetes Event Driven Autoscaling (KEDA) est utilisĂ© — un opĂ©rateur Kubernetes open source. Il s'intĂšgre Ă  Horizontal Pod Autoscaler pour garantir une mise Ă  l'Ă©chelle fluide (y compris jusqu'Ă  zĂ©ro) pour les charges de travail dĂ©clenchĂ©es par des Ă©vĂ©nements. Le code est disponible sur GitHub.

Une vue d'ensemble du fonctionnement du systĂšme

Autoscaling des applications Kubernetes avec Prometheus et KEDA

Le schéma ci-dessous décrit briÚvement comment tout cela fonctionne :

  1. L'application fournit des métriques concernant le nombre d'accÚs HTTP au format Prometheus.
  2. Prometheus est configuré pour collecter ces indicateurs.
  3. Le scaler Prometheus dans KEDA est configuré pour mettre automatiquement à l'échelle l'application en fonction du nombre d'accÚs HTTP.

Je vais maintenant décrire en détail chaque élément.

KEDA et Prometheus

Prometheus est un ensemble d'outils open source pour la surveillance et l'alerte des systÚmes, faisant partie de Fondation Cloud Native Computing. Il collecte des métriques provenant de diverses sources et les conserve sous forme de données de séries temporelles. Pour la visualisation des données, il est possible d'utiliser Grafana ou d'autres outils de visualisation fonctionnant avec l'API Kubernetes.

KEDA prend en charge le concept de scaler — il agit comme un pont entre KEDA et un systĂšme externe. L'implĂ©mentation du scaler est spĂ©cifique Ă  chaque systĂšme cible et en extrait les donnĂ©es. Ensuite, KEDA les utilise pour contrĂŽler la mise Ă  l'Ă©chelle automatique.

Les scaleurs prennent en charge plusieurs sources de donnĂ©es, telles que Kafka, Redis et Prometheus. Cela signifie que KEDA peut ĂȘtre utilisĂ© pour l'auto-scaling des dĂ©ploiements Kubernetes, en utilisant les mĂ©triques Prometheus comme critĂšres.

Application de test

L'application Golang de test offre un accĂšs HTTP et remplit deux fonctions importantes :

  1. Elle utilise la bibliothĂšque cliente Prometheus Go pour instrumenter l'application et fournir la mĂ©trique http_requests, qui contient un compteur des requĂȘtes. Le point final oĂč les mĂ©triques Prometheus sont disponibles se trouve Ă  l'URI /metrics.
    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "nombre de requĂȘtes HTTP",
       })
    
  2. En rĂ©ponse Ă  la requĂȘte GET l'application augmente la valeur de la clĂ© (access_count) dans Redis. C'est un moyen simple d'effectuer le travail dans le cadre du gestionnaire HTTP, ainsi que de vĂ©rifier les mĂ©triques Prometheus. La valeur de la mĂ©trique doit ĂȘtre identique Ă  celle de access_count dans 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("Impossible d'incrémenter le compteur redis", err)
                   os.Exit(1)
               }
               resp := "Accédé le " + time.Now().String() + "nCompteur d'accÚs " + strconv.Itoa(int(count))
               w.Write([]byte(resp))
           })
           http.ListenAndServe(":8080", nil)
       }
    

L'application est déployée dans Kubernetes via Déploiement. Un service est également créé ClusterIP, permettant au serveur Prometheus de recevoir les métriques de l'application.

Voici manifeste de déploiement pour l'application.

Serveur Prometheus

Le manifeste de déploiement de Prometheus se compose de :

  • ConfigMap — pour transmettre la configuration de Prometheus ;
  • DĂ©ploiement — pour dĂ©ployer Prometheus dans le cluster Kubernetes ;
  • ClusterIP — service pour accĂ©der Ă  l'interface utilisateur de Prometheus ;
  • ClusterRole, ClusterRoleBinding et ServiceAccount — pour la dĂ©couverte automatique des services dans Kubernetes.

Voici manifeste pour exécuter Prometheus.

KEDA Prometheus ScaledObject

Le scaleur agit comme un pont entre KEDA et le systĂšme externe Ă  partir duquel les mĂ©triques doivent ĂȘtre rĂ©cupĂ©rĂ©es. ScaledObject — ressource configurable, qui doit ĂȘtre dĂ©ployĂ©e pour synchroniser le dĂ©ploiement avec la source d'Ă©vĂ©nements, dans ce cas, avec Prometheus.

ScaledObject contient des informations sur le scaling du déploiement, des métadonnées sur la source d'événements (par exemple, des secrets pour la connexion, le nom de la file d'attente), l'intervalle d'interrogation, la période de récupération et d'autres données. Il conduit à la ressource appropriée d'auto-scaling (définition HPA) pour le scaling du déploiement.

Lorsque l'objet ScaledObject est supprimé, la définition HPA correspondante est nettoyée.

Voici la définition ScaledObject pour notre exemple, il utilise 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]))

Considérez les points suivants :

  1. Il fait référence à Déploiement avec le nom go-prom-app.
  2. Le type de trigger est Prometheus. L'adresse du serveur Prometheus est mentionnĂ©e avec le nom de la mĂ©trique, la valeur seuil et la requĂȘte PromQL, qui sera utilisĂ©e. La requĂȘte PromQL est sum(rate(http_requests[2m])).
  3. Selon pollingInterval, KEDA interroge l'objectif auprĂšs de Prometheus toutes les quinze secondes. Au moins un pod est supportĂ© (minReplicaCount), et le nombre maximum de pods ne dĂ©passe pas maxReplicaCount (dans cet exemple — dix).

Peut ĂȘtre fixĂ© minReplicaCount Ă  zĂ©ro. Dans ce cas, KEDA active le dĂ©ploiement de zĂ©ro Ă  un, puis fournit HPA pour un scaling automatique ultĂ©rieur. Il est Ă©galement possible de faire l逆, c'est-Ă -dire de faire passer de un Ă  zĂ©ro. Dans cet exemple, nous n'avons pas choisi zĂ©ro car il s'agit d'un service HTTP et non d'un systĂšme Ă  la demande.

La magie du scaling automatique

La valeur seuil est utilisĂ©e comme dĂ©clencheur pour le scaling du dĂ©ploiement. Dans notre exemple, la requĂȘte PromQL sum(rate(http_requests[2m])) renvoie une valeur agrĂ©gĂ©e du taux de requĂȘtes HTTP (nombre de requĂȘtes par seconde), mesurĂ©e au cours des deux derniĂšres minutes.

Étant donnĂ© que la valeur seuil est de trois, il y aura un pod tant que la valeur sum(rate(http_requests[2m])) est infĂ©rieure Ă  trois. Si la valeur augmente, un pod supplĂ©mentaire est ajoutĂ© chaque fois que sum(rate(http_requests[2m])) elle augmente de trois. Par exemple, si la valeur passe de 12 Ă  14, alors le nombre de pods est de quatre.

Essayons maintenant de configurer !

Configuration préalable

Tout ce dont vous avez besoin est un cluster Kubernetes et un utilitaire configuré kubectl. Dans cet exemple, nous utilisons un cluster minikube, mais vous pouvez en prendre un autre. Pour installer le cluster, il y a guide.

Installer la derniĂšre version sur 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/

Installez kubectl, pour accéder au cluster Kubernetes.

Installer la derniĂšre version sur 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

Installation de KEDA

Vous pouvez déployer KEDA de plusieurs maniÚres, qui sont énumérées dans documentation. J'utilise un YAML monolithique :

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

KEDA et ses composants sont installés dans l'espace de noms keda. La commande pour vérifier :

kubectl get pods -n keda

Attendez que le pod KEDA Operator dĂ©marre — passe en État de fonctionnement. Et ensuite continuez.

Installation de Redis avec Helm

Si vous n'avez pas installé Helm, utilisez ceci guide. La commande pour l'installation sur Mac :

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

helm init initialise l'interface en ligne de commande locale et installe également Tiller dans le cluster Kubernetes.

kubectl get pods -n kube-system | grep tiller

Attendez que le pod Tiller passe à l'état de fonctionnement.

Note du traducteur: L'auteur utilise Helm@2, qui nécessite l'installation du composant serveur Tiller. Actuellement, Helm@3 est à jour, il n'a pas besoin de la partie serveur.

AprÚs l'installation de Helm, il suffit d'une commande pour démarrer Redis :

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

Vérifiez que Redis a démarré avec succÚs :

kubectl get pods/redis-server-master-0

Attendez que le pod Redis passe à l'état Running.

Déploiement de l'application

Commande pour le déploiement :

kubectl apply -f go-app.yaml

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

Vérifiez que tout a démarré :

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

Attendez que Redis passe à l'état Running.

Déploiement du serveur Prometheus

Le manifeste Prometheus utilise Kubernetes Service Discovery pour Prometheus. Cela permet de découvrir dynamiquement les pods de l'application en fonction de l'étiquette du service.

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

Pour le déploiement :

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

Vérifiez que tout a démarré :

kubectl get pods -l=app=prometheus-server

Attendez que le pod Prometheus passe à l'état Running.

Windows VPS pour le travail à distance kubectl port-forward pour accéder à l'interface utilisateur de Prometheus (ou au serveur API) à l'adresse http://localhost:9090.

kubectl port-forward service/prometheus-service 9090

Déploiement de la configuration d'autoscaling KEDA

Commande pour créer ScaledObject:

kubectl apply -f keda-prometheus-scaledobject.yaml

Vérifiez les journaux de l'opérateur KEDA :

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

Le résultat ressemble à ceci :

time="2019-10-15T09:38:28Z" level=info msg="Surveillance de ScaledObject :
default/prometheus-scaledobject"
time="2019-10-15T09:38:28Z" level=info msg="HPA créé avec 
namespace default et nom keda-hpa-go-prom-app"

VĂ©rifiez sous les applications. Une instance doit ĂȘtre en cours d'exĂ©cution car minReplicaCount Ă©gal Ă  1 :

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

Vérifiez que la ressource HPA a été créée avec succÚs :

kubectl get hpa

Vous devriez voir quelque chose comme :

NOM                   RÉFÉRENCE                CIBLES     MINPODS   MAXPODS   RÉPLICAS   ÂGE
keda-hpa-go-prom-app   Deployment/go-prom-app   0/3 (moyenne)   1         10        1          45s

Vérification de la disponibilité : accÚs à l'application

Pour accéder au point de terminaison REST de notre application, exécutez :

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

Vous pouvez maintenant accéder à l'application Go en utilisant l'adresse http://localhost:8080. Pour ce faire, exécutez la commande :

curl http://localhost:8080/test

Le résultat ressemble à ceci :

Accédé le 2019-10-21 11:29:10.560385986 +0000 UTC 
m=+406004.817901246
Nombre d'accĂšs 1

À ce stade, vĂ©rifiez Ă©galement Redis. Vous verrez que la clĂ© access_count a Ă©tĂ© augmentĂ©e Ă  1 :

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

Assurez-vous que la valeur de la mĂ©trique http_requests est la mĂȘme :

curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests nombre de requĂȘtes HTTP
# TYPE http_requests compteur
http_requests 1

Création de charge

Nous allons utiliser hey — un utilitaire pour gĂ©nĂ©rer une charge :

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

Vous pouvez également télécharger l'utilitaire pour Linux ou Windows.

Lancez-le :

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

Par dĂ©faut, l'utilitaire envoie 200 requĂȘtes. Vous pouvez le vĂ©rifier en utilisant les mĂ©triques Prometheus, ainsi que Redis.

curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests nombre de requĂȘtes HTTP
# TYPE http_requests compteur
http_requests 201
kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
201

Confirmez la valeur de la mĂ©trique rĂ©elle (renvoyĂ©e par la requĂȘte 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"]}]}}

Dans ce cas, le résultat réel est 1,686057971014493 et s'affiche dans le champ value. Ce n'est pas suffisant pour l'échelle, car le seuil que nous avons fixé est de 3.

Plus de charge !

Dans un nouveau terminal, surveillez le nombre de pods de l'application :

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

Augmentons la charge avec la commande :

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

AprĂšs un certain temps, vous verrez que HPA redimensionne le dĂ©ploiement et lance de nouveaux pods. VĂ©rifiez HPA pour en ĂȘtre sĂ»r :

kubectl get hpa
NOM                   RÉFÉRENCE                CIBLES         MINPODS   MAXPODS   RÉPLICAS   ÂGE
keda-hpa-go-prom-app   Deployment/go-prom-app   1830m/3 (moyenne)   1         10        6          4m22s

Si la charge est variable, le dĂ©ploiement sera rĂ©duit au point oĂč seul un pod fonctionne. Si vous souhaitez vĂ©rifier la mĂ©trique rĂ©elle (retournĂ©e par la requĂȘte PromQL), utilisez la commande :

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

Nettoyage

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

Conclusion

KEDA permet de mettre à l'échelle automatiquement vos déploiements Kubernetes (vers/depuis zéro) en fonction des données provenant de métriques externes. Par exemple, sur la base des métriques Prometheus, de la longueur de la file d'attente dans Redis, ou du délai de consommation dans un sujet Kafka.

KEDA s'intÚgre à une source externe et fournit également ses métriques via le Metrics Server pour le Horizontal Pod Autoscaler.

Bonne chance !

Que lire d'autre :

  1. Meilleures pratiques et recommandations pour exécuter des conteneurs et Kubernetes dans des environnements de production.
  2. 90+ outils utiles pour Kubernetes : déploiement, gestion, monitoring, sécurité et plus encore.
  3. Notre chaĂźne Autour de Kubernetes sur Telegram.

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster