Debuggen von MQTT über Websockets auf Envoy 1.28.0
Ich habe unsere Envoy-Installation von Envoy 1.11.1 auf 1.28.0 migriert und verwende nun auch SNI zur Auswahl des richtigen Zertifikats.
Ein großer Teil dieser Migration ist die Aktualisierung der Syntax der Konfiguration für Envoy von der API v2 auf die API v3.
Das Upgrade verlief gut, außer dass unser Websocket-basierter MQTT-Dienst (basierend auf VerneMQ) nicht wie erwartet funktionierte.
Zuerst nahm ich an, dass das Problem in envoy lag. Nachdem ich viele Timeout-Optionen ausprobiert und mir die envoy-Dokumentation angesehen habe, habe ich beschlossen, mit einer neuen Route und einem anderen Broker (Mosquitto) zu experimentieren.
Die folgende Konfiguration funktioniert mit Mosquitto als Broker, für den Fall, dass jemand anderes über das gleiche Problem stolpert.
Hier ein Auszug aus meiner envoy.yaml (die vollständige Konfiguration besteht aus über 87000 Zeilen, die von einem Template-Skript generiert werden, wegen der SNI und der Notwendigkeit, individuelle Listener pro Domain zu haben, wie ich oben erwähnt habe):
statische_Ressourcen:
Hörer:
- Adresse:
socket_address:
Adresse: 0.0.0.0
port_value: 443
per_connection_buffer_limit_bytes: 32768 # 32 KiB
Listener_Filter:
- name: tls_inspector
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector
filter_chains:
- filter_chain_match:
server_names: ["picockpit.com", "www.picockpit.com", "picockpit.com:443", "www.picockpit.com:443"]
transport_socket:
Name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_certificates:
- certificate_chain: { filename: "/certs/letsencrypt/live/picockpit.com/fullchain.pem" }
private_key: { dateiname: "/certs/letsencrypt/live/picockpit.com/privkey.pem" }
alpn_protocols: [ "h2,http/1.1" ]
filter:
- name: envoy.filters.network.http_connection_manager
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_präfix: ingress_http
codec_type: AUTO
http_filters:
- Name: envoy.filters.http.compressor
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.http.compressor.v3.Compressor
compressor_library:
name: text_optimiert
typed_config:
'@type': type.googleapis.com/envoy.extensions.compression.gzip.compressor.v3.Gzip
komprimierungsstufe: BEST_SPEED
komprimierung_strategie: DEFAULT_STRATEGY
speicher_level: 9
fenster_bits: 15
chunk_size: 16384
- Name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
common_http_protocol_options:
idle_timeout: 3600s # 1 Stunde
use_remote_address: true
xff_num_trusted_hops: 0
route_config:
virtual_hosts:
- name: backend
Domains: ["picockpit.com", "www.picockpit.com", "picockpit.com:443", "www.picockpit.com:443"]
Routen:
- match: { path: "/pidoctor"}
redirect:
path_redirect: "/raspberry-pi/pidoctor-raspberry-pi-system-health-monitor/"
- match: { prefix: "/pidoctor/"}
redirect:
path_redirect: "/raspberry-pi/pidoctor-raspberry-pi-system-health-monitor/"
- match: { prefix: "/mqtt/test" }
route:
prefix_rewrite: "/mqtt"
cluster: ziel_test
Timeout: 0s
idle_timeout: 0s
upgrade_configs:
- upgrade_type: "Websocket"
aktiviert: true
- übereinstimmen: { prefix: "/" }
route:
cluster: target_main
Timeout: 0s
cluster:
- name: ziel_test
connect_timeout: 5s
per_connection_buffer_limit_bytes: 32768 # 32 KiB
Typ: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: ziel_test
Endpunkte:
- lb_endpoints:
- endpoint:
Adresse:
socket_address:
Adresse: mosquitto-test.test-network
port_wert: 8025
Beachten Sie, dass ich einen großen Teil der Konfiguration anderer Dienste und Routen ausgelassen habe und Ihnen die target_main-Cluster-Informationen nicht gegeben habe (weil sie für die MQTT-über-Websockets-Situation irrelevant sind).
Beachten Sie den Wert timeout: 0s, was wichtig ist, damit MQTT-Verbindungen fortgesetzt werden können und nicht wie standardmäßig vorgesehen nach 15 Sekunden abgebrochen werden.
Ich habe auch andere Teile hervorgehoben, die meiner Meinung nach relevant sind, damit Verbindungen zu Websockets aufgerüstet werden können (damit MQTT über sie übertragen werden kann). Beachten Sie auch die Port-Nummern die als zusätzliche Domänenübereinstimmungen eingegeben werden.
Mosquitto docker-compose.yml:
Version: '3.6'
Dienstleistungen:
mosquitto:
image: eclipse-mosquitto
container_name: mosquitto-test
Rechnername: mosquitto-test
Netzwerke:
- test_net
Neustart: "nein"
Benutzer: "root:root"
Datenträger:
- Typ: bind
Quelle: ./mosquitto.conf
Ziel: /mosquitto/config/mosquitto.conf
Netzwerke:
test_net:
extern:
name: test-netze
mosquitto.conf:
Hörer 8025
Protokoll Websockets
allow_anonymous wahr
log_type all
Tool zur Überprüfung der Verbindung:
Aktualisierung 13.11.2023
MQTT ist wieder online, auch mit VerneMQ:
Ich hatte VerneMQ zwar mehrmals neu gestartet, aber offenbar nicht lange genug gewartet, bis es sich stabilisiert hatte. Ein Kollege hat es heute neu gestartet, und jetzt funktioniert es. Es scheint, dass es 10 - 15 Minuten braucht (in unserem Setup), um voll ansprechbar zu werden und angemessen zu arbeiten.
Daher kann ich bestätigen, dass die obige Konfiguration für envoy auch mit VerneMQ funktioniert.
Gelernte Lektion
Wenn etwas nicht funktioniert, versuchen, das Problem im Zusammenspiel mit einem anderen Werkzeug zu reproduzieren - Wenn es dort funktioniert, dann liegt das Problem möglicherweise nicht bei dem ersten Werkzeug, das Sie geändert haben, sondern bei dem zweiten Werkzeug, mit dem es zusammenarbeiten muss.
und einige zusätzliche Leckereien:
Online-Dokumentation
- https://www.envoyproxy.io/docs
- https://www.envoyproxy.io/docs/envoy/v1.28.0/ (speziell für die aktuelle envoy-Version)
- https://github.com/envoyproxy/envoy/blob/main/configs/envoyproxy_io_proxy_http3_downstream.yaml - Beispiel einer HTTP3-Konfiguration
- https://codilime.com/blog/envoy-configuration/ - Verständnis für den Gesandten
- https://pi3g.com/envoy-docker-and-websockets-debugging-and-configuration/ - über Websockets und envoy (Websockets werden in PiCockpit verwendet, um MQTT zu transportieren) - dieser vorherige Artikel basiert auf v1.11.1 von envoy
Nützliche Tools
- https://http3check.net/ - ermöglicht die Prüfung auf HTTP/3-Unterstützung
- HiveMQ Websocket-Client