Envoy. 1. Uvod

Pozdravljam! To je kratek članek, ki odgovarja na vprašanja: "Kaj je envoy?", "Zakaj je potreben?" in "Kako začeti?".

Hvad er det

Envoy je L4-L7 uravnoteževalnik, napisan v C++, ki je osredotočen na visoko zmogljivost in razpoložljivost. Po eni strani je nekakšna analogija nginx in haproxy, primerljiv z njimi po zmogljivosti. Po drugi strani pa je bolj usmerjen v mikroservisno arhitekturo in ima funkcionalnosti, ki niso nič manjše od uravnoteževalnikov na javi in go, kot sta zuul ali traefik.

Tabela primerjave haproxy/nginx/envoy, ki sicer ne zahteva absolutne resnice, ampak daje splošen pregled.

nginx
haproxy
envoy
traefik

zvezd na githubu
11.2k/mirror
1.1k/mirror
12.4k
27.6k

napisano v
C
C
C++
go

API
ne
samo socket/push
dataplane/pull
pull

aktivno zdravstveno preverjanje
ne
da
da
da

Open tracing
zunanji vtičnik
ne
da
da

JWT
zunanji vtičnik
ne
da
ne

Ekstenzija
Lua/C
Lua/C
Lua/C++
ne

Zakaj

To je mlad projekt, ki mu manjka veliko, nekaj pa je v zgodnji alfa fazi. A envoy, vključno s hitrim napredkom zaradi mladosti, že ima veliko zanimivih možnosti: dinamično konfiguracijo, množico pripravljenih filtrov in preprost vmesnik za pisanje lastnih filtrov.
To prinaša področja uporabe, vendar sta tukaj najprej dva antipatterna:

  • Servisiranje statike.

Problem je v tem, da v envoy trenutno ni podpore za predpomnjenje. Fantje iz google poskušajo to popravimo. Ideja je enkrat implementirati v na envoy vse zapletenosti (zoo headerjev) v skladu z RFC, za konkretne implementacije pa narediti vmesnik. A to je še vedno v razpravi, arhitektura je v razpravi, PR odprt (ko sem pisal članek, so PR združili, a ta točka je še vedno aktualna).

Zaenkrat pa uporabite nginx za statiko.

  • Statistična konfiguracija.

Lahko jo uporabite, vendar envoy niso jo ustvarili za to. Možnosti v statični konfiguraciji ne bodo razkrite. Obstaja veliko vidikov:

Ko urejate konfiguracijo v yaml, boste delali napake, se pritoževali nad razvijalci zaradi obsežnosti in razmišljali, da so konfiguracije nginx/haproxy, čeprav manj strukturirane, vendar bolj jedrnate. To je bistvo. Konfiguracija Nginx in Haproxy je bila zasnovana za ročno urejanje, medtem ko je envoy namenjena generiranju iz kode. Cela konfiguracija je opisana v protobuf, njena generacija po proto datotekah je veliko težja.

Scenariji canary, b/g implementacije in še marsikaj drugega se normalno izvajajo le v dinamični konfiguraciji. Ne trdim, da tega ne moremo storiti v statiki, vse to počnemo. Toda za to je potrebno obkrožiti s kostmi, v katerem koli od uravnoteževalnikov, v envoy vključno s tem.

Naloge, pri katerih je Envoy nezamenljiv:

  • Usklajevanje prometa v zapletenih in dinamičnih sistemih. Sem spada tudi service mesh, vendar to ni nujno samo on.
  • Potrebnost funkcionalnosti razdeljene sledenja, zapletene avtentikacije ali drugega, kar je na voljo v envoy osnovni različici ali se enostavno implementira, medtem ko je v nginx/haproxy treba uporabiti lua in dvomljive vtičnike.

Oboje je potrebno, da zagotovi visoko zmogljivost.

Kako to funkcionira

Envoy se distribuira v binarnih oblikah samo kot docker slika. V sliki je že primer statične konfiguracije. Vendar nas ta zanima le za razumevanje strukture.

envoy.yaml statična konfiguracija

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
    # Komentirajte naslednjo vrstico, da testirate na v6 omrežjih
    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

Dinamična konfiguracija

Katero težavo iščemo? Ne moremo kar tako vzeti in ponovno naložiti konfiguracije uravnoteževalnika pod obremenitvijo, pojavljale se bodo 'majhne' težave:

  • Validacija konfiguracije.

Konfiguracija je lahko obsežna, lahko je zelo obsežna, če jo ponovno naložimo v celoti, se možnosti, da se kje pojavijo napake, povečajo.

  • Dolgoživost povezav.

Ob inicializaciji novega poslušalnika je treba poskrbeti za povezave, ki delujejo na starem, če se spremembe dogajajo pogosto in so prisotne dolgožive povezave, bo treba poiskati kompromis. Pozdrav, kubernetes ingress na nginx.

  • Aktivni health-checki.

Če imamo aktivne health-checke, je treba vse ponovno preveriti z novo konfiguracijo, preden pošljemo promet. Če je veliko upstreamov, to zahteva čas. Pozdrav, haproxy.

Kako se to rešuje v envoy, dinamično učitavajući konfiguraciju, po principu modela, moguće je podijeliti je na posebne dijelove i ne ponovo inicijalizirati one dijelove koji se nisu mijenjali. Na primjer, listener koji se skupo ponovo inicijalizira, a rijetko se mijenja.

Конфигурация envoy (iz prethodne datoteke) ima sljedeće entitete:

  • listener — listener koji visi na određenom ip/portu
  • virtual host — virtualni host po imenu domene
  • route — pravilo balansiranja
  • cluster — grupa upstream-a s parametrima balansiranja
  • endpoint — adresa instance upstream-a

Svaki od ovih entiteta plus neki drugi mogu se dinamički popuniti, za što se u konfiguraciji navodi adresa servisa s kojeg će se dobiti konfiguracija. Servis može biti REST ili gRPC, a preferira se korištenje gRPC.

Servisi se imenuju na sljedeći način: LDS, VHDS, RDS, CDS i EDS. Mogu se kombinirati statička i dinamička konfiguracija, s ograničenjem da dinamički resurs ne može biti naveden u statičkom.

Za većinu zadataka dovoljno je implementirati posljednja tri servisa, oni se nazivaju ADS (Aggregated Discovery Service), za java i go postoji gotova implementacija gRPC dataplane u kojoj je dovoljno samo popuniti objekte iz vlastitog izvora.

Konfiguracija dobiva sljedeći oblik:

envoy.yaml dinamička konfiguracija

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

Ob zagonu se prikaže naslednje: envoy s ovom konfiguracijom, povezat će se na control-plane i pokušati zatražiti konfiguraciju RDS, CDS i EDS. Kako proces interakcije prolazi opisano je ovde.

Ukratko, envoy šalje zahtjev, s naznakom tipa traženog resursa, verzijom i parametrima čvora. Kao odgovor dobiva resurs i verziju, ako na control-plane verzija nije promijenjena, ne odgovara.
Postoje 4 opcije interakcije:

  • Jedan gRPC stream za sve tipove resursa, šalje se potpuno stanje resursa.
  • Ločeni tokovi, polno stanje.
  • Eden tok, inkrementalno stanje.
  • Ločeni tokovi, inkrementalno stanje.

Inkrementalni xDS omogoča zmanjšanje prometa med kontrolnim vlaknom in envoy, to je pomembno za velike konfiguracije. Vendar pa zapleta interakcijo, saj se v zahtevi pošilja seznam virov za odjavo in prijavo.

V našem primeru uporabljamo ADS — en tok za RDS, CDS, EDS in neinkrementalni način. Za vklop inkrementalnega načina je potrebno navesti api_type: DELTA_GRPC

Ker v zahtevi obstajajo parametri vozlišča, lahko pošiljamo različne vire na kontrolno vlakno za različne instance, envoyto je priročno za gradnjo službene mreže.

Ogrevanje

Na envoy ob zagonu ali ob prejemu nove konfiguracije iz kontrolnega vlakna se zažene postopek ogrevanja virov. Ta je razdeljen na ogrevanje poslušalca in ogrevanje grozda. Prvi se zažene ob spremembah v RDS/LDS, drugi pa ob CDS/EDS. To pomeni, da se, če se spremenijo samo upstreami, poslušalec ne ponovno ustvari.

Med postopkom ogrevanja se pričakujejo odvisni viri iz kontrolnega vlakna v času prekoračitve. Če rok poteče, inicializacija ne bo uspešna, nov poslušalec ne bo začel poslušati vrata.
Vrstni red inicializacije: EDS, CDS, aktivni zdravstveni pregledi, RDS, LDS. Ko so aktivni zdravstveni pregledi vklopljeni, bo promet tekel na upstream šele po enem uspešnem zdravstvenem pregledu.

Če je bil poslušalec ponastavljen, stari preide v stanje DRAIN in bo odstranjen po zaprtju vseh povezav ali poteku roka --drain-time-s, privzeto 10 minut.

Nadaljuje se.

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster