Sveiki! Šis ir neliels raksts, kas atbild uz jautājumiem: "kas ir envoy?", "kāpēc tas ir nepieciešams?" un "no kā sākt?".
Kas tas ir
Envoy ir L4-L7 slodzes balansētājs, kas uzrakstīts C++, orientēts uz augstu veiktspēju un pieejamību. No vienas puses, tas ir zināmā mērā līdzīgs nginx un haproxy, salīdzināms ar tiem pēc veiktspējas. No otras puses, tas vairāk orientējas uz mikrosistēmu arhitektūru un tam ir funkcionalitāte, kas nav sliktāka par balansētājiem, kas uzrakstīti Java un Go, piemēram, zuul vai traefik.
Haproxy/nginx/envoy salīdzinājuma tabula, tā nepretendē uz absolūto patiesību, bet sniedz vispārēju ainu.
nginx
haproxy
envoy
traefik
zvaigznes githubā
11.2k/mirror
1.1k/mirror
12.4k
27.6k
uzrakstīts uz
C
C
C++
go
API
nē
socket only/push
dataplane/pull
pull
aktīvā veselības pārbaude
nē
jā
jā
jā
Open tracing
ārējais spraudnis
nē
jā
jā
JWT
ārējais spraudnis
nē
jā
nē
Paplašinājums
Lua/C
Lua/C
Lua/C++
nē
Kāpēc
Paplašinājums ir jauns projekts, tajā trūkst daudz, kas nepieciešams, daži ir agrīnajā alfa fāzē. Bet envoy, tostarp pateicoties jaunumam, tas ātri attīstās un jau šobrīd ir daudz interesantu iespēju: dinamiskā konfigurācija, daudz gatavu filtrus, vienkāršs interfeiss, lai rakstītu savus filtrus.
No tā izriet pielietojuma jomas, bet sākumā divi antipatterni:
- Statikas piegāde.
Fakts ir tāds, ka šobrīd envoy nav kešatmiņas atbalsta. Google komanda mēģina to . Ideja ir vienreiz īstenot visas nianses (header zoo) atbilstību RFC, bet konkrētām realizācijām izveidot interfeisu. Taču pagaidām tas vēl nav pat alfa, arhitektūra ir apspriešanas procesā, envoy atvērts (kamēr es rakstīju rakstu, PR tika apvienots, bet šis punkts vēl ir aktuāls). Līdz tam izmantojiet nginx statiku.
Statiskā konfigurācija.
- To var izmantot, bet
tā nav izveidota šim nolūkam. Iespējas statiskajā konfigurācijā netiks atklātas. Ir daudz aspektu: envoy Rediģējot konfigurāciju YAML, jūs kļūdīsieties, nolādēsiet izstrādātājus par sarežģītību un domāsiet, ka nginx/haproxy konfigurācijas, lai arī mazāk strukturētas, ir lakoniskākas. Par to ir runa. Nginx un Haproxy konfigurācijas tika veidotas, lai tās rediģētu ar rokām, bet
tika izstrādāta tā, lai to ģenerētu no koda. Visa konfigurācija ir aprakstīta envoy protobuf Canary, b/g izvietošanas scenāriji un daudz kas cits, normāli tiek realizēti tikai dinamiskajā konfigurācijā. Es nesaku, ka to nevar izdarīt statikā, mēs to viss darām. Bet tam ir nepieciešams izveidot ikdienas risinājumus jebkurā no balansētājiem,
tostarp. envoy t.sk.
Uzdevumi, kuros Envoy ir neaizvietojams:
- Satiksmes līdzsvarošana sarežģītās un dinamiskās sistēmās. Tas attiecas uz pakalpojumu tīklu, taču tas nav obligāti tikai tas.
- Nepieciešamība pēc funkcionalitātes sadalītā izsekošanā, sarežģītā autorizācijā vai kādā citā, kas ir pieejams envoy no kārbas vai ērti īstenojams, tomēr nginx/haproxy ir jāsaskaras ar lua un apšaubāmiem spraudņiem.
Abos gadījumos, ja nepieciešams, jānodrošina augsta veiktspēja.
Efemerāli vispārējie mākonīši
Envoy tiek izplatīts tikai kā docker attēls. Attēlā jau ir piemērs statiskajai konfigurācijai. Bet mums tas ir interesants tikai struktūras izpratnei.
envoy.yaml statiskā konfigurācija
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
# Aizvietot nākamo rindu, lai pārbaudītu v6 tīkliem
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.comDinamisks konfigurācija
Kādu problēmu mēs risinām? Nav iespējams vienkārši restartēt līdzsvarošanas konfigurāciju zem slodzes, radīsies "nelielas" problēmas:
- Konfigurācijas validācija.
Konfiegs var būt liels, var būt ļoti liels, kad mēs to restartējam visu reizē, kļūdas iespēja palielinās.
- Ilgstošas savienojumi.
Jaunu klausītāju inicializācijas procesā, jāparūpējas par savienojumiem, kas strādā iepriekšējā, ja izmaiņas notiek bieži un ir ilgstošas savienojumi, būs jāmeklē kompromiss. Sveiki, kubernetes ieplūde nginx.
- Aktīvie veselības pārbaudes.
Ja mums ir aktīvie veselības pārbaudes, visus ir jāpārbauda jaunajā konfigurācijā pirms trafika sūtīšanas. Ja ir daudz augšupplūdes, tas prasa laiku. Sveiki, haproxy.
Kā to risina envoy, i ielādējot konfigurāciju dinamiski, pa pool modeļiem, to var sadalīt atsevišķās daļās un nepārstartēt to daļu, kas nemainījās. Piemēram, listeners, kuru pārstartēt ir dārgi, mainās reti.
Konfigurācija envoy (no augstāk minētā faila) ir šādas entītijas:
- listener — listeners, kas pieslēgts konkrētajam ip/portam
- virtual host — virtuālais host pēc domēna vārda
- route — balansēšanas noteikums
- klasteris — augšējās grupas ar balansēšanas parametriem
- beigām — augšējā instance adrese
Katra no šīm entītijām plus dažas citas var tikt aizpildītas dinamiski, tam konfigurācijā jānorāda pakalpojuma adrese, no kuras iegūs konfigurāciju. Pakalpojums var būt REST vai gRPC, dodot priekšroku gRPC.
Pakalpojumi tiek saukti atbilstoši: LDS, VHDS, RDS, CDS un EDS. Var kombinēt statisko un dinamisko konfigurāciju, ar ierobežojumu, ka dinamiskā resursa nevar norādīt statiskajā.
Lielākajā daļā uzdevumu ir pietiekami īstenot pēdējos trīs pakalpojumus, tos sauc par ADS (Apvienotā atklāšanas pakalpojums), un go ir gatava gRPC dataplane īstenošana, kurā pietiek tikai aizpildīt objektus no sava avota.
Konfigurācija iegūst sekojošo izskatu:
envoy.yaml dinamiskā konfigurācija
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: 6565Palaidumā envoy ar šo konfigurāciju tas pieslēgsies control-plane un mēģinās pieprasīt RDS, CDS un EDS konfigurāciju. Kā notiek mijiedarbības process ir aprakstīts .
Ja īsummā, envoy tiek sūtīts pieprasījums ar norādītu pieprasītā resursa tipu, versiju un mezgla parametriem. Atbildē tiek saņemts resurss un versija, ja control-plane versija nav mainījusies, tas neatbild.
Ir 4 mijiedarbības varianti:
- Viens gRPC straume visiem resursu tipiem, tiek nosūtīta pilna resursa stāvokļa informācija.
- Atsevišķi straumi, pilna stāvokļa.
- Viens straume, inkrementālais stāvoklis.
- Atsevišķi straumi, inkrementālais stāvoklis.
Inkrementālais xDS samazina trafiku starp control-plane un envoy, tas ir aktuāli lielām konfigurācijām. Bet tas sarežģī mijiedarbību, pieprasījumā tiek nosūtīts resursu saraksts atteikšanās un parakstīšanās gadījumā.
Mūsu piemērā tiek izmantots ADS — viens straume RDS, CDS, EDS un neinkrementālais režīms. Lai ieslēgtu inkrementālo režīmu, jānorāda api_type: DELTA_GRPC
Tā kā pieprasījumā ir mezgla parametri, mēs varam control-plane nosūtīt dažādus resursus atšķirīgiem instancēm envoy, tas ir ērti service mesh izveidei.
Warmup
Uz envoy sākumā vai saņemot jaunu konfigurāciju no control-plane sākas resursu sasilšanas process. Tas ir sadalīts, uz listener warmup un cluster warmup. Pirmais tiek aktivizēts, kad ir izmaiņas RDS/LDS, otrais — CDS/EDS. Tas nozīmē, ka, ja mainās tikai augšupplūdes, listener netiek pārveidots.
Sasilšanas procesā tiek gaidīti atkarīgie resursi no control-plane izslēgšanas laikā. Ja laiks ir beidzies, inicializācija nebūs veiksmīga, jauno listener neuzsāks klausīties portu.
Inicializācijas secība: EDS, CDS, aktīva veselības pārbaude, RDS, LDS. Aktīvās veselības pārbaudēs satiksme nonāks augšupplūdes vienīgi pēc vienas veiksmīgas veselības pārbaudes.
Ja listener tika pārveidots, vecais pāriet uz DRAIN stāvokli un tiks noņemts pēc visu savienojumu slēgšanas vai laika beigām --drain-time-s, pēc noklusējuma 10 minūtes.
Turpinājums sekos.
Avots: habr.com
