Migration von Nginx zu Envoy Proxy

Hallo, Habr! Ich präsentiere Ihnen die Übersetzung des Beitrags: Migration von Nginx zu Envoy Proxy.

Envoy ist ein hochleistungsfähiger, verteilter Proxy-Server (geschrieben in C++), der für einzelne Dienste und Anwendungen konzipiert wurde. Er fungiert auch als Kommunikationsbus und "universelle Datenebene", die für große Mikroservice-Architekturen "Service Mesh" entwickelt wurde. Bei der Entwicklung wurden Lösungen für Probleme berücksichtigt, die bei Servern wie NGINX, HAProxy, Hardware-Load-Balancern und Cloud-Load-Balancern auftraten. Envoy arbeitet mit jeder Anwendung zusammen und abstrahiert das Netzwerk, indem es plattformunabhängige Funktionen bereitstellt. Wenn der gesamte Dienstverkehr innerhalb der Infrastruktur über das Envoy-Netzwerk läuft, wird es einfacher, Problemstellen mithilfe konsistenter Beobachtungsmöglichkeiten zu visualisieren, die allgemeine Leistung zu optimieren und zentrale Funktionen an einem bestimmten Ort hinzuzufügen.

Funktionen

  • Architektur außerhalb des Prozesses: Envoy ist ein eigenständiger, hochleistungsfähiger Server, der nur wenig Arbeitsspeicher benötigt. Er arbeitet mit jeder Programmiersprache oder jedem Framework zusammen.
  • Unterstützung für HTTP/2 und gRPC: Envoy bietet erstklassige Unterstützung für HTTP/2 und gRPC für eingehende und ausgehende Verbindungen. Es handelt sich um einen transparenten Proxy von HTTP/1.1 auf HTTP/2.
  • Erweiterte Lastverteilung: Envoy unterstützt erweiterte Funktionen der Lastverteilung, einschließlich automatischer Wiederholungen, Circuit Breaking, globaler Ratenbegrenzung, Anfragen-Dimming, lokaler Lastverteilung innerhalb von Zonen usw.
  • API zur Konfigurationsverwaltung: Envoy stellt eine zuverlässige API für die dynamische Verwaltung seiner Konfiguration zur Verfügung.
  • Überwachung: Tiefgehende Überwachung des L7-Verkehrs, integrierte Unterstützung für verteiltes Tracing und Überwachung von MongoDB, DynamoDB und vielen anderen Anwendungen.

Schritt 1 — Beispielkonfiguration für NGINX

In diesem Szenario wird eine eigens erstellte Datei verwendet nginx.conf, basierend auf einem vollständigen Beispiel aus der NGINX Wiki. Sie können die Konfiguration im Editor betrachten, indem Sie nginx.conf

die ursprüngliche NGINX-Konfiguration öffnen

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

Die NGINX-Konfiguration besteht typischerweise aus drei wesentlichen Elementen:

  1. Der Konfiguration des NGINX-Servers, der Protokollstrukturen und der Gzip-Funktionalität. Diese wird global in allen Fällen definiert.
  2. Die NGINX-Konfiguration, um Anfragen für den Host one.example.com auf Port 8080 anzunehmen.
  3. Die Konfiguration des Zielorts, wie der Verkehr für verschiedene Teile der URL verarbeitet werden soll.

Nicht alle Konfigurationen werden auf den Envoy Proxy angewendet, und Sie müssen einige Parameter nicht festlegen. Der Envoy Proxy hat vier Schlüsseltypen, die die grundlegende Infrastruktur unterstützen, die von NGINX angeboten wird. Der Kern ist:

  • Listener: Sie legen fest, wie der Envoy Proxy eingehende Anfragen empfängt. Derzeit unterstützt der Envoy Proxy nur TCP-basierte Listener. Sobald die Verbindung hergestellt ist, wird sie an eine Reihe von Filtern zur Verarbeitung weitergeleitet.
  • Filter: Diese sind Teil einer Pipeline-Architektur, die eingehende und ausgehende Daten verarbeiten kann. Zu dieser Funktionalität gehören Filter wie Gzip, das die Daten vor dem Senden an den Client komprimiert.
  • Router: Sie leiten den Datenverkehr zum gewünschten Ziel weiter, das als Cluster definiert ist.
  • Cluster: Sie definieren den Endpunkt für den Datenverkehr und die Konfigurationsparameter.

Wir werden diese vier Komponenten nutzen, um die Envoy Proxy-Konfiguration zu erstellen, die eine bestimmte NGINX-Konfiguration widerspiegelt. Das Ziel von Envoy ist die Arbeit mit APIs und dynamische Konfiguration. In diesem Fall wird die grundlegende Konfiguration statische, festgelegte Parameter aus NGINX verwenden.

Schritt 2 — NGINX-Konfiguration

Erster Teil nginx.conf definiert einige interne Komponenten von NGINX, die konfiguriert werden müssen.

Arbeiterverbindungen

Die folgende Konfiguration definiert die Anzahl der Arbeitsprozesse und Verbindungen. Sie zeigt an, wie NGINX skaliert wird, um der Nachfrage gerecht zu werden.

worker_processes  2;

events {
  worker_connections   2000;
}

Envoy Proxy verwaltet Arbeitsprozesse und Verbindungen auf unterschiedliche Weise.

Envoy erstellt einen Arbeitsprozess für jeden Hardware-Thread im System. Jeder Arbeitsprozess führt eine nicht blockierende Ereignisschleife aus, die verantwortlich ist für

  1. Das Lauschen auf jeden Listener
  2. Die Annahme neuer Verbindungen
  3. Die Erstellung eines Satzes von Filtern für die Verbindung
  4. Die Verarbeitung aller Ein- und Ausgabeoperationen während der Lebensdauer der Verbindung.

Alle weiteren Verarbeitungen der Verbindung werden vollständig im Arbeitsprozess bearbeitet, einschließlich jeglichem Umleitungsverhalten.

Für jeden Arbeitsstrom in Envoy gibt es eine Verbindung im Pool. Somit stellen HTTP/2-Verbindungspools nur eine Verbindung für jeden externen Host gleichzeitig her. Bei vier Arbeitsströmen gibt es jeweils vier HTTP/2-Verbindungen für jeden externen Host im stabilen Zustand. Indem alles in einem Arbeitsstrom gehalten wird, kann fast der gesamte Code ohne Blockierung geschrieben werden, als wäre er ein-threaded. Wenn mehr Arbeitsströme zugewiesen werden, als notwendig sind, kann dies zu einem ineffizienten Speicherverbrauch führen, eine große Anzahl von inaktiven Verbindungen erzeugen und die Rückführung von Verbindungen in den Pool verringern.

Für weitere Informationen besuchen Sie Envoy Proxy Blog.

HTTP-Konfiguration

Der folgende NGINX-Konfigurationsblock definiert die HTTP-Einstellungen, wie zum Beispiel:

  • Welche MIME-Typen unterstützt werden
  • Standard-Timeouts
  • Gzip-Konfiguration

Diese Aspekte können Sie mit Filtern im Envoy-Proxy anpassen, was wir später besprechen werden.

Schritt 3 – Server-Konfiguration

Im HTTP-Konfigurationsblock gibt die NGINX-Konfiguration an, den Port 8080 zu überwachen und auf eingehende Anfragen für die Domains zu antworten: one.example.com und www.one.example.com.

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

Im Inneren von Envoy werden sie von Listenern verwaltet.

Listener von Envoy

Der wichtigste Aspekt beim Einstieg in den Envoy Proxy ist die Definition der Listener. Sie müssen eine Konfigurationsdatei erstellen, die beschreibt, wie Sie eine Instanz von Envoy starten möchten.

Der folgende Ausschnitt erstellt einen neuen Listener und bindet ihn an den Port 8080. Die Konfiguration gibt dem Envoy Proxy an, an welchen Ports er für eingehende Anfragen gebunden werden soll.

Der Envoy Proxy verwendet YAML-Notation für seine Konfiguration. Um sich mit dieser Notation vertraut zu machen, schauen Sie hier. den Link.

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

Es ist nicht notwendig, server_name, da die Filter von Envoy Proxy dies übernehmen werden.

Schritt 4 – Konfiguration des Standorts

Wenn eine Anfrage an NGINX eingeht, bestimmt der Standortblock, wie der Datenverkehr verarbeitet und wohin er geleitet wird. Im folgenden Ausschnitt wird der gesamte Verkehr zur Website an den Upstream-Cluster mit dem Namen targetCluster. Der Upstream-Cluster legt die Knoten fest, die die Anfrage verarbeiten sollen. Wir werden dies im nächsten Schritt besprechen.

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

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

In Envoy werden diese durch Filters behandelt.

Envoy-Filter

Für die statische Konfiguration legen Filter fest, wie eingehende Anfragen bearbeitet werden. In diesem Fall setzen wir Filter, die entsprechen server_names im vorherigen Schritt. Wenn eingehende Anfragen eingehen, die bestimmten Domains und Routen entsprechen, wird der Verkehr zum Cluster geleitet. Dies entspricht der aufsteigenden Konfiguration von 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

Name envoy.http_connection_manager ist ein integrierter Filter im Envoy Proxy. Weitere Filter umfassen Redis, Mongo, TCP. Eine vollständige Liste finden Sie in Dokumentation..

Für weitere Informationen über andere Lastverteilungsmethoden besuchen Sie Die Envoy-Dokumentation.

Schritt 5 — Proxy- und Upstream-Konfiguration

In der NGINX-Konfiguration definiert der upstream ein Set von Zielservern, die den Datenverkehr bearbeiten werden. Hier wurden zwei Cluster zugewiesen.

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

In Envoy wird das durch Cluster verwaltet.

Envoy-Cluster

Das Äquivalent zu upstream wird als Cluster definiert. In diesem Fall wurden Hosts festgelegt, die den Datenverkehr bedienen werden. Der Zugang zu den Hosts, wie beispielsweise die Zeitüberschreitung, wird als Clusterkonfiguration definiert. Dies ermöglicht eine genauere Kontrolle über Aspekte wie die Zeitüberschreitung und die Lastverteilung.

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

Bei Verwendung der Dienstentdeckung STRICT_DNS Envoy wird die angegebenen DNS-Ziele kontinuierlich und asynchron auflösen. Jede zurückgegebene IP-Adresse als Ergebnis der DNS-Abfrage wird als expliziter Host im darüber liegenden Cluster betrachtet. Das bedeutet, wenn die Abfrage zwei IP-Adressen zurückgibt, geht Envoy davon aus, dass es zwei Hosts im Cluster gibt, und beide sollten lastbalanciert werden. Wenn ein Host aus dem Ergebnis entfernt wird, nimmt Envoy an, dass er nicht mehr existiert, und wird den Verkehr aus allen vorhandenen Verbindungspools auswählen.

Für weitere Informationen siehe: Die Dokumentation des Envoy-Proxys.

Schritt 6 — Zugriff auf Protokolle und Fehler

Endkonfiguration — Protokollierung. Anstatt Fehlerprotokolle auf die Festplatte zu übertragen, verwendet der Envoy Proxy einen Cloud-Ansatz. Alle Anwendungsprotokolle werden in stdout und stderr.

Wenn Benutzer eine Anfrage stellen, sind Zugriffsprotokolle optional und standardmäßig deaktiviert. Um die Zugriffsprotokolle für HTTP-Anfragen zu aktivieren, aktivieren Sie die Konfiguration access_log für den HTTP-Connection-Manager. Der Pfad kann entweder ein Gerät wie stdout, oder eine Datei auf der Festplatte sein, je nach Ihren Anforderungen.

Die folgende Konfiguration leitet alle Zugriffsprotokolle an stdout (Hinweis des Übersetzers – stdout ist erforderlich, um envoy innerhalb von Docker zu verwenden. Wenn Sie es außerhalb von Docker verwenden, ersetzen Sie /dev/stdout durch den Pfad zu einer regulären Protokolldatei). Kopieren Sie den Abschnitt in den Konfigurationsbereich für den Verbindungsmanager:

Zugriffsprotokoll:
- name: envoy.file_access_log
  config:
    path: "/dev/stdout"

Die Ergebnisse sollten wie folgt aussehen:

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

Standardmäßig hat Envoy eine Formatzeile, die die Einzelheiten der HTTP-Anforderung enthält:

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

Das Ergebnis dieser Formatzeile:

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

Der Inhalt der Ausgabe kann angepasst werden, indem das Formatfeld festgelegt wird. Beispiel:

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

Die Protokollzeile kann auch im JSON-Format ausgegeben werden, indem das Feld json_formatverwendet. Zum Beispiel:

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

Für weitere Informationen zur Protokollierungsstrategie besuchen Sie

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

Die Protokollierung ist nicht die einzige Möglichkeit, Einblicke in die Arbeit mit Envoy Proxy zu erhalten. Es sind erweiterte Trace- und Metrik-Funktionen integriert. Sie können mehr erfahren in der Dokumentation zur Tracierung oder über Das interaktive Tracierungs-Skript.

Schritt 7 — Starten

Nun haben Sie die Konfiguration von NGINX auf Envoy Proxy übertragen. Der letzte Schritt besteht darin, eine Instanz von Envoy Proxy zu starten, um sie zu testen.

Starten als Benutzer

Am Anfang der NGINX-Konfiguration steht die Zeile user www www; die angibt, dass NGINX als Benutzer mit niedrigeren Privilegien ausgeführt wird, um die Sicherheit zu erhöhen.

Envoy Proxy verwendet einen Cloud-Ansatz für das Management des Prozessbesitzers. Wenn wir Envoy Proxy über einen Container starten, können wir einen Benutzer mit niedrigeren Privilegien angeben.

Envoy Proxy starten

Der folgende Befehl startet den Envoy Proxy in einem Docker-Container auf dem Host. Dieser Befehl ermöglicht es Envoy, eingehende Anfragen über Port 80 zu empfangen. Allerdings, wie in der Listener-Konfiguration angegeben, hört der Envoy Proxy auf den eingehenden Verkehr über Port 8080. Dies ermöglicht, dass der Prozess als Nutzer mit niedrigen Berechtigungen läuft.

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

Testen

Mit dem laufenden Proxy können nun Tests durchgeführt und bearbeitet werden. Der folgende cURL-Befehl sendet eine Anfrage mit dem in der Proxy-Konfiguration definierten Host-Header.

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

Die HTTP-Anfrage wird zu einem Fehler führen 503. Dies liegt daran, dass eingehende Verbindungen nicht funktionieren und nicht verfügbar sind. Daher hat der Envoy Proxy keine verfügbaren Zieladressen für die Anfrage. Der folgende Befehl startet eine Reihe von HTTP-Diensten, die der für Envoy definierten Konfiguration entsprechen.

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

Mit verfügbaren Diensten kann Envoy den Verkehr erfolgreich an das Ziel weiterleiten.

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

Sie sollten eine Antwort sehen, die angibt, welcher Docker-Container die Anfrage verarbeitet hat. In den Protokollen des Envoy Proxy sollten Sie ebenfalls die ausgegebene Zugriffskette sehen.

Zusätzliche HTTP-Antwortheader (HTTP Response)

In den Headern der gültigen Antwort erkennen Sie zusätzliche HTTP-Header. Der Header zeigt die Zeit an, die der übergeordnete Host für die Verarbeitung der Anfrage benötigt hat. Dies wird in Millisekunden ausgedrückt. Dies ist nützlich, wenn der Kunde die Bearbeitungszeit im Vergleich zur Netzwerkverzögerung bestimmen möchte.

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

Endkonfiguration

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 }

Zusätzliche Informationen vom Übersetzer

Die Installationsanleitungen für den Envoy Proxy finden Sie auf der Website https://www.getenvoy.io/

Standardmäßig fehlt im RPM die Systemd-Service-Konfiguration.

Fügen Sie die Systemd-Service-Konfiguration in /etc/systemd/system/envoy.service hinzu:

[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

Sie müssen das Verzeichnis /etc/envoy/ erstellen und dort die Konfiguration config.yaml ablegen.

Es gibt einen Telegram-Chat zum Envoy Proxy: https://t.me/envoyproxy_ru

Der Envoy Proxy unterstützt keine Verteilung statischer Inhalte. Daher stimmen Sie bitte für das Feature ab: https://github.com/envoyproxy/envoy/issues/378

Nur registrierte Benutzer können an der Umfrage teilnehmen. Bitte melden Sie sich an.Sind Sie an Contour interessiert?

Hat dieser Beitrag Sie dazu animiert, den Envoy Proxy zu installieren und zu testen?

  • ja

  • nein

75 Nutzer haben abgestimmt. 18 Nutzer haben sich enthalten.

Quelle: habr.com

Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server 🔥 Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server | ProHoster