Envoy. 1. Introduktion

Hej! Detta Àr en kort artikel som svarar pÄ frÄgorna: "vad Àr envoy?", "varför behövs det?" och "hur börjar man?".

Vad Àr detta

Envoy Ă€r en L4-L7 lastbalanserare skriven i C++, designad för hög prestanda och tillgĂ€nglighet. Å ena sidan Ă€r det en slags analog till nginx och haproxy, och har jĂ€mförbar prestanda. Å andra sidan Ă€r den mer inriktad pĂ„ mikrotjĂ€nstarkitektur och har funktionalitet som Ă€r minst lika bra som lastbalanserare pĂ„ java och go, som zuul eller traefik.

JÀmförande tabell för haproxy/nginx/envoy, den gör inte ansprÄk pÄ absolut sanning, men ger en allmÀn bild.

nginx
haproxy
envoy
traefik

stjÀrnor pÄ github
11.2k/mirror
1.1k/mirror
12.4k
27.6k

skriven i
C
C
C++
go

API
nej
endast socket/push
dataplan/pull
pull

aktiv hÀlsokontroll
nej
ja
ja
ja

Öppen spĂ„rning
extern plugin
nej
ja
ja

JWT
extern plugin
nej
ja
nej

Utvidgning
Lua/C
Lua/C
Lua/C++
nej

Varför

Detta Àr ett ungt projekt, det saknar mycket, och en del Àr i tidig alfa. Men envoy, delvis tack vare sin ungdom, utvecklas snabbt och har redan nu mÄnga intressanta möjligheter: dynamisk konfiguration, mÄnga fÀrdiga filter, ett enkelt grÀnssnitt för att skriva egna filter.
Detta ger upphov till anvÀndningsomrÄden, men för att börja med tvÄ antipatterns:

  • Leverera statisk innehĂ„ll.

Problemet Àr att det för nÀrvarande finns envoy ingen support för caching. Killarna frÄn google försöker fÄ detta ÄtgÀrdas. Idén Àr att en gÄng implementera i envoy alla nyanser (djungeln av headers) i enlighet med RFC, och för specifika implementationer skapa ett grÀnssnitt. Men just nu Àr det inte ens alfa, arkitekturen diskuteras, PR öppet (medan jag skrev artikeln sÄ mergades PR, men denna punkt Àr fortfarande aktuell).

Tills vidare, anvÀnd nginx för statiskt innehÄll.

  • Statisk konfiguration.

Den kan anvÀndas, men envoy den skapades inte för detta. Möjligheterna i statisk konfiguration kommer inte att avslöjas. Det finns mÄnga punkter:

Genom att redigera konfigurationen i yaml kommer du att göra misstag, förbanna utvecklarna för deras omfattande beskrivning och tÀnka att konfigureringsfiler för nginx/haproxy, Àven om de Àr mindre strukturerade, Àr mer koncisa. Det Àr essensen. Konfigurationen för Nginx och Haproxy skapades för manuell redigering, medan envoy Àr skapad för att genereras frÄn kod. Hela konfigurationen Àr beskriven i protobuf, att generera den via proto-filer Àr mycket svÄrare att göra fel.

Scenarier för canary, b/g-deploy och mycket mer kan normalt genomföras endast i dynamisk konfiguration. Jag sÀger inte att detta inte kan göras i statisk, vi gör allt detta. Men för detta krÀvs det att man bygger pÄ workaround-lösningar, i vilken som helst av lastbalanserarna, i envoy Àven.

Uppgifter dÀr Envoy Àr ovÀrderlig:

  • Lastbalansering av trafik i komplexa och dynamiska system. HĂ€r ingĂ„r service mesh, men det Ă€r inte nödvĂ€ndigtvis bara det.
  • Behovet av funktionalitet för distribuerad spĂ„rning, komplex autentisering eller annat som finns i envoy standard eller som kan implementeras enkelt, medan i nginx/haproxy behövs lua och tveksamma plugins.

BÄda behöver vid behov sÀkerstÀlla hög prestanda.

Hur det fungerar

Envoy distribueras i binÀrform endast som dockerbild. I bilden finns det redan ett exempel pÄ statisk konfiguration. Men vi Àr endast intresserade av den för att förstÄ strukturen.

envoy.yaml statisk konfiguration

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
    # Kommentera ut följande rad för att testa pÄ v6-nÀtverk
    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 konfiguration

Vilket problem söker vi en lösning pÄ? Man kan inte bara ta och ladda om balancerarens konfiguration under belastning, det kommer att uppstÄ "smÄ" problem:

  • Validering av konfiguration.

Konfigurationen kan vara stor, den kan vara vÀldigt stor, om vi laddar om allt pÄ en gÄng ökar chansen att det finns ett fel nÄgonstans.

  • LĂ„ngvariga anslutningar.

Vid initiering av en ny lyssnare, mÄste man ta hand om anslutningarna som arbetar pÄ den gamla, om Àndringarna sker ofta och det finns lÄngvariga anslutningar, mÄste man hitta en kompromiss. Hej, kubernetes ingress pÄ nginx.

  • Aktiva hĂ€lsokontroller.

Om vi har aktiva hÀlsokontroller, bör vi kontrollera dem alla pÄ den nya konfigurationen innan vi skickar trafik. Om det finns mÄnga upstreams tar det tid. Hej, haproxy.

Hur detta löses i envoy, genom att dynamiskt ladda konfigureringen, enligt poolmodellen, kan den delas upp i separata delar och inte ominitieras för den del som inte har Àndrats. Till exempel en lyssnare, som Àr kostsam att ominitiera, och som sÀllan Àndras.

Konfiguration envoy (frÄn filen ovan) har följande entiteter:

  • lyssnare — en lyssnare som Ă€r kopplad till en viss ip/port
  • virtuell vĂ€rd — en virtuell vĂ€rd baserad pĂ„ domĂ€nnamn
  • route — balansregler
  • cluster — en grupp upstreams med balansparameterar
  • endpoint — adress till en upstream-instans

Varje av dessa entiteter samt vissa andra kan fyllas i dynamiskt, för detta anges en tjÀnstadress i konfigurationen varifrÄn konfigurationen ska hÀmtas. TjÀnsten kan vara REST eller gRPC, helst bör gRPC anvÀndas.

TjÀnsterna kallas respektive: LDS, VHDS, RDS, CDS och EDS. Statisk och dynamisk konfiguration kan kombineras, med begrÀnsningen att en dynamisk resurs inte kan anges i den statiska.

För de flesta uppgifter Àr det tillrÀckligt att implementera de tre senaste tjÀnsterna, de kallas ADS (Aggregated Discovery Service), för java och go har en fÀrdig gRPC dataplane-implementation dÀr det endast Àr nödvÀndigt att fylla i objekten frÄn sin egen kÀlla.

Konfigurationen fÄr följande utseende:

envoy.yaml dynamisk konfiguration

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

NÀr den körs visas följande: envoy med denna konfiguration, kommer den att ansluta till control-plane och försöka begÀra RDS, CDS och EDS-konfigurationen. Hur interaktionsprocessen gÄr till Àr beskrivet hÀr.

Kort sagt, envoy skickar en begÀran med typ av begÀrd resurs, version och nodparametrar. I svaret fÄr den resursen och versionen, om versionen pÄ control-plane inte har Àndrats, svarar den inte.
Det finns fyra alternativ för interaktion:

  • En gRPC-ström för alla typer av resurser skickar den fullstĂ€ndiga statusen för resursen.
  • Separata strömmar, fullstĂ€ndigt tillstĂ„nd.
  • En ström, inkrementellt tillstĂ„nd.
  • Separata strömmar, inkrementellt tillstĂ„nd.

Inkrementell xDS minskar trafiken mellan kontrollplanet och envoy, vilket Àr relevant för stora konfigurationer. Men det komplicerar interaktionen, en lista över resurser för avprenumeration och prenumeration överförs i förfrÄgan.

I vĂ„rt exempel anvĂ€nds ADS – en ström för RDS, CDS, EDS och icke-inkrementellt lĂ€ge. För att aktivera inkrementellt lĂ€ge mĂ„ste du ange api_type: DELTA_GRPC

Eftersom det finns nodparametrar i förfrÄgan kan vi skicka olika resurser till olika instanser pÄ kontrollplanet envoy, vilket Àr praktiskt för att bygga en service mesh.

UppvÀrmning

PÄ envoy vid start eller nÀr en ny konfiguration tas emot frÄn kontrollplanet startar processen för uppvÀrmning av resurser. Den Àr uppdelad i listener-uppvÀrmning och cluster-uppvÀrmning. Den första startar vid förÀndringar i RDS/LDS, den andra vid CDS/EDS. Det betyder att om bara upstreams Àndras, kommer lyssnaren inte att Äterskapas.

Under uppvÀrmningen förvÀntas beroende resurser frÄn kontrollplanet inom tidsgrÀnsen. Om tidsgrÀnsen har passerat, kommer initieringen att misslyckas, den nya lyssnaren kommer inte att börja lyssna pÄ porten.
Initieringsordning: EDS, CDS, aktiv hÀlsokontroll, RDS, LDS. NÀr aktiva hÀlsokontroller Àr aktiverade, gÄr trafik till upstreamen endast efter en lyckad hÀlsokontroll.

Om lyssnaren Äterskapas gÄr den gamla över till tillstÄndet DRAIN och kommer att tas bort efter att alla anslutningar har stÀngts eller tidsgrÀnsen har löpt ut --drain-time-s, som standard 10 minuter.

FortsÀttning följer.

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster