Horizontales Pod-Autoscaling (HPA).

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:

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:

  1. Verwaltete Erfassung für Ihren Cluster einrichten
  2. 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
    
  3. 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 Messwert foo zu erreichen.

  4. Wenn Sie Workload Identity 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 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
    
  5. 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
    
  6. 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 oder histogram, obwohl nicht typisierte Messwerte das Suffix unknown oder unknown:counter haben können. Suchen Sie den Messwert in Cloud Monitoring mithilfe des Metrics Explorer, um das Suffix zu prüfen.
  7. Aktualisieren Sie den bereitgestellten HPA, um den Messwert aus Cloud Monitoring abzufragen. Der Messwert foo wird als prometheus.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.

    1. Aktualisieren Sie den bereitgestellten HPA mit folgendem Befehl:

      kubectl edit hpa custom-metric-prometheus-sd
      
    2. Ändern Sie den Wert des Felds pods.metric.name von foo in prometheus.googleapis.com|foo|gauge. Der Bereich spec 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, der 20 sein soll. Da die Bereitstellung festlegt, dass der Wert des Messwerts 40 ist, erhöht der HPA-Controller die Anzahl der Pods bis zum Wert des Felds maxReplicas (5), um den Durchschnittswert des Messwerts für alle Pods auf 20 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.

  8. 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 von 1 in 5.

    NAME                          REFERENCE                                TARGETS        MINPODS   MAXPODS   REPLICAS   AGE
    custom-metric-prometheus-sd   Deployment/custom-metric-prometheus-sd   40/20          1         5         5          *
    
  9. 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 als 40 ist, wird die Bereitstellung herunterskaliert.

    Verwenden Sie beispielsweise kubectl edit, um den Wert des Felds pods.target.averageValue in der HPA-Konfiguration von 20 in 100 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
    
  10. 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 von 5 in 1. 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          *
    
  11. 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:

  1. Verwaltete Erfassung für Ihren Cluster einrichten
  2. Stellen Sie den Prometheus-Frontend-UI-Proxy in Ihrem Cluster bereit. Wenn Sie Workload Identity verwenden, müssen Sie auch ein Dienstkonto konfigurieren und autorisieren.
  3. 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.
  4. 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.
  5. Führen Sie die folgenden Befehle jeweils in einer separaten Terminalsitzung aus:

    1. 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"
    2. Sehen Sie sich das horizontale Pod-Autoscaling an:
      kubectl get hpa prometheus-example-app --watch
    3. Beobachten Sie, wie die Arbeitslast vertikal skaliert wird:
      kubectl get po -lapp.kubernetes.io/name=prometheus-example-app --watch
  6. 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 Aufruf describe 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": []
    }