Ratenbegrenzung in Google Cloud Armor mit Envoy konfigurieren

Auf dieser Seite wird beschrieben, wie Sie mit Cloud Armor die globale serverseitige Ratenbegrenzung für Ihr Service Mesh konfigurieren. Mit dieser Funktion können Sie für den gesamten Traffic, der bei Ihrem Dienst eingeht, eine Ratenbegrenzung für die faire Nutzung anwenden. So können Sie die verfügbare Kapazität Ihrer Dienste fair aufteilen und das Risiko minimieren, dass böswillige oder fehlerhafte Clients Ihre Dienste überlasten. Weitere Informationen zur Ratenbegrenzung finden Sie in der Übersicht zur Ratenbegrenzung.

Google Kubernetes Engine (GKE) für Envoy konfigurieren

Hinweise

Bevor Sie beginnen, müssen Sie die folgenden APIs aktivieren:

  • container.googleapis.com
  • compute.googleapis.com
  • trafficdirector.googleapis.com
  • networkservices.googleapis.com
  • meshconfig.googleapis.com
  • monitoring.googleapis.com

Sie können alle APIs mit dem folgenden Google Cloud CLI-Befehl aktivieren:

gcloud services enable \
    container.googleapis.com \
    compute.googleapis.com \
    trafficdirector.googleapis.com \
    networkservices.googleapis.com \
    meshconfig.googleapis.com \
    monitoring.googleapis.com

Erstellen Sie dann die Umgebungsvariablen, die in diesem Dokument verwendet werden:

export PROJECT_ID=PROJECT_ID
export PROJECT_NUMBER="$(gcloud projects describe "${PROJECT_ID}" --format="value(projectNumber)")"
export CLUSTER=CLUSTER
export ZONE=ZONE
export MESH_NAME=MESH_NAME
export MESH_URI=projects/${PROJECT_NUMBER}/locations/global/meshes/${MESH_NAME}

Ersetzen Sie die folgenden Variablen durch Informationen aus Ihrem Projekt:

  • Ersetzen Sie PROJECT_ID durch Ihre Projekt-ID.
  • Ersetzen Sie ZONE durch die Zone, in der Sie den GKE-Cluster erstellen möchten.
  • Ersetzen Sie CLUSTER durch den Namen des Clusters.
  • Ersetzen Sie MESH_NAME durch den Namen des Mesh.

GKE-Cluster erstellen

  1. Verwenden Sie den folgenden Befehl, um einen GKE-Cluster in der Zone zu erstellen, die Sie im vorherigen Abschnitt angegeben haben:

     gcloud container clusters create "CLUSTER" \
         --zone="ZONE" \
         --scopes="cloud-platform" \
         --tags="allow-envoy-health-checks" \
         --enable-ip-alias
    
  2. Rufen Sie die Anmeldedaten für den neuen Cluster ab:

     gcloud container clusters get-credentials "CLUSTER" \
         --zone="ZONE"
    

Automatisches Einfügen aktivieren

  1. Wenden Sie die MutatingWebhookConfiguration-Ressource mit dem folgenden Befehl auf Ihren Cluster an. Wenn ein Pod erstellt wird, wird der clusterinterne Admission-Controller aufgerufen und weist den verwalteten Sidecar-Injector an, dem Pod den Envoy-Container hinzuzufügen.

    cat <<EOF | kubectl apply -f -
    apiVersion: admissionregistration.k8s.io/v1
    kind: MutatingWebhookConfiguration
    metadata:
     labels:
       app: sidecar-injector
     name: td-mutating-webhook
    webhooks:
    - admissionReviewVersions:
      - v1beta1
      - v1
      clientConfig:
        url: https://meshconfig.googleapis.com/v1internal/projects/PROJECT_ID/locations/ZONE/clusters/CLUSTER/channels/rapid/targets/${MESH_URI}:tdInject
      failurePolicy: Fail
      matchPolicy: Exact
      name: namespace.sidecar-injector.csm.io
      namespaceSelector:
        matchExpressions:
        - key: td-injection
          operator: Exists
      reinvocationPolicy: Never
      rules:
      - apiGroups:
        - ""
        apiVersions:
        - v1
        operations:
        - CREATE
        resources:
        - pods
        scope: '*'
      sideEffects: None
      timeoutSeconds: 30
    EOF
    
  2. Aktivieren Sie die Sidecar-Injektion für den Standard-Namespace. Der Sidecar-Injektor fügt Sidecar-Container in Pods ein, die unter dem Standard-Namespace erstellt werden.

    kubectl label namespace default td-injection=enabled
    
  3. Speichern Sie die folgende GKE-Konfiguration für Ihren Dienst als service_sample.yaml.

    apiVersion: v1
    kind: Service
    metadata:
     name: service-test
     annotations:
       cloud.google.com/neg: '{"exposed_ports":{"80":{"name": "rate-limit-demo-neg"}}}'
    spec:
     ports:
     - port: 80
       name: service-test
       targetPort: 8000
     selector:
       run: app1
     type: ClusterIP
    
    ---
    
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: app1
     labels:
       run: app1
    spec:
     replicas: 1
     selector:
       matchLabels:
         run: app1
     template:
       metadata:
         labels:
           run: app1
         annotations:
           cloud.google.com/proxyMetadata: '{"app": "rate-limit-demo"}'
           cloud.google.com/includeInboundPorts: "8000"
           cloud.google.com/sidecarProxyVersion: "1.34.1-gke.1"
       spec:
         containers:
         - image: mendhak/http-https-echo:37
           name: app1
           ports:
           - containerPort: 8000
           env:
           - name: VALIDATION_NONCE
             value: "http"
           - name: HTTP_PORT
             value: "8000"
         securityContext:
           fsGroup: 1337
    
  4. Wenden Sie das Dienstbeispiel an, das Sie im vorherigen Schritt erstellt haben:

    kubectl apply -f service_sample.yaml
    
  5. Speichern Sie die folgende GKE-Konfiguration für Ihren Client als client_sample.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
     labels:
       run: client
     name: load-generator
    spec:
     replicas: 1
     selector:
       matchLabels:
         run: client
     template:
       metadata:
         labels:
           run: client
       spec:
         containers:
         - name: load-generator
           image: envoyproxy/nighthawk-dev
           command: ["/bin/sh", "-c"]
           args: ["echo 'Nighthawk client pod is running' && sleep infinity"]
           resources:
             requests:
               cpu: 200m
               memory: 256Mi
             limits:
               cpu: 1
               memory: 512Mi
         securityContext:
           fsGroup: 1337
    
  6. Wenden Sie das Clientbeispiel an, das Sie im vorherigen Schritt erstellt haben:

    kubectl apply -f client_sample.yaml
    

Cloud Service Mesh für die Ratenbegrenzung einrichten

Mit den Schritten in diesem Abschnitt bereiten Sie Cloud Service Mesh für die Ratenbegrenzung vor.

  1. Erstellen Sie die Spezifikation der Mesh-Ressource und speichern Sie sie in einer Datei mit dem Namen mesh.yaml:

    name: MESH_NAME
    interceptionPort: 15001
    
  2. Erstellen Sie die Mesh-Ressource mit der Spezifikation mesh.yaml.

      gcloud network-services meshes import "MESH_NAME" \
          --source=mesh.yaml \
          --location=global
    
  3. Erstellen Sie eine Systemdiagnose.

      gcloud compute health-checks create http rate-limit-demo-hc \
          --use-serving-port
    
  4. Erstellen Sie eine Firewallregel, um eingehende Systemdiagnoseverbindungen zu Instanzen in Ihrem Netzwerk zuzulassen.

      gcloud compute firewall-rules create rate-limit-demo-fw-allow-hc \
          --action ALLOW \
          --direction INGRESS \
          --source-ranges 35.191.0.0/16,130.211.0.0/22 \
          --target-tags allow-envoy-health-checks \
          --rules tcp
    
  5. Erstellen Sie einen globalen Backend-Dienst mit dem Load-Balancing-Schema INTERNAL_SELF_MANAGED und fügen Sie die Systemdiagnose hinzu.

      gcloud compute backend-services create rate-limit-demo-service \
          --global \
          --health-checks rate-limit-demo-hc \
          --load-balancing-scheme INTERNAL_SELF_MANAGED
    
  6. Fügen Sie dem Backend-Dienst die NEG rate-limit-demo-neg hinzu.

      gcloud compute backend-services add-backend rate-limit-demo-service \
          --global \
          --network-endpoint-group rate-limit-demo-neg \
          --network-endpoint-group-zone "ZONE" \
          --balancing-mode RATE \
          --max-rate-per-endpoint 5
    
  7. Erstellen Sie die Spezifikation HTTPRoute und speichern Sie sie in einer Datei mit dem Namen http_route.yaml:

    name: rate-limit-demo-http-route
    hostnames:
    - service-test
    - service-test:80
    meshes:
    - projects/PROJECT_ID/locations/global/meshes/MESH_NAME
    rules:
    - action:
       destinations:
       - serviceName: "projects/PROJECT_ID/locations/global/backendServices/rate-limit-demo-service"
    
  8. Erstellen Sie die HTTPRoute-Ressource mit der Spezifikation in der Datei http_route.yaml.

      gcloud network-services http-routes import rate-limit-demo-http-route \
          --source=http_route.yaml \
          --location=global
    

Ratenbegrenzung mit Envoy konfigurieren

In den folgenden Abschnitten wird beschrieben, wie Sie die serverseitige Ratenbegrenzung für Ihr Service Mesh konfigurieren. Im ersten Abschnitt wird beschrieben, wie Sie ein globales serverseitiges Ratenlimit für alle Clients festlegen. Im zweiten Abschnitt erfahren Sie, wie Sie unterschiedliche Ratenlimits für verschiedene Clientgruppen erzwingen.

Serverseitige globale Ratenbegrenzung konfigurieren

In diesem Beispiel erstellen Sie eine serverseitige Ratenbegrenzungsregel, die die Ratenbegrenzung für alle Clients erzwingt.

  1. Erstellen Sie in einer YAML-Datei mit dem Namen rate-limit-policy.yaml eine Cloud Armor-Sicherheitsrichtlinie mit dem Typ CLOUD_ARMOR_INTERNAL_SERVICE.

    name: "rate-limit-policy"
    type: CLOUD_ARMOR_INTERNAL_SERVICE
    rules:
    - priority: 2147483647
      match:
        config:
          srcIpRanges: ["*"]
        versionedExpr: SRC_IPS_V1
      action: "fairshare"
      rateLimitOptions:
        rateLimitThreshold:
          count: 10000
          intervalSec: 60
        exceedAction: "deny(429)"
        conformAction: "allow"
        enforceOnKey: "ALL"
    
  2. Erstellen Sie die Sicherheitsrichtlinie mit dem Namen rate-limit-policy:

      gcloud beta compute security-policies create rate-limit-policy \
          --global \
          --file-name=rate-limit-policy.yaml
    
  3. Erstellen Sie in einer YAML-Datei eine Endpunktrichtlinie, die auf die Sicherheitsrichtlinie verweist, die Sie im vorherigen Schritt erstellt haben. In diesen Beispielen heißt die Datei endpoints-policies.yaml.

    name: "rate-limit-ep"
    endpointMatcher:
     metadataLabelMatcher:
       metadataLabelMatchCriteria: MATCH_ALL
       metadataLabels:
       - labelName: app
         labelValue: rate-limit-demo
    type: SIDECAR_PROXY
    securityPolicy: projects/PROJECT_ID/locations/global/securityPolicies/rate-limit-policy
    
  4. Erstellen Sie eine Endpunktrichtlinie mit dem Namen rate-limit-ep:

      gcloud beta network-services endpoint-policies import rate-limit-ep \
          --source=endpoints-policies.yaml \
          --location=global
    

Unterschiedliche serverseitige Ratenbegrenzungen für verschiedene Clientgruppen konfigurieren

In diesem Beispiel erstellen Sie verschiedene serverseitige Ratenbegrenzungsregeln, mit denen unterschiedliche Ratenbegrenzungsschwellen für Gruppen von Clients erzwungen werden.

  1. Erstellen Sie eine Cloud Armor-Sicherheitsrichtlinie vom Typ CLOUD_ARMOR_INTERNAL_SERVICE mit mehreren Ratenbegrenzungsregeln, wie in der folgenden Datei definiert. In diesen Beispielen heißt die Datei per-client-security-policy.yaml.

    name: "per-client-security-policy"
    type: CLOUD_ARMOR_INTERNAL_SERVICE
    rules:
    - priority: 0
      match:
        expr:
          expression: "request.headers['user'] == 'demo'"
      action: "fairshare"
      rateLimitOptions:
        rateLimitThreshold:
          count: 1000
          intervalSec: 60
        exceedAction: "deny(429)"
        conformAction: "allow"
        enforceOnKey: "ALL"
    - priority: 2147483647
      match:
        config:
          srcIpRanges: ["*"]
        versionedExpr: SRC_IPS_V1
      action: "fairshare"
      rateLimitOptions:
        rateLimitThreshold:
          count: 10000
          intervalSec: 60
        exceedAction: "deny(429)"
        conformAction: "allow"
        enforceOnKey: "ALL"
    

    Diese Richtlinie wendet die Ratenbegrenzung auf Anfragen an, die einen HTTP-Header mit dem Namen user und dem Wert demo enthalten, wenn Cloud Service Mesh innerhalb von 60 Sekunden mehr als 1.000 solcher Anfragen empfängt. Anfragen ohne diesen HTTP-Header werden stattdessen ratenbeschränkt,wenn Cloud Service Mesh innerhalb von 60 Sekunden mehr als 10.000 solcher Anfragen empfängt.

  2. Verwenden Sie den folgenden Befehl, um die Richtlinie mit dem Namen per-client-security-policy zu erstellen:

      gcloud beta compute security-policies create per-client-security-policy \
          --global \
          --file-name=per-client-security-policy.yaml
    

    Erstellen Sie eine Endpunktrichtlinie, die auf die Sicherheitsrichtlinie verweist, die Sie im vorherigen Schritt erstellt haben, z. B. die in der folgenden Datei definierte. In diesem Beispiel heißt die Datei per-client-endpoints-policies.yaml.

    name: "rate-limit-ep"
    endpointMatcher:
     metadataLabelMatcher:
       metadataLabelMatchCriteria: MATCH_ALL
       metadataLabels:
       - labelName: app
         labelValue: rate-limit-demo
    type: SIDECAR_PROXY
    securityPolicy: projects/PROJECT_ID/locations/global/securityPolicies/per-client-security-policy
    

    Verwenden Sie den folgenden Befehl, um eine Endpunktrichtlinie mit dem Namen rate-limit-ep zu erstellen:

      gcloud beta network-services endpoint-policies import rate-limit-ep \
          --source=per-client-endpoints-policies.yaml \
          --location=global
    

Einrichtung validieren

Mit dem Nighthawk-Tool für Lasttests können Sie Traffic generieren, um zu prüfen, ob Ihre Ratenbegrenzungsregeln wie erwartet funktionieren. Verwenden Sie den folgenden Befehl, um mit Nighthawk Traffic zu generieren:

kubectl exec -it deploy/load-generator -c load-generator -- \
    nighthawk_client http://service-test \
    --open-loop --no-default-failure-predicates \
    --rps 60 \
    --duration 360 \
    --connections 10 \
    --protocol http1 \
    --request-header user:demo

Aktivieren Sie als Nächstes mit dem folgenden Befehl die Envoy-Debug-Logs:

kubectl exec -it deploy/app1 -c app1 -- wget -q -O - \
    --post-data="" 'http://localhost:15000/logging?level=debug'

Informationen zum Aufrufen der Nutzungsberichte, die Envoy an den Verwaltungsserver sendet, finden Sie unter Auf Logs zugreifen.

Die Testergebnisse liefern folgende Informationen:

  • Es dauert etwa fünf Minuten, bis die Ratenbegrenzung wirksam wird.
  • Nach der anfänglichen Aufwärmphase sehen Sie etwa 15–21 QPS in der Nighthawk-Clientausgabe benchmark.http_2xx. Das bedeutet,dass Cloud Armor etwa 1.000 Anfragen pro Minute zulässt.

Informationen dazu, wie Sie die Effektivität Ihrer Cloud Armor-Sicherheitsrichtlinienregeln ansehen, finden Sie unter Monitoring-Dashboard ansehen.

Ratenbegrenzung deaktivieren

Sie können die Ratenbegrenzung mit einer der folgenden Methoden deaktivieren:

  • Sie können die Endpunktrichtlinien und Sicherheitsrichtlinien löschen, die Sie mit Ihren Ratenbegrenzungsregeln konfiguriert haben.
  • Sie können die Sicherheitsrichtlinie von Ihrer Endpunktrichtlinie trennen, indem Sie die Endpunktrichtlinie aktualisieren und das Feld securityPolicies entfernen.

In den folgenden Abschnitten wird beschrieben, wie Sie die Ratenbegrenzung mit den einzelnen Methoden deaktivieren.

Endpunktrichtlinie und Sicherheitsrichtlinie löschen

Verwenden Sie zuerst den folgenden gcloud-Befehl, um die Endpunktrichtlinie mit dem Namen rate-limit-ep zu löschen. Wenn Sie den Namen aus dem ersten oder zweiten Beispiel auf dieser Seite verwendet haben, heißt die Endpunktrichtlinie endpoints-policies bzw. per-client-endpoints-policies.

gcloud beta network-services endpoint-policies delete --location=global rate-limit-ep

Verwenden Sie dann den folgenden gcloud-Befehl, um eine Sicherheitsrichtlinie zu löschen. Ersetzen Sie dabei per-client-security-policy durch den Namen Ihrer Sicherheitsrichtlinie. Wenn Sie den Namen aus dem ersten oder zweiten Beispiel auf dieser Seite verwendet haben, hat Ihre Sicherheitsrichtlinie denselben Namen wie Ihre Endpunktrichtlinie.

gcloud beta compute security-policies delete --global per-client-security-policy

Sicherheitsrichtlinie von Ihrer Endpunktrichtlinie trennen

Aktualisieren Sie zuerst die Datei endpoint-policy.yaml, um das Feld securityPolcies zu entfernen:

name: "rate-limit-ep"
endpointMatcher:
  metadataLabelMatcher:
    metadataLabelMatchCriteria: MATCH_ALL
    metadataLabels:
    - labelName: app
      labelValue: rate-limit-demo
type: SIDECAR_PROXY

Verwenden Sie dann den folgenden Befehl, um die Endpunktrichtlinie mit dem Namen rate-limit-ep mit den Änderungen an der Datei endpoint-policy.yaml zu aktualisieren:

gcloud beta network-services endpoint-policies import rate-limit-ep \
    --source=endpoints-policies.yaml \
    --location=global