Questo documento descrive come abilitare la scalabilità automatica orizzontale dei pod (HPA) per Google Cloud Managed Service per Prometheus. Puoi attivare l'HPA eseguendo una delle seguenti operazioni:
- Utilizzo della libreria Custom Metrics Stackdriver Adapter, sviluppata e supportata da Google Cloud.
- Utilizzando la libreria di terze parti Prometheus Adapter.
Devi scegliere l'uno o l'altro. Non puoi utilizzare entrambe le risorse perché le definizioni delle risorse si sovrappongono, come descritto in Risoluzione dei problemi.
Utilizza l'adattatore Stackdriver per metriche personalizzate
Metriche personalizzate Stackdriver Adapter supporta le metriche di query di Managed Service per Prometheus a partire dalla versione v0.13.1 dell'adattatore.
Per impostare una configurazione HPA di esempio utilizzando l'adattatore Stackdriver per metriche personalizzate, segui questi passaggi:
- Configura la raccolta gestita nel tuo cluster.
Installa l'adattatore Stackdriver per metriche personalizzate nel tuo cluster.
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml
Esegui il deployment di un esportatore di metriche Prometheus di esempio e di una risorsa 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
Questo comando esegue il deployment di un'applicazione di esportazione che emette la metrica
foo
e una risorsa HPA. L'HPA scala questa applicazione fino a 5 repliche per raggiungere il valore target per la metricafoo
.Se utilizzi Workload Identity, devi concedere anche il ruolo Visualizzatore Monitoring all'account di servizio in cui viene eseguito l'adattatore. Salta questo passaggio se Workload Identity non è abilitato sul 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
Definisci una risorsa PodMonitoring inserendo la seguente configurazione in un file denominato
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
Esegui il deployment della nuova risorsa PodMonitoring:
kubectl -n default apply -f podmonitoring.yaml
Nel giro di un paio di minuti, Managed Service per Prometheus elabora le metriche recuperate dall'esportatore e le archivia in Cloud Monitoring utilizzando un nome in formato lungo. Le metriche di Prometheus vengono archiviate secondo le seguenti convenzioni:
- Il prefisso
prometheus.googleapis.com
. - In genere questo suffisso è uno dei seguenti:
gauge
,counter
,summary
ohistogram
, sebbene le metriche non digitate potrebbero avere il suffissounknown
ounknown:counter
. Per verificare il suffisso, cerca la metrica in Cloud Monitoring utilizzando Metrics Explorer.
- Il prefisso
Aggiorna l'HPA di cui è stato eseguito il deployment per eseguire query sulla metrica da Cloud Monitoring. La metrica
foo
viene importata comeprometheus.googleapis.com/foo/gauge
. Per rendere la metrica interrogabile da parte della risorsa HorizontalPodAutoscaler di cui è stato eseguito il deployment, utilizza il nome in formato lungo nell'HPA di cui è stato eseguito il deployment, ma devi modificarlo sostituendo tutte le barre (/
) con il carattere barra verticale (|
):prometheus.googleapis.com|foo|gauge
. Per ulteriori informazioni, consulta la sezione Metriche disponibili in Stackdriver del repository di metriche personalizzate di Stackdriver Adapter.Aggiorna l'HPA di cui è stato eseguito il deployment eseguendo questo comando:
kubectl edit hpa custom-metric-prometheus-sd
Modifica il valore del campo
pods.metric.name
dafoo
aprometheus.googleapis.com|foo|gauge
. La sezionespec
dovrebbe avere il seguente aspetto:spec: maxReplicas: 5 metrics: - pods: metric: name: prometheus.googleapis.com|foo|gauge target: averageValue: "20" type: AverageValue type: Pods minReplicas: 1
In questo esempio, la configurazione HPA cerca che il valore medio della metrica
prometheus.googleapis.com/foo/gauge
sia20
. Poiché il deployment imposta il valore della metrica40
, il controller HPA aumenta il numero di pod fino al valore del campomaxReplicas
(5
) per provare a ridurre il valore medio della metrica in tutti i pod a20
.La query HPA ha come ambito lo spazio dei nomi e il cluster in cui è installata la risorsa HPA. Di conseguenza, metriche identiche in altri cluster e spazi dei nomi non influiscono sulla scalabilità automatica.
Per osservare lo scale up del carico di lavoro, esegui questo comando:
kubectl get hpa custom-metric-prometheus-sd --watch
Il valore del campo
REPLICAS
cambia da1
a5
.NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE custom-metric-prometheus-sd Deployment/custom-metric-prometheus-sd 40/20 1 5 5 *
Per fare lo scale down del deployment, aggiorna il valore della metrica target in modo che sia superiore a quello della metrica esportata. In questo esempio, il deployment imposta il valore della metrica
prometheus.googleapis.com/foo/gauge
su40
. Se imposti il valore di destinazione su un numero superiore a40
, verrà eseguito lo fare lo scale down del deployment.Ad esempio, utilizza
kubectl edit
per modificare il valore del campopods.target.averageValue
nella configurazione HPA da20
a100
.kubectl edit hpa custom-metric-prometheus-sd
Modifica la sezione delle specifiche in modo che corrisponda a quanto segue:
spec: maxReplicas: 5 metrics: - pods: metric: name: prometheus.googleapis.com|foo|gauge target: averageValue: "100" type: AverageValue type: Pods minReplicas: 1
Per osservare lo fare lo scale down del carico di lavoro, esegui questo comando:
kubectl get hpa custom-metric-prometheus-sd --watch
Il valore del campo
REPLICAS
cambia da5
a1
. In base alla progettazione, questo si verifica più lentamente rispetto allo scale up del numero di pod:NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE custom-metric-prometheus-sd Deployment/custom-metric-prometheus-sd 40/100 1 5 1 *
Per eseguire la pulizia dell'esempio di cui è stato eseguito il deployment, esegui questi comandi:
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
Per ulteriori informazioni, consulta l'esempio di Prometheus nel repository delle metriche personalizzate di Stackdriver Adapter o consulta la sezione sulla scalabilità di un'applicazione.
Utilizzare l'adattatore Prometheus
Le configurazioni dell'adattatore Prometheus esistenti possono essere usate per la scalabilità automatica con poche modifiche. La configurazione dell'adattatore Prometheus per la scalabilità con Managed Service per Prometheus presenta due limitazioni aggiuntive rispetto alla scalabilità con Prometheus upstream:
Le query devono essere instradate tramite il proxy dell'interfaccia utente frontend di Prometheus, proprio come quando esegui una query su Managed Service per Prometheus utilizzando l'API o l'interfaccia utente di Prometheus. Per l'adattatore Prometheus, devi modificare il deployment
prometheus-adapter
per cambiare il valoreprometheus-url
come segue:--prometheus-url=http://frontend.NAMESPACE_NAME.svc:9090/
dove NAMESPACE_NAME è lo spazio dei nomi in cui viene eseguito il deployment del frontend.
Non puoi utilizzare un matcher regex sul nome di una metrica nel campo
.seriesQuery
della configurazione delle regole. Devi invece specificare completamente i nomi delle metriche.
Poiché i dati possono richiedere un po' più tempo prima di essere disponibili in Managed Service per Prometheus rispetto a Prometheus upstream, la configurazione di una logica di scalabilità automatica eccessivamente eager potrebbe causare comportamenti indesiderati. Sebbene non ci sia alcuna garanzia sull'aggiornamento dei dati, in genere i dati sono disponibili per le query 3-7 secondi dopo essere stati inviati a Managed Service per Prometheus, esclusa la latenza di rete.
Tutte le query eseguite dall'adattatore Prometheus hanno un ambito globale. Ciò significa che
se hai applicazioni in due spazi dei nomi che emettono metriche con nomi identici,
una configurazione HPA che utilizza questa metrica scala utilizzando i dati di entrambe
le applicazioni. Ti consigliamo di utilizzare sempre i filtri namespace
o cluster
in PromQL per evitare di applicare la scalabilità utilizzando dati errati.
Per impostare una configurazione HPA di esempio utilizzando Prometheus-adapter e Managed collection, segui questi passaggi:
- Configura la raccolta gestita nel tuo cluster.
- Esegui il deployment del proxy della UI frontend di Prometheus nel tuo cluster. Se utilizzi Workload Identity, devi anche configurare e autorizzare un account di servizio.
- Esegui il deployment dei manifest nella directory
examples/hpa/
all'interno del repository prometheus-engine:example-app.yaml
: un deployment e un servizio di esempio che invia metriche.pod-monitoring.yaml
: una risorsa che configura lo scraping delle metriche di esempio.hpa.yaml
: la risorsa HPA che configura la scalabilità per il carico di lavoro.
Assicurati che
prometheus-adapter
sia installato nel cluster. A questo scopo, puoi eseguire il deployment del manifest di installazione di esempio nel cluster. Questo manifest è configurato per:- Esegui una query su un proxy frontend di cui è stato eseguito il deployment nello spazio dei nomi
default
. - Emetti PromQL per calcolare e restituire la metrica
http_requests_per_second
dal deployment di esempio.
- Esegui una query su un proxy frontend di cui è stato eseguito il deployment nello spazio dei nomi
Esegui questi comandi, ciascuno in una sessione di terminale separata:
- Genera carico HTTP sul servizio
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"
- Guarda Horizontal Pod Autoscaler:
kubectl get hpa prometheus-example-app --watch
- Guarda lo scale up del carico di lavoro:
kubectl get po -lapp.kubernetes.io/name=prometheus-example-app --watch
- Genera carico HTTP sul servizio
Interrompi la generazione del carico HTTP utilizzando Ctrl+C e controlla lo scale down del carico di lavoro.
Risoluzione dei problemi
Metriche personalizzate Stackdriver Adapter utilizza definizioni di risorse con gli stessi nomi di quelli in Prometheus Adapter, prometheus-adapter. Questa sovrapposizione di nomi significa che l'esecuzione di più di un adattatore nello stesso cluster causa errori.
L'installazione dell'adattatore Prometheus in un cluster in cui in precedenza era installata l'adattatore di metriche
personalizzate potrebbe generare errori come
FailedGetObjectMetric
a causa di nomi in conflitto. Per risolvere questo problema, potrebbe essere necessario eliminare gli apiservices v1beta1.external.metrics.k8s.io
, v1beta1.custom.metrics.k8s.io
e v1beta2.custom.metrics.k8s.io
precedentemente registrati dall'Adattatore delle metriche personalizzate.
Suggerimenti per la risoluzione dei problemi:
Alcune metriche di sistema di Cloud Monitoring, come le metriche Pub/Sub, hanno un ritardo di almeno 60 secondi. Poiché l'adattatore Prometheus esegue le query utilizzando il timestamp corrente, l'esecuzione di query su queste metriche con Prometheus Adapter potrebbe restituire erroneamente alcun dato. Per eseguire query sulle metriche ritardate, utilizza il modificatore
offset
in PromQL per modificare lo offset temporale della query in base alla quantità necessaria.Per verificare che il proxy della UI frontend funzioni come previsto e che non ci siano problemi con le autorizzazioni, esegui questo comando in un terminale:
kubectl -n NAMESPACE_NAME port-forward svc/frontend 9090
Quindi, apri un altro terminale ed esegui questo comando:
curl --silent 'localhost:9090/api/v1/series?match%5B%5D=up'
Quando il proxy UI frontend funziona correttamente, la risposta nel secondo terminale è simile alla seguente:
curl --silent 'localhost:9090/api/v1/series?match%5B%5D=up' | jq . { "status": "success", "data": [ ... ] }
Se ricevi un errore 403, significa che il proxy UI frontend non è configurato correttamente. Per informazioni su come risolvere un errore 403, consulta la guida alla configurazione e all'autorizzazione di un account di servizio.
Per verificare che la metrica personalizzata apiserver sia disponibile, esegui questo comando:
kubectl get apiservices.apiregistration.k8s.io v1beta1.custom.metrics.k8s.io
Quando l'apiserver è disponibile, la risposta è simile alla seguente:
$ 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
Per verificare che l'HPA funzioni come previsto, esegui questo comando:
$ 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 Se la risposta contiene un'istruzione come
FailedGetPodsMetric
, si verifica un errore dell'HPA. Di seguito viene illustrata una risposta alla chiamatadescribe
quando l'HPA non funziona:$ 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 Se l'HPA ha un esito negativo, assicurati di generare metriche con
load-generator
. Puoi controllare direttamente l'API delle metriche personalizzate con il comando:kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/" | jq .
Un output riuscito dovrebbe essere simile al seguente:
$ 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" ] } ] }
Se non ci sono metriche, non ci saranno dati sotto
"resources"
nell'output, ad esempio:kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/" | jq . { "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "custom.metrics.k8s.io/v1beta1", "resources": [] }