Extensibilité du plan de données avec EnvoyFilter

Vous pouvez utiliser l'API EnvoyFilter pour étendre les fonctionnalités du plan de données dans Cloud Service Mesh, ce qui n'est pas possible avec d'autres API Istio. Avec l'API EnvoyFilter, vous pouvez 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 de l'implémentation interne. Vous devez donc faire très attention lorsque vous utilisez cette fonctionnalité, car des configurations incorrectes peuvent 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'EnvoyFilter API, consultez la section 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 side-cars Envoy. Elle ne s'étend pas à l'exactitude de la configuration spécifiée à l'aide d'API par extension.

Champs d'API compatibles

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

  • targetRefs : non compatible
  • configPatches[].applyTo : seul HTTP_FILTER est compatible
  • configPatches[].patch.operation : seuls INSERT_FIRST et INSERT_BEFORE sont compatibles lorsqu'ils sont utilisés avec le filtre de route.
  • configPatches[].patch.value.type_url: consultez la section 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 compatibles qu'avec l'opération INSERT_BEFORE :
    • configPatches[].match.listener : seul filter est compatible.
    • configPatches[].match.listener.filter.name : seul envoy.filters.network.http_connection_manager est compatible.
    • configPatches[].match.listener.filter.subFilter.name : seul envoy.filters.http.router est compatible.

Extensions compatibles

Voici la liste des extensions compatibles, ainsi que les champs d'API compatibles pour différents canaux de publication. 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 ce tutoriel terminé, vous pouvez éviter les coûts continus 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 déjà fait, 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'exemple d'application, 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 la valeur 2/2 ne s'affiche pas après 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 à 5 requêtes/min.

  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 ne soient facturées sur votre Google Cloud compte pour, supprimez le projet ou 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 la section Résoudre les problèmes d'extensibilité du plan de données.