Pod-Autoscaling anhand von Messwerten optimieren

In dieser Anleitung wird gezeigt, wie Sie Ihre GKE-Arbeitslasten (Google Kubernetes Engine) anhand von Messwerten, die in Cloud Monitoring verfügbar sind, automatisch skalieren.

In dieser Anleitung können Sie das Autoscaling basierend auf einem der folgenden Messwerte einrichten:

Pub/Sub

Pub/Sub-Rückstand

Sie können basierend auf einem externen Messwert skalieren, der die Anzahl nicht bestätigter Nachrichten angibt, die noch in einemPub/Sub-Abo enthalten sind. Dadurch kann die Latenz wirksam reduziert werden, bevor sie zu einem Problem wird. Es kann aber auch den Ressourcenverbrauch gegenüber dem Autoscaling basierend auf der CPU-Auslastung erhöhen.

Benutzerdefinierter Messwert

Benutzerdefinierter Prometheus-Messwert

Sie können basierend auf einem benutzerdefinierten Messwert skalieren, über Google Managed Prometheus im Prometheus-Format exportiert wird. Der Prometheus-Messwert muss vom Typ Gauge sein.

Beim Autoscaling geht es im Wesentlichen darum, ein akzeptables Verhältnis zwischen Kosten und Latenz zu finden. Sie können eine Kombination dieser Messwerte und anderer Messwerte ausprobieren, um eine für Sie geeignete Richtlinie zu finden.

Adapter für benutzerdefinierte Messwerte bereitstellen

Der Adapter für benutzerdefinierte Messwerte ermöglicht Ihrem Cluster, Messwerte mit Cloud Monitoring zu senden und zu empfangen.

Pub/Sub

Die Vorgehensweise bei der Installation des Adapters für benutzerdefinierte Messwerte unterscheidet sich für Cluster mit und ohne Aktivierung der Identitätsföderation von Arbeitslasten für GKE. Wählen Sie jene Option aus, die der Konfiguration entspricht, die Sie beim Erstellen des Clusters ausgewählt haben.

Workload Identity

Ermöglichen Sie dem Nutzer, die erforderlichen Autorisierungsrollen zu erstellen:

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

Stellen Sie den Adapter für benutzerdefinierte Messwerte in Ihrem Cluster bereit:

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

Der Adapter verwendet das Kubernetes-Dienstkonto custom-metrics-stackdriver-adapter im Namespace custom-metrics. Erlauben Sie diesem Dienstkonto, Cloud Monitoring-Messwerte zu lesen, indem Sie die Rolle Monitoring Viewer zuweisen:

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

Alte Authentifizierungsmethode

Ermöglichen Sie dem Nutzer, die erforderlichen Autorisierungsrollen zu erstellen:

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

Stellen Sie den Adapter für benutzerdefinierte Messwerte in Ihrem Cluster bereit:

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

Benutzerdefinierter Messwert

Die Vorgehensweise bei der Installation des Adapters für benutzerdefinierte Messwerte unterscheidet sich für Cluster mit und ohne Aktivierung der Identitätsföderation von Arbeitslasten für GKE. Wählen Sie jene Option aus, die der Konfiguration entspricht, die Sie beim Erstellen des Clusters ausgewählt haben.

Workload Identity

Ermöglichen Sie dem Nutzer, die erforderlichen Autorisierungsrollen zu erstellen:

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

Stellen Sie den Adapter für benutzerdefinierte Messwerte in Ihrem Cluster bereit:

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

Der Adapter verwendet das Kubernetes-Dienstkonto custom-metrics-stackdriver-adapter im Namespace custom-metrics. Erlauben Sie diesem Dienstkonto, Cloud Monitoring-Messwerte zu lesen, indem Sie die Rolle Monitoring Viewer zuweisen:

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

Alte Authentifizierungsmethode

Ermöglichen Sie dem Nutzer, die erforderlichen Autorisierungsrollen zu erstellen:

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

Stellen Sie den Adapter für benutzerdefinierte Messwerte in Ihrem Cluster bereit:

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

Anwendung mit Messwerten bereitstellen

Laden Sie das Repository mit dem Anwendungscode für diese Anleitung herunter:

Pub/Sub

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
cd kubernetes-engine-samples/databases/cloud-pubsub

Benutzerdefinierter Messwert

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
cd kubernetes-engine-samples/observability/custom-metrics-autoscaling/google-managed-prometheus

Das Repository enthält Code, der Messwerte in Cloud Monitoring exportiert:

Pub/Sub

Diese Anwendung fragt ein Pub/Sub-Abo nach neuen Nachrichten ab und bestätigt sie beim Eingang. Pub/Sub-Abomesswerte werden von Cloud Monitoring automatisch erfasst.

from google import auth
from google.cloud import pubsub_v1


def main():
    """Continuously pull messages from subsciption"""

    # read default project ID
    _, project_id = auth.default()
    subscription_id = 'echo-read'

    subscriber = pubsub_v1.SubscriberClient()
    subscription_path = subscriber.subscription_path(
        project_id, subscription_id)

    def callback(message: pubsub_v1.subscriber.message.Message) -> None:
        """Process received message"""
        print(f"Received message: ID={message.message_id} Data={message.data}")
        print(f"[{datetime.datetime.now()}] Processing: {message.message_id}")
        time.sleep(3)
        print(f"[{datetime.datetime.now()}] Processed: {message.message_id}")
        message.ack()

    streaming_pull_future = subscriber.subscribe(
        subscription_path, callback=callback)
    print(f"Pulling messages from {subscription_path}...")

    with subscriber:
        try:
            streaming_pull_future.result()
        except Exception as e:
            print(e)

Benutzerdefinierter Messwert

Diese Anwendung antwortet auf jede Webanfrage an den Pfad /metrics mit einem konstanten Messwert im Prometheus-Format.

metric := prometheus.NewGauge(
	prometheus.GaugeOpts{
		Name: *metricName,
		Help: "Custom metric",
	},
)
prometheus.MustRegister(metric)
metric.Set(float64(*metricValue))

http.Handle("/metrics", promhttp.Handler())
log.Printf("Starting to listen on :%d", *port)
err := http.ListenAndServe(fmt.Sprintf(":%d", *port), nil)

Das Repository enthält außerdem ein Kubernetes-Manifest, um die Anwendung in Ihrem Cluster bereitzustellen. Ein Deployment ist ein Kubernetes-API-Objekt, mit dem Sie mehrere Replikate von Pods ausführen können, die auf die Knoten in einem Cluster verteilt sind:

Pub/Sub

Das Manifest unterscheidet sich für Cluster mit oder ohne Aktivierung der Identitätsföderation von Arbeitslasten für GKE. Wählen Sie jene Option aus, die der Konfiguration entspricht, die Sie beim Erstellen des Clusters ausgewählt haben.

Workload Identity

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pubsub
spec:
  selector:
    matchLabels:
      app: pubsub
  template:
    metadata:
      labels:
        app: pubsub
    spec:
      serviceAccountName: pubsub-sa
      containers:
      - name: subscriber
        image: us-docker.pkg.dev/google-samples/containers/gke/pubsub-sample:v2

Alte Authentifizierungsmethode

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pubsub
spec:
  selector:
    matchLabels:
      app: pubsub
  template:
    metadata:
      labels:
        app: pubsub
    spec:
      volumes:
      - name: google-cloud-key
        secret:
          secretName: pubsub-key
      containers:
      - name: subscriber
        image: us-docker.pkg.dev/google-samples/containers/gke/pubsub-sample:v2
        volumeMounts:
        - name: google-cloud-key
          mountPath: /var/secrets/google
        env:
        - name: GOOGLE_APPLICATION_CREDENTIALS
          value: /var/secrets/google/key.json

Benutzerdefinierter Messwert

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: custom-metrics-gmp
  name: custom-metrics-gmp
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      run: custom-metrics-gmp
  template:
    metadata:
      labels:
        run: custom-metrics-gmp
    spec:
      containers:
      # sample container generating custom metrics
      - name: prometheus-dummy-exporter
        image: us-docker.pkg.dev/google-samples/containers/gke/prometheus-dummy-exporter:v0.2.0
        command: ["./prometheus-dummy-exporter"]
        args:
        - --metric-name=custom_prometheus
        - --metric-value=40
        - --port=8080

Mit der PodMonitoring-Ressource exportiert der Google Cloud Managed Service for Prometheus die Prometheus-Messwerte in Cloud Monitoring:

apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
  name: "custom-metrics-exporter"
spec:
  selector:
    matchLabels:
      run: custom-metrics-gmp
  endpoints:
  - port: 8080
    path: /metrics
    interval: 15s

Ab GKE Standard-Version 1.27 oder GKE Autopilot-Version 1.25 ist Google Cloud Managed Service for Prometheus aktiviert. Informationen zum Aktivieren von Google Cloud Managed Service for Prometheus in Clustern in früheren Versionen finden Sie unter Verwaltete Sammlung aktivieren.

Stellen Sie die Anwendung in Ihrem Cluster bereit:

Pub/Sub

Die Vorgehensweise bei der Bereitstellung Ihrer Anwendung unterscheidet sich für Cluster mit oder ohne Aktivierung der Identitätsföderation von Arbeitslasten für GKE. Wählen Sie jene Option aus, die der Konfiguration entspricht, die Sie beim Erstellen des Clusters ausgewählt haben.

Workload Identity

  1. Aktivieren Sie die Pub/Sub API für Ihr Projekt:

    gcloud services enable cloudresourcemanager.googleapis.com pubsub.googleapis.com
    
  2. Erstellen Sie ein Pub/Sub-Thema und ‑Abo:

    gcloud pubsub topics create echo
    gcloud pubsub subscriptions create echo-read --topic=echo
    
  3. Stellen Sie die Anwendung in Ihrem Cluster bereit:

    kubectl apply -f deployment/pubsub-with-workload-identity.yaml
    
  4. Diese Anwendung definiert ein Kubernetes-Dienstkonto des Typs pubsub-sa. Weisen Sie ihm die Rolle Pub/Sub-Subscriber zu, damit die Anwendung Nachrichten im Pub/Sub-Thema veröffentlichen kann.

    gcloud projects add-iam-policy-binding projects/$PROJECT_ID \
      --role=roles/pubsub.subscriber \
      --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$PROJECT_ID.svc.id.goog/subject/ns/default/sa/pubsub-sa
    

    Im vorherigen Befehl wird eine Hauptkonto-ID verwendet, die es IAM ermöglicht, direkt auf ein Kubernetes-Dienstkonto zu verweisen.

    Best Practice:

    Verwenden Sie Hauptkonto-IDs, aber beachten Sie die Einschränkung in der Beschreibung einer alternativen Methode.

Alte Authentifizierungsmethode

  1. Aktivieren Sie die Pub/Sub API für Ihr Projekt:

    gcloud services enable cloudresourcemanager.googleapis.com pubsub.googleapis.com
    
  2. Erstellen Sie ein Pub/Sub-Thema und ‑Abo:

    gcloud pubsub topics create echo
    gcloud pubsub subscriptions create echo-read --topic=echo
    
  3. Erstellen Sie ein Dienstkonto mit Zugriff auf Pub/Sub:

    gcloud iam service-accounts create autoscaling-pubsub-sa
    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member "serviceAccount:autoscaling-pubsub-sa@$PROJECT_ID.iam.gserviceaccount.com" \
      --role "roles/pubsub.subscriber"
    
  4. Laden Sie die Dienstkontoschlüsseldatei herunter:

    gcloud iam service-accounts keys create key.json \
      --iam-account autoscaling-pubsub-sa@$PROJECT_ID.iam.gserviceaccount.com
    
  5. Importieren Sie den Dienstkontoschlüssel als Secret in Ihren Cluster:

    kubectl create secret generic pubsub-key --from-file=key.json=./key.json
    
  6. Stellen Sie die Anwendung in Ihrem Cluster bereit:

    kubectl apply -f deployment/pubsub-with-secret.yaml
    

Benutzerdefinierter Messwert

kubectl apply -f custom-metrics-gmp.yaml

Nachdem Sie einen Moment auf die Bereitstellung der Anwendung gewartet haben, erreichen alle Pods den Status Ready:

Pub/Sub

kubectl get pods

Ausgabe:

NAME                     READY   STATUS    RESTARTS   AGE
pubsub-8cd995d7c-bdhqz   1/1     Running   0          58s

Benutzerdefinierter Messwert

kubectl get pods

Ausgabe:

NAME                                  READY   STATUS    RESTARTS   AGE
custom-metrics-gmp-865dffdff9-x2cg9   1/1     Running   0          49s

Messwerte in Cloud Monitoring ansehen

Bei der Ausführung der Anwendung werden die Messwerte in Cloud Monitoring geschrieben.

So rufen Sie mit dem Metrics Explorer die Messwerte für eine überwachte Ressource auf:

  1. Rufen Sie in der Google Cloud Console die Seite  Metrics Explorer auf:

    Zum Metrics Explorer

    Wenn Sie diese Seite über die Suchleiste suchen, wählen Sie das Ergebnis aus, dessen Zwischenüberschrift Monitoring ist.

  2. Erweitern Sie im Element Messwert das Menü Messwert auswählen und wählen Sie dann einen Ressourcentyp und einen Messwerttyp aus. So erstellen Sie beispielsweise die CPU-Auslastung einer virtuellen Maschine:
    1. (Optional) Um die Optionen des Menüs zu reduzieren, geben Sie einen Teil des Messwertnamens in die Filterleiste ein. Geben Sie für dieses Beispiel utilization ein.
    2. Wählen Sie im Menü Aktive Ressourcen die Option VM-Instanz aus.
    3. Wählen Sie im Menü Aktive Messwertkategorien die Option Instanz aus.
    4. Wählen Sie im Menü Aktive Messwerte die Option CPU-Auslastung aus und klicken Sie dann auf Übernehmen.
  3. Verwenden Sie das Element Filter, um zu filtern, welche Zeitreihen angezeigt werden.

  4. Verwenden Sie zum Kombinieren von Zeitreihen die Menüs für das Element Aggregation. Wenn Sie beispielsweise die CPU-Auslastung für Ihre VMs basierend auf ihrer Zone anzeigen lassen möchten, legen Sie das erste Menü auf Durchschnitt und das zweite Menü auf Zone fest.

    Alle Zeitreihen werden angezeigt, wenn das erste Menü des Elements Aggregation auf Nicht aggregiert gesetzt ist. Die Standardeinstellungen für das Element Aggregation werden durch den ausgewählten Messwerttyp bestimmt.

Der Ressourcentyp und die Messwerte lauten:

Pub/Sub

Metrics Explorer

Ressourcentyp: pubsub_subscription

Messwert: pubsub.googleapis.com/subscription/num_undelivered_messages

Benutzerdefinierter Messwert

Metrics Explorer

Ressourcentyp: prometheus_target

Messwert: prometheus.googleapis.com/custom_prometheus/gauge

Je nach Messwert werden im Cloud Monitoring Metrics Explorer möglicherweise noch nicht viele Aktivitäten angezeigt. Seien Sie nicht überrascht, wenn Ihr Messwert nicht aktualisiert wird.

HorizontalPodAutoscaler-Objekt erstellen

Wenn Sie den Messwert in Cloud Monitoring sehen, können Sie einen HorizontalPodAutoscaler bereitstellen, um die Größe des Deployments basierend auf dem Messwert anzupassen.

Pub/Sub

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: pubsub
spec:
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - external:
      metric:
       name: pubsub.googleapis.com|subscription|num_undelivered_messages
       selector:
         matchLabels:
           resource.labels.subscription_id: echo-read
      target:
        type: AverageValue
        averageValue: 2
    type: External
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: pubsub

Benutzerdefinierter Messwert

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: custom-metrics-gmp-hpa
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: custom-metrics-gmp
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - type: Pods
    pods:
      metric:
        name: prometheus.googleapis.com|custom_prometheus|gauge
      target:
        type: AverageValue
        averageValue: 20

Stellen Sie den HorizontalPodAutoscaler in Ihrem Cluster bereit:

Pub/Sub

kubectl apply -f deployment/pubsub-hpa.yaml

Benutzerdefinierter Messwert

kubectl apply -f custom-metrics-gmp-hpa.yaml

Last generieren

Bei einigen Messwerten müssen Sie möglicherweise eine Last generieren, um das Autoscaling zu sehen:

Pub/Sub

Veröffentlichen Sie 200 Nachrichten an das Pub/Sub-Thema:

for i in {1..200}; do gcloud pubsub topics publish echo --message="Autoscaling #${i}"; done

Benutzerdefinierter Messwert

Nicht zutreffend: Der in diesem Beispiel verwendete Code exportiert für den benutzerdefinierten Messwert den konstanten Wert 40. Für den HorizontalPodAutoscaler ist der Zielwert 20 festgelegt, sodass er versucht, das Deployment automatisch vertikal zu skalieren.

Es kann einige Minuten dauern, bis der HorizontalPodAutoscaler auf die Messwertänderungen reagiert.

Hochskalieren von HorizontalPodAutoscaler beobachten

Mit folgendem Befehl können Sie die aktuelle Anzahl von Replikaten des Deployments prüfen:

kubectl get deployments

Nachdem der Messwert einige Zeit für die Übertragung hatte, erstellt das Deployment fünf Pods zur Verarbeitung des Rückstands.

Sie können auch den Status und die letzte Aktivität des HorizontalPodAutoscalers prüfen, indem Sie folgenden Befehl ausführen:

kubectl describe hpa