Migrering från Nginx till Envoy Proxy

Hej, Habr! Jag uppmärksammar en översättning av inlägget: Migrering från Nginx till Envoy Proxy.

Envoy är en högpresterande distribuerad proxyserver (skriven i C++) designad för enskilda tjänster och applikationer, den är också en kommunikationsbuss och ett "universellt dataplan" designat för stora mikrotjänster "servicemesh"-arkitekturer. När man skapade den togs hänsyn till lösningar på problem som uppstod under utvecklingen av servrar som NGINX, HAProxy, hårdvarulastbalanserare och molnlastbalanserare. Envoy arbetar tillsammans med varje applikation och abstraherar nätverket för att tillhandahålla gemensam funktionalitet oavsett plattform. När all tjänstetrafik i en infrastruktur flyter genom Envoy-nätet blir det lätt att visualisera problemområden med konsekvent observerbarhet, justera övergripande prestanda och lägga till kärnfunktioner på en specifik plats.

Capabilities

  • Out-of-process arkitektur: envoy är en fristående, högpresterande server som tar upp en liten mängd RAM. Det fungerar tillsammans med alla applikationsspråk eller ramverk.
  • http/2- och grpc-stöd: envoy har förstklassigt http/2- och grpc-stöd för inkommande och utgående anslutningar. Detta är en transparent proxy från http/1.1 till http/2.
  • Avancerad lastbalansering: envoy stöder avancerade lastbalanseringsfunktioner inklusive automatiska återförsök, kedjebrytning, global hastighetsbegränsning, förfrågningsskuggning, lokal belastningsbalansering, etc.
  • Configuration Management API: envoy tillhandahåller ett robust API för att dynamiskt hantera din konfiguration.
  • Observerbarhet: Djup observerbarhet av L7-trafik, inbyggt stöd för distribuerad spårning och observerbarhet av mongodb, dynamodb och många andra applikationer.

Steg 1 — Exempel NGINX Config

Det här skriptet använder en specialgjord fil nginx.conf, baserat på det fullständiga exemplet från NGINX Wiki. Du kan se konfigurationen i editorn genom att öppna nginx.conf

nginx källkonfiguration

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-konfigurationer har vanligtvis tre nyckelelement:

  1. Konfigurering av NGINX-server, loggstruktur och Gzip-funktionalitet. Detta definieras globalt i alla fall.
  2. Konfigurerar NGINX för att acceptera förfrågningar till värden one.example.com på port 8080.
  3. Ställa in målplatsen, hur man hanterar trafik för olika delar av URL:en.

All konfiguration kommer inte att gälla för Envoy Proxy, och du behöver inte konfigurera vissa inställningar. Envoy Proxy har fyra nyckeltyper, som stöder kärninfrastrukturen som erbjuds av NGINX. Kärnan är:

  • Lyssnare: De bestämmer hur Envoy Proxy accepterar inkommande förfrågningar. Envoy Proxy stöder för närvarande endast TCP-baserade lyssnare. När en anslutning väl har upprättats skickas den till en uppsättning filter för bearbetning.
  • Filter: De är en del av en pipeline-arkitektur som kan behandla inkommande och utgående data. Denna funktion inkluderar filter som Gzip, som komprimerar data innan den skickas till klienten.
  • Routrar: De vidarebefordrar trafik till önskad destination, definierad som ett kluster.
  • Kluster: De definierar slutpunkten för trafik- och konfigurationsparametrar.

Vi kommer att använda dessa fyra komponenter för att skapa en Envoy Proxy-konfiguration för att matcha en specifik NGINX-konfiguration. Envoys mål är att arbeta med API:er och dynamisk konfiguration. I det här fallet kommer baskonfigurationen att använda statiska, hårdkodade inställningar från NGINX.

Steg 2 - NGINX-konfiguration

Den första delen nginx.conf definierar vissa NGINX-interna enheter som behöver konfigureras.

Arbetaranslutningar

Konfigurationen nedan bestämmer antalet arbetsprocesser och anslutningar. Detta indikerar hur NGINX kommer att skala för att möta efterfrågan.

worker_processes  2;

events {
  worker_connections   2000;
}

Envoy Proxy hanterar arbetsflöden och kopplingar på olika sätt.

Envoy skapar en arbetstråd för varje hårdvaratråd i systemet. Varje arbetstråd kör en icke-blockerande händelseloop som är ansvarig för

  1. Lyssnar på varje lyssnare
  2. Accepterar nya anslutningar
  3. Skapa en uppsättning filter för en anslutning
  4. Bearbeta alla I/O-operationer under anslutningens livstid.

All ytterligare anslutningsbearbetning hanteras helt och hållet i arbetartråden, inklusive eventuell vidarebefordran.

För varje arbetartråd i Envoy finns en anslutningspool. Så HTTP/2-anslutningspooler upprättar bara en anslutning per extern värd åt gången, om det finns fyra arbetartrådar kommer det att finnas fyra HTTP/2-anslutningar per extern värd i ett stabilt tillstånd. Genom att hålla allt i en arbetstråd kan nästan all kod skrivas utan blockering, som om den vore enkeltrådad. Om fler arbetartrådar allokeras än nödvändigt kan detta leda till slöseri med minne, skapa ett stort antal lediga anslutningar och minska antalet gånger som anslutningar returneras till poolen.

För mer information besök Envoy Proxy blogg.

HTTP-konfiguration

Följande NGINX-konfigurationsblock definierar HTTP-inställningar som:

  • Vilka mimetyper stöds
  • Standard Timeouts
  • Gzip-konfiguration

Du kan anpassa dessa aspekter med hjälp av filter i Envoy Proxy, som vi kommer att diskutera senare.

Steg 3 - Serverkonfiguration

I HTTP-konfigurationsblocket anger NGINX-konfigurationen att lyssna på port 8080 och svara på inkommande förfrågningar om domäner one.example.com и www.one.example.com.

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

Inuti Envoy kontrolleras det av Lyssnare.

Envoy lyssnare

Den viktigaste aspekten av att komma igång med Envoy Proxy är att definiera dina lyssnare. Du måste skapa en konfigurationsfil som beskriver hur du vill köra Envoy-instansen.

Utdraget nedan kommer att skapa en ny lyssnare och binda den till port 8080. Konfigurationen talar om för Envoy Proxy vilka portar den ska binda till för inkommande förfrågningar.

Envoy Proxy använder YAML-notation för sin konfiguration. För en introduktion till denna notation, se här länk.

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

Inget behov av att definiera servernamn, eftersom Envoy Proxy-filter kommer att hantera detta.

Steg 4 - Platskonfiguration

När en begäran kommer in i NGINX bestämmer platsblocket hur trafiken ska bearbetas och vart den ska dirigeras. I följande fragment överförs all trafik till webbplatsen till ett uppströms (översättarens anmärkning: uppströms är vanligtvis en applikationsserver) med namnet targetCluster. Uppströmsklustret definierar noderna som ska behandla begäran. Vi kommer att diskutera detta i nästa steg.

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

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

Hos Envoy gör Filters detta.

Envoy filter

För en statisk konfiguration avgör filter hur inkommande förfrågningar ska behandlas. I det här fallet ställer vi in ​​filter som matchar servernamn i föregående steg. När inkommande förfrågningar kommer som matchar vissa domäner och rutter, dirigeras trafiken till klustret. Detta motsvarar en NGINX bottom-up-konfiguration.

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

namn envoy.http_connection_manager är ett inbyggt filter i Envoy Proxy. Andra filter inkluderar Redis, mongo, TCP. Du hittar hela listan på dokumentation.

För mer information om andra policyer för belastningsbalansering, besök Envoy dokumentation.

Steg 5 - Proxy- och uppströmskonfiguration

I NGINX definierar uppströmskonfigurationen en uppsättning målservrar som kommer att behandla trafik. I det här fallet tilldelades två kluster.

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

I Envoy hanteras detta av kluster.

Envoy kluster

Uppströmsekvivalenten definieras som kluster. I det här fallet har värdarna som kommer att betjäna trafiken identifierats. Det sätt på vilket värdar nås, såsom timeouts, definieras som en klusterkonfiguration. Detta möjliggör mer granulär kontroll över aspekter som latens och lastbalansering.

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 }}
    ]

När du använder service discovery STRICT_DNS Envoy kommer kontinuerligt och asynkront att lösa de angivna DNS-målen. Varje returnerad IP-adress från DNS-resultatet kommer att betraktas som en explicit värd i uppströmsklustret. Detta innebär att om en begäran returnerar två IP-adresser, kommer Envoy att anta att det finns två värdar i klustret, och båda måste vara lastbalanserade. Om en värd tas bort från resultatet kommer Envoy att anta att den inte längre existerar och kommer att dra trafik från befintliga anslutningspooler.

För mer information se Envoy proxy dokumentation.

Steg 6 — Loggåtkomst och fel

Den slutliga konfigurationen är registrering. Istället för att skjuta felloggar till disk använder Envoy Proxy ett molnbaserat tillvägagångssätt. Alla applikationsloggar matas ut till stdout и stderr.

När användare gör en begäran är åtkomstloggar valfria och inaktiverade som standard. För att aktivera åtkomstloggar för HTTP-förfrågningar, aktivera konfigurationen access_log för HTTP-anslutningshanteraren. Sökvägen kan antingen vara en enhet som t.ex stdout, eller en fil på disk, beroende på dina krav.

Följande konfiguration kommer att omdirigera alla åtkomstloggar till stdout (översättarens anmärkning - stdout krävs för att använda envoy inuti docker. Om den används utan docker, ersätt sedan /dev/stdout med sökvägen till en vanlig loggfil). Kopiera kodavsnittet till konfigurationsavsnittet för anslutningshanteraren:

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

Resultaten ska se ut så här:

      - 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:

Som standard har Envoy en formatsträng som innehåller information om HTTP-förfrågan:

[%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 denna formatsträng är:

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

Utdatainnehållet kan anpassas genom att ställa in formatfältet. Till exempel:

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"

Loggraden kan också matas ut i JSON-format genom att ställa in fältet json_format. Till exempel:

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

För mer information om envoy Registration Methodology, besök

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

Loggning är inte det enda sättet att få insikt i att arbeta med Envoy Proxy. Den har avancerade spårnings- och mätfunktioner inbyggda. Du kan ta reda på mer på spårningsdokumentation eller via Interaktivt spårningsskript.

Steg 7 - Starta

Du har nu migrerat din konfiguration från NGINX till Envoy Proxy. Det sista steget är att starta en Envoy Proxy-instans för att testa den.

Kör som användare

Överst på NGINX-konfigurationsraden användare www www; anger att köra NGINX som en lågprivilegierad användare för att förbättra säkerheten.

Envoy Proxy tar ett molnbaserat tillvägagångssätt för att hantera vem som äger en process. När vi kör Envoy Proxy genom en container kan vi ange en lågprivilegierad användare.

Startar Envoy Proxy

Kommandot nedan kommer att köra Envoy Proxy genom en Docker-behållare på värden. Det här kommandot ger Envoy möjligheten att lyssna efter inkommande förfrågningar på port 80. Men som specificerats i lyssnarkonfigurationen lyssnar Envoy Proxy efter inkommande trafik på port 8080. Detta gör att processen kan köras som en lågprivilegierad användare.

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

testning

När proxyn körs kan tester nu göras och bearbetas. Följande cURL-kommando utfärdar en begäran med värdhuvudet definierat i proxykonfigurationen.

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

HTTP-begäran kommer att resultera i ett fel 503. Detta beror på att uppströmsanslutningar inte fungerar och inte är tillgängliga. Därför har Envoy Proxy inga tillgängliga destinationer för begäran. Följande kommando startar en serie HTTP-tjänster som matchar den konfiguration som definierats för Envoy.

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

Med de tjänster som är tillgängliga kan Envoy framgångsrikt proxytrafik till sin destination.

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

Du bör se ett svar som anger vilken Docker-container som behandlade begäran. I Envoy Proxy-loggarna bör du också se en åtkomststrängutgång.

Ytterligare HTTP-svarsrubriker

Du kommer att se ytterligare HTTP-rubriker i svarsrubriker för den faktiska begäran. Rubriken visar den tid uppströmsvärden tillbringade med att bearbeta begäran. Uttryckt i millisekunder. Detta är användbart om klienten vill bestämma servicetid jämfört med nätverkslatens.

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

Slutlig konfiguration

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 }

Ytterligare information från översättaren

Instruktioner för installation av Envoy Proxy finns på webbplatsen https://www.getenvoy.io/

Som standard har rpm ingen systemd servicekonfiguration.

Lägg till systemd service config /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åste skapa en katalog /etc/envoy/ och placera config.yaml config där.

Det finns en telegramchatt med envoy proxy: https://t.me/envoyproxy_ru

Envoy Proxy stöder inte visning av statiskt innehåll. Vem kan därför rösta på funktionen: https://github.com/envoyproxy/envoy/issues/378

Endast registrerade användare kan delta i undersökningen. Logga in, Snälla du.

Uppmuntrade det här inlägget dig att installera och testa envoy proxy?

  • ja

  • ingen

75 användare röstade. 18 användare avstod från att rösta.

Källa: will.com

Lägg en kommentar