Ich versuche, einen Docker-Schwarm einzurichten.
Meine Knoten müssen über TLS kommunizieren.
Ich habe ein Zertifikat für den Managerknoten mit extendedKeyUsage = serverAuth erstellt
Ich habe den Managerknoten mit dem folgenden daemon.json konfiguriert:
{
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"],
"tlscacert": "/var/docker/ca.pem",
"tlscert": "/var/docker/server-cert.pem",
"tlskey": "/var/docker/server-key.pem",
"tlsverify": true
}
Um dies zu testen, habe ich ein Client-Zertifikat erstellt, es verwendet, um von meinem Laptop aus eine Verbindung mit der Docker-API herzustellen, und ich kann erfolgreich eine Verbindung herstellen.
Jetzt muss ich dem Schwarm einen Worker-Knoten hinzufügen.
Ich habe es auf die gleiche Weise wie den Manager-Knoten eingerichtet; mit einem ähnlichen daemon.json. Ich habe einen SSL-Schlüssel mit extendedKeyUsage = serverAuth verwendet und die Client-Verbindung auf die gleiche Weise wie auf dem Manager-Knoten nachgewiesen.
Dann habe ich im Manager Docker Swarm Init ausgeführt
Um den Worker-Knoten dem Swarm hinzuzufügen, verwende ich den folgenden Befehl: docker swarm join --token XXX dockman.myhost.com:2376
Aber ich erhalte eine Fehlermeldung:
Error response from daemon: rpc error: code = Unavailable desc = all SubConns are in TransientFailure, latest connection error: connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate"
Ich dachte, ich könnte es weiter testen, indem ich versuche, vom Worker-Knoten aus eine Verbindung zur Docker-API auf dem Manager-Knoten herzustellen:
sudo docker --tlsverify --tlscacert=/var/docker/ca.pem --tlscert=./server-cert.pem --tlskey=./server-key.pem -H=127.0.0.1:2376 version
Das Ergebnis ist:
Client: Docker Engine - Community
Version: 19.03.5
API version: 1.40
Go version: go1.12.12
Git commit: 633a0ea838
Built: Wed Nov 13 07:29:52 2019
OS/Arch: linux/amd64
Experimental: false
The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: Get https://127.0.0.1:2376/v1.40/version: remote error: tls: bad certificate
Dieser zweite Test hat mir viel mehr Stoff zum Nachdenken gegeben. Natürlich wird er fehlschlagen, weil ich versuche, eine Verbindung mit einem Server-Zertifikat und nicht mit einem Client-Zertifikat herzustellen, aber ist das nicht genau das, was der Docker Swarm Join versucht? Es ergibt für mich keinen Sinn, das Client-Zertifikat in daemon.json einzufügen. Ich habe gegoogelt, wie man ein einziges Zertifikat sowohl für den Server als auch für den Client erstellt, und es ist möglich, scheint aber eine schlechte Praxis zu sein. Ich hätte gedacht, dass es im Tutorial behandelt würde, wenn es erforderlich wäre.
Ich stecke an diesem Punkt fest. Ich kann nicht herausfinden, welche Zertifikatskonfiguration erforderlich ist.
Ich habe verfolgt https://github.com/docker/docker.github.io/blob/master/swarm/configure-tls.md Hier wird die Erstellung von Zertifikaten beschrieben, die Client- oder Serverauthentifizierung wird jedoch überhaupt nicht erwähnt.
Aktualisierung 1
Ich habe ein Dokument gefunden, in dem stand, dass Zertifikate Client und Server sein müssen
https://hub.docker.com/_/swarm/
Also habe ich das Knotenzertifikat so umgestaltet, dass es sowohl als Client als auch als Server fungiert. Jetzt funktioniert der Befehl der Docker-Version, wenn er vom Knoten ausgeführt wird, aber nicht der Swarm-Join.
Antwort1
Sie verwechseln den Swarm-Modus ( docker swarm
und ähnliche CLIs) mit dem klassischen containerbasierten Swarm (gehostet als Container auf Docker Hub). Dies sind zwei verschiedene Tools.
Die beiden Dokumentationssätze finden Sie unter:
- Schwarmmodus:https://docs.docker.com/engine/swarm/
- Klassischer Schwarm:https://github.com/docker/classicswarm(frühere Dokumentation wurde von der Docker-Website entfernt)
Im Swarm-Modus ist keine manuelle TLS-Konfiguration erforderlich, da alles integriert ist und die Ports für den Swarm-Modus nicht mit den Ports für den Docker-API-Socket übereinstimmen. Sie möchten die Docker-API nicht ohne triftigen Grund im Netzwerk verfügbar machen (dies ist eine häufige Quelle von Hacks), und der Swarm-Modus ist kein Grund.
Daher sollten Sie die -H
Option aus dem dockerd
Befehl entfernen, zusammen mit allen dort vorhandenen TLS-Optionen. Führen Sie den Befehl dann docker swarm init
auf dem ersten Manager aus, der die TLS-Anmeldeinformationen generiert und ein Token bereitstellt, das einen Hash der selbst signierten Zertifikate enthält. Anschließend führen die anderen Manager und Worker einen aus, docker swarm join
um die Client-Zertifikate zu generieren, eine Verbindung zum Manager herzustellen, den Hash der Manager-Zertifikate anhand des Tokens zu validieren und sich mit dem geheimen Teil des Join-Tokens gegenüber dem Manager zu authentifizieren.
Das Obige verschlüsselt die Managementebene zwischen Managern und Arbeitern. Um die in Overlay-Netzwerken zwischen Arbeitern übertragenen Daten zu verschlüsseln, müssen Sie IPSec in den von Ihnen erstellten Overlay-Netzwerken aktivieren:
docker network create --opt encrypted --driver overlay app-overlay-net
Die Dokumentation zu dieser Funktion finden Sie unter:https://docs.docker.com/v17.09/engine/userguide/networking/overlay-security-model/
Antwort2
Ich hatte Recht, dass alle Zertifikate sowohl Client- als auch Server-Zertifikate sein mussten, damit sie funktionierten.
Dann stieß ich auf weitere Probleme. Das Hauptproblem war, dass die virtuellen Maschinen auf dem von mir verwendeten Host die Verwendung von Port 4789 verbieten, da dieser von VMWare verwendet wird. Dies ist der Standard-Datenpfad-Port, der für das Overlay-Netzwerk verwendet wird.
Ich musste alle Knoten und Manager vollständig aus dem Schwarm entfernen (und ihn effektiv löschen) und ihn mit dem Parameter „data-path-port“ neu starten:
docker swarm init --data-path-port=7777
(Ich habe auch die Werbeadresse als IP für jeden Knoten angegeben, aber ich glaube nicht, dass das erforderlich war.)
Natürlich gingen bei diesem Vorgang alle meine Docker-Geheimnisse, die Docker-Konfiguration und einige meiner Docker-Netzwerke verloren und mussten neu erstellt werden.
Nachdem ich dies abgeschlossen und die Firewall so geändert hatte, dass sie UDP-Kommunikation zwischen Knoten über den Datenpfad-Port zuließ, funktionierte alles wieder.
Da das Schwarmnetzwerk verschlüsselt ist, sollte meiner Meinung nach alles funktionieren.