Hallo, Habr! Hier ist eine Übersetzung des Beitrags:
Envoy ist ein leistungsstarker verteilter Proxyserver (geschrieben in C++), der für einzelne Dienste und Anwendungen entwickelt wurde. Er ist außerdem ein Kommunikationsbus und eine „universelle Datenebene“ für große Microservice-„Service Mesh“-Architekturen. Bei der Erstellung wurden Lösungen für Probleme berücksichtigt, die bei der Entwicklung von Servern wie NGINX, HAProxy, Hardware Load Balancern und Cloud Load Balancern entstanden sind. Envoy arbeitet mit jeder Anwendung zusammen und abstrahiert das Netzwerk, um unabhängig von der Plattform gemeinsame Funktionen bereitzustellen. Wenn der gesamte Serviceverkehr in einer Infrastruktur durch das Envoy-Mesh fließt, können Problembereiche mit konsistenter Beobachtbarkeit einfach visualisiert, die Gesamtleistung optimiert und Kernfunktionen an einem bestimmten Standort hinzugefügt werden.
Capabilities
- Out-of-Process-Architektur: Envoy ist ein eigenständiger Hochleistungsserver, der wenig RAM beansprucht. Es funktioniert in Verbindung mit jeder Anwendungssprache oder jedem Framework.
- http/2- und grpc-Unterstützung: envoy verfügt über erstklassige http/2- und grpc-Unterstützung für ein- und ausgehende Verbindungen. Dies ist ein transparenter Proxy von http/1.1 bis http/2.
- Erweiterter Lastausgleich: Envoy unterstützt erweiterte Lastausgleichsfunktionen, einschließlich automatischer Wiederholungsversuche, Kettenunterbrechung, globale Ratenbegrenzung, Anforderungsschatten, lokaler Zonenlastausgleich usw.
- Konfigurationsverwaltungs-API: envoy bietet eine robuste API für die dynamische Verwaltung Ihrer Konfiguration.
- Beobachtbarkeit: Umfassende Beobachtbarkeit des L7-Verkehrs, native Unterstützung für verteiltes Tracing und Beobachtbarkeit von Mongodb, Dynamodb und vielen anderen Anwendungen.
Schritt 1 – Beispiel einer NGINX-Konfiguration
Dieses Skript verwendet eine speziell gestaltete Datei nginx.conf, basierend auf dem vollständigen Beispiel von
Nginx-Quellkonfiguration
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-Konfigurationen bestehen typischerweise aus drei Schlüsselelementen:
- Konfigurieren des NGINX-Servers, der Protokollstruktur und der Gzip-Funktionalität. Dies ist in allen Fällen global definiert.
- Konfigurieren von NGINX zum Akzeptieren von Anfragen an den Host one.example.com auf Port 8080.
- Einrichten des Zielstandorts und Umgang mit Datenverkehr für verschiedene Teile der URL.
Nicht alle Konfigurationen gelten für Envoy Proxy und Sie müssen einige Einstellungen nicht konfigurieren. Envoy Proxy hat vier Schlüsseltypen, die die von NGINX angebotene Kerninfrastruktur unterstützen. Der Kern ist:
- Zuhörer: Sie bestimmen, wie Envoy Proxy eingehende Anfragen entgegennimmt. Envoy Proxy unterstützt derzeit nur TCP-basierte Listener. Sobald eine Verbindung hergestellt ist, wird sie zur Verarbeitung an eine Reihe von Filtern weitergeleitet.
- Filter: Sie sind Teil einer Pipeline-Architektur, die ein- und ausgehende Daten verarbeiten kann. Zu dieser Funktionalität gehören Filter wie Gzip, das die Daten komprimiert, bevor sie an den Client gesendet werden.
- Router: Sie leiten den Datenverkehr an das gewünschte Ziel weiter, das als Cluster definiert ist.
- Cluster: Sie definieren den Endpunkt für Datenverkehr und Konfigurationsparameter.
Wir werden diese vier Komponenten verwenden, um eine Envoy-Proxy-Konfiguration zu erstellen, die einer bestimmten NGINX-Konfiguration entspricht. Das Ziel von Envoy ist die Arbeit mit APIs und dynamischer Konfiguration. In diesem Fall verwendet die Basiskonfiguration statische, hartcodierte Einstellungen von NGINX.
Schritt 2 – NGINX-Konfiguration
Der erste Teil nginx.conf definiert einige NGINX-Interna, die konfiguriert werden müssen.
Arbeitnehmerverbindungen
Die folgende Konfiguration bestimmt die Anzahl der Arbeitsprozesse und Verbindungen. Dies zeigt, wie NGINX skaliert wird, um der Nachfrage gerecht zu werden.
worker_processes 2;
events {
worker_connections 2000;
}
Envoy Proxy verwaltet Arbeitsabläufe und Verbindungen auf unterschiedliche Weise.
Envoy erstellt einen Arbeitsthread für jeden Hardware-Thread im System. Jeder Arbeitsthread führt eine nicht blockierende Ereignisschleife aus, für die er verantwortlich ist
- Jedem Zuhörer zuhören
- Akzeptieren Sie neue Verbindungen
- Erstellen einer Reihe von Filtern für eine Verbindung
- Verarbeiten Sie alle E/A-Vorgänge während der Lebensdauer der Verbindung.
Die gesamte weitere Verbindungsverarbeitung wird vollständig im Worker-Thread abgewickelt, einschließlich etwaigem Weiterleitungsverhalten.
Für jeden Worker-Thread in Envoy gibt es einen Verbindungspool. Daher stellen HTTP/2-Verbindungspools jeweils nur eine Verbindung pro externem Host her. Wenn vier Arbeitsthreads vorhanden sind, gibt es in einem stabilen Zustand vier HTTP/2-Verbindungen pro externem Host. Indem alles in einem Arbeitsthread gehalten wird, kann fast der gesamte Code ohne Blockierung geschrieben werden, als wäre er Single-Threaded. Wenn mehr Arbeitsthreads als nötig zugewiesen werden, kann dies zu einer Verschwendung von Speicher führen, wodurch eine große Anzahl inaktiver Verbindungen entsteht und die Anzahl der Verbindungen, die an den Pool zurückgegeben werden, verringert wird.
Für weitere Informationen besuchen Sie
HTTP-Konfiguration
Der folgende NGINX-Konfigurationsblock definiert HTTP-Einstellungen wie:
- Welche MIME-Typen werden unterstützt?
- Standardzeitüberschreitungen
- Gzip-Konfiguration
Sie können diese Aspekte mithilfe von Filtern in Envoy Proxy anpassen, worauf wir später noch eingehen.
Schritt 3 – Serverkonfiguration
Im HTTP-Konfigurationsblock gibt die NGINX-Konfiguration an, Port 8080 abzuhören und auf eingehende Anfragen für Domänen zu antworten one.example.com и www.one.example.com.
server {
listen 8080;
server_name one.example.com www.one.example.com;
Innerhalb von Envoy wird es von Listenern gesteuert.
Gesandte Zuhörer
Der wichtigste Aspekt beim Einstieg in Envoy Proxy ist die Definition der Listener. Sie müssen eine Konfigurationsdatei erstellen, die beschreibt, wie Sie die Envoy-Instanz ausführen möchten.
Der folgende Codeausschnitt erstellt einen neuen Listener und bindet ihn an Port 8080. Die Konfiguration teilt Envoy Proxy mit, an welche Ports er sich für eingehende Anfragen binden soll.
Envoy Proxy verwendet für seine Konfiguration die YAML-Notation. Eine Einführung in diese Notation finden Sie hier
Copy to Editorstatic_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
Keine Notwendigkeit zur Definition Servername, da Envoy-Proxy-Filter dies handhaben.
Schritt 4 – Standortkonfiguration
Wenn eine Anfrage bei NGINX eingeht, bestimmt der Standortblock, wie der Datenverkehr verarbeitet und wohin er weitergeleitet werden soll. Im folgenden Fragment wird der gesamte Datenverkehr zur Site an einen Upstream-Cluster (Anmerkung des Übersetzers: Upstream ist normalerweise ein Anwendungsserver) mit dem Namen übertragen ZielCluster. Der Upstream-Cluster definiert die Knoten, 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;
}
Bei Envoy erledigt Filters dies.
Envoy-Filter
Bei einer statischen Konfiguration bestimmen Filter, wie eingehende Anfragen verarbeitet werden. In diesem Fall setzen wir passende Filter Servernamen im vorherigen Schritt. Wenn eingehende Anfragen eingehen, die mit bestimmten Domänen und Routen übereinstimmen, wird der Datenverkehr an den Cluster weitergeleitet. Dies entspricht einer 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
Name envoy.http_connection_manager ist ein integrierter Filter in Envoy Proxy. Andere Filter umfassen Redis, Mongo, TCP. Die vollständige Liste finden Sie unter
Weitere Informationen zu anderen Lastausgleichsrichtlinien finden Sie unter
Schritt 5 – Proxy- und Upstream-Konfiguration
In NGINX definiert die Upstream-Konfiguration eine Reihe von Zielservern, die den Datenverkehr verarbeiten. In diesem Fall wurden zwei Cluster zugewiesen.
upstream targetCluster {
172.18.0.3:80;
172.18.0.4:80;
}
In Envoy wird dies durch Cluster verwaltet.
Envoy-Cluster
Das Upstream-Äquivalent wird als Cluster definiert. In diesem Fall wurden die Hosts definiert, die den Datenverkehr bedienen. Die Art und Weise, wie auf Hosts zugegriffen wird, beispielsweise Timeouts, wird als Clusterkonfiguration definiert. Dies ermöglicht eine detailliertere Kontrolle über Aspekte wie Latenz und Lastausgleich.
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 Diensterkennung STRICT_DNS Envoy löst die angegebenen DNS-Ziele kontinuierlich und asynchron auf. Jede vom DNS-Ergebnis zurückgegebene IP-Adresse wird als expliziter Host im Upstream-Cluster betrachtet. Das heißt, wenn eine Anfrage zwei IP-Adressen zurückgibt, geht Envoy davon aus, dass es zwei Hosts im Cluster gibt und beide einen Lastausgleich durchführen müssen. Wenn ein Host aus dem Ergebnis entfernt wird, geht Envoy davon aus, dass er nicht mehr existiert, und ruft den Datenverkehr aus allen vorhandenen Verbindungspools ab.
Weitere Informationen finden Sie unter
Schritt 6 – Protokollzugriff und Fehler
Die endgültige Konfiguration ist die Registrierung. Anstatt Fehlerprotokolle auf die Festplatte zu übertragen, verfolgt Envoy Proxy einen cloudbasierten Ansatz. Alle Anwendungsprotokolle werden an ausgegeben stdout и stderr.
Wenn Benutzer eine Anfrage stellen, sind Zugriffsprotokolle optional und standardmäßig deaktiviert. Um Zugriffsprotokolle für HTTP-Anfragen zu aktivieren, aktivieren Sie die Konfiguration access_log für den HTTP-Verbindungsmanager. Der Pfad kann entweder ein Gerät wie z stdoutoder eine Datei auf der Festplatte, je nach Ihren Anforderungen.
Die folgende Konfiguration leitet alle Zugriffsprotokolle um stdout (Anmerkung des Übersetzers – stdout ist erforderlich, um Envoy in Docker zu verwenden. Bei Verwendung ohne Docker ersetzen Sie /dev/stdout durch den Pfad zu einer regulären Protokolldatei.) Kopieren Sie den Ausschnitt in den Konfigurationsabschnitt für den Verbindungsmanager:
Copy to Clipboardaccess_log:
- name: envoy.file_access_log
config:
path: "/dev/stdout"
Die Ergebnisse sollten so 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 verfügt Envoy über eine Formatzeichenfolge, die die Details der HTTP-Anfrage 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 Formatzeichenfolge ist:
[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 Ausgabeinhalt kann durch Festlegen des Formatfelds angepasst werden. Zum Beispiel:
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"
Durch Setzen des Feldes kann die Protokollzeile auch im JSON-Format ausgegeben werden json_format. Zum Beispiel:
access_log:
- name: envoy.file_access_log
config:
path: "/dev/stdout"
json_format: {"protocol": "%PROTOCOL%", "duration": "%DURATION%", "request_method": "%REQ(:METHOD)%"}
Weitere Informationen zur Envoy-Registrierungsmethodik finden Sie unter
Die Protokollierung ist nicht die einzige Möglichkeit, Einblicke in die Arbeit mit Envoy Proxy zu gewinnen. Es verfügt über erweiterte Ablaufverfolgungs- und Metrikfunktionen. Mehr erfahren Sie unter
Schritt 7 – Starten
Sie haben nun die Konfiguration von NGINX auf Envoy Proxy migriert. Der letzte Schritt besteht darin, eine Envoy Proxy-Instanz zu starten, um sie zu testen.
Als Benutzer ausführen
Ganz oben in der NGINX-Konfigurationszeile Benutzer www www; Gibt an, NGINX als Benutzer mit geringen Berechtigungen auszuführen, um die Sicherheit zu verbessern.
Envoy Proxy verfolgt einen cloudbasierten Ansatz zur Verwaltung der Eigentümer eines Prozesses. Wenn wir Envoy Proxy über einen Container ausführen, können wir einen Benutzer mit geringen Berechtigungen angeben.
Envoy Proxy starten
Mit dem folgenden Befehl wird Envoy Proxy über einen Docker-Container auf dem Host ausgeführt. Dieser Befehl gibt Envoy die Möglichkeit, auf eingehende Anfragen auf Port 80 zu warten. Wie in der Listener-Konfiguration angegeben, lauscht Envoy Proxy jedoch auf eingehenden Datenverkehr auf Port 8080. Dadurch kann der Prozess als Benutzer mit geringen Berechtigungen ausgeführt werden.
docker run --name proxy1 -p 80:8080 --user 1000:1000 -v /root/envoy.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy
Testing
Bei laufendem Proxy können nun Tests durchgeführt und verarbeitet werden. Der folgende cURL-Befehl gibt eine Anfrage mit dem in der Proxy-Konfiguration definierten Host-Header aus.
curl -H "Host: one.example.com" localhost -i
Die HTTP-Anfrage führt zu einem Fehler 503. Dies liegt daran, dass Upstream-Verbindungen nicht funktionieren und nicht verfügbar sind. Daher verfügt Envoy Proxy über keine verfügbaren Ziele 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 den verfügbaren Diensten kann Envoy den Datenverkehr erfolgreich an sein 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 Envoy-Proxy-Protokollen sollte auch eine Zugriffszeichenfolgenausgabe angezeigt werden.
Zusätzliche HTTP-Antwortheader
In den Antwortheadern der eigentlichen Anfrage werden zusätzliche HTTP-Header angezeigt. Der Header zeigt die Zeit an, die der Upstream-Host mit der Verarbeitung der Anfrage verbracht hat. Ausgedrückt in Millisekunden. Dies ist nützlich, wenn der Client die Servicezeit im Vergleich zur Netzwerklatenz ermitteln möchte.
x-envoy-upstream-service-time: 0
server: envoy
Endgültige 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 }
Zusätzliche Informationen vom Übersetzer
Anweisungen zur Installation von Envoy Proxy finden Sie auf der Website
Standardmäßig verfügt rpm über keine systemd-Dienstkonfiguration.
Systemd-Dienstkonfiguration /etc/systemd/system/envoy.service hinzufügen:
[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 ein Verzeichnis /etc/envoy/ erstellen und die config.yaml-Konfiguration dort ablegen.
Es gibt einen Telegram-Chat mit Envoy-Proxy:
Envoy Proxy unterstützt die Bereitstellung statischer Inhalte nicht. Wer kann also für das Feature stimmen:
An der Umfrage können nur registrierte Benutzer teilnehmen.
Hat Sie dieser Beitrag dazu ermutigt, den Envoy-Proxy zu installieren und zu testen?
-
ja
-
Nein
75 Benutzer haben abgestimmt. 18 Benutzer enthielten sich der Stimme.
Source: habr.com