Configurer la limitation du débit Google Cloud Armor avec Envoy

Cette page vous explique comment configurer une limitation du débit côté serveur globale pour votre service mesh à l'aide de Cloud Armor. Vous pouvez utiliser cette fonctionnalité pour appliquer une limitation du débit de partage équitable à tout le trafic arrivant à votre service. Cela vous permet de partager équitablement la capacité disponible de vos services et d'atténuer le risque de surcharge de vos services par des clients malveillants ou au comportement inapproprié. Pour en savoir plus sur la limitation du débit, consultez la présentation de la limitation du débit.

Configurer Google Kubernetes Engine (GKE) pour Envoy

Avant de commencer

Avant de commencer, vous devez activer les API suivantes :

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

Vous pouvez activer toutes les API à l'aide de la commande Google Cloud CLI suivante :

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

Créez ensuite les variables d'environnement utilisées dans ce document :

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}

Remplacez les variables suivantes par les informations de votre projet :

  • Remplacez PROJECT_ID par l'ID de votre projet.
  • Remplacez ZONE par la zone dans laquelle vous souhaitez créer votre cluster GKE.
  • Remplacez CLUSTER par le nom du cluster.
  • Remplacez MESH_NAME par le nom du maillage.

Créer un cluster GKE

  1. Utilisez la commande suivante pour créer un cluster GKE dans la zone que vous avez spécifiée dans la section précédente :

     gcloud container clusters create "CLUSTER" \
         --zone="ZONE" \
         --scopes="cloud-platform" \
         --tags="allow-envoy-health-checks" \
         --enable-ip-alias
    
  2. Obtenez les identifiants de votre nouveau cluster :

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

Activer l'injection automatique

  1. Exécutez la commande suivante pour appliquer la ressource MutatingWebhookConfiguration à votre cluster. Lorsqu'un pod est créé, le contrôleur d'admission du cluster est appelé et indique à l'injecteur de side-car géré d'ajouter le conteneur Envoy au 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. Activez l'injection side-car pour l'espace de noms par défaut. L'injecteur de side-car injecte des conteneurs side-car pour les pods créés sous l'espace de noms par défaut.

    kubectl label namespace default td-injection=enabled
    
  3. Enregistrez la configuration GKE suivante pour votre service sous le nom 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. Appliquez l'exemple de service que vous avez créé à l'étape précédente :

    kubectl apply -f service_sample.yaml
    
  5. Enregistrez la configuration GKE suivante pour votre client sous le nom 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. Appliquez l'exemple de client que vous avez créé à l'étape précédente :

    kubectl apply -f client_sample.yaml
    

Configurer Cloud Service Mesh pour la limitation du débit

Suivez les étapes de cette section pour préparer Cloud Service Mesh à la limitation du débit.

  1. Créez la spécification de ressource Mesh et enregistrez-la dans un fichier nommé mesh.yaml :

    name: MESH_NAME
    interceptionPort: 15001
    
  2. Créez la ressource Mesh à l'aide de la spécification mesh.yaml.

      gcloud network-services meshes import "MESH_NAME" \
          --source=mesh.yaml \
          --location=global
    
  3. Créez une vérification d'état :

      gcloud compute health-checks create http rate-limit-demo-hc \
          --use-serving-port
    
  4. Créez une règle de pare-feu pour autoriser les connexions de vérification d'état entrantes aux instances de votre réseau.

      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. Créez un service de backend global avec un schéma d'équilibrage de charge INTERNAL_SELF_MANAGED et ajoutez la vérification de l'état.

      gcloud compute backend-services create rate-limit-demo-service \
          --global \
          --health-checks rate-limit-demo-hc \
          --load-balancing-scheme INTERNAL_SELF_MANAGED
    
  6. Ajoutez le NEG rate-limit-demo-neg au service de 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. Créez la spécification HTTPRoute et enregistrez-la dans un fichier nommé 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. Créez la ressource HTTPRoute à l'aide de la spécification du fichier http_route.yaml.

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

Configurer la limitation du débit avec Envoy

Les sections suivantes expliquent comment configurer la limitation du débit côté serveur pour votre maillage de services. La première section vous explique comment configurer une limite de fréquence globale côté serveur pour tous les clients, et la deuxième section vous explique comment appliquer différentes limites de fréquence pour différents groupes de clients.

Configurer la limitation globale du débit côté serveur

Dans cet exemple, vous allez créer une règle de limitation du débit côté serveur qui s'applique à tous les clients.

  1. Dans un fichier YAML nommé rate-limit-policy.yaml, créez une règle de sécurité Cloud Armor avec le type 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. Créez la stratégie de sécurité appelée rate-limit-policy :

      gcloud beta compute security-policies create rate-limit-policy \
          --global \
          --file-name=rate-limit-policy.yaml
    
  3. Dans un fichier YAML, créez une règle de point de terminaison qui fait référence à la règle de sécurité que vous avez créée à l'étape précédente. Dans ces exemples, ce fichier est appelé 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. Créez une règle de point de terminaison nommée rate-limit-ep :

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

Configurer différentes limites de fréquence côté serveur pour différents groupes de clients

Dans cet exemple, vous allez créer différentes règles de limitation du débit côté serveur qui appliquent différents seuils de limitation du débit pour des groupes de clients.

  1. Créez une stratégie de sécurité Cloud Armor avec le type CLOUD_ARMOR_INTERNAL_SERVICE et plusieurs règles de limitation du débit, comme celle définie dans le fichier suivant. Dans ces exemples, ce fichier est appelé 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"
    

    Cette règle applique une limitation du débit aux requêtes contenant un en-tête HTTP avec le nom user et la valeur demo si Cloud Service Mesh reçoit plus de 1 000 requêtes de ce type dans un intervalle de 60 secondes. Les requêtes qui ne comportent pas cet en-tête HTTP sont en revanche limitées en débit si Cloud Service Mesh reçoit plus de 10 000 requêtes de ce type au cours d'une période de 60 secondes.

  2. Exécutez la commande suivante pour créer la règle, qui est appelée per-client-security-policy :

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

    Créez une règle de point de terminaison qui fait référence à la règle de sécurité que vous avez créée à l'étape précédente, comme celle définie dans le fichier suivant. Dans cet exemple, ce fichier s'appelle 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
    

    Exécutez la commande suivante pour créer une stratégie de point de terminaison nommée rate-limit-ep :

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

Valider votre configuration

Vous pouvez utiliser l'outil de test de charge Nighthawk pour générer du trafic et vérifier si vos règles de limitation du débit fonctionnent comme prévu. Utilisez la commande suivante pour générer du trafic avec 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

Ensuite, utilisez la commande suivante pour activer les journaux de débogage Envoy :

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

Pour afficher les rapports d'utilisation qu'Envoy envoie au serveur de gestion, consultez Accéder à vos journaux.

Voici ce que vous pouvez attendre des résultats de votre test :

  • Il faut environ cinq minutes pour que la limitation du débit prenne effet.
  • Après la période de préchauffage initiale, vous devriez voir environ 15 à 21 requêtes par seconde dans le compteur de sortie du client Nighthawk benchmark.http_2xx. Cela signifie que Cloud Armor autorise environ 1 000 requêtes par minute.

Pour afficher l'efficacité de vos règles de stratégie de sécurité Cloud Armor, consultez Afficher le tableau de bord de surveillance.

Désactiver la limitation du débit

Vous pouvez désactiver la limitation du débit en utilisant l'une des méthodes suivantes :

  • Vous pouvez supprimer les règles de sécurité et les règles pour les points de terminaison que vous avez configurées avec vos règles de limitation du débit.
  • Vous pouvez dissocier la stratégie de sécurité de votre règle de point de terminaison en mettant à jour cette dernière pour supprimer le champ securityPolicies.

Les sections suivantes vous expliquent comment désactiver la limitation du débit à l'aide de chaque méthode.

Supprimer une règle de point de terminaison et une règle de sécurité

Tout d'abord, utilisez la commande gcloud suivante pour supprimer votre stratégie de point de terminaison nommée rate-limit-ep. Si vous avez utilisé le nom fourni dans le premier ou le deuxième exemple de cette page, la règle de point de terminaison est nommée endpoints-policies ou per-client-endpoints-policies, respectivement.

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

Ensuite, exécutez la commande gcloud suivante pour supprimer une stratégie de sécurité, en remplaçant per-client-security-policy par le nom de votre stratégie de sécurité. Si vous avez utilisé le nom fourni dans le premier ou le deuxième exemple de cette page, votre stratégie de sécurité porte le même nom que votre stratégie de point de terminaison.

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

Dissocier une stratégie de sécurité de votre stratégie de point de terminaison

Commencez par mettre à jour votre fichier endpoint-policy.yaml pour supprimer le champ securityPolcies :

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

Ensuite, exécutez la commande suivante pour mettre à jour la stratégie de point de terminaison nommée rate-limit-ep avec les modifications apportées au fichier endpoint-policy.yaml :

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