Gezant. 1. Inleiding

Groeten! Dit is een kort artikel dat antwoord geeft op de vragen: “wat is een gezant?”, “waarom is het nodig?” en "waar te beginnen?".

Wat is dit

Envoy is een L4-L7-balancer geschreven in C++, gericht op hoge prestaties en beschikbaarheid. Aan de ene kant is dit op de een of andere manier een analoog van nginx en haproxy, qua prestaties vergelijkbaar met hen. Aan de andere kant is het meer gericht op microservice-architectuur en heeft het functionaliteit niet slechter dan java en go balancers, zoals zuul of traefik.

Vergelijkingstabel van haproxy/nginx/envoy, het beweert niet de absolute waarheid te zijn, maar geeft een algemeen beeld.

nginx
haproxy
verzonden
Traefik

sterren op github
11.2k/spiegel
1.1k/spiegel
12.4k
27.6k

geschreven in
C
C
C + +
go

API
geen
alleen stopcontact/duwen
datavlak/trekken
trek

actieve gezondheidscheck
geen
ja
ja
ja

Open traceren
externe plug-in
geen
ja
ja

JWT
externe plug-in
geen
ja
geen

uitbreiding
Lua/C
Lua/C
Lua/C++
geen

Wat voor

Dit is een jong project, er ontbreken veel dingen, sommige bevinden zich in de vroege alfa. Maar verzonden, mede door zijn jeugd, ontwikkelt zich snel en heeft al veel interessante features: dynamische configuratie, veel kant-en-klare filters, een eenvoudige interface om je eigen filters te schrijven.
Hieruit volgen toepassingsgebieden, maar eerst zijn er 2 antipatronen:

  • Statische terugslag.

Feit is dat er op dit moment in verzonden geen caching-ondersteuning. De Google-jongens proberen dit op te lossen. Het idee zal eenmalig worden uitgevoerd verzonden alle subtiliteiten (zoo headers) van RFC-compliance, en voor specifieke implementaties een interface maken. Maar voorlopig is het niet eens alfa, de architectuur staat ter discussie, PR open (terwijl ik het PR-artikel aan het schrijven was, bevroor de PR, maar dit punt is nog steeds relevant).

Gebruik voorlopig nginx voor statische gegevens.

  • Statische configuratie.

Je kunt het gebruiken, maar verzonden Daar is het niet voor gemaakt. Functies in een statische configuratie worden niet zichtbaar. Er zijn veel momenten:

Bij het bewerken van de configuratie in yaml zul je je vergissen, de ontwikkelaars uitschelden voor breedsprakigheid en denken dat de nginx/haproxy-configuraties, hoewel minder gestructureerd, beknopter zijn. Dat is het punt. De configuratie van Nginx en Haproxy is gemaakt voor handmatige bewerking, en verzonden voor het genereren uit code. De gehele configuratie wordt beschreven in prototype, het genereren ervan uit protobestanden is veel moeilijker om een ​​fout te maken.

Implementatiescenario's van Canary, b/g en nog veel meer worden normaal gesproken alleen in een dynamische configuratie geïmplementeerd. Ik zeg niet dat dit niet statisch kan worden gedaan, we doen het allemaal. Maar hiervoor moet je krukken aantrekken, in een van de balancers, in verzonden met inbegrip van.

Taken waarvoor Envoy onmisbaar is:

  • Verkeersbalancering in complexe en dynamische systemen. Dit omvat de service mesh, maar dit is niet noodzakelijkerwijs de enige.
  • De behoefte aan gedistribueerde traceringsfunctionaliteit, complexe autorisatie of andere functionaliteit die beschikbaar is in verzonden out-of-the-box of handig geïmplementeerd, maar in nginx/haproxy moet je omringd zijn door lua en dubieuze plug-ins.

Beide leveren, indien nodig, hoge prestaties.

Hoe werkt dit

Envoy wordt alleen in binaire bestanden gedistribueerd als een docker-image. De afbeelding bevat al een voorbeeld van een statische configuratie. Maar we zijn er alleen in geïnteresseerd om de structuur te begrijpen.

envoy.yaml statische configuratie

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

Dynamische configuratie

Voor welk probleem zoeken we een oplossing? Je kunt de load balancer-configuratie niet zomaar opnieuw laden onder belasting; er zullen ‘kleine’ problemen optreden:

  • Configuratievalidatie.

De configuratie kan groot zijn, het kan heel groot zijn, als we het allemaal in één keer overbelasten, wordt de kans op een fout ergens groter.

  • Verbindingen met een lange levensduur.

Wanneer u een nieuwe luisteraar initialiseert, moet u zorgen voor de verbindingen die op de oude draaien; als er vaak wijzigingen optreden en er sprake is van verbindingen met een lange levensduur, moet u op zoek naar een compromis. Hallo, kubernetes-ingang op nginx.

  • Actieve gezondheidscontroles.

Als we actieve gezondheidscontroles hebben, moeten we ze allemaal dubbel controleren in de nieuwe configuratie voordat we verkeer verzenden. Als er veel upstreams zijn, kost dit tijd. Hallo haproxy.

Hoe wordt dit opgelost in verzondenDoor de configuratie dynamisch te laden, volgens het poolmodel, kunt u deze in afzonderlijke delen verdelen en het deel dat niet is gewijzigd niet opnieuw initialiseren. Bijvoorbeeld een luisteraar, die duur is om opnieuw te initialiseren en zelden verandert.

Configuratie verzonden (uit het bovenstaande bestand) heeft de volgende entiteiten:

  • luisteraar — luisteraar hangt aan een specifiek IP/poort
  • virtuele host - virtuele host op domeinnaam
  • route - evenwichtsregel
  • cluster — een groep upstreams met balanceringsparameters
  • eindpunt — adres van het stroomopwaartse exemplaar

Elk van deze entiteiten plus enkele andere kan dynamisch worden ingevuld; hiervoor specificeert de configuratie het adres van de service waarvandaan de configuratie zal worden ontvangen. De service kan REST of gRPC zijn, gRPC heeft de voorkeur.

De diensten heten respectievelijk: LDS, VHDS, RDS, CDS en EDS. U kunt een statische en dynamische configuratie combineren, met de beperking dat een dynamische bron niet kan worden gespecificeerd in een statische bron.

Voor de meeste taken is het voldoende om de laatste drie services te implementeren, deze worden ADS (Aggregated Discovery Service) genoemd. Java en daar is een kant-en-klare implementatie van gRPC-dataplane waarin u alleen de objecten uit uw bron hoeft in te vullen.

De configuratie heeft de volgende vorm:

envoy.yaml dynamische configuratie

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

Bij het uitvoeren van verzonden met deze configuratie zal het verbinding maken met het besturingsvlak en proberen de RDS-, CDS- en EDS-configuratie op te vragen. Er wordt beschreven hoe het interactieproces verloopt hier.

In het kort, verzonden verzendt een verzoek met vermelding van het type bron dat wordt aangevraagd, de versie en parameters van het knooppunt. Als reactie hierop ontvangt het een bron en een versie; als de versie op het besturingsvlak niet is gewijzigd, reageert het niet.
Er zijn 4 interactiemogelijkheden:

  • Eén gRPC-stream voor alle soorten bronnen, de volledige status van de bron wordt verzonden.
  • Aparte streams, volledige staat.
  • Eén stroom, incrementele status.
  • Afzonderlijke streams, incrementele status.

Met incrementele xDS kunt u het verkeer tussen het besturingsvlak en verzonden, dit is relevant voor grote configuraties. Maar het bemoeilijkt de interactie; het verzoek bevat een lijst met bronnen voor het afmelden en abonneren.

In ons voorbeeld wordt gebruik gemaakt van ADS: één stream voor RDS, CDS, EDS en niet-incrementele modus. Om de incrementele modus in te schakelen, moet u dit opgeven api_type: DELTA_GRPC

Omdat het verzoek knooppuntparameters bevat, kunnen we voor verschillende instanties verschillende bronnen naar het besturingsvlak sturen verzonden, dit is handig voor het bouwen van een servicemesh.

Opwarmen

Op verzonden bij het opstarten of bij het ontvangen van een nieuwe configuratie van het besturingsvlak wordt het opwarmproces van de bronnen gestart. Het is onderverdeeld in luisteraaropwarming en clusteropwarming. De eerste wordt gelanceerd wanneer er wijzigingen zijn in RDS/LDS, de tweede wanneer CDS/EDS. Dit betekent dat als alleen upstreams veranderen, de luisteraar niet opnieuw wordt gemaakt.

Tijdens het opwarmproces worden tijdens de time-out afhankelijke bronnen van het besturingsvlak verwacht. Als de time-out optreedt, zal de initialisatie niet succesvol zijn en zal de nieuwe luisteraar niet beginnen te luisteren op de poort.
Initialisatievolgorde: EDS, CDS, actieve statuscheck, RDS, LDS. Als actieve statuscontroles zijn ingeschakeld, wordt het verkeer pas na één succesvolle statuscontrole stroomopwaarts gestuurd.

Als de luisteraar opnieuw is gemaakt, gaat de oude naar de DRAIN-status en wordt verwijderd nadat alle verbindingen zijn gesloten of de time-out is verstreken --drain-time-s, standaard 10 minuten.

Worden voortgezet.

Bron: www.habr.com

Voeg een reactie