Zdravím! Toto je krátky článok, ktorý odpovedá na otázky: " čo je envoy?", "na čo sa používa?" a "ako začať?".
Čo to je
Envoy je L4-L7 vyvažovač zaťaženia napísaný v C++, zameraný na vysoký výkon a dostupnosť. Z jednej strany je to akýsi ekvivalent nginx a haproxy, porovnateľný s nimi svojím výkonom. Na druhej strane, je viac zameraný na mikroservisnú architektúru a má funkčnosť, ktorá nie je horšia ako vyvažovače v jazykoch Java a Go, ako sú zuul alebo traefik.
Tabuľka porovnania haproxy/nginx/envoy, nepretenduje na absolútnu pravdu, ale poskytuje celkový obraz.
nginx
haproxy
envoy
traefik
hviezd na github
11.2k/mirror
1.1k/mirror
12.4k
27.6k
napísaný v
C
C
C++
go
API
nie
len socket/push
dataplane/pull
pull
aktívny healthcheck
nie
áno
áno
áno
Open tracing
externý plugin
nie
áno
áno
JWT
externý plugin
nie
áno
nie
Prípona
Lua/C
Lua/C
Lua/C++
nie
Prečo
Toto je mladý projekt, chýba mu mnoho vecí, niečo je v ranných alfa verziách. Ale envoy, vrátane mladej fázy, sa rýchlo vyvíja a už teraz má mnoho zaujímavých funkcií: dynamickú konfiguráciu, množstvo predpripravených filtrov, jednoduché rozhranie na písanie vlastných filtrov.
Z toho vyplývajú oblasti aplikácií, ale na začiatok 2 antipatterny:
- Podávanie statiky.
Faktom je, že v súčasnosti v envoy neexistuje podpora caching. Tím z Google sa snaží to . Myšlienka jednorazového implementovania v na envoy všetky nuansy (zoo hlavičiek) dodržiavania RFC, a pre konkrétne implementácie vytvoriť rozhranie. Ale zatiaľ to nie je ani alfa, architektúra je v diskusii, otvorený (kým som písal článok, PR bol zlúčený, ale tento bod je stále aktuálny).
A zatiaľ používajte na statické súbory nginx.
- Statická konfigurácia.
Môže sa používať, ale envoy nebol vytvorený na tento účel. Možnosti v statickej konfigurácii nebudú úplne využité. Mnoho aspektov:
Pri úprave konfigurácie v yaml sa môžete pomýliť, nadávať vývojárov za zdĺhavý popis a myslieť si, že konfigurácie nginx/haproxy, aj keď menej štruktúrované, sú stručnejšie. V tom je pointa. Konfigurácia Nginx a Haproxy bola navrhnutá na úpravy ručne, zatiaľ čo envoy bola navrhnutá na generovanie z kódu. Celá konfigurácia je popísaná v , generovanie podľa proto súborov je oveľa ťažšie na chyby.
Scenáre canary, b/g nasadenia a mnoho iného, sa normálne realizujú len v dynamickej konfigurácii. Netrvám, že to nemožno urobiť v statickej, všetko to robíme. Ale na to treba mať veľa obstdorov, v ktoromkoľvek z vyvažovačov, vrátane. envoy Okrem toho.
Úlohy, pri ktorých je Envoy nepostrádateľný:
- Vyvažovanie prevádzky v zložitých a dynamických systémoch. Tu patrí service mesh, ale nemusí byť jediný.
- Potrebnosť funkcie distribuovaného trasovania, zložitého oprávnenia alebo iného, ktorý je prítomný v envoy základnej výbave alebo sa pohodlne implementuje, zatiaľ čo v nginx/haproxy je potrebné sa obliecť do lua a pochybného pluginu.
Oba prístupy môžu, ak je to potrebné, zabezpečiť vysoký výkon.
Ako to funguje
Envoy sa distribuuje v binárkach iba ako docker obraz. V obraze už existuje príklad statickej konfigurácie. Ale pre nás je zaujímavý iba pre pochopenie štruktúry.
envoy.yaml statická konfigurácia
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
# Odkomentujte nasledujúcu líniu, aby ste otestovali na sieti v6
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.comDynamická konfigurácia
Aké problémy sa snažíme vyriešiť? Nemôžete jednoducho zobrať a reštartovať konfiguráciu vyvažovača pod záťažou, vzniknú "malé" problémy:
- Validácia konfigurácie.
Konfigurácia môže byť veľká, môže byť veľmi veľká, ak ju preťažujeme celú naraz, šance na chyby niekde rastú.
- Dlhodobé spojenia.
Pri inicializácii nového poslucháča je potrebné dbať na spojenia, ktoré fungujú na starom, ak sa zmeny vyskytujú často a existujú dlhodobé spojenia, bude potrebné hľadať kompromis. Ahoj, kubernetes ingress na nginx.
- Aktívne health-checky.
Ak máme aktívne health-checky, bolo by dobré ich všetky prekontrolovať na novej konfigurácii pred tým, ako pošleme prevádzku. Ak je veľa upstreamov, zaberie to čas. Ahoj, haproxy.
Ako sa to rieši v envoy, načítaním konfigurácie dynamicky, podľa pool modelu, môže byť rozdelená na samostatné časti a nie je potrebné reinitializovať tú časť, ktorá sa nezmenila. Napríklad listener, ktorý je nákladný na reinitializáciu, sa mení len zriedka.
Konfigurácia envoy (z vyššie uvedeného súboru) má nasledujúce entity:
- listener — listener visí na určitej ip/porte
- virtual host — virtuálny host podľa názvu domény
- route — pravidlo vyvažovania
- cluster — skupina upstreamov s parametrami vyvažovania
- endpoint — adresa inštancie upstreamu
Každú z týchto entít plus niektoré ďalšie je možné vyplniť dynamicky, na to sa v konfigurácii uvádza adresa služby, odkiaľ bude konfigurácia získaná. Služba môže byť REST alebo gRPC, uprednostňuje sa používanie gRPC.
Služby sa nazývajú zodpovedajúco: LDS, VHDS, RDS, CDS a EDS. Je možné kombinovať statickú a dynamickú konfiguráciu, s obmedzením, že dynamický zdroj nemožno uviesť v statickom.
Pre väčšinu úloh stačí implementovať posledné tri služby, nazývajú sa ADS (Aggregated Discovery Service), pre a go existuje hotová implementácia gRPC dataplane, v ktorej stačí iba vyplniť objekty zo svojho zdroja.
Konfigurácia nadobúda nasledujúcu podobu:
envoy.yaml dynamická konfigurácia
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: 6565Pri spustení sa zobrazuje nasledujúce: envoy s touto konfiguráciou sa pripojí k control-plane a pokúsi sa vyžiadať konfigurácie RDS, CDS a EDS. Ako prebieha proces interakcie je opísané .
Ak zhrniem, envoy posiela žiadosť, s uvedením typu požadovaného zdroja, verziou a parametrami uzla. V odpovedi dostane zdroj a verziu, ak sa verzia na control-plane nezmenila, neodpovedá.
Existujú 4 varianty interakcie:
- Jeden gRPC stream pre všetky typy zdrojov, posiela sa kompletný stav zdroja.
- Oddelené streamy, plný stav.
- Jeden stream, inkrementálny stav.
- Oddelené streamy, inkrementálny stav.
Inkrementálne xDS umožňuje znížiť prevádzku medzi control-plane a envoy, je to relevantné pre veľké konfigurácie. Ale zložitosti interakcie, v požiadavke sa odosiela zoznam zdrojov na odhlásenie a prihlásenie.
V našom príklade sa používa ADS — jeden stream pre RDS, CDS, EDS a nie inkrementálny režim. Pre aktiváciu inkrementálneho režimu je potrebné zadať api_type: DELTA_GRPC
Keďže v požiadavke sú parametre uzla, môžeme na control-plane posielať rôzne zdroje pre rôzne inštancie envoy, to je praktické pre budovanie service mesh.
Warmup
Na envoy pri spustení alebo po získaní novej konfigurácie od control-plane sa spúšťa proces warmup zdrojov. Je rozdelený na warmup listenera a warmup clusteru. Prvý sa spúšťa pri zmenách v RDS/LDS, druhý pri CDS/EDS. To znamená, že ak sa menia len upstreamy, listener sa neprebuduje.
V priebehu warmupu sa očakávajú závislé zdroje od control-plane počas timeoutu. Ak timeout uplynul a inicializácia nebude úspešná, nový listener nezačne počúvať port.
Poradie inicializácie: EDS, CDS, aktívny health check, RDS, LDS. Pri zapnutých aktívnych health checkoch, prevádzka pôjde na upstream, až po jednom úspešnom health checku.
Ak bol listener znovu vytvorený, starý prechádza do stavu DRAIN a bude odstránený po uzavretí všetkých spojení alebo uplynutí timeoutu --drain-time-s, predvolene 10 minút.
Pokračovanie nasleduje.
Zdroj: habr.com
