Load Balancer in Orchestrierungssystemen (Kubernetes, Nomad und andere) stellen mehr Anforderungen als nur den Load Balancing. Erstens sollte der Load Balancer in der Lage sein, ein Verzeichnis mit einer Liste von Diensten zu lesen, zu denen der Datenverkehr umgeleitet werden soll (oder optional die Registrierung von Diensten zu ermöglichen, um sie in den Datenverkehr aufzunehmen). Zweitens machen Sie es dynamisch, weil Orchestrierungssysteme können die Anzahl der Dienstreplikate jederzeit erhöhen oder verringern oder an andere Adressen im Netzwerk verschieben. Und drittens, ohne den Verkehr zu stoppen.
Im heutigen Beitrag werde ich die Arbeit mit zwei Load Balancern beschreiben - Traefik und HAProxy. Diese Load Balancer können mit einer beeindruckenden Liste von Orchestrierungswerkzeugen arbeiten. In den Beispielen wird beschrieben, wie Sie mit dem Nomad-Orchestrierungssystem arbeiten.
Im
letzten Beitrag habe ich bereits ein Beispiel für Load Balancers gegeben - Fabio. Seine Einschränkungen: Funktioniert nur mit http / https-Protokollen und nur mit Consul. Im Gegensatz zu Fabio arbeitet Load Balancers Traefik mit einer beeindruckenden Anzahl verschiedener Systeme. Hier ist eine unvollständige Liste von der Entwicklerseite: Docker, Schwarmmodus, Kubernetes, Marathon, Konsul, usw., Rancher, Amazon ECS, ...
Ich werde das Beispiel aus dem
vorherigen Beitrag fortsetzen , in dem mehrere Replikate des Django-Dienstes erstellt wurden.
Traefik kann von der Entwicklerseite als ausführbare Datei für die gängigsten Betriebssysteme heruntergeladen werden. Um sich in Nomad (tatsächlich in Consul) zu integrieren, müssen Sie eine Konfigurationsdatei erstellen:
[entryPoints] [entryPoints.http] address = ":5001" [web] address = ":8080" [consulCatalog] endpoint = "127.0.0.1:8500" domain = "consul.localhost" exposedByDefault = false prefix = "traefik"
Führen Sie dann den Befehl mit der angegebenen Konfigurationsdatei aus:
traefik -c nomad/traefik.toml
Danach wird UI Traefik auf Port 8080 verfügbar sein, der noch keine Dienste veröffentlicht hat. Es gibt verschiedene Möglichkeiten, Dienste zu veröffentlichen, die letztendlich dasselbe tun: Sie laden Schlüssel- / Wertdaten in das Traefik-System. Wir werden die Gelegenheit nutzen, Schlüssel / Wert-Paare über Service-Tags festzulegen. Erweitern wir die Konfigurationsdatei des Django-Dienstes mit dem Parameter tags:
job "django-job" { datacenters = ["dc1"] type = "service" group "django-group" { count = 3 restart { attempts = 2 interval = "30m" delay = "15s" mode = "fail" } ephemeral_disk { size = 300 } task "django-job" { driver = "docker" config { image = "apapacy/tut-django:1.0.1" port_map { lb = 8000 } } resources { network { mbits = 10 port "lb" {} } } service { name = "django" tags = [ "traefik.enable=true", "traefik.frontend.entryPoints=http", "traefik.frontend.rule=Host:localhost;PathStrip:/test", "traefik.tags=exposed" ] port = "lb" check { name = "alive" type = "http" path = "/" interval = "10s" timeout = "2s" } } } } }
In diesem Beispiel wird der Dienst auf dem localhost-Host veröffentlicht und auf der / test-Route bereitgestellt. Traefik hat ein flexibles und vollständiges Regelsystem für die Konfiguration von Routen entwickelt, einschließlich der Arbeit mit regulären Ausdrücken. Die Liste der Parameter für die
Regeln in der Entwicklerdokumentation.
Nach dem Ausführen des
nomad job run nomad/django.conf
Regeln angewendet und der Datenverkehr vom Load Balancer wird an den Dienst geleitet. Dementsprechend können Sie diese Parameter ändern, eine neue
nomad job run nomad/django.conf
, und alle Änderungen werden ohne störenden Verkehrsstopp angewendet.
Der Nachteil von Traefik ist, dass es mit den Protokollen der http / https-Familie funktioniert (nur für den Fall, dass diese Familie auch Web-Sockets enthält). Dennoch besteht die Möglichkeit, dass mit anderen Protokollen gearbeitet werden muss. Fahren wir also mit der nächsten umfassenderen Lösung fort, die auf HAProxy basiert. Vor einiger Zeit hatte HAProxy Probleme mit dem Softloading, was die Verwendung mit Orchestrierungssystemen erschwerte (während des Neustarts musste die Bewegung von Paketen auf Netzwerkebene gestoppt werden). Das ist jetzt kein Problem mehr.
Zuerst müssen Sie Haproxy auf Ihrem Computer installieren. Hier funktioniert die Option zur Installation im Container nicht. In Haproxy war es erst kürzlich möglich, den Prozess im "Soft" -Modus neu zu starten, aber der Docker-Container stoppt immer noch, da der zweite Prozess tatsächlich mit Haproxy beginnt. Er ändert sich nur im Standby-Modus - was mit dem Docker und seinem Prinzip "Eins" nicht funktioniert -container ist ein Prozess. "
Damit Haproxy funktioniert, müssen Sie über eine Konfigurationsdatei verfügen, die die erforderlichen Regeln enthält. Nomad (tatsächlich in Consul) verwendet ein Vorlagensystem, das Konfigurationen generieren kann:
global debug defaults log global mode http option httplog option dontlognull timeout connect 5000 timeout client 50000 timeout server 50000 frontend http_front bind *:5001 stats uri /haproxy?stats default_backend http_back backend http_back balance roundrobin{{range service "django"}} server {{.Node}} {{.Address}}:{{.Port}} check{{end}}
Das Schlüsselwort
range
in diesem Fall als Iterator. Für die drei "Django" -Dienste wird die folgende Konfigurationsdatei generiert:
global debug defaults log global mode http option httplog option dontlognull timeout connect 5000 timeout client 50000 timeout server 50000 frontend http_front bind *:5001 stats uri /haproxy?stats default_backend http_back backend http_back balance roundrobin server 228.195.86.224 127.0.0.1:21469 check server 228.195.86.224 127.0.0.1:25872 check server 228.195.86.224 127.0.0.1:25865 check
Die Bibliothek
https://github.com/hashicorp/consul-template wird verwendet, um den Generierungsprozess gemäß der Vorlage im
laufenden Betrieb zu starten. Aus der Ressource des Entwicklers können Sie die ausführbare Datei für alle gängigen Betriebssysteme herunterladen und den Vorgang im Auftrag eines nicht autorisierten Benutzers mit dem folgenden Befehl starten:
consul-template -template="haproxy/haproxy.cfg.tmpl:haproxy/haproxy.cfg:./haproxy/haproxy.reload.sh"
Der Parameter
-template
enthält durch Doppelpunkte getrennte Parameter 1) den Namen der Vorlage, 2) den Namen der resultierenden Konfigurationsdatei 3) den Befehl, der ausgeführt wird, nachdem die Datei generiert wurde. Die Datei wird automatisch generiert, wenn die in der Vorlage enthaltenen Variablen geändert werden (z. B. wird die Anzahl der Replikate des Django-Dienstes geändert).
Nach dem Starten der Template-Engine, die die erste Konfiguration generiert, können Sie haproxy ausführen:
haproxy -D -f haproxy/haproxy.cfg -p `pwd`/haproxy.pid
Wir geben die PID-Datei explizit an, um ein Signal an die "weiche" Haproxy-Überladung senden zu können:
haproxy -D -f ./haproxy/haproxy.cfg -p `pwd`/haproxy.pid -sf $(cat `pwd`/haproxy.pid)
In diesem Beispiel wird der Dienst auf Port 5001 veröffentlicht. Auf demselben Port können Sie die Statistiken von Haproxy selbst unter der Adresse
/haproxy?stats
.
AKTUALISIERT 24.02.2019 22:43 Uhr
Laut
dem Kommentar von
@ usego wurde der Betrieb von Haproxy im Docker-Container zusätzlich verfeinert, insbesondere gemäß dem Fragment aus der Dokumentation
github.com/neo4j/docker-library-docs/tree/master/haproxy#reloading-configKonfiguration neu laden
Wenn Sie einen Bind-Mount für die Konfiguration verwendet und Ihre Datei haproxy.cfg bearbeitet haben, können Sie die ordnungsgemäße Neuladefunktion von HAProxy verwenden, indem Sie ein SIGHUP an den Container senden:
$ docker kill -s HUP my-running-haproxy
Das Entrypoint-Skript im Image prüft, ob der Befehl haproxy ausgeführt wird, und ersetzt ihn durch den haproxy-systemd-wrapper von HAProxy upstream, der sich um die Signalverarbeitung kümmert, um das ordnungsgemäße Neuladen durchzuführen. Unter der Haube wird die Option -sf von Haproxy verwendet, sodass "zwei kleine Fenster mit einer Länge von jeweils einigen Millisekunden vorhanden sind, in denen bei hohen Lasten möglicherweise einige Verbindungsfehler auftreten" (siehe Stoppen und Neustarten von HAProxy).
Bei diesem Ansatz wird die Konfiguration wirklich neu geladen, jedoch aufgrund einer Unterbrechung des aktuellen Prozesses. Und dies bedeutet, dass die Dienste zwar sehr unbedeutend sind, aber dennoch eine Zeit der Unzugänglichkeit aufweisen und einige Kunden möglicherweise eine Fehlermeldung beobachten. Manchmal ist dies jedoch nicht das Hauptauswahlkriterium. Daher werde ich zusätzlich die Konfiguration docker-compose.yml zum Starten von Haproxy in Docker angeben:
version: '3' services: haproxy_lb: image: haproxy volumes: - ./haproxy:/usr/local/etc/haproxy network_mode: host
Der Befehl, der die Haproxy-Konfiguration überlastet, ändert sich ebenfalls:
consul-template -template="haproxy/haproxy.cfg.tmpl:haproxy/haproxy.cfg:docker kill -s HUP $(docker-compose ps -q haproxy_lb)"
Zu den Vorteilen dieser Implementierung gehört die Möglichkeit, ohne die Installation von Haproxy zu arbeiten.
Beispielcode ist im Repository verfügbar.Nützliche Links:
1. www.haproxy.com/blog/haproxy-and-consul-with-dns-for-service-discovery2.m.mattmclaugh.com/traefik-and-consul-catalog-example-2c33fc1480c03. www.hashicorp.com/blog/load-balancing-strategies-for-consulapapacy@gmail.com
24. Februar 2019