Configura la limitazione di frequenza di Google Cloud Armor con Envoy

Questa pagina mostra come configurare limitazione di frequenza lato server globale per il mesh di servizi utilizzando Cloud Armor. Puoi utilizzare questa funzionalità per applicare limitazione di frequenzaà di condivisione equa a tutto il traffico in arrivo al tuo servizio, in modo da condividere equamente la capacità disponibile dei tuoi servizi e ridurre il rischio che client dannosi o con comportamenti anomali sovraccarichino i tuoi servizi. Per ulteriori informazioni sulla limitazione di frequenza, consulta la panoramica della limitazione della frequenza.

Configurare Google Kubernetes Engine (GKE) per Envoy

Prima di iniziare

Prima di iniziare, devi abilitare le seguenti API:

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

Puoi abilitare tutte le API utilizzando il seguente comando Google Cloud CLI:

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

Poi, crea le variabili di ambiente utilizzate in questo documento:

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}

Sostituisci le seguenti variabili con le informazioni del tuo progetto:

  • Sostituisci PROJECT_ID con l'ID progetto
  • Sostituisci ZONE con la zona in cui intendi creare il cluster GKE.
  • Sostituisci CLUSTER con il nome del cluster.
  • Sostituisci MESH_NAME con il nome della mesh.

Crea un cluster GKE

  1. Utilizza il seguente comando per creare un cluster GKE nella zona che hai specificato nella sezione precedente:

     gcloud container clusters create "CLUSTER" \
         --zone="ZONE" \
         --scopes="cloud-platform" \
         --tags="allow-envoy-health-checks" \
         --enable-ip-alias
    
  2. Recupera le credenziali del nuovo cluster:

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

Attiva l'inserimento automatico

  1. Utilizza il seguente comando per applicare la risorsa MutatingWebhookConfiguration al tuo cluster. Quando viene creato un pod, viene richiamato il controller di ammissione in-cluster che indica all'iniettore di sidecar gestito di aggiungere il container Envoy al pod.

    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. Abilita l'inserimento di sidecar per lo spazio dei nomi predefinito. L'iniettore sidecar inserisce i container sidecar per i pod creati nello spazio dei nomi predefinito.

    kubectl label namespace default td-injection=enabled
    
  3. Salva la seguente configurazione GKE per il tuo servizio come 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. Applica l'esempio di servizio che hai creato nel passaggio precedente:

    kubectl apply -f service_sample.yaml
    
  5. Salva la seguente configurazione GKE per il client come 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. Applica il campione client che hai creato nel passaggio precedente:

    kubectl apply -f client_sample.yaml
    

Configura Cloud Service Mesh per limitazione di frequenza

Utilizza i passaggi descritti in questa sezione per preparare Cloud Service Mesh per la limitazione della frequenza.

  1. Crea la specifica della risorsa Mesh e salvala in un file denominato mesh.yaml:

    name: MESH_NAME
    interceptionPort: 15001
    
  2. Crea la risorsa Mesh utilizzando la specifica mesh.yaml.

      gcloud network-services meshes import "MESH_NAME" \
          --source=mesh.yaml \
          --location=global
    
  3. Crea un controllo di integrità:

      gcloud compute health-checks create http rate-limit-demo-hc \
          --use-serving-port
    
  4. Crea una regola firewall per consentire le connessioni di controllo di integrità in entrata alle istanze nella tua rete.

      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. Crea un servizio di backend globale con uno schema di bilanciamento del carico di INTERNAL_SELF_MANAGED e aggiungi il controllo di integrità.

      gcloud compute backend-services create rate-limit-demo-service \
          --global \
          --health-checks rate-limit-demo-hc \
          --load-balancing-scheme INTERNAL_SELF_MANAGED
    
  6. Aggiungi il NEG rate-limit-demo-neg al servizio di backend.

      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. Crea la specifica HTTPRoute e salvala in un file denominato 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. Crea la risorsa HTTPRoute utilizzando la specifica nel file http_route.yaml.

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

Configurare limitazione di frequenza con Envoy

Le sezioni seguenti spiegano come configurare la limitazione della frequenza lato server per il mesh di servizi. La prima sezione mostra come impostare un limite di frequenza globale lato server per tutti i client, mentre la seconda sezione mostra come applicare limiti di frequenza diversi per gruppi di client diversi.

Configurare la limitazione globale della frequenza lato server

In questo esempio, crei una regola di limitazione di frequenza lato server che impone limitazione di frequenza su tutti i client.

  1. In un file YAML denominato rate-limit-policy.yaml, crea un criterio di sicurezza Cloud Armor con il tipo 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. Crea il criterio di sicurezza denominato rate-limit-policy:

      gcloud beta compute security-policies create rate-limit-policy \
          --global \
          --file-name=rate-limit-policy.yaml
    
  3. In un file YAML, crea una policy endpoint che faccia riferimento alla policy di sicurezza che hai creato nel passaggio precedente. In questi esempi, questo file è denominato 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. Crea una policy endpoint denominata rate-limit-ep:

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

Configurare limiti di frequenza lato server diversi per gruppi di client diversi

In questo esempio, crei regole di limitazione di frequenza lato server diverse che impongono soglie dilimitazione di frequenzaa diverse per gruppi di client.

  1. Crea un criterio di sicurezza di Cloud Armor con il tipo CLOUD_ARMOR_INTERNAL_SERVICE con più regole di limitazione di frequenza, come quella definita nel seguente file. In questi esempi, questo file è denominato 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"
    

    Questo criterio applica limitazione di frequenza alle richieste contenenti un'intestazione HTTP con il nome user e il valore demo se Cloud Service Mesh riceve più di 1000 richieste di questo tipo in un periodo di 60 secondi. Le richieste che non hanno questa intestazione HTTP vengono invece limitate se Cloud Service Mesh riceve più di 10.000 richieste di questo tipo in un periodo di 60 secondi.

  2. Utilizza il seguente comando per creare la policy, denominata per-client-security-policy:

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

    Crea una policy endpoint che faccia riferimento alla policy di sicurezza che hai creato nel passaggio precedente, come quella definita nel seguente file. In questo esempio, il file si chiama 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
    

    Utilizza il seguente comando per creare una policy endpoint denominata rate-limit-ep:

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

Convalidare la configurazione

Puoi utilizzare lo strumento di test di carico Nighthawk per generare traffico e verificare se le regole di limitazione di frequenza funzionano come previsto. Utilizza il seguente comando per generare traffico con Nighthawk:

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

Quindi, utilizza il comando seguente per abilitare i log di debug di Envoy:

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

Per visualizzare i report sull'utilizzo che Envoy invia al server di gestione, consulta Accesso ai log.

Dai risultati del test puoi aspettarti di vedere quanto segue:

  • Ci vogliono circa cinque minuti prima che limitazione di frequenza entri in vigore.
  • Dopo il periodo iniziale di riscaldamento, vengono visualizzate circa 15-21 QPS dall'output del client Nighthawk benchmark.http_2xx. Ciò significa che Cloud Armor consente circa 1000 richieste al minuto.

Per visualizzare l'efficacia delle regole dei criteri di sicurezza di Cloud Armor, consulta Visualizzazione della dashboard di monitoraggio.

Disattiva limitazione di frequenza

Puoi disattivare la limitazione di frequenza utilizzando uno dei seguenti metodi:

  • Puoi eliminare le policy degli endpoint e le policy di sicurezza che hai configurato con le regolelimitazione di frequenzaa.
  • Puoi scollegare il criterio di sicurezza dal criterio endpoint aggiornando il criterio endpoint per rimuovere il campo securityPolicies.

Le sezioni seguenti spiegano come disattivare la limitazione di frequenza utilizzando ciascun metodo.

Eliminare una policy endpoint e una policy di sicurezza

Innanzitutto, utilizza il seguente comando gcloud per eliminare la policy dell'endpoint denominata rate-limit-ep. Se hai utilizzato il nome fornito nel primo o nel secondo esempio di questa pagina, la policy dell'endpoint si chiama rispettivamente endpoints-policies o per-client-endpoints-policies.

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

Quindi, utilizza il seguente comando gcloud per eliminare una policy di sicurezza, sostituendo per-client-security-policy con il nome della tua policy di sicurezza. Se hai utilizzato il nome fornito nel primo o nel secondo esempio di questa pagina, il nome della tua norma di sicurezza è lo stesso della norma dell'endpoint.

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

Scollega una policy di sicurezza dalla policy endpoint

Innanzitutto, aggiorna il file endpoint-policy.yaml per rimuovere il campo securityPolcies:

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

Quindi, utilizza il seguente comando per aggiornare la policy dell'endpoint denominata rate-limit-ep con le modifiche apportate al file endpoint-policy.yaml:

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