In diesem Dokument wird beschrieben, wie Sie horizontales Pod-Autoscaling (HPA) für Google Cloud Managed Service for Prometheus aktivieren. Sie können HPA aktivieren. Führen Sie dazu einen der folgenden Schritte aus:
- Verwendung der von Google Cloud entwickelten und unterstützten Bibliothek Benutzerdefinierter Messwert-Stackdriver-Adapter
- Verwendung der Drittanbieterbibliothek Prometheus Adapter
Sie müssen sich für einen Ansatz entscheiden. Sie können nicht beide verwenden, da sich ihre Ressourcendefinitionen überschneiden, wie unter Fehlerbehebung beschrieben.
Stackdriver-Adapter für benutzerdefinierte Messwerte verwenden
Der Stackdriver-Adapter für benutzerdefinierte Messwerte unterstützt die Abfrage von Messwerten aus Managed Service for Prometheus ab Version 0.13.1 des Adapters.
So richten Sie eine HPA-Beispielkonfiguration mit dem Stackdriver-Adapter für benutzerdefinierte Messwerte ein:
- Verwaltete Erfassung für Ihren Cluster einrichten
Installieren Sie den Stackdriver-Adapter für benutzerdefinierte Messwerte in Ihrem Cluster.
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml
Stellen Sie einen Beispiel-Exporter für Prometheus-Messwerte und eine HPA-Ressource bereit:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/examples/prometheus-to-sd/custom-metrics-prometheus-sd.yaml
Mit diesem Befehl wird eine Exporter-Anwendung bereitgestellt, die den Messwert
foo
und eine HPA-Ressource ausgibt. Der HPA skaliert diese Anwendung auf bis zu fünf Replikate, um den Zielwert für den Messwertfoo
zu erreichen.Wenn Sie Workload Identity Federation for GKE verwenden, müssen Sie dem Dienstkonto, unter dem der Adapter ausgeführt wird, auch die Rolle „Monitoring-Betrachter“ zuweisen. Überspringen Sie diesen Schritt, wenn Sie Workload Identity Federation for GKE nicht in Ihrem Kubernetes-Cluster aktiviert haben.
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
Definieren Sie eine PodMonitoring-Ressource. Fügen Sie dazu die folgende Konfiguration in eine Datei mit dem Namen
podmonitoring.yaml
ein.apiVersion: monitoring.googleapis.com/v1 kind: PodMonitoring metadata: name: prom-example spec: selector: matchLabels: run: custom-metric-prometheus-sd endpoints: - port: 8080 interval: 30s
Stellen Sie die neue PodMonitoring-Ressource bereit:
kubectl -n default apply -f podmonitoring.yaml
Innerhalb weniger Minuten verarbeitet Managed Service for Prometheus die aus dem Exporter extrahierten Messwerte und speichert sie in Cloud Monitoring unter einem Langnamen. Prometheus-Messwerte werden nach den folgenden Konventionen gespeichert:
- Das Präfix
prometheus.googleapis.com
. - Dieses Suffix ist normalerweise
gauge
,counter
,summary
oderhistogram
, obwohl nicht typisierte Messwerte das Suffixunknown
oderunknown:counter
haben können. Suchen Sie den Messwert in Cloud Monitoring mithilfe des Metrics Explorer, um das Suffix zu prüfen.
- Das Präfix
Aktualisieren Sie den bereitgestellten HPA, um den Messwert aus Cloud Monitoring abzufragen. Der Messwert
foo
wird alsprometheus.googleapis.com/foo/gauge
aufgenommen. Damit der Messwert von der bereitgestellten HorizontalPodAutoscaler-Ressource abgefragt werden kann, verwenden Sie den Langnamen im bereitgestellten HPA. Sie müssen ihn jedoch ändern, indem Sie alle Schrägstriche (/
) durch den senkrechten Strich (|
) ersetzen:prometheus.googleapis.com|foo|gauge
. Weitere Informationen finden Sie im Bereich Messwerte aus Stackdriver des Stackdriver-Adapter-Repositorys für benutzerdefinierte Messwerte.Aktualisieren Sie den bereitgestellten HPA mit folgendem Befehl:
kubectl edit hpa custom-metric-prometheus-sd
Ändern Sie den Wert des Felds
pods.metric.name
vonfoo
inprometheus.googleapis.com|foo|gauge
. Der Bereichspec
sollte wie im folgenden Beispiel aussehen:spec: maxReplicas: 5 metrics: - pods: metric: name: prometheus.googleapis.com|foo|gauge target: averageValue: "20" type: AverageValue type: Pods minReplicas: 1
In diesem Beispiel sucht die HPA-Konfiguration nach dem Durchschnittswert des Messwerts
prometheus.googleapis.com/foo/gauge
, der20
sein soll. Da die Bereitstellung festlegt, dass der Wert des Messwerts40
ist, erhöht der HPA-Controller die Anzahl der Pods bis zum Wert des FeldsmaxReplicas
(5
), um den Durchschnittswert des Messwerts für alle Pods auf20
zu reduzieren.Die HPA-Abfrage gilt für den Namespace und den Cluster, in dem die HPA-Ressource installiert ist. Daher wirken sich identische Messwerte in anderen Clustern und Namespaces nicht auf das Autoscaling aus.
Führen Sie den folgenden Befehl aus, um die Skalierung der Arbeitslast zu beobachten:
kubectl get hpa custom-metric-prometheus-sd --watch
Der Wert des Felds
REPLICAS
ändert sich von1
in5
.NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE custom-metric-prometheus-sd Deployment/custom-metric-prometheus-sd 40/20 1 5 5 *
Zum Herunterskalieren der Bereitstellung aktualisieren Sie den Zielmesswert so, dass er höher als der exportierte Messwert ist. In diesem Beispiel legt die Bereitstellung für den Wert des Messwerts
prometheus.googleapis.com/foo/gauge
40
fest. Wenn Sie den Zielwert auf eine Zahl festlegen, die größer als40
ist, wird die Bereitstellung herunterskaliert.Verwenden Sie beispielsweise
kubectl edit
, um den Wert des Feldspods.target.averageValue
in der HPA-Konfiguration von20
in100
zu ändern.kubectl edit hpa custom-metric-prometheus-sd
Ändern Sie den Bereich „spec“ so:
spec: maxReplicas: 5 metrics: - pods: metric: name: prometheus.googleapis.com|foo|gauge target: averageValue: "100" type: AverageValue type: Pods minReplicas: 1
Führen Sie den folgenden Befehl aus, um die Herunterskalierung der Arbeitslast zu beobachten:
kubectl get hpa custom-metric-prometheus-sd --watch
Der Wert des Felds
REPLICAS
ändert sich von5
in1
. Dies geschieht bewusst langsamer als beim Hochskalieren der Anzahl der Pods:NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE custom-metric-prometheus-sd Deployment/custom-metric-prometheus-sd 40/100 1 5 1 *
Führen Sie die folgenden Befehle aus, um das bereitgestellte Beispiel zu bereinigen:
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
Weitere Informationen finden Sie im Prometheus-Beispiel im Stackdriver-Adapter-Repository für benutzerdefinierte Messwerte oder unter Anwendung skalieren.
Prometheus-Adapter verwenden
Vorhandene Konfigurationen des Prometheus-Adapters können mit nur wenigen Änderungen für das Autoscaling verwendet werden. Bei der Konfiguration von prometheus-adapter für die Skalierung mit Managed Service for Prometheus fallen im Vergleich zur Skalierung mit Upstream-Prometheus zwei zusätzliche Einschränkungen an:
Abfragen müssen über den Proxy-UI-Proxy von Prometheus weitergeleitet werden, genauso wie bei der Abfrage von Managed Service for Prometheus mithilfe der Prometheus API oder UI. Bei einem Prometheus-Adapter müssen Sie das
prometheus-adapter
-Deployment bearbeiten, um denprometheus-url
-Wert so zu ändern:.--prometheus-url=http://frontend.NAMESPACE_NAME.svc:9090/
Dabei ist NAMESPACE_NAME der Namespace, in dem das Frontend bereitgestellt wird.
Sie können keinen Regex-Matcher für einen Messwertnamen im Feld
.seriesQuery
der Regelkonfiguration verwenden. Stattdessen müssen Sie Messwertnamen vollständig angeben.
Da die Bereitstellung von Daten im verwalteten Dienst für Prometheus im Vergleich zu Upstream-Prometheus etwas länger dauern kann, kann das Konfigurieren einer übermäßig flexiblen Autoscaling-Logik zu unerwünschtem Verhalten führen. Obwohl es keine Garantie für die Datenaktualität gibt, sind Daten in der Regel 3–7 Sekunden nach dem Senden an Managed Service for Prometheus verfügbar, und zwar ohne Netzwerklatenz.
Alle von prometheus-adapter ausgegebenen Abfragen sind global. Wenn Sie also Anwendungen in zwei Namespaces haben, die identisch benannte Messwerte ausgeben, wird eine HPA-Konfiguration, die diese Messwerte verwendet, anhand von Daten aus beiden Anwendungen skaliert. Wir empfehlen, in Ihrer PromQL immer die Filter namespace
oder cluster
zu verwenden, um die Skalierung mit falschen Daten zu vermeiden.
Führen Sie die folgenden Schritte aus, um eine HPA-Beispielkonfiguration mit dem Prometheus-Adapter und der verwalteten Sammlung einzurichten:
- Verwaltete Erfassung für Ihren Cluster einrichten
- Stellen Sie den Prometheus-Frontend-UI-Proxy in Ihrem Cluster bereit. Wenn Sie die Workload Identity Federation for GKE verwenden, müssen Sie auch ein Dienstkonto konfigurieren und autorisieren.
- Stellen Sie die Manifeste im Verzeichnis
examples/hpa/
im prometheus-engine-Repository bereit:example-app.yaml
: Ein Beispiel für eine Bereitstellung und einen Dienst, der Messwerte ausgibt.pod-monitoring.yaml
: Eine Ressource, die die Extraktion der Beispielmesswerte konfiguriert.hpa.yaml
: Die HPA-Ressource, die die Skalierung für Ihre Arbeitslast konfiguriert.
Prüfen Sie, ob
prometheus-adapter
in Ihrem Cluster installiert ist. Dazu stellen Sie das Beispielinstallationsmanifest in Ihrem Cluster bereit. Dieses Manifest ist für Folgendes konfiguriert:- Abfragen eines Frontend-Proxys, der im Namespace
default
bereitgestellt ist. - Ausführen der PromQL, um den Messwert
http_requests_per_second
aus der Beispielbereitstellung zu berechnen und zurückzugeben.
- Abfragen eines Frontend-Proxys, der im Namespace
Führen Sie die folgenden Befehle jeweils in einer separaten Terminalsitzung aus:
- Generieren Sie die HTTP-Last für den Dienst
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"
- Sehen Sie sich das horizontale Pod-Autoscaling an:
kubectl get hpa prometheus-example-app --watch
- Beobachten Sie, wie die Arbeitslast vertikal skaliert wird:
kubectl get po -lapp.kubernetes.io/name=prometheus-example-app --watch
- Generieren Sie die HTTP-Last für den Dienst
Beenden Sie mit HTTP+C das Generieren der HTTP-Last und beobachten Sie, wie die Arbeitslast herunterskaliert wird.
Fehlerbehebung
Der Stackdriver-Adapter für benutzerdefinierte Messwerte verwendet Ressourcendefinitionen mit denselben Namen wie im Prometheus-Adapter, prometheus-adapter. Wenn sich die Namen überschneiden, bedeutet dies, dass die Ausführung mehrerer Adapter im selben Cluster Fehler verursacht.
Die Installation des Prometheus-Adapters in einem Cluster, auf dem zuvor der Stackdriver-Adapter für benutzerdefinierte Messwerte installiert wurde, kann aufgrund von Namenskonflikten Fehler auslösen wie FailedGetObjectMetric
. Um dieses Problem zu lösen, müssen Sie möglicherweise die API-Dienste v1beta1.external.metrics.k8s.io
, v1beta1.custom.metrics.k8s.io
und v1beta2.custom.metrics.k8s.io
löschen, die zuvor vom Adapter für benutzerdefinierte Messwerte registriert wurden.
Tipps zur Fehlerbehebung:
Einige Cloud Monitoring-Systemmesswerte wie Pub/Sub-Messwerte werden um 60 Sekunden oder mehr verzögert. Da der Prometheus-Adapter Abfragen mit dem aktuellen Zeitstempel ausführt, kann die Abfrage dieser Messwerte mit dem Prometheus-Adapter fälschlicherweise dazu führen, dass keine Daten verfügbar sind. Verwenden Sie zum Abfragen verzögerter Messwerte den
offset
-Modifikator in PromQL, um den Zeitversatz der Abfrage um den erforderlichen Betrag zu ändern.Führen Sie den folgenden Befehl in einem Terminal aus, um zu überprüfen, ob der Frontend-UI-Proxy wie beabsichtigt funktioniert und keine Probleme mit den Berechtigungen vorliegen:
kubectl -n NAMESPACE_NAME port-forward svc/frontend 9090
Öffnen Sie als Nächstes ein anderes Terminal und führen Sie den folgenden Befehl aus:
curl --silent 'localhost:9090/api/v1/series?match%5B%5D=up'
Wenn der Proxy der Frontend-Benutzeroberfläche ordnungsgemäß funktioniert, sieht die Antwort im zweiten Terminal in etwa so aus:
curl --silent 'localhost:9090/api/v1/series?match%5B%5D=up' | jq . { "status": "success", "data": [ ... ] }
Wenn Sie einen 403-Fehler erhalten, ist der Proxy der Frontend-Benutzeroberfläche nicht richtig konfiguriert. Informationen zum Beheben eines 403-Fehlers finden Sie in der Anleitung Dienstkonto konfigurieren und autorisieren.
Führen Sie den folgenden Befehl aus, um zu prüfen, ob der API-Server für benutzerdefinierte Messwerte verfügbar ist:
kubectl get apiservices.apiregistration.k8s.io v1beta1.custom.metrics.k8s.io
Wenn der API-Server verfügbar ist, sieht die Antwort in etwa so aus:
$ 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
Führen Sie den folgenden Befehl aus, um zu prüfen, ob Ihr HPA wie vorgesehen funktioniert:
$ 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 Wenn die Antwort eine Anweisung wie
FailedGetPodsMetric
enthält, schlägt der HPA fehl. Im Folgenden wird eine Antwort auf den Aufrufdescribe
dargestellt, wenn das HPA fehlschlägt:$ 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 Wenn das HPA fehlschlägt, achten Sie darauf, dass Sie Messwerte mit dem
load-generator
generieren. Sie können die API für benutzerdefinierte Messwerte direkt mit dem folgenden Befehl prüfen:kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/" | jq .
Eine erfolgreiche Ausgabe sollte so aussehen:
$ 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" ] } ] }
Wenn keine Messwerte vorhanden sind, enthält die Ausgabe unter
"resources"
keine Daten. Beispiel:kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/" | jq . { "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "custom.metrics.k8s.io/v1beta1", "resources": [] }