Migration de Nginx vers Envoy Proxy

Bonjour, Habr ! Je vous propose la traduction de cet article : Migration de Nginx vers Envoy Proxy.

Envoy est un proxy distribué hautes performances (écrit en C++) conçu pour des services et applications spécifiques. C'est également un bus de communication et un « plan de données universel », développé pour de grandes architectures de microservices « service mesh ». Lors de sa création, des solutions aux problÚmes rencontrés dans le développement de serveurs tels que NGINX, HAProxy, équilibrateurs de charge matériels et équilibrateurs de charge cloud ont été prises en compte. Envoy fonctionne avec chaque application et abstrait le réseau, fournissant des fonctionnalités communes indépendamment de la plateforme. Lorsque tout le trafic de services dans l'infrastructure passe par la grille Envoy, il devient facile de visualiser les zones problématiques grùce à une observabilité cohérente, à la configuration de la performance globale et à l'ajout de fonctionnalités essentielles à des endroits spécifiques.

Fonctionnalités

  • Architecture hors processus : envoy est un serveur autonome et hautes performances qui utilise une faible quantitĂ© de mĂ©moire vive. Il fonctionne avec n'importe quel langage d'application ou framework.
  • Support HTTP/2 et gRPC : envoy a un support de premier ordre pour HTTP/2 et gRPC pour les connexions entrantes et sortantes. C'est un proxy transparent de HTTP/1.1 Ă  HTTP/2.
  • Équilibrage de charge avancĂ© : envoy prend en charge des fonctionnalitĂ©s avancĂ©es d'Ă©quilibrage de charge, y compris les tentatives automatiques, le circuit breaker, la limitation de dĂ©bit globale, le shadowing des requĂȘtes, l'Ă©quilibrage de charge locale par zone, etc.
  • API pour la gestion de configuration : envoy fournit une API robuste pour la gestion dynamique de sa configuration.
  • ObservabilitĂ© : observabilitĂ© approfondie du trafic L7, support intĂ©grĂ© pour le traçage distribuĂ© et observabilitĂ© pour MongoDB, DynamoDB et de nombreuses autres applications.

Étape 1 – Exemple de configuration NGINX

Ce scénario utilise un fichier créé spécialement nginx.conf, basé sur un exemple complet de NGINX Wiki. Vous pouvez voir la configuration dans l'éditeur en ouvrant nginx.conf

la configuration source de NGINX.

utilisateur www www;
pid /var/run/nginx.pid;
worker_processes 2;

events {
  worker_connections   2000;
}

http {
  gzip on;
  gzip_min_length  1100;
  gzip_buffers     4 8k;
  gzip_types       text/plain;

  log_format main      '$remote_addr - $remote_user [$time_local]  '
    '"$request" $status $bytes_sent '
    '"$http_referer" "$http_user_agent" '
    '"$gzip_ratio"';

  log_format download  '$remote_addr - $remote_user [$time_local]  '
    '"$request" $status $bytes_sent '
    '"$http_referer" "$http_user_agent" '
    '"$http_range" "$sent_http_content_range"';

  upstream targetCluster {
    172.18.0.3:80;
    172.18.0.4:80;
  }

  server {
    listen        8080;
    server_name   one.example.com  www.one.example.com;

    access_log   /var/log/nginx.access_log  main;
    error_log  /var/log/nginx.error_log  info;

    location / {
      proxy_pass         http://targetCluster/;
      proxy_redirect     off;

      proxy_set_header   Host             $host;
      proxy_set_header   X-Real-IP        $remote_addr;
    }
  }
}

Les configurations NGINX comportent généralement trois éléments clés :

  1. La configuration du serveur NGINX, la structure des journaux et la fonctionnalité Gzip. Cela est défini globalement dans tous les cas.
  2. Configuration de NGINX pour recevoir des requĂȘtes sur l'hĂŽte one.example.com sur le port 8080.
  3. Configuration de l'emplacement cible, comment traiter le trafic pour différentes parties de l'URL.

Toute la configuration ne sera pas appliquée au Proxy Envoy, et vous n'aurez pas besoin de configurer certains paramÚtres. Le Proxy Envoy a quatre types clés, qui soutiennent l'infrastructure de base proposée par NGINX. Le noyau est :

  • Écouteurs : Ils dĂ©terminent comment le Proxy Envoy reçoit les demandes entrantes. Actuellement, le Proxy Envoy ne prend en charge que les Ă©couteurs basĂ©s sur TCP. Une fois la connexion Ă©tablie, elle est transmise Ă  un ensemble de filtres pour traitement.
  • Filtres : Ils font partie de l'architecture de pipeline, qui peut traiter les donnĂ©es entrantes et sortantes. Cette fonctionnalitĂ© comprend des filtres comme Gzip, qui compresse les donnĂ©es avant de les envoyer au client.
  • Routeurs : Ils redirigent le trafic vers la destination requise, dĂ©finie comme un cluster.
  • Clusters : Ils dĂ©finissent le point final pour le trafic et les paramĂštres de configuration.

Nous allons utiliser ces quatre composants pour créer la configuration du Proxy Envoy afin de correspondre à une configuration NGINX donnée. L'objectif d'Envoy est de travailler avec l'API et des configurations dynamiques. Dans ce cas, la configuration de base utilisera des paramÚtres statiques, fixes issus de NGINX.

Étape 2 - Configuration NGINX

PremiĂšre partie nginx.conf dĂ©finit certains composants internes de NGINX qui doivent ĂȘtre configurĂ©s.

Worker Connections (Connexions de Travail)

La configuration ci-dessous définit le nombre de processus de travail et de connexions. Cela indique comment NGINX va évoluer pour répondre à la demande.

worker_processes  2;

events {
  worker_connections   2000;
}

Envoy Proxy gÚre différemment les processus de travail et les connexions.

Envoy crée un flux de travail pour chaque thread matériel dans le systÚme. Chaque flux de travail exécute une boucle d'événements non bloquante qui est responsable de

  1. L'écoute de chaque auditeur (listener)
  2. L'acceptation de nouvelles connexions
  3. La création d'un ensemble de filtres pour la connexion
  4. Le traitement de toutes les opérations d'entrée/sortie pendant la durée de vie de la connexion.

Tout traitement ultérieur de la connexion est entiÚrement géré dans le flux de travail, y compris tout comportement de redirection.

Pour chaque flux de travail dans Envoy, il existe une connexion dans le pool. Ainsi, les pools de connexions HTTP/2 Ă©tablissent une seule connexion pour chaque hĂŽte externe Ă  la fois ; avec quatre flux de travail, il y aura quatre connexions HTTP/2 pour chaque hĂŽte externe en Ă©tat stable. En gardant tout dans un seul flux de travail, presque tout le code peut ĂȘtre Ă©crit sans blocages, comme s'il Ă©tait Ă  thread unique. Si trop de flux de travail sont allouĂ©s, cela peut entraĂźner une utilisation inefficace de la mĂ©moire, la crĂ©ation d'un grand nombre de connexions inactives et une diminution du nombre de retours de connexion dans le pool.

Pour plus d'informations, visitez Blog d'Envoy Proxy.

Configuration HTTP

Le bloc de configuration NGINX suivant définit les paramÚtres HTTP, tels que :

  • Quels types mime sont pris en charge
  • Les dĂ©lais d'attente par dĂ©faut
  • Configuration de Gzip

Vous pouvez configurer ces aspects Ă  l'aide de filtres dans Envoy Proxy, ce que nous discuterons plus tard.

Étape 3 — Configuration du serveur

Dans le bloc de configuration HTTP, la configuration NGINX indique d'écouter le port 8080 et de répondre aux demandes entrantes pour les domaines one.example.com et www.one.example.com.

 server {
    listen        8080;
    server_name   one.example.com  www.one.example.com;

À l'intĂ©rieur d'Envoy, cela est gĂ©rĂ© par des Auditeurs.

Auditeurs d'Envoy

L'aspect le plus important pour commencer à travailler avec Envoy Proxy est la définition des auditeurs. Vous devez créer un fichier de configuration qui décrit comment vous souhaitez lancer une instance d'Envoy.

Le fragment ci-dessous crĂ©era un nouvel auditeur et le liera au port 8080. La configuration indique Ă  Envoy Proxy quels ports il doit Ă©couter pour les requĂȘtes entrantes.

Envoy Proxy utilise la notation YAML pour sa configuration. Pour découvrir cette notation, consultez ici. le lien.

Copy to Editorstatic_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 8080 }

Aucun besoin de définir server_name, car les filtres d'Envoy Proxy s'en occuperont.

Étape 4 — Configuration de l'emplacement

Lorsque la requĂȘte arrive dans NGINX, le bloc d'emplacement dĂ©termine comment traiter et oĂč diriger le trafic. Dans le fragment suivant, tout le trafic vers le site est transfĂ©rĂ© au cluster upstream (remarque du traducteur : l'upstream est gĂ©nĂ©ralement constituĂ© de serveurs d'applications) nommĂ© targetCluster. Le cluster upstream dĂ©finit les nƓuds qui traitent la requĂȘte. Nous aborderons cela Ă  l'Ă©tape suivante.

location / {
    proxy_pass         http://targetCluster/;
    proxy_redirect     off;

    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
}

Dans Envoy, cela est géré par les filtres.

Filtres Envoy

Pour la configuration statique, les filtres dĂ©terminent comment traiter les requĂȘtes entrantes. Dans ce cas, nous configurons des filtres qui correspondent Ă  server_names de l'Ă©tape prĂ©cĂ©dente. Lorsque des requĂȘtes entrantes correspondant Ă  certains domaines et routes arrivent, le trafic est dirigĂ© vers le cluster. C'est l'Ă©quivalent de la configuration montante de NGINX.

Copy to Editor    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        config:
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains:
                - "one.example.com"
                - "www.one.example.com"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: targetCluster
          http_filters:
          - name: envoy.router

Nom envoy.http_connection_manager est un filtre intégré dans Envoy Proxy. D'autres filtres incluent Redis, Mongo, TCP. Vous pouvez trouver la liste complÚte dans documentation.

Pour plus d'informations sur d'autres politiques d'équilibrage de charge, visitez La documentation d'Envoy.

Étape 5 — Configuration du Proxy et de l'Upstream

Dans NGINX, la configuration upstream définit un ensemble de serveurs cibles qui traiteront le trafic. Dans ce cas, deux clusters ont été assignés.

  upstream targetCluster {
    172.18.0.3:80;
    172.18.0.4:80;
  }

Dans Envoy, cela est géré par des clusters.

Clusters Envoy

L'équivalent upstream est défini comme des clusters. Dans ce cas, des hÎtes ont été définis pour gérer le trafic. La méthode d'accÚs aux hÎtes, comme le temps d'attente, est définie comme la configuration du cluster. Cela permet de contrÎler plus précisément la granularité d'aspects tels que le temps d'attente et l'équilibrage de charge.

Copy to Editor  clusters:
  - name: targetCluster
    connect_timeout: 0.25s
    type: STRICT_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    hosts: [
      { socket_address: { address: 172.18.0.3, port_value: 80 }},
      { socket_address: { address: 172.18.0.4, port_value: 80 }}
    ]

Lors de l'utilisation de la dĂ©tection de services STRICT_DNS Envoy rĂ©soudra en continu et de maniĂšre asynchrone les cibles DNS spĂ©cifiĂ©es. Chaque adresse IP retournĂ©e par la rĂ©solution DNS sera considĂ©rĂ©e comme un hĂŽte explicite dans le cluster ascendant. Cela signifie que si la requĂȘte retourne deux adresses IP, Envoy supposera qu'il y a deux hĂŽtes dans le cluster, et les deux devront ĂȘtre Ă©quilibrĂ©s en charge. Si un hĂŽte est retirĂ© des rĂ©sultats, Envoy suppose qu'il n'existe plus et va extraire le trafic de tout pool de connexions existant.

Pour plus d'informations, voir La documentation du proxy Envoy.

Étape 6 — AccĂ©der aux journaux et aux erreurs

La configuration finale — enregistrement. Au lieu de transmettre les journaux d'erreurs sur le disque, Envoy Proxy utilise une approche cloud. Tous les journaux d'applications sont redirigĂ©s vers stdout et stderr.

Lorsque les utilisateurs effectuent une requĂȘte, les journaux d'accĂšs sont facultatifs et dĂ©sactivĂ©s par dĂ©faut. Pour activer les journaux d'accĂšs pour les requĂȘtes HTTP, activez la configuration access_log pour le gestionnaire de connexions HTTP. Le chemin peut ĂȘtre soit un pĂ©riphĂ©rique, comme stdout, soit un fichier sur le disque, en fonction de vos exigences.

La configuration suivante redirigera tous les journaux d'accĂšs vers stdout (note du traducteur — stdout est nĂ©cessaire pour utiliser envoy Ă  l'intĂ©rieur de docker. Si utilisĂ© sans docker, remplacez /dev/stdout par le chemin vers un fichier journal standard). Copiez ce segment dans la section de configuration pour le gestionnaire de connexions :

Copy to Clipboardaccess_log:
- name: envoy.file_access_log
  config:
    path: "\/dev\/stdout"

Les résultats devraient ressembler à ceci :

      - name: envoy.http_connection_manager
        config:
          codec_type: auto
          stat_prefix: ingress_http
          access_log:
          - name: envoy.file_access_log
            config:
              path: "\/dev\/stdout"
          route_config:

Par dĂ©faut, Envoy a une chaĂźne de format qui inclut les dĂ©tails de la requĂȘte HTTP :

[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"n

Le résultat de cette ligne de format :

[2018-11-23T04:51:00.281Z] "GET / HTTP/1.1" 200 - 0 58 4 1 "-" "curl/7.47.0" "f21ebd42-6770-4aa5-88d4-e56118165a7d" "one.example.com" "172.18.0.4:80"

Le contenu de la sortie peut ĂȘtre configurĂ© en dĂ©finissant le champ de format. Par exemple :

access_log:
- name: envoy.file_access_log
  config:
    path: "/dev/stdout"
    format: "[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"n"

La ligne de journal peut Ă©galement ĂȘtre produite au format JSON en dĂ©finissant le champ json_format. Par exemple :

access_log:
- name: envoy.file_access_log
  config:
    path: "/dev/stdout"
    json_format: {"protocol": "%PROTOCOL%", "duration": "%DURATION%", "request_method": "%REQ(:METHOD)%"}

Pour plus d'informations sur la méthode de journalisation d'Envoy, visitez

https://www.envoyproxy.io/docs/envoy/latest/configuration/access_log#config-access-log-format-dictionaries

La journalisation n'est pas le seul moyen d'obtenir une vue d'ensemble du fonctionnement d'Envoy Proxy. Des capacités avancées de traçage et de métriques y sont intégrées. Vous pouvez en savoir plus dans la documentation de traçage ou via Le scénario de traçage interactif.

Étape 7 — DĂ©marrage

Vous avez maintenant traduit la configuration de NGINX vers Envoy Proxy. La derniÚre étape consiste à lancer une instance d'Envoy Proxy pour le tester.

Démarrer en tant qu'utilisateur

En haut de la configuration NGINX, la ligne user www www; indique que NGINX doit ĂȘtre exĂ©cutĂ© en tant qu'utilisateur Ă  faibles privilĂšges pour des raisons de sĂ©curitĂ©.

Envoy Proxy adopte une approche cloud pour gérer qui possÚde le processus. Lorsque nous exécutons Envoy Proxy via un conteneur, nous pouvons spécifier un utilisateur à faibles privilÚges.

Démarrer Envoy Proxy

La commande ci-dessous exécutera Envoy Proxy via un conteneur Docker sur l'hÎte. Cette commande permet à Envoy d'écouter les demandes entrantes sur le port 80. Cependant, comme indiqué dans la configuration de l'auditeur, Envoy Proxy écoute le trafic entrant sur le port 8080. Cela permet au processus de s'exécuter en tant qu'utilisateur à faibles privilÚges.

docker run --name proxy1 -p 80:8080 --user 1000:1000 -v /root/envoy.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy

Test

Avec le proxy en fonctionnement, des tests peuvent maintenant ĂȘtre effectuĂ©s et traitĂ©s. La commande cURL suivante envoie une demande avec l'en-tĂȘte d'hĂŽte dĂ©fini dans la configuration du proxy.

curl -H "Host: one.example.com" localhost -i

Une demande HTTP entraĂźnera une erreur 503. Cela est dĂ» au fait que les connexions montantes ne fonctionnent pas et qu'elles sont indisponibles. Ainsi, Envoy Proxy n'a pas de destinataires disponibles pour la requĂȘte. La commande suivante lancera une sĂ©rie de services HTTP qui correspondent Ă  la configuration dĂ©finie pour Envoy.

docker run -d katacoda/docker-http-server; docker run -d katacoda/docker-http-server;

Avec les services disponibles, Envoy peut successfully proxy le trafic vers sa destination.

curl -H "Host: one.example.com" localhost -i

Vous devriez voir une rĂ©ponse indiquant quel conteneur Docker a traitĂ© la requĂȘte. Dans les journaux d'Envoy Proxy, vous devriez Ă©galement voir la ligne d'accĂšs imprimĂ©e.

En-tĂȘtes supplĂ©mentaires de la rĂ©ponse HTTP

Dans les en-tĂȘtes de la rĂ©ponse de la requĂȘte valide, vous verrez des en-tĂȘtes HTTP supplĂ©mentaires. L'en-tĂȘte affiche le temps que l'hĂŽte en amont a mis Ă  traiter la requĂȘte. Cela s'exprime en millisecondes. C'est utile si le client veut dĂ©terminer le temps de service par rapport Ă  la latence rĂ©seau.

x-envoy-upstream-service-time: 0
server: envoy

Configuration finale

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 8080 }
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        config:
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains:
                - "one.example.com"
                - "www.one.example.com"
              routes:
              - match:
                  prefix: "\/"
                route:
                  cluster: targetCluster
          http_filters:
          - name: envoy.router
          clusters:
  - name: targetCluster
    connect_timeout: 0.25s
    type: STRICT_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    hosts: [
      { socket_address: { address: 172.18.0.3, port_value: 80 }},
      { socket_address: { address: 172.18.0.4, port_value: 80 }}
    ]

admin:
  access_log_path: \/tmp\/admin_access.log
  address:
    socket_address: { address: 0.0.0.0, port_value: 9090 }

Informations supplémentaires du traducteur

Vous pouvez trouver les instructions d'installation d'Envoy Proxy sur le site https://www.getenvoy.io/

Par défaut, le rpm n'inclut pas de configuration de service systemd.

Ajoutez la configuration de service systemd \/etc\/systemd\/system\/envoy.service :

[Unit]
Description=Envoy Proxy
Documentation=https:\/\/www.envoyproxy.io\/\nAfter=network-online.target
Requires=envoy-auth-server.service
Wants=nginx.service

[Service]
User=root
Restart=on-failure
ExecStart=\/usr\/bin\/envoy --config-path \/etc\/envoy\/config.yaml
[Install]
WantedBy=multi-user.target

Vous devez créer un répertoire \/etc\/envoy\/ et y placer le fichier de configuration config.yaml.

Il y a un chat Telegram sur envoy proxy : https://t.me/envoyproxy_ru

Envoy Proxy ne prend pas en charge la distribution de contenu statique. Donc, qui peut voter pour cette fonctionnalité : https://github.com/envoyproxy/envoy/issues/378

Seuls les utilisateurs enregistrés peuvent participer au sondage. Connectez-vous, s'il vous plaßt.

Ce post vous a-t-il incité à installer et tester envoy proxy ?

  • oui

  • non

75 utilisateurs ont voté. 18 utilisateurs se sont abstenus.

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster