Envoy. 1. Ievads

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 izlabot. 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). PR 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 , ģenerējot to no proto failiem ir daudz grūtāk kļūdīties.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.com

Dinamisks 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), java 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: 6565

Palaidumā 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 šeit.

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

Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem 🔥 Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem | ProHoster