Ce document explique comment activer l'autoscaling horizontal des pods (HPA) pour Google Cloud Managed Service pour Prometheus. Vous pouvez activer le HPA en effectuant l'une des opérations suivantes :
- À l'aide de la bibliothèque de l'adaptateur de métriques personnalisées Stackdriver, développée et compatible avec Google Cloud.
- À l'aide de la bibliothèque tierce de l'adaptateur Prometheus.
Vous devez choisir l'une ou l'autre de ces approches. Vous ne pouvez pas utiliser les deux, car leurs définitions de ressources se chevauchent, comme décrit dans la section Dépannage.
Utiliser l'adaptateur de métriques personnalisées Stackdriver
L'adaptateur de métriques personnalisées Stackdriver permet d'interroger des métriques du service géré pour Prometheus à partir de la version 0.13.1 de l'adaptateur.
Pour définir un exemple de configuration HPA à l'aide de l'adaptateur de métriques personnalisées Stackdriver, procédez comme suit :
- Configurez la collecte gérée pour votre cluster.
Installez l'adaptateur de métriques personnalisées Stackdriver dans votre cluster.
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml
Déployez un exemple d'exportateur de métriques Prometheus et une ressource HPA :
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/examples/prometheus-to-sd/custom-metrics-prometheus-sd.yaml
Cette commande déploie une application d'exportation qui émet la métrique
foo
et une ressource HPA. Le HPA effectue le scaling de cette application jusqu'à cinq instances répliquées pour atteindre la valeur cible de la métriquefoo
.Si vous utilisez Workload Identity Federation for GKE, vous devez également attribuer le rôle de lecteur Monitoring au compte de service sous lequel l'adaptateur s'exécute. Ignorez cette étape si Workload Identity Federation for GKE n'est pas activée sur votre cluster Kubernetes.
export PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format 'get(projectNumber)') gcloud projects add-iam-policy-binding projects/PROJECT_ID \ --role roles/monitoring.viewer \ --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/custom-metrics/sa/custom-metrics-stackdriver-adapter
Définissez une ressource PodMonitoring en plaçant la configuration suivante dans un fichier nommé
podmonitoring.yaml
.apiVersion: monitoring.googleapis.com/v1 kind: PodMonitoring metadata: name: prom-example spec: selector: matchLabels: run: custom-metric-prometheus-sd endpoints: - port: 8080 interval: 30s
Déployez la nouvelle ressource PodMonitoring :
kubectl -n default apply -f podmonitoring.yaml
En quelques minutes, le service géré pour Prometheus traite les métriques extraites de l'exportateur et les stocke dans Cloud Monitoring à l'aide d'un nom long. Les métriques Prometheus sont stockées avec les conventions suivantes :
- Le préfixe
prometheus.googleapis.com
. - Ce suffixe est généralement
gauge
,counter
,summary
ouhistogram
, bien que les métriques non spécifiées puissent comporter le suffixeunknown
ouunknown:counter
. Pour vérifier le suffixe, recherchez la métrique dans Cloud Monitoring à l'aide de l'explorateur de métriques.
- Le préfixe
Mettez à jour le HPA déployé pour interroger la métrique à partir de Cloud Monitoring. La métrique
foo
est ingérée en tant queprometheus.googleapis.com/foo/gauge
. Pour que la métrique puisse être interrogée par la ressource HorizontalPodAutoscaler déployée, vous devez utiliser le nom complet dans le HPA déployé, mais vous devez le modifier en remplaçant toutes les barres obliques (/
) par la barre verticale (|
) :prometheus.googleapis.com|foo|gauge
. Pour en savoir plus, consultez la section Métriques disponibles depuis Stackdriver du dépôt de l'adaptateur de métriques personnalisées Stackdriver.Mettez à jour le HPA déployé en exécutant la commande suivante :
kubectl edit hpa custom-metric-prometheus-sd
Remplacez la valeur
foo
du champpods.metric.name
parprometheus.googleapis.com|foo|gauge
. La sectionspec
doit ressembler à l'exemple qui suit :spec: maxReplicas: 5 metrics: - pods: metric: name: prometheus.googleapis.com|foo|gauge target: averageValue: "20" type: AverageValue type: Pods minReplicas: 1
Dans cet exemple, la configuration HPA cherche à ce que la valeur moyenne de la métrique
prometheus.googleapis.com/foo/gauge
soit de20
. Comme le déploiement définit que la valeur de la métrique est40
, le contrôleur HPA augmente le nombre de pods jusqu'à la valeur du champmaxReplicas
(5
) pour essayer de réduire la valeur moyenne de la métrique sur tous les pods à20
.La requête HPA s'étend à l'espace de noms et au cluster dans lesquels la ressource HPA est installée. Par conséquent, les métriques identiques dans d'autres clusters et espaces de noms n'affectent pas votre autoscaling.
Pour surveiller le scaling à la hausse de la charge de travail, exécutez la commande suivante :
kubectl get hpa custom-metric-prometheus-sd --watch
La valeur du champ
REPLICAS
passe de1
à5
.NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE custom-metric-prometheus-sd Deployment/custom-metric-prometheus-sd 40/20 1 5 5 *
Pour effectuer le scaling à la baisse du déploiement, mettez à jour la valeur de la métrique cible afin qu'elle soit supérieure à la valeur de la métrique exportée. Dans cet exemple, le déploiement définit la valeur de la métrique
prometheus.googleapis.com/foo/gauge
sur40
. Si vous définissez la valeur cible sur un nombre supérieur à40
, le déploiement subit un scaling à la baisse.Par exemple, utilisez
kubectl edit
pour remplacer la valeur20
du champpods.target.averageValue
dans la configuration du HPA par100
.kubectl edit hpa custom-metric-prometheus-sd
Modifiez la section "spec" pour qu'elle corresponde aux éléments suivants :
spec: maxReplicas: 5 metrics: - pods: metric: name: prometheus.googleapis.com|foo|gauge target: averageValue: "100" type: AverageValue type: Pods minReplicas: 1
Pour surveiller le scaling à la baisse de la charge de travail, exécutez la commande suivante :
kubectl get hpa custom-metric-prometheus-sd --watch
La valeur du champ
REPLICAS
passe de5
à1
. De par sa conception, ce scaling est plus lent que le scaling à la hausse du nombre de pods :NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE custom-metric-prometheus-sd Deployment/custom-metric-prometheus-sd 40/100 1 5 1 *
Pour nettoyer l'exemple déployé, exécutez les commandes suivantes :
kubectl delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml kubectl delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/examples/prometheus-to-sd/custom-metrics-prometheus-sd.yaml kubectl delete podmonitoring/prom-example
Pour en savoir plus, consultez l'exemple Prometheus dans le dépôt de l'adaptateur de métriques personnalisées Stackdriver, ou consultez la section Procéder au scaling d'une application.
Utiliser l'adaptateur Prometheus
Les configurations prometheus-adapter existantes permettent d'effectuer l'autoscaling en apportant seulement quelques modifications. La configuration de prometheus-adapter avec Managed Service pour Prometheus présente deux restrictions supplémentaires par rapport au scaling à l'aide de Prometheus en amont :
Les requêtes doivent être acheminées via le proxy d'interface Prometheus, de la même manière que lorsque vous interrogez Managed Service pour Prometheus à l'aide de l'API ou de l'interface utilisateur Prometheus. Pour prometheus-adapter, vous devez modifier le déploiement
prometheus-adapter
pour définir la valeurprometheus-url
comme suit :--prometheus-url=http://frontend.NAMESPACE_NAME.svc:9090/
où NAMESPACE_NAME est l'espace de noms dans lequel l'interface est déployée.
Vous ne pouvez pas utiliser un outil de mise en correspondance des expressions régulières sur un nom de métrique dans le champ
.seriesQuery
de la configuration des règles. Vous devez spécifier les noms complets des métriques.
Les données pouvant prendre un peu plus de temps pour être disponibles dans Managed Service pour Prometheus par rapport à une règle Prometheus en amont, la configuration d'une logique d'autoscaling trop excessive peut entraîner un comportement indésirable. Bien qu'il n'y ait aucune garantie en ce qui concerne la fraîcheur des données, celles-ci sont généralement disponibles pour les requêtes trois à sept secondes après leur envoi à Managed Service pour Prometheus, à l'exception de la latence du réseau.
Toutes les requêtes émises par prometheus-adapter ont un champ d'application global. Cela signifie que si des applications situées dans deux espaces de noms différents émettent des métriques portant le même nom, le scaling d'une configuration HPA utilisant ces métriques va se baser sur les données des deux applications. Nous vous recommandons de toujours utiliser des filtres namespace
ou cluster
dans votre requête PromQL pour éviter tout scaling exploitant des données incorrectes.
Pour définir un exemple de configuration HPA à l'aide de prometheus-adapter et d'une collecte gérée, procédez comme suit :
- Configurez la collecte gérée pour votre cluster.
- Déployez le proxy d'interface Prometheus dans votre cluster. Si vous utilisez Workload Identity Federation for GKE, vous devez également configurer et autoriser un compte de service.
- Déployez les fichiers manifestes dans le répertoire
examples/hpa/
du dépôt prometheus-engine :example-app.yaml
: exemple de déploiement et de service qui émet des métriques.pod-monitoring.yaml
: ressource qui configure le scraping des exemples de métriques.hpa.yaml
: ressource HPA qui configure le scaling de votre charge de travail.
Assurez-vous que
prometheus-adapter
est installé dans votre cluster. Pour ce faire, déployez l'exemple de fichier manifeste d'installation sur votre cluster. Ce fichier manifeste est configuré pour :- Interroger un proxy d'interface déployé dans l'espace de noms
default
. - Utiliser PromQL pour calculer et renvoyer la métrique
http_requests_per_second
de l'exemple de déploiement.
- Interroger un proxy d'interface déployé dans l'espace de noms
Exécutez les commandes suivantes, chacune dans une session de terminal distincte :
- Générez une charge HTTP sur le service
prometheus-example-app
:kubectl run -i --tty load-generator --rm --image=busybox:1.28 --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://prometheus-example-app; done"
- Observez l'autoscaler horizontal de pods :
kubectl get hpa prometheus-example-app --watch
- Observez le scaling à la hausse de la charge de travail :
kubectl get po -lapp.kubernetes.io/name=prometheus-example-app --watch
- Générez une charge HTTP sur le service
Arrêtez la génération de la charge HTTP à l'aide de Ctrl+C et observez le scaling à la baisse de la charge de travail.
Dépannage
L'adaptateur de métriques personnalisées Stackdriver utilise des définitions de ressources portant les mêmes noms que celles de l'adaptateur Prometheus, prometheus-adapter. Ce chevauchement de noms signifie que l'exécution de plusieurs adaptateurs dans le même cluster va entraîner des erreurs.
L'installation de l'adaptateur Prometheus dans un cluster contenant précédemment l'adaptateur de métriques personnalisées Stackdriver installé peut générer des erreurs du type FailedGetObjectMetric
en raison de conflits de noms. Pour résoudre ce problème, vous devrez peut-être supprimer les services API v1beta1.external.metrics.k8s.io
, v1beta1.custom.metrics.k8s.io
et v1beta2.custom.metrics.k8s.io
précédemment enregistrés par l'adaptateur de métriques personnalisées.
Conseils de dépannage
Certaines métriques système Cloud Monitoring, telles que les métriques Pub/Sub, sont retardées de 60 secondes ou plus. Étant donné que l'adaptateur Prometheus exécute des requêtes à l'aide du code temporel actuel, l'interrogation de ces métriques à l'aide de l'adaptateur Prometheus peut ne pas générer de données à tort. Pour interroger des métriques retardées, utilisez le modificateur
offset
dans PromQL afin de remplacer l'horodatage de votre requête par celui requis.Pour vérifier que le proxy d'interface utilisateur fonctionne comme prévu et qu'il n'y a aucun problème avec les autorisations, exécutez la commande suivante dans un terminal :
kubectl -n NAMESPACE_NAME port-forward svc/frontend 9090
Ensuite, ouvrez un autre terminal et exécutez la commande suivante :
curl --silent 'localhost:9090/api/v1/series?match%5B%5D=up'
Lorsque le proxy d'interface utilisateur fonctionne correctement, la réponse du second terminal est semblable à celle-ci :
curl --silent 'localhost:9090/api/v1/series?match%5B%5D=up' | jq . { "status": "success", "data": [ ... ] }
Si vous recevez une erreur 403, le proxy d'interface utilisateur n'est pas correctement configuré. Pour plus d'informations sur la façon de résoudre une erreur 403, consultez le guide Configurer et autoriser un compte de service.
Pour vérifier que le serveur d'API de métriques personnalisées est disponible, exécutez la commande suivante :
kubectl get apiservices.apiregistration.k8s.io v1beta1.custom.metrics.k8s.io
Lorsque le serveur d'API est disponible, la réponse est semblable à ce qui suit :
$ kubectl get apiservices.apiregistration.k8s.io v1beta1.custom.metrics.k8s.io NAME SERVICE AVAILABLE AGE v1beta1.custom.metrics.k8s.io monitoring/prometheus-adapter True 33m
Pour vérifier que votre HPA fonctionne comme prévu, exécutez la commande suivante :
$ kubectl describe hpa prometheus-example-app Name: prometheus-example-app Namespace: default Labels:
Annotations: Reference: Deployment/prometheus-example-app Metrics: ( current / target ) "http_requests_per_second" on pods: 11500m / 10 Min replicas: 1 Max replicas: 10 Deployment pods: 2 current / 2 desired Conditions: Type Status Reason Message ---- ------ ------ ------- AbleToScale True ReadyForNewScale recommended size matches current size ScalingActive True ValidMetricFound the HPA was able to successfully calculate a replica count from pods metric http_requests_per_second ScalingLimited False DesiredWithinRange the desired count is within the acceptable range Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SuccessfulRescale 47s horizontal-pod-autoscaler New size: 2; reason: pods metric http_requests_per_second above target Lorsque la réponse contient une instruction telle que
FailedGetPodsMetric
, le HPA échoue. L'exemple suivant illustre une réponse à l'appeldescribe
en cas d'échec du HPA :$ kubectl describe hpa prometheus-example-app Name: prometheus-example-app Namespace: default Reference: Deployment/prometheus-example-app Metrics: ( current / target ) "http_requests_per_second" on pods:
/ 10 Min replicas: 1 Max replicas: 10 Deployment pods: 1 current / 1 desired Conditions: Type Status Reason Message ---- ------ ------ ------- AbleToScale True ReadyForNewScale recommended size matches current size ScalingActive False FailedGetPodsMetric the HPA was unable to compute the replica count: unable to get metric http_requests_per_second: unable to fetch metrics from custom metrics API: the server could not find the metric http_requests_per_second for pods ScalingLimited False DesiredWithinRange the desired count is within the acceptable range Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedGetPodsMetric 104s (x11 over 16m) horizontal-pod-autoscaler unable to get metric http_requests_per_second: unable to fetch metrics from custom metrics API: the server could not find the metric http_requests_per_second for pods En cas d'échec du HPA, assurez-vous de générer des métriques avec
load-generator
. Vous pouvez vérifier l'API de métriques personnalisées directement à l'aide de la commande suivante :kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/" | jq .
Si la commande aboutit, vous devriez obtenir le résultat suivant :
$ kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/" | jq . { "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "custom.metrics.k8s.io/v1beta1", "resources": [ { "name": "namespaces/http_requests_per_second", "singularName": "", "namespaced": false, "kind": "MetricValueList", "verbs": [ "get" ] }, { "name": "pods/http_requests_per_second", "singularName": "", "namespaced": true, "kind": "MetricValueList", "verbs": [ "get" ] } ] }
S'il n'y a pas de métriques, il n'y aura pas de données sous
"resources"
dans le résultat, par exemple :kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/" | jq . { "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "custom.metrics.k8s.io/v1beta1", "resources": [] }