Bonjour Habr! J'attire votre attention sur une traduction du message :
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
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 :
- Configuration du serveur NGINX, de la structure des journaux et de la fonctionnalité Gzip. Ceci est défini globalement dans tous les cas.
- Configurer NGINX pour accepter les demandes adressées à l'hôte un.exemple.com sur le port 8080.
- 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
- A l'écoute de chaque auditeur
- Accepter de nouvelles connexions
- Création d'un ensemble de filtres pour une connexion
- 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
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
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
Pour plus d'informations sur les autres politiques d'équilibrage de charge, visitez
É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
É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
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
É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.
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 :
Envoy Proxy ne prend pas en charge la diffusion de contenu statique. Par conséquent, qui peut voter pour la fonctionnalité :
Seuls les utilisateurs enregistrés peuvent participer à l'enquête.
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