Envoy. 1. Hyrje

Përshëndetje! Ky është një artikull i vogël që përgjigjet pyetjeve: "çfarë është envoy?", "përse ka nevojë?" dhe "nga ku të filloj?".

ÇfarĂ« Ă«shtĂ« kjo

Envoy është një balancues i ngarkesës L4-L7 i shkruar në C++, i fokusuar në performancën dhe disponueshmërinë e lartë. Në një anë, është një farë analogji me nginx dhe haproxy, të krahasueshëm me ta në performancë. Nga ana tjetër, është më shumë i orientuar ndaj arkitekturës së mikroshërbimeve dhe ka funksionalitete që nuk janë më pak të mira se balancuesit në java dhe go, si zuul ose traefik.

Tabela e krahasimit haproxy/nginx/envoy, ajo nuk pretendojnë të jetë e vërteta absolute, por jep një pamje të përgjithshme.

nginx
haproxy
envoy
traefik

yjet në github
11.2k/mirror
1.1k/mirror
12.4k
27.6k

shkruar në
C
C
C++
go

API
jo
socket only/push
dataplane/pull
pull

kontroll aktiv i shëndetit
jo
po
po
po

Open tracing
plugin i jashtëm
jo
po
po

JWT
plugin i jashtëm
jo
po
jo

Zgjerim
Lua/C
Lua/C
Lua/C++
jo

Pse

Ky është një projekt i ri, në të ka shumë gjëra që mungojnë, disa janë në alfa të hershme. Por envoy, përfshirë falë rinisë, zhvillohet shpejt dhe tashmë ka shumë mundësi interesante: konfigurim dinamik, shumë filtra të gatshëm, një ndërfaqe të thjeshtë për të shkruar filtrat tuaj.
Nga kjo dalin fushat e përdorimit, por për fillim 2 antipatern:

  • DorĂ«zimi i statikĂ«s.

Fakti është se, tani për tani, në envoy nuk ka mbështetje për caching. Djemtë nga google po përpiqen ta rregullojnë. Ideja është të realizohet njëherë në envoy të gjitha hollësitë (zoo e headers) përputhshmëria me RFC, dhe për zbatime specifike të bëhet një ndërfaqe. Por për tani kjo ashtë edhe jo alfa, arkitektura është në diskutim, PR e hapur (derisa po shkruaja artikullin, PR u bashkua, por ky pikë është ende aktual).

Dhe për tani përdorni nginx për statikën.

  • Konfigurimi statik.

Mund ta përdorni, por envoy u krijua jo për këtë. Mundësitë në konfigurimin statik nuk do të shpalosen. Ka shumë momente:

Duke redaktuar konfigurimin nĂ« yaml, do tĂ« gaboni, do t’i mallkoni zhvilluesit pĂ«r fjalosje dhe do tĂ« mendoni se konfigurimet nginx/haproxy, ndoshta mĂ« pak tĂ« strukturuara, por mĂ« tĂ« qarta. Kjo Ă«shtĂ« e vĂ«rteta. Konfigurimi i Nginx dhe Haproxy u krijua pĂ«r redaktimin manual, ndĂ«rsa ai i envoy pĂ«r gjenerimin nga kodi. E gjithĂ« konfigurimi Ă«shtĂ« e pĂ«rshkruar nĂ« protobuf, duke e gjeneruar atĂ« nga skedarĂ«t proto Ă«shtĂ« shumĂ« mĂ« e vĂ«shtirĂ« tĂ« gabosh.

Skenarët canary, b/g deploy dhe shumë gjëra të tjera, realizohen normalisht vetëm në konfigurimin dinamik. Unë nuk po them që kjo nuk mund të bëhet në statikë, ne e bëjmë të gjithë këtë. Por për këtë duhet të përdorni kulla, në cilindo nga balancuesit, në envoy në përfshirë.

Detyrat në të cilat Envoy është i pazëvendësueshëm:

  • Balancimi i trafikut nĂ« sisteme tĂ« komplikuara dhe dinamike. KĂ«tu pĂ«rfshihet service mesh, por kjo nuk Ă«shtĂ« domosdoshmĂ«risht vetĂ«m ai.
  • Nevoja pĂ«r funksionalitetin e gjurmimit tĂ« shpĂ«rndarĂ«, autorizimit tĂ« komplikuar ose njĂ« tjetĂ«r qĂ« ekziston nĂ« envoy mĂ«nyrĂ« standarde ose implementohet lehtĂ«sisht, ndryshe nĂ« nginx/haproxy duhet tĂ« pĂ«rdorim lua dhe plugina tĂ« dyshimta.

Të dyja janë të nevojshme për të siguruar performancë të lartë.

Si funksionon kjo

Envoy shpërndahet në binarë vetëm si imazh docker. Në imazh tashmë ka një shembull të konfiguracionit statik. Por ne e kemi interes vetëm për të kuptuar strukturën.

envoy.yaml konfigurimi statik

resources_static:
  dëgjuesit:
  - emri: dëgjuesi_0
    adresa:
      socket_address:
        protokolli: TCP
        adresa: 0.0.0.0
        vlera_porti: 10000
    zinxhirët_filtrues:
    - filtrat:
      - emri: envoy.http_connection_manager
        konfigurimi_typed:
          "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
          stat_prefix: ingress_http
          konfigurimi_rrugësh:
            emri: local_route
            pritë virtuale:
            - emri: shërbimi_vendës
              domainet: ["*"]
              rrugët:
              - përputh:
                  prefiksi: "\/"
                rrugë:
                  host_rewrite: www.google.com
                  klasteri: service_google
          filtrat_http:
          - emri: envoy.router
  klasteret:
  - emri: service_google
    connect_timeout: 0.25s
    lloji: LOGICAL_DNS
    # Komentoni rreshtin e mëposhtëm për të testuar në rrjetet v6
    dns_lookup_family: V4_ONLY
    politika_lb: ROUND_ROBIN
    ngarkesa_remis:
      emri_klasteri: service_google
      pikat:
      - lb_endpoints:
        - pika:
            adresa:
              socket_address:
                adresa: www.google.com
                vlera_porti: 443
    transport_socket:
      emri: envoy.transport_sockets.tls
      konfigurimi_typed:
        "@type": type.googleapis.com/envoy.api.v2.auth.UpstreamTlsContext
        sni: www.google.com

Konfigurimi dinamik

ÇfarĂ« problemi po kĂ«rkojmĂ« tĂ« zgjidhim? Nuk mund tĂ« rindezim thjesht konfigurimin e balancuesit nĂ«n ngarkesĂ«, do tĂ« ndodhin "probleme tĂ« vogla":

  • Validimi i konfiguracionit.

Konfigurimi mund të jetë i madh, madje shumë i madh, nëse e ngarkojmë të gjithë në një kohë, shanset që të ketë ndonjë gabim do të rriten.

  • Koneksionet afatgjata.

Kur inicializohet një dëgjues i ri, duhet të kujdesemi për lidhjet që punojnë në të vjetrit, nëse ndryshimet ndodhin shpesh dhe ka konneksione afatgjata, do të duhet të kërkojmë një kompromis. Përshëndetje, kubernetes ingress në nginx.

  • Kontrollet aktive tĂ« shĂ«ndetit.

Nëse kemi kontrolle aktive të shëndetit, duhet t'i verifikojmë të gjitha në konfigurimin e ri para se të dërgojmë trafikun. Nëse ka shumë upstream, kjo kërkon kohë. Përshëndetje, haproxy.

Si zgjidhet kjo në envoy, duke ngarkon dinamikisht konfigurimin, sipas modelit të pulsave, mund ta ndanit atë në pjesë të veçanta dhe të mos e ri-inizializoni atë pjesë që nuk është ndryshuar. Për shembull, një dëgjues, që ri-inizializohet me shpenzime të mëdha, ndryshohet rrallë.

Konfigurimi envoy (nga skedari më sipër) ka entitete të mëposhtme:

  • dĂ«gjues — dĂ«gjuesi qĂ« Ă«shtĂ« i varur nĂ« njĂ« ip/port tĂ« caktuar
  • mikpritĂ«si virtual — mikpritĂ«si virtual sipas emrit tĂ« domain-it
  • rrugĂ«n — rregulli i balansimit
  • grupi — grupi i upstream-Ă«ve me parametrat e balansimit
  • endpoint — adresa e instancĂ«s sĂ« upstream-it

Çdo nga kĂ«to entitete, plus disa tĂ« tjera, mund tĂ« plotĂ«sohen dinamikisht, pĂ«r kĂ«tĂ«, nĂ« konfigurim tregohet adresa e shĂ«rbimit nga ku do tĂ« merret konfigurimi. ShĂ«rbimi mund tĂ« jetĂ« REST ose gRPC, Ă«shtĂ« mĂ« e preferueshme tĂ« pĂ«rdoret gRPC.

Shërbimet quhen përkatësisht: LDS, VHDS, RDS, CDS dhe EDS. Mund të kombinoni konfigurimin statik dhe dinamik, me kushtin që burimi dinamik të mos tregojë në një statik.

Për shumicën e detyrave, mjafton të realizoni tre shërbimet e fundit, ato quhen ADS (Shërbimi i Zbulimit të Agreguar), për java dhe go ka një implementim të gatshëm gRPC dataplane ku mjafton të plotësoni objektet nga burimi juaj.

Konfigurimi merr formën e mëposhtme:

envoy.yaml konfigurimi dinamik

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

Kur aktivizohet envoy ky konfigurim, do të lidhet me control-plane dhe do të përpiqet të kërkojë konfigurimin RDS, CDS dhe EDS. Si ndodh procesi i ndërveprimit është e përshkruar këtu.

Nëse e përmbledhim, envoy dërgon një kërkesë, duke treguar llojin e burimit që kërkon, versionin dhe parametrat e nodës. Në përgjigje merr burimin dhe versionin, nëse në control-plane versioni nuk ka ndryshuar, ai nuk përgjigjet.
Ka 4 mundësi ndërveprimi:

  • NjĂ« gRPC stream pĂ«r tĂ« gjitha llojet e burimeve, dĂ«rgohet statusi i plotĂ« i burimit.
  • Stream tĂ« ndara, gjendje e plotĂ«.
  • NjĂ« stream, gjendje inkrementale.
  • Stream tĂ« ndara, gjendje inkrementale.

xDS inkremental lejon të reduktojë trafikun ndërmjet control-plane dhe envoy, kjo është e rëndësishme për konfigurime të mëdha. Por e komplikon ndërveprimin, në kërkesë dërgohet një listë e burimeve për anullim dhe abonim.

NĂ« shembullin tonĂ« pĂ«rdoret ADS — njĂ« stream pĂ«r RDS, CDS, EDS dhe modalitetin jo-inkremental. PĂ«r tĂ« aktivizuar modalitetin inkremental, duhet tĂ« specifikoni api_type: DELTA_GRPC

Duke pasur parasysh që në kërkesë ka parametra nodi, mund të dërgojmë burime të ndryshme për instancat e ndryshme në control-plane envoy, kjo është e përshtatshme për ndërtimin e service mesh.

Ngrohje

Në envoy në fillim ose kur merr një konfigurim të ri nga control-plane nis procesin e ngrohjes së burimeve. Ajo ndahet në ngrohjen e dëgjuesit dhe ngrohjen e klasterit. E para niset kur ndodhin ndryshime në RDS/LDS, e dyta në CDS/EDS. Kjo do të thotë se nëse ndryshojnë vetëm upstream-t, dëgjuesi nuk krijohet sërish.

Në procesin e ngrohjes, priten burimet e varura nga control-plane brenda një kohëmatësi. Nëse koha e matjes skadon dhe inicializimi nuk është i suksesshëm, dëgjuesi i ri nuk do të fillojë të dëgjojë portin.
Rendi i inicializimit: EDS, CDS, kontrolli aktiv i shëndetit, RDS, LDS. Kur janë aktivizuar kontrollet aktive të shëndetit, trafiku do të shkojë në upstream, vetëm pas një kontrolli të suksesshëm.

Nëse dëgjuesi krijohet sërish, i vjetri kalon në gjendjen DRAIN, dhe do të hiqet pas mbylljes së të gjitha lidhjeve ose skadimit të kohëmatësit --drain-time-s, për default është 10 minuta.

Vazhdon...

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster