Migrering fra Nginx til Envoy Proxy

Hei, Habr! Jeg vil gjerne dele oversettelsen av dette innlegget med dere: Migrering fra Nginx til Envoy Proxy.

Envoy er en høyytelses, distribuert proxy-server (skrevet i C++) designet for individuelle tjenester og applikasjoner. Det fungerer også som en kommunikasjonsring og 'universal data plane', utviklet for store mikrotjenestearkitekturer, også kjent som service mesh. Under utviklingen ble det tatt hensyn til løsningene på problemer som oppsto med servere som NGINX, HAProxy, maskinvare belastningsbalansere og skybaserte belastningsbalansere. Envoy jobber sammen med hver applikasjon og abstraherer nettverket, og gir felles funksjoner uavhengig av plattform. Når all tjenestetrafikk i infrastrukturen går gjennom Envoy-nettet, blir det enkelt å visualisere problemområder ved hjelp av enhetlig observabilitet, justere felles ytelse og legge til kjernefunksjoner på spesifikke steder.

Funksjoner

  • Arkitektur utenfor prosessen: Envoy er en autonom, høyytelsesserver som krever lite minne. Den fungerer sammen med hvilket som helst programmeringsspråk eller rammeverk.
  • Støtte for http/2 og grpc: Envoy har førsteklasses støtte for http/2 og grpc for innkommende og utgående forbindelser. Det er en gjennomsiktig proxy fra http/1.1 til http/2.
  • Avansert belastningsbalansering: Envoy støtter avanserte funksjoner for belastningsbalansering, inkludert automatiske gjenopplivningsforsøk, kjedeavbrudd, global hastighetsbegrensning, forespørselsskyggelegging, lokal sonal belastningsbalansering osv.
  • API for konfigurasjonsstyring: Envoy tilbyr et robust API for dynamisk styring av sin konfigurasjon.
  • Observabilitet: Dyp observabilitet for L7-trafikk, innebygd støtte for distribuert sporing samt observabilitet for mongodb, dynamodb og mange andre applikasjoner.

Trinn 1 - Eksempel på NGINX-konfigurasjon

I dette scenariet brukes en spesiallaget fil nginx.conf, basert på et fullt eksempel fra NGINX Wiki. Du kan se konfigurasjonen i redaktøren ved å åpne nginx.conf

Den originale nginx-konfigurasjonen

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-konfigurasjoner har vanligvis tre nøkkelkomponenter:

  1. Konfigurasjon av NGINX-serveren, loggstrukturen og Gzip-funksjonaliteten. Dette defineres globalt i alle tilfeller.
  2. Konfigurasjon av NGINX for å motta forespørselene på verten one.example.com på port 8080.
  3. Konfigurasjon av målplasseringen, hvordan håndtere trafikk for forskjellige deler av URL-en.

Ikke all konfigurasjon vil bli anvendt på Envoy Proxy, og du trenger ikke å konfigurere noen parametre. Envoy Proxy har fire nøkkelkategorier, som støtter den grunnleggende infrastrukturen levert av NGINX. Kjernen er:

  • Lyttere: De definerer hvordan Envoy Proxy mottar innkommende forespørselen. For øyeblikket støtter Envoy Proxy bare lyttere basert på TCP. Når forbindelsen er etablert, blir den sendt til et sett med filtre for behandling.
  • Filtre: De er en del av en rørledningsarkitektur som kan håndtere innkommende og utgående data. Denne funksjonaliteten inkluderer filtre som Gzip, som komprimerer data før de sendes til klienten.
  • Rutere: De omdirigerer trafikk til den nødvendige destinasjonen, definert som en klynge.
  • Klynger: De definerer endepunktet for trafikken og konfigurasjonsparametrene.

Vi vil bruke disse fire komponentene for å opprette en konfigurasjon av Envoy Proxy for å samsvare med en spesifikk NGINX-konfigurasjon. Målet med Envoy er å jobbe med API-er og dynamisk konfigurasjon. I dette tilfellet vil den grunnleggende konfigurasjonen bruke statiske, faste parametre fra NGINX.

Trinn 2 — NGINX-konfigurasjon

Første del nginx.conf definerer noen interne komponenter av NGINX som må konfigureres.

Worker Connections

Den angitte konfigurasjonen definerer antallet arbeidsprosesser og forbindelser. Dette indikerer hvordan NGINX vil skalere for å imøtekomme etterspørselen.

worker_processes  2;

events {
  worker_connections   2000;
}

Envoy Proxy håndterer arbeidsprosesser og forbindelser på forskjellige måter.

Envoy lager en arbeidsstrøm for hver maskinvaretråd i systemet. Hver arbeidsstrøm kjører en ikke-blokkerende hendelsesløkke som er ansvarlig for

  1. Å lytte på hver lytter (listener)
  2. Å akseptere nye forbindelser
  3. Å lage et filtersett for forbindelsen
  4. Å håndtere alle inndata-og utgangsoperasjoner gjennom forbindelsens livsløp.

All videre behandling av forbindelsen håndteres fullstendig i arbeidsstrømmen, inkludert enhver videresendingsoppførsel.

For hver arbeidsstrøm i Envoy finnes det en forbindelse i en pool. Dermed etablerer HTTP/2-tilkoblingspulene bare én forbindelse per ekstern vert om gangen, med fire arbeidsstrømmer vil det være fire HTTP/2-forbindelser for hver ekstern vert i stabil tilstand. Når alt holdes i én arbeidsstrøm, kan nesten all koden skrives uten blokker, som om den var en-tråds. Hvis flere arbeidsstrømmer tildeles enn nødvendig, kan det føre til ineffektiv minnebruk, opprettelse av mange inaktive forbindelser og redusert antall tilkoblinger tilbake til pulen.

For more information, visit Envoy Proxy blogg.

HTTP-konfigurasjon

Den følgende NGINX-konfigurasjonsblokken definerer HTTP-innstillingene, som:

  • Hvilke mime-typer som støttes
  • Standard tidsavbrudd
  • Gzip-konfigurasjon

Du kan konfigurere disse aspektene med filtre i Envoy Proxy, noe vi vil diskutere senere.

Steg 3 — Serverkonfigurasjon

I HTTP-konfigurasjonsblokken angir NGINX å lytte på port 8080 og svare på innkommende forespørsel til domener one.example.com og www.one.example.com.

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

Inne i Envoy styres dette av lyttere.

Lyttere i Envoy

Det viktigste aspektet ved å komme i gang med Envoy Proxy er å definere lytterne. Du må lage en konfigurasjonsfil som beskriver hvordan du vil kjøre en instans av Envoy.

Følgende fragment vil opprette en ny lytter og binde den til port 8080. Konfigurasjonen angir hvilke porter Envoy Proxy skal binde seg til for innkommende forespørsel.

Envoy Proxy bruker YAML-notasjon for sin konfigurasjon. For en introduksjon til denne notasjonen, se her lenken.

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

Det er ikke nødvendig å definere server_name, siden Envoy Proxy-filtre vil håndtere dette.

Trinn 4 – Konfigurasjon av beliggenhet

Når en forespørsel kommer til NGINX, definerer lokasjonsblokken hvordan man skal håndtere og hvor trafikken skal sendes. I følgende fragment sendes all trafikk til nettstedet til upstream (oversettelsesnotat: upstream er vanligvis applikasjonsservere) klyngen med navnet targetCluster. Upstream-klyngen definerer nodene som skal håndtere forespørselen. Vi vil diskutere dette i neste trinn.

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

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

I Envoy håndterer Filters dette.

Envoy Filters

For statisk konfigurasjon definerer filtrene hvordan innkommende forespørsel skal håndteres. I dette tilfellet setter vi opp filtre som samsvarer med server_names i forrige trinn. Når innkommende forespørsel kommer som samsvarer med bestemte domener og ruter, dirigeres trafikken til klyngen. Dette er ekvivalent med upstream-konfigurasjonen i NGINX.

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

Navn envoy.http_connection_manager er et innebygd filter i Envoy Proxy. Andre filtre inkluderer Redis, Mongo, TCP. Du finner en fullstendig liste i dokumentasjonen.

For mer informasjon om andre lastbalanseringspolitikker, besøk Dokumentasjonen til Envoy.

Trinn 5 – Proxy- og upstream-konfigurasjon

I NGINX definerer upstream-konfigurasjonen en gruppe målservere som skal håndtere trafikken. I dette tilfellet ble to klynger tildelt.

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

I Envoy håndteres dette av klynger.

Envoy Klynger

Upstream-tilsvaret defineres som klynger. I dette tilfellet ble det definert verter som vil håndtere trafikken. Måten å få tilgang til vertene på, for eksempel ventetid, defineres som klyngekonfigurasjon. Dette gjør det mulig å kontrollere granulariteten av aspekter som ventetid og lastbalansering mer presist.

Kopier til redaktør  klynger:
  - navn: 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 }}
    ]

Ved bruk av tjenesteoppdagelse STRICT_DNS Envoy vil kontinuerlig og asynkront løse opp angitte DNS-mål. Hver IP-adresse som returneres fra DNS, vil bli betraktet som en eksplisitt vert i upstream-klyngen. Dette betyr at hvis en forespørsel returnerer to IP-adresser, vil Envoy anta at det er to verter i klyngen, og begge skal lastbalanseres. Hvis en vert fjernes fra resultatet, antar Envoy at den ikke lenger eksisterer og vil trekke trafikken fra eventuelle eksisterende forbindelsespools.

For mer informasjon, se Dokumentasjonen for Envoy-proxy.

Trinn 6 — Tilgang til logger og feil

Endelig konfigurasjon — logging. I stedet for å sende feillogger til disk, bruker Envoy Proxy en skytilnærming. Alle applikasjonslogger skrives ut til stdout og stderr.

Når brukere sender forespørsel, er tilgangslogger valgfrie og er som standard deaktivert. For å aktivere tilgangslogger for HTTP-forespørsel, aktiver konfigurasjonen access_log for HTTP-tilkoblingsbehandlere. Stien kan være enten en enhet, slik som stdout, eller en fil på disk, avhengig av dine krav.

Den følgende konfigurasjonen vil dirigere alle tilganglogger til stdout (notat fra oversetter — stdout er nødvendig for å bruke Envoy inne i Docker. Hvis det brukes uten Docker, bytt ut /dev/stdout med en sti til en vanlig loggfil). Kopier fragmentet til konfigurasjonsdelen for tilkoblingshåndtereren:

Kopier til utklippstavlen access_log:
- navn: envoy.file_access_log
  config:
    path: "\/dev\/stdout"

Resultatene skal se slik ut:

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

Som standard har Envoy en formatstreng som inkluderer detaljer om HTTP-forespørselen:

[%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

Resultatet av denne formatlinjen:

[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"

Innholdet i utdataene kan konfigureres ved å angi formatfeltet. For eksempel:

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"

Logglinjen kan også skrives ut i JSON-format ved å angi feltet json_format. For eksempel:

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

For mer informasjon om hvordan du logger i Envoy, besøk

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

Logging er ikke den eneste måten å få innsikt i driften av Envoy Proxy. Den inkluderer avanserte funksjoner for sporing og metrikker. Du kan lære mer i dokumentasjonen for sporing eller via Interaktiv sporing.

Trinn 7 – Kjøring

Nå har du oversatt konfigurasjonen fra NGINX til Envoy Proxy. Siste trinn er å starte en instans av Envoy Proxy for testing.

Kjøring som bruker

Øverst i NGINX-konfigurasjonen, linjen user www www; angir at NGINX kjøres som en lavprivilegert bruker for økt sikkerhet.

Envoy Proxy bruker en skytilnærming for å administrere hvem som eier prosessen. Når vi kjører Envoy Proxy gjennom en container, kan vi spesifisere en lavprivilegert bruker.

Å kjøre Envoy Proxy

Kommandoen nedenfor vil kjøre Envoy Proxy gjennom en Docker-container på verten. Denne kommandoen gir Envoy muligheten til å lytte etter innkommende forespørsel på port 80. Men, som angitt i konfigurasjonen av lytteren, lytter Envoy Proxy til innkommende trafikk gjennom port 8080. Dette tillater at prosessen kjører som en lavprivilegert bruker.

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

Testing

Med proxyen kjørt, kan tester nå utføres og behandles. Følgende cURL-kommando gir en forespørsel med vertens overskrift, definert i proxy-konfigurasjonen.

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

HTTP-forespørselen vil resultere i en feil 503Dette skyldes at de oppadgående forbindelsene ikke fungerer og derfor ikke er tilgjengelige. Dermed har Envoy Proxy ingen tilgjengelige mål for forespørselen. Den følgende kommandoen vil starte en serie HTTP-tjenester som samsvarer med konfigurasjonen som er definert for Envoy.

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

Med tilgjengelige tjenester kan Envoy effektivt proxy-trafikken til destinasjonen.

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

Du bør se et svar som indikerer hvilken Docker-container som håndterte forespørselen. I loggene til Envoy Proxy skal du også se den genererte tilgangsstrengen.

Ytterligere HTTP svaroverskrifter (HTTP Response)

I overskriftene til det gyldige svaret på forespørselen vil du se ytterligere HTTP-overskrifter. Overskriften viser tiden som oppstrømsverten brukte på å behandle forespørselen. Dette uttrykkes i millisekunder. Dette er nyttig hvis klienten ønsker å bestemme behandlingstiden sammenlignet med nettverksforsinkelsen.

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

Endelig konfigurasjon

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 }

Ytterligere informasjon fra oversetteren

Installasjonsinstruksjoner for Envoy Proxy kan du finne på nettsiden https://www.getenvoy.io/

Som standard mangler rpm systemd service konfigurasjon.

Legg til systemd service konfigurasjonen i \/etc\/systemd\/system\/envoy.service:

[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

Du må opprette en katalog \/etc\/envoy\/ og legge konfigurasjonen config.yaml dit.

Det er en Telegram-chat for envoy proxy: https://t.me/envoyproxy_ru

Envoy Proxy har ikke støtte for distribusjon av statisk innhold. Derfor, hvem kan stemme for denne funksjonen: https://github.com/envoyproxy/envoy/issues/378

Kun registrerte brukere kan delta i undersøkelsen. Logg inn, vær så snill.

Har dette innlegget inspirert deg til å installere og teste envoy proxy?

  • ja

  • nei

75 brukere stemte. 18 brukere avholdt seg.

Kilde: habr.com

Kjøp pålitelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere 🔥 Kjøp pålitelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere | ProHoster