sugo. 1. Panimula

Pagbati! Sinasagot ng maikling artikulong ito ang mga tanong: "Ano ang Envoy?", "Bakit ko ito kailangan?", at "Saan ako magsisimula?"

Ano ito?

Ang Envoy ay isang L4-L7 load balancer na nakasulat sa C++, na nakatuon sa mataas na performance at availability. Sa isang banda, ito ay medyo kahalintulad sa nginx at haproxy, maihahambing sa pagganap. Sa kabilang banda, mas nakatuon ito sa mga arkitektura ng microservice at nag-aalok ng functionality na maihahambing sa mga load balancer ng Java at Go, gaya ng zuul o traefik.

Ang haproxy/nginx/envoy comparison table ay hindi inaangkin na ang ganap na katotohanan, ngunit ito ay nagbibigay ng pangkalahatang larawan.

nginx
haproxy
nagpadala
traefik

mga bituin sa GitHub
11.2k/salamin
1.1k/salamin
12.4k
27.6k

nakasulat sa
C
C
C + +
go

API
hindi
socket lang/push
dataplane/pull
paghila

aktibong pagsusuri sa kalusugan
hindi
oo
oo
oo

Buksan ang pagsubaybay
panlabas na plugin
hindi
oo
oo

J.W.T.
panlabas na plugin
hindi
oo
hindi

palugit
Lua/C
Lua/C
Lua/C++
hindi

Ano para sa

Ito ay isang batang proyekto, mayroong maraming mga bagay na nawawala, ang ilan sa mga ito ay nasa maagang alpha. Pero nagpadala, bahagyang dahil sa kabataan nito, ay mabilis na umuunlad at mayroon nang maraming kawili-wiling mga tampok: dynamic na pagsasaayos, maraming handa na mga filter, isang simpleng interface para sa pagsulat ng iyong sariling mga filter.
Ang mga lugar ng aplikasyon ay sumusunod mula dito, ngunit una, dalawang anti-pattern:

  • Static recoil.

Ang bagay ay na sa sandaling ito sa nagpadala Walang suporta sa pag-cache. Sinusubukan ng mga lalaki sa Google na ayusin ito. upang ayusinAng ideya ay upang ipatupad ito paminsan-minsan nagpadala Ang lahat ng mga subtleties (isang zoo ng mga header) ng pagsunod sa RFC, at lumikha ng isang interface para sa mga partikular na pagpapatupad. Ngunit hindi pa ito alpha; pinag-uusapan pa rin ang arkitektura. PR bukas (habang isinusulat ko ang artikulo, ang PR ay pinagsama, ngunit ang puntong ito ay may kaugnayan pa rin).

Samantala, gumamit ng nginx para sa statics.

  • Static na pagsasaayos.

Maaari mong gamitin ito, ngunit nagpadala Hindi ito ginawa para sa layuning ito. Ang mga kakayahan ng isang static na pagsasaayos ay hindi ganap na maisasakatuparan. Mayroong maraming mga puntos:

Kapag nag-e-edit ng configuration ng YAML, magkakamali ka, susumpain ang mga developer sa pagiging masyadong verbose, at iniisip na ang nginx/haproxy configs, habang hindi gaanong structured, ay mas maigsi. Iyon ang punto. Ang mga configuration ng Nginx at Haproxy ay nilikha para sa manu-manong pag-edit, habang nagpadala para sa henerasyon mula sa code. Ang buong configuration ay inilarawan sa protobuf, ang pagbuo nito mula sa mga proto file ay ginagawang mas mahirap na magkamali.

Ang mga scenario ng Canary, b/g deployment, at marami pang ibang bagay ay maipapatupad lang nang maayos sa isang dynamic na configuration. Hindi ko sinasabing hindi sila maaaring gawin nang static; ginagawa nating lahat yan. Ngunit upang magawa ito, kailangan mong gumamit ng ilang mga solusyon, sa anumang balanse, sa nagpadala kasama ang.

Mga gawain kung saan kailangang-kailangan ang Envoy:

  • Pagbalanse ng trapiko sa kumplikado at dynamic na mga sistema. Kabilang dito ang mesh ng serbisyo, ngunit hindi ito kinakailangang limitado dito.
  • Ang pangangailangan para sa distributed tracing, complex authorization, o iba pang functionality na available sa nagpadala Madali itong ipatupad sa labas ng kahon o maginhawa, habang sa nginx/haproxy kailangan mong i-wrap ang iyong sarili sa lua at mga kaduda-dudang plugin.

Parehong magagamit upang magbigay ng mataas na pagganap kapag kinakailangan.

Как это работает

Ang Envoy ay ipinamahagi bilang isang binary Docker na imahe lamang. Kasama na sa larawan ang isang sample na static na configuration, ngunit interesado lang kami dito upang maunawaan ang istraktura.

envoy.yaml static na configuration

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

Dynamic na pagsasaayos

Anong problema ang hinahanap nating lutasin? Hindi lang natin mai-reload ang configuration ng load balancer; ilang "minor" na isyu ang lalabas:

  • Pagpapatunay ng configuration.

Ang config ay maaaring malaki, maaari itong maging napakalaki, kung labis nating i-overload ang lahat ng ito nang sabay-sabay, ang mga pagkakataon ng isang error sa isang lugar ay tumataas.

  • Mga pangmatagalang compound.

Kapag nagpapasimula ng isang bagong tagapakinig, kailangan mong alagaan ang mga koneksyon na tumatakbo sa luma. Kung madalas mangyari ang mga pagbabago at may mga pangmatagalang koneksyon, kailangan mong maghanap ng kompromiso. Hello, Kubernetes ingress sa nginx.

  • Mga aktibong pagsusuri sa kalusugan.

Kung mayroon kaming mga aktibong pagsusuri sa kalusugan, dapat naming suriin muli ang lahat sa bagong configuration bago magpadala ng trapiko. Kung mayroong maraming upstream, ito ay tumatagal ng oras. Hello, haproxy.

Paano ito naresolba sa nagpadalaSa pamamagitan ng dynamic na paglo-load ng configuration gamit ang isang model pool, maaari mong hatiin ito sa magkakahiwalay na bahagi at maiwasang muling simulan ang mga bahaging hindi nagbago. Halimbawa, maaaring gamitin ang isang tagapakinig, na mahal upang muling simulan at bihirang magbago.

Configuration nagpadala (mula sa file sa itaas) ay may mga sumusunod na entity:

  • nakikinig — isang tagapakinig na nakabitin sa isang partikular na IP/port
  • virtual host — virtual host sa pamamagitan ng domain name
  • ruta — tuntunin sa pagbabalanse
  • kumpol — isang pangkat ng mga upstream na may mga parameter ng pagbabalanse
  • endpoint — upstream na instance address

Ang bawat isa sa mga entity na ito, kasama ang ilang iba pa, ay maaaring dynamic na ma-populate sa pamamagitan ng pagtukoy sa address ng serbisyo kung saan kukunin ang configuration sa configuration. Maaaring REST o gRPC ang serbisyo, ngunit mas gusto ang gRPC.

Ang mga serbisyo ay pinangalanan nang naaayon: LDS, VHDS, RDS, CDS, at EDS. Maaaring pagsamahin ang mga static at dynamic na configuration, kasama ang caveat na hindi maaaring tukuyin ang isang dynamic na mapagkukunan sa loob ng isang static.

Para sa karamihan ng mga gawain, sapat na upang ipatupad ang huling tatlong serbisyo, ang mga ito ay tinatawag na ADS (Aggregated Discovery Service), para sa Dyaba and go ay may handa nang pagpapatupad ng gRPC dataplane, kung saan kailangan mo lang punan ang mga bagay mula sa iyong pinagmulan.

Ang pagsasaayos ay tumatagal ng sumusunod na anyo:

envoy.yaml dynamic na configuration

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

Sa pagsisimula nagpadala Gamit ang configuration na ito, ito ay kumonekta sa control plane at susubukang hilingin ang RDS, CDS, at EDS configuration. Ang proseso ng pakikipag-ugnayan ay inilarawan sa ibaba. dito.

Sa madaling salita, nagpadala Nagpapadala ng kahilingan na tumutukoy sa hiniling na uri ng mapagkukunan, bersyon, at mga parameter ng node. Natatanggap nito ang mapagkukunan at bersyon bilang tugon. Kung ang bersyon sa control plane ay hindi nagbago, hindi ito tumutugon.
Mayroong 4 na opsyon para sa pakikipag-ugnayan:

  • Isang gRPC stream para sa lahat ng uri ng mapagkukunan, ang buong estado ng mapagkukunan ay ipinadala.
  • Hiwalay na mga batis, buong kondisyon.
  • Isang stream, incremental na estado.
  • Hiwalay na mga stream, incremental na estado.

Ang incremental na xDS ay nagbibigay-daan upang bawasan ang trapiko sa pagitan ng control-plane at nagpadalaIto ay may kaugnayan para sa malalaking configuration. Gayunpaman, pinapalubha nito ang pakikipag-ugnayan, dahil ang kahilingan ay nangangailangan ng isang listahan ng mga mapagkukunan upang mag-unsubscribe at mag-subscribe.

Gumagamit ang aming halimbawa ng ADS—isang stream para sa RDS, CDS, EDS, at non-incremental mode. Upang paganahin ang incremental mode, kailangan mong tukuyin api_type: DELTA_GRPC

Dahil ang kahilingan ay naglalaman ng mga parameter ng node, maaari kaming magpadala ng iba't ibang mga mapagkukunan sa control plane para sa iba't ibang mga pagkakataon. nagpadala, ito ay maginhawa para sa pagbuo ng isang service mesh.

Pag-init

Sa nagpadala Sa startup o kapag tumatanggap ng bagong configuration mula sa control plane, inilulunsad ang proseso ng pag-init ng mapagkukunan. Nahahati ito sa listener warmup at cluster warmup. Ang una ay inilunsad kapag nagbago ang RDS/LDS, ang huli ay kapag nagbago ang CDS/EDS. Nangangahulugan ito na kung ang mga upstream lamang ang nagbabago, ang nakikinig ay hindi muling nilikha.

Sa panahon ng proseso ng warmup, ang mga umaasa na mapagkukunan mula sa control plane ay hinihintay sa panahon ng timeout. Kung mag-expire ang timeout, mabibigo ang initialization, at hindi magsisimulang makinig ang bagong listener sa port.
Order ng pagsisimula: EDS, CDS, aktibong pagsusuri sa kalusugan, RDS, LDS. Kung ang mga aktibong pagsusuri sa kalusugan ay pinagana, ang trapiko ay aakyat lamang pagkatapos ng isang matagumpay na pagsusuri sa kalusugan.

Kung muling likhain ang isang tagapakinig, ang luma ay mapupunta sa DRAIN na estado at tatanggalin pagkatapos maisara ang lahat ng koneksyon o mag-expire ang timeout. --drain-time-s, default na 10 minuto.

Upang magpatuloy.

Pinagmulan: www.habr.com

Magdagdag ng komento