TL;DR — Résumé Rapide

Guide complet Envoy Proxy pour service mesh et edge proxy. Couvre xDS API, équilibrage de charge, mTLS, observabilité, circuit breaking et sidecar Kubernetes.

Envoy Proxy est le plan de données au cœur des service meshes modernes. Créé à l’origine chez Lyft pour résoudre l’observabilité et la fiabilité des microservices à grande échelle, Envoy est aujourd’hui le sidecar de facto pour Istio, l’edge proxy de nombreux contrôleurs d’ingress et un proxy L3/L4/L7 polyvalent utilisé par Google, AWS et des milliers d’entreprises. Ce guide couvre l’architecture d’Envoy, la configuration statique et dynamique, les algorithmes d’équilibrage de charge, le pipeline d’observabilité, la gestion TLS et les filtres avancés.

Prérequis

  • Docker (pour les tests autonomes) ou un cluster Kubernetes.
  • Connaissance de base de HTTP, TLS et des concepts de proxy inverse.
  • Familiarité avec la syntaxe de configuration YAML.
  • curl et optionnellement jq pour tester les endpoints.

Architecture d’Envoy

Envoy fonctionne comme un proxy réseau hors processus — il s’exécute à côté de votre application plutôt que comme une bibliothèque à l’intérieur. Cela rend le proxy indépendant du langage et permet des mises à jour indépendantes.

Composants principaux :

  • Listeners — Ports réseau sur lesquels Envoy écoute (les connexions downstream arrivent ici).
  • Chaînes de filtres — Liste ordonnée de filtres réseau et HTTP appliqués à chaque connexion.
  • Clusters — Groupes nommés d’endpoints upstream (vos services backend).
  • Endpoints — Paires IP:port individuelles au sein d’un cluster, découvertes via EDS ou config statique.
  • Routes — Règles mappant les requêtes entrantes vers des clusters selon le chemin, l’en-tête ou les paramètres de requête.

Modèle de threads : Envoy utilise un thread principal pour la gestion plus un thread worker par cœur CPU. Chaque thread worker gère les connexions indépendamment avec de l’I/O non bloquant. Aucune contention de verrou sur le chemin critique — chaque worker a son propre pool de connexions.

Hot restart : Envoy prend en charge les mises à jour binaires sans interruption via un handshake en mémoire partagée entre l’ancien et le nouveau processus. Le nouveau processus prend en charge les connexions existantes sans perdre de trafic.


Configuration Statique (envoy.yaml)

La façon la plus rapide de démarrer est une configuration YAML statique avec toutes les ressources définies inline :

admin:
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 9901

static_resources:
  listeners:
    - name: listener_0
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 10000
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                stat_prefix: ingress_http
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: backend
                      domains: ["*"]
                      routes:
                        - match:
                            prefix: "/"
                          route:
                            cluster: service_backend
                            timeout: 15s
                            retry_policy:
                              retry_on: "5xx,reset,connect-failure"
                              num_retries: 3
                http_filters:
                  - name: envoy.filters.http.router
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

  clusters:
    - name: service_backend
      connect_timeout: 0.5s
      type: STRICT_DNS
      lb_policy: ROUND_ROBIN
      load_assignment:
        cluster_name: service_backend
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: backend-service
                      port_value: 8080
      health_checks:
        - timeout: 1s
          interval: 10s
          unhealthy_threshold: 2
          healthy_threshold: 2
          http_health_check:
            path: /health

Le bloc admin expose l’API de gestion d’Envoy sur le port 9901. Utilisez-le pour interroger /stats, /clusters, /config_dump et /healthcheck/fail pour les tests de circuit-breaker.


Configuration Dynamique : L’API xDS

Les configurations statiques fonctionnent pour les déploiements simples mais deviennent difficiles à gérer à grande échelle. Le protocole xDS (x Discovery Service) d’Envoy permet à un plan de contrôle de pousser des changements de configuration au moment de l’exécution — sans rechargement, sans redémarrage.

Types de ressources xDS :

APIGère
LDS (Listener Discovery Service)Listeners et chaînes de filtres
RDS (Route Discovery Service)Virtual hosts et tables de routes
CDS (Cluster Discovery Service)Définitions de clusters et politiques
EDS (Endpoint Discovery Service)Santé individuelle des endpoints IP:port
SDS (Secret Discovery Service)Certificats TLS et clés privées

ADS (Aggregated Discovery Service) : Combine toutes les APIs xDS en un seul stream gRPC bidirectionnel. C’est le mode recommandé car il garantit l’ordre — un nouveau cluster est toujours livré avant la route qui le référence, évitant les erreurs 503 temporaires lors des mises à jour.

Delta xDS : Au lieu d’envoyer l’état complet à chaque mise à jour, le delta xDS n’envoie que les ressources ajoutées, modifiées ou supprimées. Essentiel pour les grandes mailles avec des milliers de clusters.


Algorithmes d’Équilibrage de Charge

Envoy prend en charge six politiques d’équilibrage de charge sélectionnables par cluster :

PolitiqueMeilleur Pour
ROUND_ROBINCapacité uniforme du backend, choix par défaut
LEAST_REQUESTDurée variable des requêtes, évite les backends surchargés
RING_HASHHash cohérent — affinité de cache, services avec état
RANDOMSimple, faible overhead, résistant aux endpoints lents
MAGLEVHash cohérent de Google — distribution plus uniforme
CLUSTER_PROVIDEDDélègue la décision au type de cluster upstream

Observabilité

Envoy est dogmatique sur l’observabilité — il a été conçu pour rendre les systèmes distribués déboguables. Trois piliers intégrés :

Statistiques : Envoy émet des milliers de compteurs, jauges et histogrammes. Exposez-les à Prometheus via l’endpoint admin :

curl http://localhost:9901/stats/prometheus

Traçage Distribué : Envoy génère et propage automatiquement les en-têtes de contexte de traçage pour Jaeger, Zipkin et OpenTelemetry. Votre application n’a qu’à transmettre ces en-têtes — Envoy gère la création des traces.

Journalisation des Accès : Journaux d’accès JSON structurés avec toutes les métadonnées de requête, incluant le cluster upstream, la durée, le code de réponse et les octets envoyés.


TLS et mTLS avec SDS

Le Secret Discovery Service (SDS) d’Envoy résout la distribution manuelle de certificats : les certificats sont récupérés d’un plan de contrôle au moment de l’exécution et renouvelés sans redémarrage du processus.

Pour le TLS mutuel entre services, le champ match_subject_alt_names applique l’identité SPIFFE — seules les connexions de services avec l’URI SPIFFE attendu sont acceptées. C’est ainsi qu’Istio implémente les réseaux zero-trust : chaque connexion pod à pod est mutuellement authentifiée via des certificats de courte durée renouvelés par SPIRE.


Filtres Avancés

Circuit Breaking : Prévient les défaillances en cascade en limitant les requêtes en attente, les nouvelles tentatives et les connexions. Configurez max_connections, max_pending_requests, max_requests et max_retries par cluster.

Détection d’Outliers : Éjecte automatiquement les hôtes non sains du pool d’équilibrage. Après cinq réponses 5xx consécutives, l’endpoint est éjecté pendant 30 secondes. max_ejection_percent évite d’éjecter tous les hôtes lors d’une dégradation globale de l’upstream.

Injection de Pannes : Injecte de la latence ou des erreurs dans un pourcentage de requêtes pour les tests de chaos, configurable par route sans changements dans le code de l’application.

Autorisation Externe : Délègue les décisions d’autorisation à un service gRPC externe (OPA, Ory Keto). Le filtre ext_authz envoie les en-têtes de requête au service d’autorisation avant de transmettre en amont.

Extensions Wasm : Envoy prend en charge les plugins de filtres WebAssembly pour la logique métier personnalisée dans tout langage compilant vers Wasm (Go, Rust, C++). Les filtres Wasm sont rechargés à chaud sans mises à jour binaires.


Envoy vs Autres Proxies

FonctionnalitéEnvoyNginxHAProxyTraefikLinkerdMOSN
Config dynamiquexDS API (sans rechargement)nginx -s reloadAPI temps réelAuto-découverte K8sxDS (limité)xDS API
Service meshOui (Istio, Consul)NonNonNon (ingress seul)Oui (Linkerd2)Oui
Protocoles L7HTTP/1.1, HTTP/2, gRPC, ThriftHTTP/1.1, HTTP/2HTTP/1.1, HTTP/2HTTP/1.1, HTTP/2HTTP/1.1, HTTP/2, gRPCHTTP/1.1, HTTP/2, Dubbo
ObservabilitéStats + traçage intégrésBasé sur modulesSocket de statsPlugin PrometheusSignaux dorés intégrésStats intégrés
mTLSSDS + SPIFFECerts manuelsCerts manuelsCerts manuelsAutomatiqueSDS
Filtres WasmOuiNonNonNonNonOui

Exemple Pratique : Envoy comme Proxy Frontal

Vous avez trois microservices (users, orders, products) derrière Envoy comme edge proxy, avec le trafic partagé entre v1 et v2 du service de commandes pour un déploiement canary :

routes:
  - match:
      prefix: "/orders"
    route:
      weighted_clusters:
        clusters:
          - name: orders_v1
            weight: 90
          - name: orders_v2
            weight: 10
        total_weight: 100

Cette configuration de cluster pondéré envoie 10% du trafic /orders vers le canary v2 sans aucun changement dans le code de l’application.


Pièges et Cas Limites

  • Sensibilité à la casse des en-têtes : Les en-têtes HTTP/2 sont en minuscules par défaut. Envoy les normalise — assurez-vous que vos services gèrent content-type, authorization en minuscules.
  • Timeouts upstream vs de route : connect_timeout du cluster (TCP) et timeout de la route (requête) sont indépendants. Le timeout de route par défaut est 15 secondes — définissez-le explicitement.
  • Budget de nouvelles tentatives : Sans limites sur retry_on, les nouvelles tentatives sous charge peuvent amplifier les défaillances. Combinez toujours les nouvelles tentatives avec un circuit breaker.

Dépannage

SymptômeCause ProbableSolution
503 upstream_reset_before_response_startedL’upstream a fermé la connexion avant de répondreVérifiez le chemin du health check ; augmentez connect_timeout
404 d’Envoy (pas de l’upstream)Aucune route correspondanteExécutez /config_dump sur le port admin ; vérifiez le domaine du virtual host
Circuit breaker ouvert dans les statsUpstream surchargéAugmentez max_pending_requests ou mettez à l’échelle l’upstream
Échec de handshake mTLSDiscordance SAN du certificatVérifiez que match_subject_alt_names correspond à l’URI SPIFFE réel
Latence P99 élevéeFamine de threadsAugmentez le nombre de threads worker avec concurrency dans le bootstrap

Résumé

  • L’API xDS permet une configuration entièrement dynamique sans redémarrage — clusters, routes, listeners et certificats se mettent à jour en direct.
  • L’équilibrage de charge offre six algorithmes dont Ring Hash pour l’affinité de cache et Least Request pour les charges de travail hétérogènes.
  • L’observabilité intégrée fournit des stats Prometheus, des en-têtes de traçage distribué et des journaux d’accès JSON structurés.
  • mTLS via SDS + SPIFFE délivre des réseaux zero-trust avec des certificats de courte durée renouvelés automatiquement.
  • Les filtres avancés rendent Envoy extensible sans toucher au code de l’application.

Articles Connexes