Extensibilité du plan de données avec EnvoyFilter

Vous pouvez utiliser l'API EnvoyFilter pour étendre les capacités du plan de données dans Cloud Service Mesh, qui ne sont pas réalisables avec d'autres API Istio. L'API EnvoyFilter vous permet de personnaliser la configuration Envoy générée à partir d'autres règles appliquées aux charges de travail, par exemple en ajoutant des filtres à la chaîne de filtres HTTP.

Remarques importantes

  • Notez que la surface de l'API est liée aux détails d'implémentation internes. Vous devez donc faire particulièrement attention lorsque vous utilisez cette fonctionnalité, car des configurations incorrectes pourraient déstabiliser le maillage. N'utilisez l'API EnvoyFilter que si les autres API Istio ne répondent pas à vos besoins.
  • L'API EnvoyFilter est compatible avec des restrictions spécifiques sur les champs et les extensions qui peuvent être utilisés à des fins de fiabilité et de compatibilité. Pour obtenir la liste exhaustive des fonctionnalités compatibles avec l'API EnvoyFilter, consultez Fonctionnalités compatibles avec les API Istio (plan de contrôle géré).
  • L'assistance proposée par Google se limite à la propagation de la configuration fournie par l'utilisateur aux charges de travail avec des sidecars Envoy. Elle ne s'étend pas à l'exactitude de la configuration spécifiée à l'aide des API par extension.

Champs d'API compatibles

L'API EnvoyFilter n'est compatible avec l'implémentation du plan de contrôle TRAFFIC_DIRECTOR qu'avec une compatibilité limitée, comme suit :

  • targetRefs : non compatible
  • configPatches[].applyTo : seule la valeur HTTP_FILTER est acceptée
  • configPatches[].patch.operation : seuls INSERT_FIRST et INSERT_BEFORE sont acceptés lorsqu'ils sont utilisés avec le filtre de route.
  • configPatches[].patch.value.type_url : consultez Extensions compatibles.
  • configPatches[].patch.filterClass : non compatible
  • configPatches[].match.proxy : non compatible
  • configPatches[].match.routeConfiguration : non compatible
  • configPatches[].match.cluster : non compatible
  • Les champs suivants ne sont acceptés que pour l'opération INSERT_BEFORE :
    • configPatches[].match.listener : seule filter est acceptée.
    • configPatches[].match.listener.filter.name : seule envoy.filters.network.http_connection_manager est acceptée.
    • configPatches[].match.listener.filter.subFilter.name : seule envoy.filters.http.router est acceptée.

Extensions acceptées

Vous trouverez ci-dessous la liste des extensions compatibles, ainsi que les champs d'API compatibles pour les différents canaux de diffusion. La définition de l'API et sa sémantique sont disponibles dans la documentation officielle d'Envoy.

type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit

Champ Rapide Standard Stable
stat_prefix
status
token_bucket
filter_enabled
filter_enforced
response_headers_to_add
request_headers_to_add_when_not_enforced
local_rate_limit_per_downstream_connection
enable_x_ratelimit_headers

type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb

Champ Rapide Standard Stable
(Aucun champ)

Exemple d'utilisation

Dans ce tutoriel, vous allez apprendre à utiliser la limitation du débit local intégrée d'Envoy pour limiter dynamiquement le trafic vers un service à l'aide de l'API EnvoyFilter.

Coûts

Ce tutoriel utilise les composants facturables suivants de Google Cloud :

Une fois que vous aurez terminé ce tutoriel, évitez de payer des frais en supprimant les ressources que vous avez créées. Pour en savoir plus, consultez la section Effectuer un nettoyage.

Avant de commencer

Déployer une passerelle d'entrée

  1. Définissez le contexte actuel de kubectl sur le cluster :

    gcloud container clusters get-credentials CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION 
    
  2. Créez un espace de noms pour votre passerelle d'entrée :

    kubectl create namespace asm-ingress
    
  3. Activez l'espace de noms pour l'injection : Les étapes dépendent de votre mise en œuvre du plan de contrôle.

    Appliquez les étiquettes d'injection par défaut à l'espace de noms.

    kubectl label namespace asm-ingress \
        istio.io/rev- istio-injection=enabled --overwrite
    
  4. Déployez l'exemple de passerelle dans le dépôt anthos-service-mesh-samples :

    kubectl apply -n asm-ingress \
        -f docs/shared/asm-ingress-gateway
    

    Résultat attendu :

    serviceaccount/asm-ingressgateway configured
    service/asm-ingressgateway configured
    deployment.apps/asm-ingressgateway configured
    gateway.networking.istio.io/asm-ingressgateway configured
    

Déployez l'exemple d'application Boutique en ligne.

  1. Si ce n'est pas le cas, définissez le contexte actuel de kubectl sur le cluster :

    gcloud container clusters get-credentials CLUSTER_NAME  \
      --project=PROJECT_ID \
      --zone=CLUSTER_LOCATION 
    
  2. Créez l'espace de noms pour l'exemple d'application :

    kubectl create namespace onlineboutique
    
  3. Ajoutez un libellé à l'espace de noms onlineboutique pour injecter automatiquement les proxys Envoy :

    kubectl label namespace onlineboutique \
       istio.io/rev- istio-injection=enabled --overwrite
    
  4. Déployez l'application exemple, le VirtualService pour l'interface et les comptes de service pour les charges de travail. Dans ce tutoriel, vous allez déployer Online Boutique, une application de démonstration de microservices.

    kubectl apply \
      -n onlineboutique \
      -f docs/shared/online-boutique/virtual-service.yaml
    
    kubectl apply \
      -n onlineboutique \
      -f docs/shared/online-boutique/service-accounts
    

Afficher vos services

  1. Affichez les pods dans l'espace de noms onlineboutique :

    kubectl get pods -n onlineboutique
    

    Résultat attendu :

    NAME                                     READY   STATUS    RESTARTS   AGE
    adservice-85598d856b-m84m6               2/2     Running   0          2m7s
    cartservice-c77f6b866-m67vd              2/2     Running   0          2m8s
    checkoutservice-654c47f4b6-hqtqr         2/2     Running   0          2m10s
    currencyservice-59bc889674-jhk8z         2/2     Running   0          2m8s
    emailservice-5b9fff7cb8-8nqwz            2/2     Running   0          2m10s
    frontend-77b88cc7cb-mr4rp                2/2     Running   0          2m9s
    loadgenerator-6958f5bc8b-55q7w           2/2     Running   0          2m8s
    paymentservice-68dd9755bb-2jmb7          2/2     Running   0          2m9s
    productcatalogservice-84f95c95ff-c5kl6   2/2     Running   0          114s
    recommendationservice-64dc9dfbc8-xfs2t   2/2     Running   0          2m9s
    redis-cart-5b569cd47-cc2qd               2/2     Running   0          2m7s
    shippingservice-5488d5b6cb-lfhtt         2/2     Running   0          2m7s
    

    Tous les pods de votre application doivent être opérationnels, avec une valeur 2/2 dans la colonne READY. Cela indique que les pods ont un proxy side-car Envoy injecté avec succès. Si 2/2 ne s'affiche pas au bout de quelques minutes, consultez le guide de dépannage.

  2. Obtenez l'adresse IP externe et définissez-la sur une variable :

    kubectl get services -n asm-ingress
    export FRONTEND_IP=$(kubectl --namespace asm-ingress \
    get service --output jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}' \
    )
    

    Vous obtenez un résultat semblable à celui-ci :

    NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                                      AGE
    asm-ingressgateway   LoadBalancer   10.19.247.233   35.239.7.64   80:31380/TCP,443:31390/TCP,31400:31400/TCP   27m
    
    
  3. Accédez à l'adresse EXTERNAL-IP dans votre navigateur Web. La boutique en ligne devrait s'afficher dans votre navigateur.

    Interface de la boutique en ligne

Appliquer la configuration de la limite de débit

Cette section applique une ressource EnvoyFilter pour limiter tout le trafic vers le service frontend à cinq requêtes par minute.

  1. Appliquez le CR au service frontend :

    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1alpha3
    kind: EnvoyFilter
    metadata:
      name: frontend-local-ratelimit
      namespace: onlineboutique
    spec:
      workloadSelector:
        labels:
          app: frontend
      configPatches:
        - applyTo: HTTP_FILTER
          match:
            context: SIDECAR_INBOUND
            listener:
              filterChain:
                filter:
                  name: "envoy.filters.network.http_connection_manager"
                  subFilter:
                    name: "envoy.filters.http.router"
          patch:
            operation: INSERT_BEFORE
            value:
              name: envoy.filters.http.local_ratelimit
              typed_config:
                "@type": type.googleapis.com/udpa.type.v1.TypedStruct
                type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
                value:
                  stat_prefix: http_local_rate_limiter
                  token_bucket:
                    max_tokens: 5
                    tokens_per_fill: 5
                    fill_interval: 60s
                  filter_enabled:
                    runtime_key: local_rate_limit_enabled
                    default_value:
                      numerator: 100
                      denominator: HUNDRED
                  filter_enforced:
                    runtime_key: local_rate_limit_enforced
                    default_value:
                      numerator: 100
                      denominator: HUNDRED
    EOF
    

    Résultat attendu :

    envoyfilter.networking.istio.io/frontend-local-ratelimit created
    
  2. Vérifiez que l'état du CR ne signale aucune erreur :

    kubectl get envoyfilter -n onlineboutique frontend-local-ratelimit -o yaml
    

    Résultat attendu :

    ...
    status:
      conditions:
      - lastTransitionTime: "2025-06-30T14:29:25.467017594Z"
        message: This resource has been accepted. This does not mean it has been propagated
          to all proxies yet
        reason: Accepted
        status: "True"
        type: Accepted
    
  3. Supprimez le déploiement loadgenerator, car il appelle le service plusieurs fois, ce qui consomme des jetons :

    kubectl delete -n onlineboutique deployment loadgenerator
    

    Résultat attendu :

    deployment.apps/loadgenerator deleted
    
  4. À l'aide de curl, vérifiez qu'au maximum cinq requêtes sont autorisées en 60 secondes. Le code 429 indique que la limitation du débit est appliquée.

    for i in {1..10}; do curl -s http://${FRONTEND_IP} -o /dev/null -w "%{http_code}\n"; sleep 1; done
    

    Résultat attendu :

    200
    200
    200
    200
    200
    429
    429
    429
    429
    429
    

Effectuer un nettoyage

Pour éviter que les ressources utilisées dans ce tutoriel continuent d'être facturées sur votre compte Google Cloud , vous pouvez supprimer le projet ou supprimer les ressources individuelles.

Supprimer le projet

Dans Cloud Shell, supprimez le projet :

  gcloud projects delete PROJECT_ID

Supprimer les ressources

  • Si vous souhaitez conserver votre cluster et supprimer l'exemple de boutique en ligne, procédez comme suit :

    1. Supprimez les espaces de noms de l'application :

      kubectl delete namespace onlineboutique
      

      Résultat attendu :

      namespace "onlineboutique" deleted
      
    2. Supprimez l'espace de noms de la passerelle d'entrée :

      kubectl delete namespace asm-ingress
      

      Résultat attendu :

      namespace "asm-ingress" deleted
      
  • Si vous souhaitez éviter des frais supplémentaires, supprimez le cluster :

    gcloud container clusters delete CLUSTER_NAME  \
      --project=PROJECT_ID \
      --zone=CLUSTER_LOCATION 
    

Dépannage

Consultez Résoudre les problèmes d'extensibilité du plan de données.