Mise à l'échelle automatique des applications Kubernetes à l'aide de Prometheus et KEDA

Mise à l'échelle automatique des applications Kubernetes à l'aide de Prometheus et KEDA« Homme ballon » par Cimuanos

L'évolutivité est une exigence clé pour les applications cloud. Avec Kubernetes, faire évoluer une application est aussi simple que d'augmenter le nombre de réplicas pour le déploiement approprié ou ReplicaSet - mais c'est un processus manuel.

Kubernetes permet aux applications d'être automatiquement mises à l'échelle (c'est-à-dire les pods dans un déploiement ou ReplicaSet) de manière déclarative à l'aide de la spécification Horizontal Pod Autoscaler. Le critère par défaut pour la mise à l'échelle automatique est les métriques d'utilisation du processeur (métriques de ressources), mais vous pouvez intégrer des métriques personnalisées et fournies en externe.

Équipe Kubernetes aaS de Mail.ru a traduit un article sur la façon d'utiliser des métriques externes pour faire évoluer automatiquement une application Kubernetes. Pour montrer comment tout fonctionne, l'auteur utilise des métriques de requêtes d'accès HTTP, qui sont collectées à l'aide de Prometheus.

Au lieu de la mise à l'échelle automatique horizontale des pods, Kubernetes Event Driven Autoscaling (KEDA) est utilisé, un opérateur Kubernetes open source. Il s'intègre nativement à Horizontal Pod Autoscaler pour fournir une mise à l'échelle automatique transparente (y compris vers/depuis zéro) pour les charges de travail basées sur des événements. Code disponible sur GitHub.

Bref aperçu du système

Mise à l'échelle automatique des applications Kubernetes à l'aide de Prometheus et KEDA

Le diagramme montre une brève description de la façon dont tout fonctionne :

  1. L'application fournit des mesures du nombre d'accès HTTP au format Prometheus.
  2. Prometheus est configuré pour collecter ces métriques.
  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 vous parler en détail de chaque élément.

KEDA et Prométhée

Prometheus est une boîte à outils open source de surveillance et d'alerte du système, qui fait partie Fondation Cloud Native Computing. Collecte des métriques provenant de diverses sources et les stocke sous forme de données de séries chronologiques. Pour visualiser les données, vous pouvez utiliser grafana ou d'autres outils de visualisation qui fonctionnent avec l'API Kubernetes.

KEDA soutient le concept de scaler - il agit comme un pont entre KEDA et le système externe. L'implémentation du scaler est spécifique à chaque système cible et en extrait les données. KEDA les utilise ensuite pour contrôler la mise à l'échelle automatique.

Les scalers prennent en charge plusieurs sources de données, par exemple Kafka, Redis, Prometheus. Autrement dit, KEDA peut être utilisé pour faire évoluer automatiquement les déploiements Kubernetes en utilisant les métriques Prometheus comme critères.

Tester l'application

L'application de test Golang fournit un accès via HTTP et remplit deux fonctions importantes :

  1. Utilise la bibliothèque client Prometheus Go pour instrumenter l'application et fournir la métrique http_requests, qui contient un nombre d'accès. Le point de terminaison où les métriques Prometheus sont disponibles est situé au niveau de l'URI /metrics.
    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "number of http requests",
       })
    
  2. En réponse à une demande GET l'application incrémente la valeur de la clé (access_count) dans Redis. Il s'agit d'un moyen simple d'effectuer le travail dans le cadre d'un gestionnaire HTTP et également de vérifier les métriques Prometheus. La valeur de la métrique doit être la même que la valeur 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("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'application est déployée sur Kubernetes via Deployment. Un service est également créé ClusterIP, il permet au serveur Prometheus d'obtenir des métriques d'application.

Ici manifeste de déploiement pour l'application.

Serveur Prometheus

Le manifeste de déploiement Prometheus comprend :

  • ConfigMap — pour transférer la configuration Prometheus ;
  • Deployment — pour déployer Prometheus dans un cluster Kubernetes ;
  • ClusterIP — service d'accès à l'interface utilisateur Prometheus ;
  • ClusterRole, ClusterRoleBinding и ServiceAccount — pour la détection automatique des services dans Kubernetes (Découverte automatique).

Ici manifeste pour exécuter Prometheus.

Objet à l'échelle KEDA Prometheus

Le scaler agit comme un pont entre KEDA et le système externe à partir duquel les métriques doivent être obtenues. ScaledObject est une ressource personnalisée qui doit être déployée pour synchroniser le déploiement avec la source d'événement, dans ce cas Prometheus.

ScaledObject contient des informations de mise à l'échelle du déploiement, des métadonnées de source d'événements (telles que les secrets de 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 en résulte la ressource de mise à l'échelle automatique correspondante (définition HPA) pour faire évoluer le déploiement.

Lorsqu'un objet ScaledObject est supprimé, la définition HPA correspondante est effacé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 pointe vers Deployment Avec nom go-prom-app.
  2. Type de déclencheur - Prometheus. L'adresse du serveur Prometheus est mentionnée avec le nom de la métrique, le seuil et Requête PromQL, qui sera utilisé. Requête PromQL - sum(rate(http_requests[2m])).
  3. selon pollingInterval,KEDA demande une cible à Prometheus toutes les quinze secondes. Au moins un sous (minReplicaCount), et le nombre maximum de pods ne dépasse pas maxReplicaCount (dans cet exemple - dix).

Peut installer minReplicaCount égal à zéro. Dans ce cas, KEDA active le déploiement de zéro à un, puis expose le HPA pour une mise à l'échelle automatique ultérieure. L'ordre inverse est également possible, c'est-à-dire une mise à l'échelle de un à zéro. Dans l'exemple, nous n'avons pas sélectionné zéro car il s'agit d'un service HTTP et non d'un système à la demande.

La magie de l'autoscaling

Le seuil est utilisé comme déclencheur pour faire évoluer le déploiement. Dans notre exemple, la requête PromQL sum(rate (http_requests [2m])) renvoie le taux de requêtes HTTP agrégé (requêtes par seconde), mesuré au cours des deux dernières minutes.

Puisque la valeur seuil est de trois, cela signifie qu'il y en aura un en dessous tant que la valeur sum(rate (http_requests [2m])) moins de trois. Si la valeur augmente, un sous supplémentaire est ajouté à chaque fois sum(rate (http_requests [2m])) augmente de trois. Par exemple, si la valeur est comprise entre 12 et 14, le nombre de pods est de quatre.

Essayons maintenant de le configurer !

préréglage

Tout ce dont vous avez besoin est un cluster Kubernetes et un utilitaire configuré kubectl. Cet exemple utilise un cluster minikube, mais vous pouvez en prendre un autre. Pour installer un cluster il y a руководство.

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

Fixer kubectlpour accéder au cluster Kubernetes.

Installez 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 KEDA

Vous pouvez déployer KEDA de plusieurs manières, elles sont répertoriées dans documentation. J'utilise 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. Commande à vérifier :

kubectl get pods -n keda

Attendez que l'opérateur KEDA démarre et accédez à Running State. Et après cela, continuez.

Installer Redis à l'aide de Helm

Si Helm n'est pas installé, utilisez ceci leadership. Commande à installer sur Mac :

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

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

kubectl get pods -n kube-system | grep tiller

Attendez que le pod Tiller passe à l'état En cours d'exécution.

Note du traducteur: L'auteur utilise Helm@2, qui nécessite l'installation du composant serveur Tiller. Désormais Helm@3 est pertinent, il ne nécessite pas de partie serveur.

Après avoir installé Helm, une seule commande suffit 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 Redis entre dans l'état Running.

Déploiement d'applications

Commande de 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 entre dans l'état Running.

Déployer un serveur Prometheus

Le manifeste de Prométhée utilise Découverte de services Kubernetes pour Prometheus. Il permet la découverte dynamique des pods d'application en fonction de l'étiquette de service.

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

Déployer:

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 Prométhée entre en état Running.

utilisation kubectl port-forward pour accéder à l'interface utilisateur Prometheus (ou au serveur API) à l'adresse http://localhost:9090.

kubectl port-forward service/prometheus-service 9090

Déploiement de la configuration de mise à l'échelle automatique 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="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"

Vérifiez sous les candidatures. Une instance doit être en cours d'exécution car minReplicaCount est é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 :

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

Bilan de santé : accès aux applications

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

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

Vous pouvez désormais accéder à votre 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 :

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

À ce stade, vérifiez également Redis. Vous verrez que la clé access_count augmenté à 1 :

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

Assurez-vous que la valeur métrique est http_requests le même:

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

Création de charge

Nous utiliserons — utilitaire de génération de 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/Unix ou Windows.

Exécuter:

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

Par défaut, l'utilitaire envoie 200 requêtes. Vous pouvez le vérifier à l'aide des métriques Prometheus ainsi que de 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

Validez 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 la mise à l'échelle, puisque le seuil que nous fixons est de 3.

Plus de charge !

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

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

Augmentons la charge à l'aide de la commande :

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

Après un certain temps, vous verrez HPA étendre le déploiement et lancer de nouveaux pods. Vérifiez votre HPA pour vous assurer :

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

Si la charge est incohérente, le déploiement sera réduit au point où un seul pod est en cours d'exécution. Si vous souhaitez vérifier la métrique réelle (renvoyé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 vous permet de faire évoluer automatiquement vos déploiements Kubernetes (de/vers 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, de la latence du consommateur dans le sujet Kafka.

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

Bonne chance!

Quoi lire d'autre :

  1. Bonnes pratiques et bonnes pratiques pour l'exécution de conteneurs et de Kubernetes dans des environnements de production.
  2. Plus de 90 outils utiles pour Kubernetes : déploiement, gestion, surveillance, sécurité, etc..
  3. Notre chaîne Autour de Kubernetes dans Telegram.

Source: habr.com

Ajouter un commentaire