Migration de Nginx vers le proxy Envoy

Bonjour Habr! J'attire votre attention sur une traduction du message : Migration de Nginx vers le proxy Envoy.

Envoy est un serveur proxy distribué hautes performances (écrit en C++) conçu pour les services et applications individuels, c'est également un bus de communication et un « plan de données universel » conçu pour les grandes architectures de « maillage de services » de microservices. Lors de sa création, les solutions aux problèmes survenus lors du développement de serveurs tels que NGINX, HAProxy, les équilibreurs de charge matérielle et les équilibreurs de charge cloud ont été prises en compte. Envoy fonctionne aux côtés de chaque application et résume le réseau pour fournir des fonctionnalités communes quelle que soit la plate-forme. Lorsque tout le trafic de services d'une infrastructure transite par le maillage Envoy, il devient facile de visualiser les zones problématiques avec une observabilité cohérente, d'ajuster les performances globales et d'ajouter des fonctionnalités de base dans un emplacement spécifique.

opportunités

  • Architecture hors processus : envoy est un serveur autonome et performant qui occupe une petite quantité de RAM. Il fonctionne en conjonction avec n’importe quel langage ou framework d’application.
  • Prise en charge http/2 et grpc : envoy dispose d'une prise en charge http/2 et grpc de première classe pour les connexions entrantes et sortantes. Il s'agit d'un proxy transparent de http/1.1 vers http/2.
  • Équilibrage de charge avancé : envoy prend en charge des fonctionnalités avancées d'équilibrage de charge, notamment les tentatives automatiques, la rupture de chaîne, la limitation de débit globale, l'observation des demandes, l'équilibrage de charge de zone locale, etc.
  • API de gestion de configuration : envoy fournit une API robuste pour gérer dynamiquement votre configuration.
  • Observabilité : observabilité approfondie du trafic L7, prise en charge native du traçage distribué et observabilité de mongodb, dynamodb et de nombreuses autres applications.

Étape 1 — Exemple de configuration NGINX

Ce script utilise un fichier spécialement conçu nginx.conf, basé sur l'exemple complet de Wiki NGINX. Vous pouvez visualiser la configuration dans l'éditeur en ouvrant nginx.conf

configuration des sources nginx

user  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. Configuration du serveur NGINX, de la structure des journaux et de la fonctionnalité Gzip. Ceci est défini globalement dans tous les cas.
  2. Configurer NGINX pour accepter les demandes adressées à l'hôte un.exemple.com sur le port 8080.
  3. Configuration de l'emplacement cible, comment gérer le trafic pour différentes parties de l'URL.

Toutes les configurations ne s'appliqueront pas à Envoy Proxy et vous n'avez pas besoin de configurer certains paramètres. Envoy Proxy a quatre types de clés, qui prennent en charge l'infrastructure de base proposée par NGINX. Le noyau est :

  • Les auditeurs: Ils déterminent comment Envoy Proxy accepte les demandes entrantes. Envoy Proxy ne prend actuellement 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 d’une architecture de pipeline capable de traiter les données entrantes et sortantes. Cette fonctionnalité inclut des filtres tels que Gzip, qui compresse les données avant de les envoyer au client.
  • Routeurs : Ils transfèrent le trafic vers la destination requise, définie comme un cluster.
  • Groupes: Ils définissent le point de terminaison pour le trafic et les paramètres de configuration.

Nous utiliserons ces quatre composants pour créer une configuration Envoy Proxy correspondant à une configuration NGINX spécifique. L'objectif d'Envoy est de travailler avec des API et une configuration dynamique. Dans ce cas, la configuration de base utilisera les paramètres statiques et codés en dur de NGINX.

Étape 2 - Configuration NGINX

La première partie nginx.conf définit certains composants internes de NGINX qui doivent être configurés.

Connexions des travailleurs

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

worker_processes  2;

events {
  worker_connections   2000;
}

Envoy Proxy gère les flux de travail et les connexions de différentes manières.

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

  1. A l'écoute de chaque auditeur
  2. Accepter de nouvelles connexions
  3. Création d'un ensemble de filtres pour une connexion
  4. Traitez toutes les opérations d’E/S pendant la durée de vie de la connexion.

Tous les autres traitements de connexion sont entièrement gérés dans le thread de travail, y compris tout comportement de transfert.

Pour chaque thread de travail dans Envoy, il existe un pool de connexions. Ainsi, les pools de connexions HTTP/2 n'établissent qu'une seule connexion par hôte externe à la fois. S'il y a quatre threads de travail, il y aura quatre connexions HTTP/2 par hôte externe dans un état stable. En gardant tout dans un seul thread de travail, presque tout le code peut être écrit sans blocage, comme s'il s'agissait d'un seul thread. Si plus de threads de travail sont alloués que nécessaire, cela peut entraîner un gaspillage de mémoire, créant un grand nombre de connexions inactives et réduisant le nombre de fois où les connexions sont renvoyées au pool.

Pour plus d'informations, visitez Blog 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
  • Délais d'expiration par défaut
  • Configuration Gzip

Vous pouvez personnaliser ces aspects à l'aide de filtres dans Envoy Proxy, dont nous parlerons plus tard.

Étape 3 - Configuration du serveur

Dans le bloc de configuration HTTP, la configuration NGINX précise d'écouter sur le port 8080 et de répondre aux requêtes entrantes pour les domaines un.exemple.com и www.one.example.com.

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

À l’intérieur d’Envoy, il est contrôlé par les auditeurs.

Envoyés auditeurs

L'aspect le plus important pour démarrer avec Envoy Proxy est de définir vos auditeurs. Vous devez créer un fichier de configuration qui décrit comment vous souhaitez exécuter l'instance Envoy.

L'extrait ci-dessous créera un nouvel écouteur et le liera au port 8080. La configuration indique à Envoy Proxy à quels ports il doit se lier pour les demandes entrantes.

Envoy Proxy utilise la notation YAML pour sa configuration. Pour une introduction à cette notation, regardez ici lien.

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

Pas besoin de définir nom du serveur, puisque les filtres Envoy Proxy géreront cela.

Étape 4 - Configuration de l'emplacement

Lorsqu'une requête arrive dans NGINX, le bloc de localisation détermine comment traiter et où acheminer le trafic. Dans le fragment suivant, tout le trafic vers le site est transféré vers un cluster en amont (note du traducteur : en amont est généralement un serveur d'applications) nommé clustercible. Le cluster en amont définit les nœuds qui doivent traiter la demande. Nous en discuterons à l’étape suivante.

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

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

Chez Envoy, Filters fait cela.

Filtres d'envoyé

Pour une configuration statique, les filtres déterminent comment traiter les demandes entrantes. Dans ce cas, nous définissons des filtres qui correspondent noms_serveurs à l'étape précédente. Lorsque des demandes entrantes correspondant à certains domaines et itinéraires arrivent, le trafic est acheminé vers le cluster. C'est l'équivalent d'une configuration ascendante 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

Pré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 sur documentation.

Pour plus d'informations sur les autres politiques d'équilibrage de charge, visitez Documentation de l'Envoyé.

Étape 5 - Configuration du proxy et en amont

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

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

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

Clusters d'envoyés

L'équivalent en amont est défini sous forme de clusters. Dans ce cas, les hôtes qui desserviront le trafic ont été identifiés. La manière dont les hôtes sont accessibles, comme les délais d'attente, est définie en tant que configuration de cluster. Cela permet un contrôle plus granulaire sur des aspects tels que la latence 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écouverte de services STRICT_DNS Envoy résoudra de manière continue et asynchrone les cibles DNS spécifiées. Chaque adresse IP renvoyée par le résultat DNS sera considérée comme un hôte explicite dans le cluster en amont. Cela signifie que si une requête renvoie deux adresses IP, Envoy supposera qu'il y a deux hôtes dans le cluster et que les deux doivent être équilibrés en charge. Si un hôte est supprimé du résultat, Envoy supposera qu'il n'existe plus et extraira le trafic de tous les pools de connexions existants.

Pour plus d'informations voir Documentation du proxy Envoy.

Étape 6 — Consigner l'accès et les erreurs

La configuration finale est l'inscription. Au lieu de transférer les journaux d'erreurs sur le disque, Envoy Proxy adopte une approche basée sur le cloud. Tous les journaux d'application sont sortis vers Stdout и stderr.

Lorsque les utilisateurs font une demande, 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 accès_log pour le gestionnaire de connexions HTTP. Le chemin peut être soit un périphérique tel que Stdout, ou un fichier sur disque, selon vos besoins.

La configuration suivante redirigera tous les journaux d'accès vers Stdout (note du traducteur - stdout est requis pour utiliser envoy dans docker. S'il est utilisé sans docker, remplacez /dev/stdout par le chemin d'accès à un fichier journal normal). Copiez l'extrait dans la section de configuration du 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 chaîne de format est :

[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 sortie peut être personnalisé 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 sortie 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éthodologie d'enregistrement 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'avoir un aperçu de l'utilisation d'Envoy Proxy. Il intègre des capacités avancées de traçage et de métriques. Vous pouvez en savoir plus sur documentation de traçage ou par Script de traçage interactif.

Étape 7 - Lancement

Vous avez maintenant migré votre configuration de NGINX vers Envoy Proxy. La dernière étape consiste à lancer une instance Envoy Proxy pour la tester.

Exécuter en tant qu'utilisateur

En haut de la ligne de configuration NGINX utilisateur wwwwww; spécifie d'exécuter NGINX en tant qu'utilisateur peu privilégié pour améliorer la sécurité.

Envoy Proxy adopte une approche basée sur le cloud pour gérer à qui appartient un processus. Lorsque nous exécutons Envoy Proxy via un conteneur, nous pouvons spécifier un utilisateur peu privilégié.

Lancement du proxy Envoy

La commande ci-dessous exécutera Envoy Proxy via un conteneur Docker sur l'hôte. Cette commande donne à Envoy la possibilité d'écouter les demandes entrantes sur le port 80. Cependant, comme spécifié dans la configuration de l'écouteur, Envoy Proxy écoute le trafic entrant sur le port 8080. Cela permet au processus de s'exécuter en tant qu'utilisateur peu privilégié.

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

Test

Une fois le proxy exécuté, des tests peuvent désormais être effectués et traités. La commande cURL suivante émet une requête avec l'en-tête d'hôte défini dans la configuration du proxy.

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

La requête HTTP entraînera une erreur 503. En effet, les connexions en amont ne fonctionnent pas et ne sont pas disponibles. Par conséquent, Envoy Proxy n’a aucune destination disponible pour la demande. La commande suivante démarrera 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;

Grâce aux services disponibles, Envoy peut réussir à proxyer 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 demande. Dans les journaux Envoy Proxy, vous devriez également voir une sortie de chaîne d'accès.

En-têtes de réponse HTTP supplémentaires

Vous verrez des en-têtes HTTP supplémentaires dans les en-têtes de réponse de la requête réelle. L'en-tête affiche le temps passé par l'hôte en amont à traiter la demande. Exprimé en millisecondes. Ceci est utile si le client souhaite déterminer le temps de service par rapport à la latence du 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 complémentaires du traducteur

Les instructions d'installation d'Envoy Proxy sont disponibles sur le site Web. https://www.getenvoy.io/

Par défaut, RPM n'a pas de configuration de service systemd.

Ajoutez la configuration du service systemd /etc/systemd/system/envoy.service :

[Unit]
Description=Envoy Proxy
Documentation=https://www.envoyproxy.io/
After=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 la configuration config.yaml.

Il existe une discussion par télégramme utilisant le proxy Envoy : https://t.me/envoyproxy_ru

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

Seuls les utilisateurs enregistrés peuvent participer à l'enquête. se connecters'il te plait.

Cet article vous a-t-il encouragé à installer et tester le proxy Envoy ?

  • oui

  • aucun

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

Source: habr.com

Ajouter un commentaire