utsending. 1. Introduksjon

Hilsener! Dette er en kort artikkel som svarer på spørsmålene: "hva er utsending?", "hvorfor er det nødvendig?" og "hvor skal du begynne?".

Hva er dette?

Envoy er en L4-L7 balanserer skrevet i C++, fokusert på høy ytelse og tilgjengelighet. På den ene siden er dette på en eller annen måte en analog av nginx og haproxy, sammenlignbar i ytelse med dem. På den annen side er den mer orientert mot mikrotjenestearkitektur og har funksjonalitet som ikke er dårligere enn java og go balansere, for eksempel zuul eller traefik.

Sammenligningstabell for haproxy/nginx/envoy, den hevder ikke å være den absolutte sannheten, men gir et generelt bilde.

nginx
haproksy
utsending
traefik

stjerner på github
11.2k/speil
1.1k/speil
12.4k
27.6k

skrevet inn
C
C
C + +
go

API
ikke
kun stikkontakt/push
dataplan/pull
trekke

aktiv helsesjekk
ikke
ja
ja
ja

Åpen sporing
ekstern plugin
ikke
ja
ja

J.W.T.
ekstern plugin
ikke
ja
ikke

forlengelse
Lua/C
Lua/C
Lua/C++
ikke

Hva for

Dette er et ungt prosjekt, det er mange ting som mangler, noen i tidlig alfa. Men utsending, også på grunn av sin ungdom, utvikler seg raskt og har allerede mange interessante funksjoner: dynamisk konfigurasjon, mange ferdige filtre, et enkelt grensesnitt for å skrive dine egne filtre.
Bruksområder følger av dette, men først er det 2 antimønstre:

  • Statisk rekyl.

Faktum er at for øyeblikket i utsending ingen bufferstøtte. Google-gutta prøver dette å fikse. Ideen vil bli implementert én gang utsending alle finessene (zoo-overskrifter) av RFC-samsvar, og for spesifikke implementeringer lage et grensesnitt. Men foreløpig er det ikke engang alfa, arkitekturen er under diskusjon, PR åpen (mens jeg skrev PR-artikkelen, frøs PR-en, men dette punktet er fortsatt relevant).

For nå, bruk nginx for statikk.

  • Statisk konfigurasjon.

Du kan bruke det, men utsending Det er ikke det den ble skapt for. Funksjoner i en statisk konfigurasjon vil ikke bli eksponert. Det er mange øyeblikk:

Når du redigerer konfigurasjonen i yaml, vil du ta feil, skjelle ut utviklerne for ordlyd og tro at nginx/haproxy-konfigurasjonene, selv om de er mindre strukturerte, er mer konsise. Det er poenget. Konfigurasjonen av Nginx og Haproxy ble opprettet for redigering for hånd, og utsending for generering fra kode. Hele konfigurasjonen er beskrevet i protobuf, å generere den fra protofiler er mye vanskeligere å gjøre en feil.

Canary, b/g-distribusjonsscenarier og mye mer implementeres normalt bare i en dynamisk konfigurasjon. Jeg sier ikke at dette ikke kan gjøres statisk, vi gjør det alle sammen. Men for dette må du sette på krykker, i hvilken som helst av balanserne, inn utsending gjelder også.

Oppgaver som utsending er uunnværlig for:

  • Trafikkbalansering i komplekse og dynamiske systemer. Dette inkluderer tjenestenettverket, men det er ikke nødvendigvis det eneste.
  • Behovet for distribuert sporingsfunksjonalitet, kompleks autorisasjon eller annen funksjonalitet som er tilgjengelig i utsending ut av esken eller praktisk implementert, men i nginx/haproxy må du være omgitt av lua og tvilsomme plugins.

Begge gir om nødvendig høy ytelse.

Hvordan fungerer det

Envoy distribueres i binærfiler bare som et docker-bilde. Bildet inneholder allerede et eksempel på en statisk konfigurasjon. Men vi er interessert i det bare for å forstå strukturen.

envoy.yaml statisk konfigurasjon

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
    # Comment out the following line to test on v6 networks
    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

Dynamisk konfigurasjon

Hvilket problem leter vi etter en løsning på? Du kan ikke bare laste belastningsbalanserkonfigurasjonen på nytt under belastning; "små" problemer vil oppstå:

  • Konfigurasjonsvalidering.

Konfigurasjonen kan være stor, den kan være veldig stor, hvis vi overbelaster alt på en gang, øker sjansene for en feil et sted.

  • Langvarige forbindelser.

Når du initialiserer en ny lytter, må du ta vare på tilkoblingene som kjører på den gamle; hvis endringer skjer ofte og det er langvarige tilkoblinger, må du se etter et kompromiss. Hei, kubernetes ingress på nginx.

  • Aktive helsesjekker.

Hvis vi har aktive helsesjekker, må vi dobbeltsjekke dem alle i den nye konfigurasjonen før vi sender trafikk. Er det mye oppstrøms tar dette tid. Hei haproxy.

Hvordan løses dette i utsendingVed å laste inn konfigurasjonen dynamisk, i henhold til bassengmodellen, kan du dele den inn i separate deler og ikke re-initialisere delen som ikke har endret seg. For eksempel en lytter, som er dyr å reinitialisere og sjelden endres.

Konfigurasjon utsending (fra filen ovenfor) har følgende enheter:

  • lytteren — lytteren henger på en bestemt ip/port
  • virtuell vert - virtuell vert etter domenenavn
  • rute - balanseregel
  • klynge — en gruppe oppstrøms med balanseparametere
  • endepunkt — oppstrøms forekomstadresse

Hver av disse enhetene pluss noen andre kan fylles ut dynamisk; for dette spesifiserer konfigurasjonen adressen til tjenesten der konfigurasjonen vil bli mottatt. Tjenesten kan være REST eller gRPC, gRPC er å foretrekke.

Tjenestene heter henholdsvis: LDS, VHDS, RDS, CDS og EDS. Du kan kombinere statisk og dynamisk konfigurasjon, med den begrensningen at en dynamisk ressurs ikke kan spesifiseres i en statisk.

For de fleste oppgaver er det nok å implementere de tre siste tjenestene, de kalles ADS (Aggregated Discovery Service), for Java og gå det er en ferdig implementering av gRPC dataplan der du bare trenger å fylle ut objektene fra kilden din.

Konfigurasjonen har følgende form:

envoy.yaml dynamisk konfigurasjon

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

Ved oppstart utsending med denne konfigurasjonen vil den koble seg til kontrollplanet og prøve å be om RDS-, CDS- og EDS-konfigurasjonen. Hvordan interaksjonsprosessen foregår er beskrevet her.

Kort oppsummert, utsending sender en forespørsel som indikerer typen ressurs som forespørres, versjonen og parameterne til noden. Som svar mottar den en ressurs og en versjon; hvis versjonen på kontrollplanet ikke er endret, svarer den ikke.
Det er 4 interaksjonsalternativer:

  • Én gRPC-strøm for alle typer ressurser, full status for ressursen sendes.
  • Separate bekker, full stand.
  • Én strøm, inkrementell tilstand.
  • Separate strømmer, inkrementell tilstand.

Inkrementell xDS lar deg redusere trafikken mellom kontrollplanet og utsending, dette er relevant for store konfigurasjoner. Men det kompliserer interaksjonen; forespørselen inneholder en liste over ressurser for av- og påmelding.

Eksempelet vårt bruker ADS – én strøm for RDS, CDS, EDS og ikke-inkrementell modus. For å aktivere inkrementell modus, må du spesifisere api_type: DELTA_GRPC

Siden forespørselen inneholder nodeparametere, kan vi sende forskjellige ressurser til kontrollplanet for forskjellige instanser utsending, dette er praktisk for å bygge et servicenettverk.

Varme opp

utsending ved oppstart eller når du mottar en ny konfigurasjon fra kontrollplanet, startes ressursoppvarmingsprosessen. Den er delt inn i lytteroppvarming og klyngeoppvarming. Den første lanseres når det er endringer i RDS/LDS, den andre når CDS/EDS. Dette betyr at hvis bare oppstrøms endres, gjenskapes ikke lytteren.

Under oppvarmingsprosessen forventes det avhengige ressurser fra kontrollplanet under tidsavbruddet. Hvis tidsavbruddet inntreffer, vil ikke initialiseringen lykkes, og den nye lytteren vil ikke begynne å lytte på porten.
Initialiseringsrekkefølge: EDS, CDS, aktiv helsesjekk, RDS, LDS. Med aktive helsesjekker aktivert, vil trafikken bare gå oppstrøms etter én vellykket helsesjekk.

Hvis lytteren ble gjenskapt, går den gamle inn i DRAIN-tilstanden og vil bli slettet etter at alle tilkoblinger er lukket eller tidsavbruddet utløper --drain-time-s, standard 10 minutter.

Skal videreføres.

Kilde: www.habr.com

Legg til en kommentar