Envoy. 1. Hyrje

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

ÇfarĂ« Ă«shtĂ« kjo

Envoy është një balancues L4-L7 i shkruar në C++, i orientuar ndaj performancës së lartë dhe disponueshmërisë. Nga njëra anë, ai është një lloj ekuivalenti i nginx dhe haproxy, i krahasueshëm me ta për nga performanca. Nga ana tjetër, ai është më shumë i orientuar ndaj arkitekturës së mikroshërbimeve dhe ka funksionalitete që nuk janë më të dobëta se balancuesit në java dhe go, siç janë zuul ose traefik.

Tabela krahasuese haproxy/nginx/envoy, ajo nuk pretendon të jetë e vërteta absolute, por ofron një pamje të përgjithshme.

nginx
haproxy
envoy
traefik

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

i shkruar në
C
C
C++
go

API
jo
socket only/push
dataplane/pull
pull

kontroll i shëndetit aktiv
jo
po
po
po

Open tracing
plugin i jashtëm
jo
po
po

JWT
plugin i jashtëm
jo
po
jo

Zgjerimi
Lua/C
Lua/C
Lua/C++
jo

Pse

Ky është një projekt i ri, ka shumë gjëra që i mungojnë, diçka është në alfa të hershme. Por envoy, përfshirë përfitimet e 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.
Kjo rezulton në fusha aplikimi, por fillimisht dy antipatere:

  • ShĂ«rbimi i statikĂ«s.

Fakti është se për momentin në envoy nuk ka mbështetje për caching. Po përpiqen ta rregullojnë. Ideja është që një herë të realizohet në envoy të gjitha nuancat (zoo e headerave) e përputhjes me RFC, dhe për zbatime specifike të bëhet një ndërfaqe. Por për momentin kjo as nuk është në alfa, arkitektura është në diskutim, PR hapur (derisa po shkruaja artikullin PR u fut, por ky pikë është ende aktual).

Dhe për momentin përdorni nginx për statik.

  • Konfigurimi statik.

Mund të përdoret, por envoy nuk u krijua për këtë. Mundësitë në konfigurimin statik nuk do të jenë të zbuluara. Ka shumë momente:

Duke redaktuar konfigurimin në yaml, do të gaboni, do të mallkoni zhvilluesit për shumëllojshmërinë dhe do të mendoni se konfigurat e nginx/haproxy, megjithëse më pak të strukturuara, janë më të lakonshme. Kjo është thelbi. Konfigurimi Nginx dhe Haproxy është krijuar për redaktim manual, ndërsa i envoy për krijim nga kodi. E gjithë konfigurimi përshkruhet në protobuf, duke e gjeneruar atë nga skedarët proto është shumë më e vështirë për të gabuar.

Skenarët e canary, b/g deploy dhe shumë të tjera, normalisht realizohen vetëm në konfigurimin dinamik. Nuk po them se kjo nuk mund të bëhet në statik, ne të gjithë e bëjmë. Por për këtë duhet të ndihmojmë me ndihma, në çdo nga balancuesit, në envoy përfshirë.

Detyrat për të cilat Envoy është thelbësor:

  • Balancimi i trafik e nĂ« sisteme komplekse dhe dinamike. KĂ«tu pĂ«rfshihet service mesh, por nuk Ă«shtĂ« vetĂ«m ai.
  • Nevoja pĂ«r funksionalitetin e ndjekjes sĂ« shpĂ«rndarĂ«, autorizim tĂ« ndĂ«rlikuar ose diçka tjetĂ«r qĂ« ekziston nĂ« envoy nga kutia ose implementohet lehtĂ«sisht, kurse nĂ« nginx/haproxy duhet tĂ« ndihmojmĂ« me lua dhe plugina tĂ« dyshimta.

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

Si funksionon

Envoy shpërndahen në binarë vetëm si një imazh docker. Në imazh tashmë ka një shembull të konfiguracionit statik. Por ne na intereson vetëm për të kuptuar strukturën.

envoy.yaml konfigurimi statik

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
    # Komentoni linjën e mëposhtme për të testuar në rrjetet v6
    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

Konfigurimi dinamik

Cila është problemi që po kërkojmë zgjidhje? Nuk mund të thjeshtë të rinisni konfigurimin e balancuesit nën ngarkesë, do të ndodhin "probleme të vogla":

  • Validimi i konfigurimit.

Konfigi mund të jetë i madh, mund të jetë shumë i madh, nëse e rinisim të gjithë njëherësh, shanset për ndonjë gabim rriten.

  • Koneksione tĂ« gjata.

Kur inicializoni një listener të ri, duhet të kujdeseni për koneksionet që punojnë në të vjetër, nëse ndryshimet ndodhin shpesh dhe ka koneksione të gjata, do të duhet të kërkoni një kompromis. Përshëndetje, kubernetes ingress në nginx.

  • Kontroll tĂ« shĂ«ndetit aktiv.

Nëse kemi kontroll të shëndetit aktiv, duhet t'i kontrollojmë të gjitha në konfigurimin e ri para se të dërgojmë trafik. Nëse ka shumë upstream-e, kjo kërkon kohë. Përshëndetje, haproxy.

Si zgjidhet kjo në envoy, duke ngarkon dinamikisht konfigurimin, sipas modelit të pulave, mund ta ndajë atë në pjesë të veçanta dhe të mos ri-inicializojë atë pjesën që nuk është ndryshuar. P.sh., një listener, që rinekalon është e kushtueshme, por ndodhi rrallë.

Konfigurimi envoy (nga skedari më sipër) ka këto entitete:

  • listener — njĂ« listener qĂ« Ă«shtĂ« nĂ« njĂ« ip/port tĂ« caktuar
  • virtual host — njĂ« host virtual sipas emrit tĂ« domain-it
  • route — njĂ« rregull balancimi
  • cluster — njĂ« grup upstream-Ă«sh me parametrat e balancimit
  • endpoint — adresa e instancĂ«s sĂ« upstream-it

Secili 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, preferohet përdorimi i gRPC.

Shërbimet quhen përkatësisht: LDS, VHDS, RDS, CDS dhe EDS. Mund të kombinohen konfigurimet statike dhe dinamike, me kufizimin që burimi dinamik nuk mund të përcaktohet në atë statik.

Për shumicën e detyrave, është e mjaftueshme të realizohen tre shërbimet e fundit, ato quhen ADS (Aggregrated Discovery Service), për java dhe për go ka një implementim të gatshëm gRPC dataplane që është e mjaftueshme të plotësohen vetëm 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 të filloni, envoy me këtë konfigurim, ai do t'i bashkohet control-plane dhe do të përpiqet të kërkojë konfigurimin RDS, CDS dhe EDS. Si ndodh procesi i ndërveprimit është përshkruar këtu.

Në mënyrë të shkurtër, envoy ai dërgon një kërkesë, me shenjimin e llojit të burimit të kërkuar, versionit dhe parametrave të nodës. Në përgjigje merr burimin dhe versionin, nëse në control-plane versioni nuk ka ndryshuar, ai nuk përgjigjet.
Ka 4 variante ndërveprimi:

  • NjĂ« gRPC stream pĂ«r tĂ« gjitha llojet e burimeve, dĂ«rgohet gjendja e plotĂ« e burimit.
  • Stream tĂ« veçanta, gjendja e plotĂ«.
  • NjĂ« stream, gjendja inkrementale.
  • Stream tĂ« veçanta, gjendja inkrementale.

Incremental xDS lejon zvogëlimin e trafikut midis 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 lista e burimeve për anullim dhe regjistrim.

NĂ« shembullin tonĂ« pĂ«rdoreshin ADS — njĂ« stream pĂ«r RDS, CDS, EDS dhe jo nĂ« mĂ«nyrĂ« inkrementale. PĂ«r tĂ« aktivizuar modin inkrental, duhet tĂ« tregohet api_type: DELTA_GRPC

Duke qenë se në kërkesë ka parameter të nodës, mund të dërgojmë burime të ndryshme për instance të ndryshme në control-plane envoy, kjo është e përshtatshme për ndërtimin e një rrjeti shërbimesh.

Ngrohja

Në envoy në fillim ose kur merr një konfigurim të ri nga control-plane nis procesin e ngrohjes së burimeve. Ai ndahet në ngrohjen e listener-it dhe ngrohjen e cluster-it. E para niset kur ka ndryshime në RDS/LDS, e dyta kur ka CDS/EDS. Kjo do të thotë se nëse ndodhin vetëm ndryshime në upstream, listener-i nuk rinovohet.

Gjatë procesit të ngrohjes, priten burime të varura nga control-plane për një periudhë të caktuar kohore. Nëse ka kaluar koha e caktuar, inicializimi nuk do të jetë i suksesshëm, listener-i i ri nuk do të fillojë të dëgjojë portin.
Rendi i inicializimit: EDS, CDS, vlerësimi aktiv të shëndetit, RDS, LDS. Me vlerësimet e shëndetit aktiv të aktivizuara, trafiku do të shkojë në upstream, vetëm pas një vlerësimi të suksesshëm.

Nëse është ri-inicializuar listener-i, i vjetri kalon në gjendjen DRAIN dhe do të hiqet pas mbylljes së të gjitha lidhjeve ose kalimit të kohës së caktuar --drain-time-s, në mënyrë default 10 minuta.

Vazhdon.

Burimi: habr.com

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