Migratie van Nginx naar Envoy Proxy

Hallo, Habr! Ik breng een vertaling van het bericht onder uw aandacht: Migratie van Nginx naar Envoy Proxy.

Envoy is een krachtige gedistribueerde proxyserver (geschreven in C++) ontworpen voor individuele services en applicaties. Het is ook een communicatiebus en een ‘universeel datavlak’ ontworpen voor grote microservice ‘service mesh’-architecturen. Bij het maken ervan werd rekening gehouden met oplossingen voor problemen die ontstonden tijdens de ontwikkeling van servers zoals NGINX, HAProxy, hardware load balancers en cloud load balancers. Envoy werkt samen met elke applicatie en abstraheert het netwerk om gemeenschappelijke functionaliteit te bieden, ongeacht het platform. Wanneer al het serviceverkeer in een infrastructuur door het Envoy-gaas stroomt, wordt het eenvoudig om probleemgebieden met consistente waarneembaarheid te visualiseren, de algehele prestaties af te stemmen en kernfunctionaliteit op een specifieke locatie toe te voegen.

Mogelijkheden

  • Out-of-process-architectuur: envoy is een op zichzelf staande, krachtige server die een kleine hoeveelheid RAM in beslag neemt. Het werkt in combinatie met elke applicatietaal of raamwerk.
  • http/2- en grpc-ondersteuning: envoy biedt eersteklas http/2- en grpc-ondersteuning voor inkomende en uitgaande verbindingen. Dit is een transparante proxy van http/1.1 tot http/2.
  • Geavanceerde taakverdeling: envoy ondersteunt geavanceerde functies voor taakverdeling, waaronder automatische nieuwe pogingen, ketenverbreking, globale snelheidsbeperking, schaduw van verzoeken, taakverdeling in lokale zones, enz.
  • Configuratiebeheer-API: envoy biedt een robuuste API voor het dynamisch beheren van uw configuratie.
  • Waarneembaarheid: Diepe waarneembaarheid van L7-verkeer, native ondersteuning voor gedistribueerde tracering en waarneembaarheid van mongodb, dynamodb en vele andere toepassingen.

Stap 1 — Voorbeeld NGINX-configuratie

Dit script maakt gebruik van een speciaal vervaardigd bestand nginx.conf, gebaseerd op het volledige voorbeeld uit NGINX-wiki. U kunt de configuratie in de editor bekijken door te openen nginx.conf

nginx bronconfiguratie

user  www www;
pid /var/run/nginx.pid;
worker_processes  2;

events {
  worker_connections   2000;
}

http {
  gzip on;
  gzip_min_length  1100;
  gzip_buffers     4 8k;
  gzip_types       text/plain;

  log_format main      '$remote_addr - $remote_user [$time_local]  '
    '"$request" $status $bytes_sent '
    '"$http_referer" "$http_user_agent" '
    '"$gzip_ratio"';

  log_format download  '$remote_addr - $remote_user [$time_local]  '
    '"$request" $status $bytes_sent '
    '"$http_referer" "$http_user_agent" '
    '"$http_range" "$sent_http_content_range"';

  upstream targetCluster {
    172.18.0.3:80;
    172.18.0.4:80;
  }

  server {
    listen        8080;
    server_name   one.example.com  www.one.example.com;

    access_log   /var/log/nginx.access_log  main;
    error_log  /var/log/nginx.error_log  info;

    location / {
      proxy_pass         http://targetCluster/;
      proxy_redirect     off;

      proxy_set_header   Host             $host;
      proxy_set_header   X-Real-IP        $remote_addr;
    }
  }
}

NGINX-configuraties hebben doorgaans drie sleutelelementen:

  1. Configureren van de NGINX-server, logstructuur en Gzip-functionaliteit. In alle gevallen is dit globaal gedefinieerd.
  2. NGINX configureren om verzoeken aan de host te accepteren een.voorbeeld.com op poort 8080.
  3. De doellocatie instellen, hoe om te gaan met verkeer voor verschillende delen van de URL.

Niet alle configuraties zijn van toepassing op Envoy Proxy en u hoeft sommige instellingen niet te configureren. Gezant Proxy heeft vier sleuteltypen, die de kerninfrastructuur ondersteunen die wordt aangeboden door NGINX. De kern is:

  • Luisteraars: Ze bepalen hoe Envoy Proxy inkomende verzoeken accepteert. Envoy Proxy ondersteunt momenteel alleen op TCP gebaseerde luisteraars. Zodra een verbinding tot stand is gebracht, wordt deze ter verwerking aan een reeks filters doorgegeven.
  • Filters: Ze maken deel uit van een pijplijnarchitectuur die inkomende en uitgaande gegevens kan verwerken. Deze functionaliteit omvat filters zoals Gzip, die de gegevens comprimeert voordat deze naar de client worden verzonden.
  • Routers: Ze sturen verkeer door naar de vereiste bestemming, gedefinieerd als een cluster.
  • Clusters: Ze definiëren het eindpunt voor verkeer en configuratieparameters.

We zullen deze vier componenten gebruiken om een ​​Envoy Proxy-configuratie te maken die past bij een specifieke NGINX-configuratie. Het doel van Envoy is om te werken met API's en dynamische configuratie. In dit geval gebruikt de basisconfiguratie statische, hardgecodeerde instellingen van NGINX.

Stap 2 - NGINX-configuratie

Het eerste deel nginx.conf definieert enkele NGINX-internals die moeten worden geconfigureerd.

Verbindingen met werknemers

Onderstaande configuratie bepaalt het aantal werkprocessen en verbindingen. Dit geeft aan hoe NGINX zal opschalen om aan de vraag te voldoen.

worker_processes  2;

events {
  worker_connections   2000;
}

Envoy Proxy beheert workflows en verbindingen op verschillende manieren.

Envoy maakt een werkthread voor elke hardwarethread op het systeem. Elke werkthread voert een niet-blokkerende gebeurtenislus uit die verantwoordelijk is voor

  1. Luisteren naar elke luisteraar
  2. Nieuwe verbindingen accepteren
  3. Een set filters maken voor een verbinding
  4. Verwerk alle I/O-bewerkingen tijdens de levensduur van de verbinding.

Alle verdere verbindingsverwerking wordt volledig afgehandeld in de werkthread, inclusief eventueel doorstuurgedrag.

Voor elke werkthread in Envoy is er een verbindingspool. HTTP/2-verbindingspools brengen dus slechts één verbinding per externe host tegelijk tot stand. Als er vier werkthreads zijn, zijn er vier HTTP/2-verbindingen per externe host in een stabiele staat. Door alles in één werkthread te bewaren, kan bijna alle code zonder blokkering worden geschreven, alsof het een enkele thread is. Als er meer werkthreads worden toegewezen dan nodig is, kan dit leiden tot geheugenverspilling, waardoor een groot aantal inactieve verbindingen ontstaat en het aantal keren dat verbindingen worden teruggestuurd naar de pool wordt verminderd.

Voor meer informatie bezoek Envoy Proxy-blog.

HTTP-configuratie

Het volgende NGINX-configuratieblok definieert HTTP-instellingen zoals:

  • Welke mime-typen worden ondersteund
  • Standaard time-outs
  • Gzip-configuratie

U kunt deze aspecten aanpassen met behulp van filters in Envoy Proxy, die we later zullen bespreken.

Stap 3 - Serverconfiguratie

In het HTTP-configuratieblok specificeert de NGINX-configuratie dat er op poort 8080 moet worden geluisterd en moet worden gereageerd op inkomende aanvragen voor domeinen een.voorbeeld.com и www.één.voorbeeld.com.

 server {
    listen        8080;
    server_name   one.example.com  www.one.example.com;

Binnen Envoy wordt het beheerd door Listeners.

Gezant luisteraars

Het belangrijkste aspect bij het aan de slag gaan met Envoy Proxy is het definiëren van uw luisteraars. U moet een configuratiebestand maken waarin wordt beschreven hoe u de Envoy-instantie wilt uitvoeren.

Met het onderstaande fragment wordt een nieuwe luisteraar gemaakt en deze aan poort 8080 gekoppeld. De configuratie vertelt Envoy Proxy aan welke poorten deze moet binden voor inkomende verzoeken.

Envoy Proxy gebruikt de YAML-notatie voor de configuratie. Voor een inleiding tot deze notatie, kijk hier link.

Copy to Editorstatic_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 8080 }

Het is niet nodig om te definiëren server naam, aangezien Envoy Proxy-filters dit afhandelen.

Stap 4 - Locatieconfiguratie

Wanneer een verzoek binnenkomt in NGINX, bepaalt het locatieblok hoe het verkeer moet worden verwerkt en waar het naartoe moet worden gerouteerd. In het volgende fragment wordt al het verkeer naar de site overgebracht naar een upstream-cluster (opmerking van de vertaler: upstream is meestal een applicatieserver) met de naam doelCluster. Het upstreamcluster definieert de knooppunten die het verzoek moeten verwerken. We zullen dit in de volgende stap bespreken.

location / {
    proxy_pass         http://targetCluster/;
    proxy_redirect     off;

    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
}

Bij Envoy doet Filters dit.

Envoy-filters

Bij een statische configuratie bepalen filters hoe binnenkomende aanvragen moeten worden verwerkt. In dit geval stellen we filters in die overeenkomen servernamen in de vorige stap. Wanneer er binnenkomende verzoeken binnenkomen die overeenkomen met bepaalde domeinen en routes, wordt het verkeer naar het cluster gerouteerd. Dit is het equivalent van een NGINX bottom-up configuratie.

Copy to Editor    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        config:
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains:
                - "one.example.com"
                - "www.one.example.com"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: targetCluster
          http_filters:
          - name: envoy.router

naam envoy.http_connection_manager is een ingebouwd filter in Envoy Proxy. Andere filters omvatten Redis, Mongo, TCP. De volledige lijst vindt u op documentatie.

Ga voor meer informatie over ander beleid voor taakverdeling naar Documentatie van de gezant.

Stap 5 - Proxy- en upstream-configuratie

In NGINX definieert de upstream-configuratie een reeks doelservers die het verkeer zullen verwerken. In dit geval werden twee clusters toegewezen.

  upstream targetCluster {
    172.18.0.3:80;
    172.18.0.4:80;
  }

In Envoy wordt dit beheerd door clusters.

Gezantenclusters

Het stroomopwaartse equivalent wordt gedefinieerd als clusters. In dit geval zijn de hosts die het verkeer zullen bedienen geïdentificeerd. De manier waarop hosts worden benaderd, zoals time-outs, wordt gedefinieerd als een clusterconfiguratie. Dit zorgt voor een meer gedetailleerde controle over aspecten zoals latentie en load-balancing.

Copy to Editor  clusters:
  - name: targetCluster
    connect_timeout: 0.25s
    type: STRICT_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    hosts: [
      { socket_address: { address: 172.18.0.3, port_value: 80 }},
      { socket_address: { address: 172.18.0.4, port_value: 80 }}
    ]

Bij gebruik van servicedetectie STRICT_DNS Envoy zal de opgegeven DNS-doelen continu en asynchroon omzetten. Elk geretourneerd IP-adres uit het DNS-resultaat wordt beschouwd als een expliciete host in het upstream-cluster. Dit betekent dat als een verzoek twee IP-adressen retourneert, Envoy ervan uitgaat dat er twee hosts in het cluster zijn en dat beide in taakverdeling moeten zijn. Als een host uit het resultaat wordt verwijderd, gaat Envoy ervan uit dat deze niet langer bestaat en haalt het verkeer uit bestaande verbindingspools.

Voor meer informatie zie Documentatie voor gezantproxy.

Stap 6 — Logtoegang en fouten

De laatste configuratie is registratie. In plaats van foutlogboeken naar schijf te pushen, kiest Envoy Proxy voor een cloudgebaseerde aanpak. Alle applicatielogboeken worden uitgevoerd naar stdout и stderr.

Wanneer gebruikers een verzoek indienen, zijn toegangslogboeken optioneel en standaard uitgeschakeld. Om toegangslogboeken voor HTTP-verzoeken in te schakelen, schakelt u de configuratie in toegang_log voor de HTTP-verbindingsbeheerder. Het pad kan een apparaat zijn, zoals stdout, of een bestand op schijf, afhankelijk van uw vereisten.

De volgende configuratie zal alle toegangslogboeken omleiden naar stdout (Opmerking van de vertaler: stdout is vereist om envoy in docker te gebruiken. Indien gebruikt zonder docker, vervang dan /dev/stdout door het pad naar een normaal logbestand). Kopieer het fragment naar de configuratiesectie voor Verbindingsbeheer:

Copy to Clipboardaccess_log:
- name: envoy.file_access_log
  config:
    path: "/dev/stdout"

De resultaten zouden er als volgt uit moeten zien:

      - name: envoy.http_connection_manager
        config:
          codec_type: auto
          stat_prefix: ingress_http
          access_log:
          - name: envoy.file_access_log
            config:
              path: "/dev/stdout"
          route_config:

Standaard heeft Envoy een indelingsreeks die de details van het HTTP-verzoek bevat:

[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"n

Het resultaat van deze formatstring is:

[2018-11-23T04:51:00.281Z] "GET / HTTP/1.1" 200 - 0 58 4 1 "-" "curl/7.47.0" "f21ebd42-6770-4aa5-88d4-e56118165a7d" "one.example.com" "172.18.0.4:80"

De uitvoerinhoud kan worden aangepast door het formaatveld in te stellen. Bijvoorbeeld:

access_log:
- name: envoy.file_access_log
  config:
    path: "/dev/stdout"
    format: "[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"n"

De logregel kan ook in JSON-formaat worden uitgevoerd door het veld in te stellen json_format. Bijvoorbeeld:

access_log:
- name: envoy.file_access_log
  config:
    path: "/dev/stdout"
    json_format: {"protocol": "%PROTOCOL%", "duration": "%DURATION%", "request_method": "%REQ(:METHOD)%"}

Ga voor meer informatie over de Envoy-registratiemethode naar

https://www.envoyproxy.io/docs/envoy/latest/configuration/access_log#config-access-log-format-dictionaries

Loggen is niet de enige manier om inzicht te krijgen in het werken met Envoy Proxy. Er zijn geavanceerde tracerings- en metrische mogelijkheden ingebouwd. Meer informatie vindt u op documentatie traceren of via Interactief traceringsscript.

Stap 7 - Start

U hebt nu uw configuratie gemigreerd van NGINX naar Envoy Proxy. De laatste stap is het starten van een Envoy Proxy-instantie om deze te testen.

Uitvoeren als gebruiker

Bovenaan de NGINX-configuratieregel gebruiker www www; specificeert om NGINX uit te voeren als een gebruiker met weinig rechten om de beveiliging te verbeteren.

Envoy Proxy hanteert een cloudgebaseerde aanpak om te beheren wie eigenaar is van een proces. Wanneer we Envoy Proxy via een container uitvoeren, kunnen we een gebruiker met weinig bevoegdheden opgeven.

Lancering van Envoy Proxy

Met de onderstaande opdracht wordt Envoy Proxy uitgevoerd via een Docker-container op de host. Met deze opdracht kan Envoy luisteren naar binnenkomende verzoeken op poort 80. Zoals gespecificeerd in de luisteraarconfiguratie luistert Envoy Proxy echter naar inkomend verkeer op poort 8080. Hierdoor kan het proces worden uitgevoerd als een gebruiker met weinig bevoegdheden.

docker run --name proxy1 -p 80:8080 --user 1000:1000 -v /root/envoy.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy

Testen

Terwijl de proxy draait, kunnen er nu tests worden gemaakt en verwerkt. De volgende cURL-opdracht geeft een verzoek uit waarbij de host-header is gedefinieerd in de proxyconfiguratie.

curl -H "Host: one.example.com" localhost -i

Het HTTP-verzoek resulteert in een fout 503. Dit komt omdat upstream-verbindingen niet werken en niet beschikbaar zijn. Daarom heeft Envoy Proxy geen beschikbare bestemmingen voor de aanvraag. Met de volgende opdracht wordt een reeks HTTP-services gestart die overeenkomen met de configuratie die voor Envoy is gedefinieerd.

docker run -d katacoda/docker-http-server; docker run -d katacoda/docker-http-server;

Met de beschikbare services kan Envoy verkeer met succes naar de bestemming sturen.

curl -H "Host: one.example.com" localhost -i

U zou een antwoord moeten zien dat aangeeft welke Docker-container het verzoek heeft verwerkt. In de Envoy Proxy-logboeken zou u ook een toegangsreeksuitvoer moeten zien.

Aanvullende HTTP-antwoordheaders

U ziet aanvullende HTTP-headers in de antwoordheaders van het daadwerkelijke verzoek. De header geeft de tijd weer die de upstream-host heeft besteed aan het verwerken van het verzoek. Uitgedrukt in milliseconden. Dit is handig als de client de servicetijd wil bepalen in vergelijking met de netwerklatentie.

x-envoy-upstream-service-time: 0
server: envoy

Laatste configuratie

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 8080 }
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        config:
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains:
                - "one.example.com"
                - "www.one.example.com"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: targetCluster
          http_filters:
          - name: envoy.router
          clusters:
  - name: targetCluster
    connect_timeout: 0.25s
    type: STRICT_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    hosts: [
      { socket_address: { address: 172.18.0.3, port_value: 80 }},
      { socket_address: { address: 172.18.0.4, port_value: 80 }}
    ]

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 0.0.0.0, port_value: 9090 }

Aanvullende informatie van de vertaler

Instructies voor het installeren van Envoy Proxy vindt u op de website https://www.getenvoy.io/

Standaard heeft rpm geen systemd-serviceconfiguratie.

Systemd-serviceconfiguratie /etc/systemd/system/envoy.service toevoegen:

[Unit]
Description=Envoy Proxy
Documentation=https://www.envoyproxy.io/
After=network-online.target
Requires=envoy-auth-server.service
Wants=nginx.service

[Service]
User=root
Restart=on-failure
ExecStart=/usr/bin/envoy --config-path /etc/envoy/config.yaml
[Install]
WantedBy=multi-user.target

U moet een map /etc/envoy/ maken en daar de configuratie config.yaml plaatsen.

Er is een telegramchat waarbij gebruik wordt gemaakt van een gezant-proxy: https://t.me/envoyproxy_ru

Envoy Proxy biedt geen ondersteuning voor het weergeven van statische inhoud. Wie kan er dus op de functie stemmen: https://github.com/envoyproxy/envoy/issues/378

Alleen geregistreerde gebruikers kunnen deelnemen aan het onderzoek. Inloggen, Alsjeblieft.

Heeft dit bericht je aangemoedigd om Envoy Proxy te installeren en te testen?

  • ja

  • geen

75 gebruikers hebben gestemd. 18 gebruikers onthielden zich van stemming.

Bron: www.habr.com

Voeg een reactie