Velkommen! Denne kort artikel besvarer spørgsmålene: "hvad er envoy?", "hvad er det til?" og "hvordan kommer man i gang?".
Hvad er det
Envoy er en L4-L7 load balancer skrevet i C++, designet til høj ydeevne og tilgængelighed. På den ene side kan det ses som en slags analog til nginx og haproxy, der kan måle sig med dem hvad angår ydeevne. På den anden side er det mere rettet mod mikrotjenestearkitektur og har funktionalitet der ikke er ringere end load balancere skrevet i java og go, som zuul eller traefik.
Sammenligningstabel for haproxy/nginx/envoy; den hævder ikke at være absolut sand, men giver et overordnet billede.
nginx
haproxy
envoy
traefik
stjerner på github
11.2k/mirror
1.1k/mirror
12.4k
27.6k
skrevet i
C
C
C++
go
API
nej
kun socket/push
dataplane/pull
pull
aktiv sundhedstjek
nej
ja
ja
ja
Open tracing
ekstern plugin
nej
ja
ja
JWT
ekstern plugin
nej
ja
nej
.sql
Lua/C
Lua/C
Lua/C++
nej
Hvorfor
Det er et ungt projekt, der mangler mange ting, og nogle er i tidlig alfa. Men envoy, blandt andet takket være dets ungdom, udvikler det sig hurtigt og har allerede mange interessante funktioner: dynamisk konfiguration, mange færdige filtre, og et enkelt interface til at skrive sine egne filtre.
Dette medfører anvendelsesområder, men for at begynde, her er 2 antipatterns:
- At servere statisk indhold.
Punktet er, at der i øjeblikket ikke er envoy understøttelse af caching. Folkene hos google forsøger at . Ideen var at implementere i en enkelt løsning alt det komplekse (zoo af headers) i overensstemmelse med RFC, og for specifikke implementeringer at lave et interface. Men indtil videre er det ikke engang alfa, arkitekturen er under diskussion, envoy det er åbent (mens jeg skrev artiklen blev PR mergeret, men dette punkt er stadig aktuelt). Indtil da anbefales det at bruge nginx til statisk indhold.
Statisk konfiguration.
- Den kan bruges, men
den blev ikke skabt til dette. Mulighederne i den statiske konfiguration vil ikke blive afsløret. Der er mange aspekter: envoy Når du redigerer konfigurationen i yaml, vil du lave fejl, bande udviklerne for overflødighed, og tænke at konfigurationer fra nginx/haproxy, selvom de er mindre strukturerede, er mere præcise. Det er essensen. Konfigurationen for Nginx og Haproxy blev designet til manuel redigering, mens
for Envoy blev lavet til generering fra kode. Hele konfigurationen er beskrevet i envoy , hvilket gør det langt sværere at lave fejl ved at generere den fra proto-filer. Canary-scenarier, b/g-udrulning og meget andet implementeres kun korrekt i dynamisk konfiguration. Jeg siger ikke, at det ikke kan gøres i statisk, vi gør alle disse ting. Men for at gøre det, skal man omgive sig med løsninger, i enhver load balancer, i
inklusive. envoy Opgaver, hvor Envoy er uundgåelig:
Задачи в которых Envoy незаменим:
- Lastbalancering af trafik i komplekse og dynamiske systemer. Dette inkluderer service mesh, men det er ikke kun det.
- Behovet for funktionalitet i distribueret tracing, kompleks autorisation eller andet, som findes i envoy out-of-the-box eller nemt implementeres, mens nginx/haproxy kræver lua og tvivlsomme plugins.
Begge dele skal sikre høj ydeevne, hvis det er nødvendigt.
Hvordan fungerer det
Envoy distribueres kun som docker-billede i binære filer. Billedet har allerede et eksempel på statisk konfiguration. Men det er kun interessant for at forstå strukturen.
envoy.yaml statisk konfiguration
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
# Kommentar på den følgende linje for at teste på v6-netværk
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.comDynamisk konfiguration
Hvilket problem prøver vi at løse? Man kan ikke bare genstarte konfigurationen af balanceringssystemet under belastning, der vil opstå "små" problemer:
- Validering af konfiguration.
Konfigurationen kan være stor, meget stor, og hvis vi genstarter hele konfigurationen på én gang, øges chancerne for fejl.
- Langvarige forbindelser.
Ved initialisering af en ny lytter skal man sørge for de forbindelser, der kører på den gamle, og hvis ændringerne sker ofte og der er langvarige forbindelser, må man finde et kompromis. Hej, kubernetes ingress på nginx.
- Aktive health checks.
Hvis vi har aktive health checks, skal vi genkontrollere dem alle på den nye konfiguration, før vi sender trafik. Hvis der er mange upstreams, tager det tid. Hej, haproxy.
Hvordan det løses i envoy, ved dynamisk at indlæse konfigurationen, ved hjælp af pool-modellen, kan den opdeles i separate dele og den del, der ikke er ændret, behøver ikke at blive geninitialiseret. For eksempel er en lytter, som er dyr at geninitialisere, og den ændres sjældent.
Konfiguration envoy (fra den ovenstående fil) har følgende enheder:
- listener — en lytter, der hænger på en bestemt ip/port
- virtual host — en virtuel vært efter domænenavn
- rute — balancing rule
- cluster — en gruppe upstreams med balancing-parametre
- endpoint — adressen til upstream-instansen
Hver af disse enheder plus nogle andre kan udfyldes dynamisk; i konfigurationen angives adressen til tjenesten, hvorfra konfigurationen vil blive hentet. Tjenesten kan være REST eller gRPC, det er at foretrække at bruge gRPC.
Tjenesterne kaldes henholdsvis: LDS, VHDS, RDS, CDS og EDS. Man kan kombinere statisk og dynamisk konfiguration, med begrænsningen at den dynamiske ressource ikke kan angives i den statiske.
Til de fleste opgaver er det tilstrækkeligt at implementere de sidste tre tjenester, de kaldes ADS (Aggregated Discovery Service), for og go har en klar implementation af gRPC dataplane, hvor det kun er nødvendigt at udfylde objekterne fra sin egen kilde.
Konfigurationen får følgende udseende:
envoy.yaml dynamisk konfiguration
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: 6565Ved opstart envoy med denne konfiguration vil den oprette forbindelse til control-plane og forsøge at anmode om konfigurationen af RDS, CDS og EDS. Hvordan interaktionen finder sted er beskrevet .
Kort sagt, envoy den sender en anmodning, med angivelse af den type ressource, versionen og nodens parametre. Som svar modtager den ressourcen og versionen; hvis versionen på control-plane ikke er ændret, svarer den ikke.
Der er 4 interaktionsmuligheder:
- En gRPC strøm for alle typer ressourcer, der sender den komplette tilstand af ressourcen.
- Separate streams, full state.
- Single stream, incremental state.
- Separate streams, incremental state.
Incremental xDS reduces traffic between the control plane and envoy, which is relevant for large configurations. However, it complicates interactions, as the request transmits a list of resources for subscription and unsubscription.
In our example, ADS is used — a single stream for RDS, CDS, EDS, and in non-incremental mode. To enable incremental mode, you need to specify api_type: DELTA_GRPC
Since the request includes node parameters, we can send different resources to different instances on the control plane envoy, making it convenient for building a service mesh.
Warmup
På envoy at startup or when receiving a new configuration from the control plane, the resource warmup process starts. It is split into listener warmup and cluster warmup. The first is initiated during changes in RDS/LDS, and the second during CDS/EDS. This means that if only upstreams change, the listener is not recreated.
During the warmup process, dependent resources are expected from the control plane within a timeout. If the timeout expires, the initialization will not be successful, and the new listener will not start listening on the port.
Initialization order: EDS, CDS, active health check, RDS, LDS. With active health checks enabled, traffic will only go to the upstream after one successful health check.
If the listener was recreated, the old one transitions to the DRAIN state and will be removed after all connections are closed or the timeout expires --drain-time-s, by default 10 minutes.
Fortsættes.
Kilde: habr.com
