Salutations! Il s'agit d'un court article qui répond aux questions : « qu'est-ce qu'un envoyé ? », « pourquoi est-il nécessaire ? et "par où commencer ?".
Qu'est ce que c'est
Envoy est un équilibreur L4-L7 écrit en C++, axé sur les hautes performances et la disponibilité. D'une part, il s'agit en quelque sorte d'un analogue de nginx et haproxy, dont les performances sont comparables. D'un autre côté, il est plus orienté vers l'architecture des microservices et n'a pas de fonctionnalités pires que les équilibreurs Java et Go, comme zuul ou traefik.
Tableau de comparaison haproxy/nginx/envoy, il ne prétend pas être la vérité absolue, mais donne une image générale.
nginx
happroxy
envoyé
Traefik
étoiles sur github
11.2k/miroir
1.1k/miroir
12.4K
27.6K
écrit en
C
C
C + +
go
API
aucun
prise uniquement/poussoir
plan de données/pull
tirer
bilan de santé actif
aucun
oui
oui
oui
Traçage ouvert
plugin externe
aucun
oui
oui
JWT
plugin externe
aucun
oui
aucun
extension
Lua/C
Lua/C
Lua/C++
aucun
Pourquoi
C'est un projet jeune, il manque beaucoup de choses, certaines en début d'alpha. Mais envoyé, également en raison de sa jeunesse, se développe rapidement et possède déjà de nombreuses fonctionnalités intéressantes : une configuration dynamique, de nombreux filtres prêts à l'emploi, une interface simple pour écrire vos propres filtres.
Les domaines d'application en découlent, mais il y a d'abord 2 anti-modèles :
- Recul statique.
Le fait est qu'à l'heure actuelle envoyé pas de prise en charge de la mise en cache. Les gars de Google essaient ça
Pour l'instant, utilisez nginx pour la statique.
- Configuration statique.
Vous pouvez l'utiliser, mais envoyé Ce n'est pas pour cela qu'il a été créé. Les fonctionnalités dans une configuration statique ne seront pas exposées. Il y a plusieurs moments :
Lors de l'édition de la configuration dans yaml, vous vous tromperez, gronderez les développeurs pour leur verbosité et penserez que les configurations nginx/haproxy, bien que moins structurées, sont plus concises. C'est le but. La configuration de Nginx et Haproxy a été créée pour être éditée à la main, et envoyé pour la génération à partir du code. L'ensemble de la configuration est décrit dans
Les scénarios de déploiement Canary, b/g et bien plus encore ne sont normalement implémentés que dans une configuration dynamique. Je ne dis pas que cela ne peut pas se faire de manière statique, nous le faisons tous. Mais pour cela, vous devez mettre des béquilles, dans n'importe lequel des équilibreurs, dans envoyé y compris
Tâches pour lesquelles Envoy est indispensable :
- Équilibrage du trafic dans des systèmes complexes et dynamiques. Cela inclut le maillage de services, mais ce n’est pas nécessairement le seul.
- Le besoin d'une fonctionnalité de traçage distribuée, d'une autorisation complexe ou d'autres fonctionnalités disponibles dans envoyé prêt à l'emploi ou facilement implémenté, mais dans nginx/haproxy, vous devez être entouré de plugins Lua et douteux.
Les deux, si nécessaire, offrent des performances élevées.
Comment ça marche
Envoy est distribué sous forme de binaires uniquement sous forme d'image Docker. L'image contient déjà un exemple de configuration statique. Mais cela ne nous intéresse que pour en comprendre la structure.
configuration statique d'envoy.yaml
static_resources:
listeners:
- name: listener_0
address:
socket_address:
protocol: TCP
address: 0.0.0.0
port_value: 10000
filter_chains:
- filters:
- name: envoy.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
host_rewrite: www.google.com
cluster: service_google
http_filters:
- name: envoy.router
clusters:
- name: service_google
connect_timeout: 0.25s
type: LOGICAL_DNS
# Comment out the following line to test on v6 networks
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service_google
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: www.google.com
port_value: 443
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.api.v2.auth.UpstreamTlsContext
sni: www.google.com
Configuration dynamique
À quel problème cherchons-nous une solution ? Vous ne pouvez pas simplement recharger la configuration de l’équilibreur de charge sous charge ; de « petits » problèmes surgiront :
- Validation des configurations.
La configuration peut être volumineuse, elle peut être très volumineuse, si on la surcharge d'un coup, les risques d'erreur quelque part augmentent.
- Des connexions durables.
Lors de l'initialisation d'un nouvel écouteur, vous devez prendre soin des connexions exécutées sur l'ancien ; si des changements se produisent fréquemment et qu'il existe des connexions de longue durée, vous devrez rechercher un compromis. Bonjour, entrée Kubernetes sur nginx.
- Bilans de santé actifs.
Si nous avons des contrôles de santé actifs, nous devons tous les revérifier dans la nouvelle configuration avant d'envoyer du trafic. S’il y a beaucoup d’amont, cela prend du temps. Bonjour haproxy.
Comment cela est-il résolu dans envoyéEn chargeant la config dynamiquement, selon le modèle du pool, vous pouvez la diviser en parties distinctes et ne pas réinitialiser la partie qui n'a pas changé. Par exemple, un écouteur, dont la réinitialisation est coûteuse et qui change rarement.
Configuration envoyé (à partir du fichier ci-dessus) a les entités suivantes :
- auditeur - écouteur suspendu à une adresse IP/port spécifique
- hôte virtuel - hôte virtuel par nom de domaine
- route - règle d'équilibrage
- grappe — un groupe d'amonts avec des paramètres d'équilibrage
- point final — adresse de l'instance en amont
Chacune de ces entités ainsi que quelques autres peuvent être renseignées dynamiquement ; pour cela, la configuration précise l'adresse du service d'où la configuration sera reçue. Le service peut être REST ou gRPC, gRPC est préférable.
Les services sont nommés respectivement : LDS, VHDS, RDS, CDS et EDS. Vous pouvez combiner une configuration statique et dynamique, avec la limitation qu'une ressource dynamique ne peut pas être spécifiée dans une ressource statique.
Pour la plupart des tâches, il suffit de mettre en œuvre les trois derniers services, ils sont appelés ADS (Aggregated Discovery Service), par exemple
La configuration prend la forme suivante :
configuration dynamique envoy.yaml
dynamic_resources:
ads_config:
api_type: GRPC
grpc_services:
envoy_grpc:
cluster_name: xds_clr
cds_config:
ads: {}
static_resources:
listeners:
- name: listener_0
address:
socket_address:
protocol: TCP
address: 0.0.0.0
port_value: 10000
filter_chains:
- filters:
- name: envoy.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
stat_prefix: ingress_http
rds:
route_config_name: local_route
config_source:
ads: {}
http_filters:
- name: envoy.router
clusters:
- name: xds_clr
connect_timeout: 0.25s
type: LOGICAL_DNS
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: xds_clr
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: xds
port_value: 6565
Lorsque vous exécutez envoyé avec cette configuration, il se connectera au plan de contrôle et tentera de demander la configuration RDS, CDS et EDS. La manière dont se produit le processus d'interaction est décrite
En bref, envoyé envoie une requête indiquant le type de ressource demandée, la version et les paramètres du nœud. En réponse, il reçoit une ressource et une version ; si la version sur le plan de contrôle n'a pas changé, il ne répond pas.
Il existe 4 options d'interaction :
- Un flux gRPC pour tous les types de ressources, l'état complet de la ressource est envoyé.
- Flux séparés, état complet.
- Un flux, état incrémentiel.
- Flux séparés, état incrémentiel.
xDS incrémentiel vous permet de réduire le trafic entre le plan de contrôle et envoyé, ceci est pertinent pour les grandes configurations. Mais cela complique l'interaction : la demande contient une liste de ressources de désabonnement et d'abonnement.
Notre exemple utilise ADS - un flux pour RDS, CDS, EDS et le mode non incrémental. Pour activer le mode incrémentiel, vous devez spécifier api_type: DELTA_GRPC
Puisque la requête contient des paramètres de nœud, nous pouvons envoyer différentes ressources au plan de contrôle pour différentes instances envoyé, c'est pratique pour créer un maillage de services.
Réchauffer
Sur envoyé au démarrage ou lors de la réception d'une nouvelle configuration du plan de contrôle, le processus de préchauffage des ressources est lancé. Il est divisé en échauffement de l’auditeur et en échauffement du cluster. Le premier est lancé lorsqu'il y a des changements dans RDS/LDS, le second lorsqu'il y a des changements dans CDS/EDS. Cela signifie que si seuls les éléments en amont changent, l'écouteur n'est pas recréé.
Pendant le processus de préchauffage, des ressources dépendantes sont attendues du plan de contrôle pendant le délai d'attente. Si le délai d'attente se produit, l'initialisation échouera et le nouvel écouteur ne commencera pas à écouter sur le port.
Ordre d'initialisation : EDS, CDS, bilan de santé actif, RDS, LDS. Lorsque les contrôles de santé actifs sont activés, le trafic remontera uniquement après un contrôle de santé réussi.
Si l'écouteur a été recréé, l'ancien passe à l'état DRAIN et sera supprimé une fois toutes les connexions fermées ou le délai d'attente expiré. --drain-time-s
, par défaut 10 minutes.
A suivre.
Source: habr.com