Blog
Welche Kunden brauchen wirklich eine eigene VM? Ein abgestufter Docker-Isolationsplan
Eine VM für jeden Kunden ist übertrieben. Hier erfahren Sie, wie Sie entscheiden, wie viel Isolation jeder Mandant benötigt – und wie Sie die Entscheidung automatisieren.
Zusammenfassung
Agenturen geraten oft in Panik, wenn ein Kunde fragt, wie wirklich isoliert seine Daten von anderen Mandanten sind. Docker-Namespaces und Cgroups bieten echte Isolation, aber sie sind nicht dasselbe wie eine Hardware-Grenze. Statt jeden Kunden auf einer VM laufen zu lassen – oder schlimmer noch, alle Kunden gleich zu behandeln – sollten Sie eine kleine Reihe von Isolationsstufen aufbauen und jeden Kunden anhand von Datensensibilität, Vertrauen und Compliance einer Stufe zuordnen. Ein gehärteter Container (Nicht-Root, entfernte Capabilities, Seccomp, schreibgeschütztes Root) deckt die meisten Websites ab; regulierte oder feindliche Workloads erhalten eine VM oder einen Container-in-VM-Hybrid. Dieser Beitrag bietet einen wiederholbaren Entscheidungsablauf, eine Vergleichstabelle und einen ehrlichen Blick darauf, wann mehr Isolation übertrieben ist.
Sind Sie an dem Punkt in einem Verkaufsgespräch angelangt, an dem der neue Kunde sagt: „Wir sind im Gesundheitswesen, zeigen Sie mir, dass unsere Daten von Ihren anderen Kunden isoliert sind“, und Sie würden lieber über alles andere sprechen?
Das ist das Agenturproblem: nicht eine perfekte Bereitstellung, sondern dieselbe zuverlässige Bereitstellung, die bei einem Dutzend Kunden mit unterschiedlichen Budgets, Risikoprofilen und Compliance-Anforderungen wiederholt wird. Hier ist die ehrliche Version. Docker-Isolation ist real, aber sie ist spezifisch. Namespaces geben jedem Container seine eigene Sicht auf Prozesse, Netzwerk und Dateisystem; Cgroups begrenzen CPU, Speicher und Datenträger-I/O, sodass Mandanten sich nicht gegenseitig aushungern können. Was Sie damit nicht bekommen, ist eine Hardware-Wand zwischen dem Container und dem Host-Kernel. Wenn ein Angreifer den Container verlässt, befindet er sich im einzigen Kernel, den Sie haben. Der Rest dieses Artikels verwandelt diese unbequeme Tatsache in eine wiederholbare Entscheidung: Klassifizieren Sie jeden Kunden nach Datensensibilität und Vertrauen, wenden Sie ein Basis-Härtungsprofil an und greifen Sie nur dann zu einer VM, wenn die Kosten eines Sicherheitsvorfalls höher sind als die Kosten der VM.
Moment, sind Container nicht bereits isoliert?
Docker läuft auf Linux-Namespaces und Cgroups, und diese Begriffe leisten echte Arbeit. Namespaces trennen Prozess-IDs, Netzwerk-Stacks, Mount-Punkte und Benutzer, sodass ein Prozess in einem Container die Prozesstabelle eines anderen nicht sehen kann. Cgroups setzen Grenzen: Geben Sie einem Container 0,5 CPU, 512 MB Speicher und ein festes Block-I/O-Gewicht, und genau das bekommt er. Eine außer Kontrolle geratene Schleife in einem Mandanten wird gedrosselt, anstatt den Nachbarn lahmzulegen. Wenn Sie keine Grenzen konfiguriert haben, haben Sie das Grundlegendste übersprungen, wofür Cgroups da sind.
Nehmen wir eine einfache PHP-Anwendung in Container A. Sie sieht ihr eigenes Dateisystem, ihre eigene Netzwerkschnittstelle, ihre eigene PID 1. Container B hat dasselbe, aber eine andere Sicht. Das sind Namespaces. Gehen Sie nun weg und lassen Sie die Speicherbegrenzung weg: Container A kann den RAM des Hosts füllen und Container B ausbremsen. Genau das zu verhindern, existieren Cgroups. Aber zwei Container können durch Namespaces voneinander isoliert sein und sich dennoch den Host-Kernel teilen – das ist der Teil, um den es bei jeder Geschichte über Container-Ausbrüche geht. Ein Exploit, der den Kernel erreicht, kann potenziell jeden Mandanten auf diesem Host erreichen.
„Docker ist isoliert“ ist ein halbwahrer Satz. Die genaue Version lautet: „Docker isoliert mit Namespaces und Cgroups, und eine Kernel-Schwachstelle ist der Blast-Radius.“ Bevor Sie einem Mandanten vertrauen, unvertrauten Code auszuführen, sitzen Sie eine Minute mit diesem Gedanken. Die Antwort ist nicht „nutzen Sie niemals Container“ – das ist die einfache Panik. Die Antwort ist ein Stufensystem.
Warum brauchen manche Kunden mehr als Namespaces?
Die ehrliche Antwort ist, dass Isolation kein Schalter ist, sondern ein Spektrum. An einem Ende haben Sie einen vollständig gemeinsamen Container, in dem effektiv alle in einer App sind. Am anderen Ende haben Sie eine separate VM pro Mandant mit eigenem Kernel. Die meiste Agenturarbeit liegt in der unbequemen Mitte, und die Mitte ist keine binäre Wahl zwischen „Docker ist in Ordnung“ und „führen Sie für alle eine VM aus“.
Was einen Kunden nach rechts drückt, ist nicht seine Größe. Es sind vier Fragen:
- Speichern sie regulierte Daten? Gesundheitsakten, Zahlungskartendetails, alles, was eine Aufsichtsbehörde als sensibel bezeichnen würde.
- Hat ein Sicherheitsvorfall auf ihrem Mandanten einen realistischen Weg zu einem anderen Mandanten? Wenn sie beliebigen Code ausführen können, ja.
- Vertrauen Sie dem Code und den Menschen, die ihn bereitstellen? Ein Kunde, der den billigsten Freiberufler engagiert, hat nicht dasselbe Vertrauensniveau wie ein Kunde, dessen Entwicklungsteam Sie kennen.
- Steht in ihrem Vertrag „dediziert“, „isoliert“ oder „privat“? Wenn ja, haben Sie bereits eine Stufe versprochen; die einzige Aufgabe ist nun, die richtige auszuwählen.
Wenn Sie diese Fragen noch nicht beantworten können, ordnen Sie den Kunden einer Basisstufe zu und notieren Sie die Annahmen. Das ist kein Sicherheitsaudit; es ist ein Plausibilitätscheck, den Sie bei jedem Onboarding wiederholen.
Wie entscheide ich pro Kunde, ohne jedes Mal ein Sicherheitsaudit durchzuführen?
Erstellen Sie eine kleine Tabelle und halten Sie sich daran. Sie brauchen keine Matrix mit vierzig Zellen. Vier Stufen decken fast jeden Kunden ab, den eine Agentur sieht.
| Kundenposition | Was sie tatsächlich trennt | Verwenden, wenn |
|---|---|---|
| Stufe 1: Gemeinsame App/Container | Nur Anwendungslogik | Interne Dienstprogramme, Daten mit geringem Risiko, Projekte, bei denen alle explizit in einem Anmeldesystem sind |
| Stufe 2: Gleicher Host, separate Container | Namespaces und Cgroups | Die meisten Marketing-Websites, Kontaktformulare, keine sensiblen Daten |
| Stufe 3: Gehärteter Container | Stufe 2 + Nicht-Root, entfernte Capabilities, Seccomp, schreibgeschütztes Root, Netzwerksegmentierung | E-Commerce, personenbezogene Daten (PII), eigener Code, dem Sie nicht vollständig vertrauen |
| Stufe 4: VM pro Mandant | Hypervisor und ein separater Kernel | Gesundheitswesen, Finanzen, Compliance-Unterlagen, unvertrauter Code, laute Nachbarn |
So sieht das in der Praxis aus. Ein Bäckerei-Kunde mit einem Kontaktformular und einem Instagram-Link kommt in Stufe 2: ein Container auf einem gemeinsamen Host, standardmäßiges Docker-Networking, Ressourcengrenzen, erledigt. Ein Online-Shop, der Kundennamen, Adressen und Zahlungsweiterleitungen speichert, kommt in Stufe 3: derselbe gemeinsame Host, aber der Container läuft als Nicht-Root-Benutzer, hat keine zusätzlichen Kernel-Capabilities, verwendet ein Seccomp-Profil und gibt nur Port 443 frei. Ein medizinisches Aufnahmeportal, das geschützte Gesundheitsinformationen speichert, kommt in Stufe 4: eine VM pro Mandant, denn die Kosten eines Sicherheitsvorfalls sind nicht „wir räumen das auf“, sondern „wir können dem Kunden nicht zeigen, dass wir ihn ernst genommen haben“.
Der ganze Trick besteht darin, dass Sie die Architektur nicht für jeden Kunden neu überdenken. Sie wählen eine Zeile aus einer Tabelle, auf die Sie sich bereits geeinigt haben. So kann eine Agentur mit fünf Personen hundert Websites betreiben, ohne hundert separate Sicherheitsbesessenheiten zu haben. Es bedeutet auch, dass der nächste Kunde keine Antwort erhält, die davon abhängt, welches Teammitglied das Telefon abgenommen hat. Für die tiefere Architekturdebatte hinter diesen Entscheidungen geht dieser Leitfaden zur Gestaltung von Multi-Tenant-Isolationsstufen ausführlicher auf die Kompromisse ein.
Wie sieht ein gehärteter Container tatsächlich aus?
Hören wir auf, „gehärtet“ zu sagen, und werden wir konkret. Das bedeutet Stufe 3 für einen typischen WordPress- oder PHP-Kunden.
Erstens: Ändern Sie den Benutzer. Die meisten offiziellen Images laufen standardmäßig weiterhin als Root; erstellen Sie in Ihrem Dockerfile einen Nicht-Root-Benutzer und führen Sie die App als diesen Benutzer aus. Das beseitigt sofort den häufigsten Weg, auf dem aus einem Container-Kompromiss ein Host-Kompromiss wird. Zweitens: Entfernen Sie die Capabilities, die Sie nicht benötigen. Führen Sie mit --cap-drop ALL aus und fügen Sie nur eine wieder hinzu, normalerweise NET_BIND_SERVICE, damit die App auf Port 80 lauschen kann. Das allein ist eine größere Änderung, als die meisten erwarten. Drittens: Machen Sie das Root-Dateisystem mit --read-only schreibgeschützt und mounten Sie beschreibbare Verzeichnisse (Uploads, das Datenbank-Datenverzeichnis) als Volumes oder tmpfs. Viertens: Wenden Sie ein Seccomp-Profil an und, falls Ihr Host es unterstützt, AppArmor oder SELinux. Schließlich: Platzieren Sie den Container in einem dedizierten Docker-Netzwerk und legen Sie nur die Ports offen, die tatsächlich erreichbar sein müssen.
Gehen wir ein WordPress-Beispiel durch. Das Basis-Image läuft wahrscheinlich als Root, also fügen Sie einen useradd-Schritt und eine USER-Direktive hinzu. Sie führen den Container mit einer Speicherbegrenzung und einer CPU-Begrenzung aus, damit ein Ansturm von Plugin-Datenverkehr dem Nachbarn nicht schadet. Sie mounten /var/www/html/wp-content/uploads als beschreibbares Volume. Sie setzen --read-only. Sie hängen es an ein Netzwerk an, das in der Nähe kein --privileged-Flag hat. Das Ergebnis ist ein Container, der früher „eine WordPress-Website“ war und jetzt „eine WordPress-Website ist, die zufällig stärker gehärtet ist als die meisten virtuellen privaten Server“ ist.
Wenn es fragil wirkt, das alles von Hand zu bauen, gibt es einen einfacheren Mittelweg: Dockers Enhanced Container Isolation, die User-Namespace-Isolation und eine sichere Container-Laufzeit verwendet. Es ist eine legitime Abkürzung, aber kein Freifahrtschein, um Nicht-Root oder das Entfernen von Capabilities zu überspringen. Der Mandant braucht weiterhin ein vernünftiges Image. Der Unterschied besteht darin, dass die kernelbezogene Angriffsfläche kleiner wird, ohne dass Sie über Nacht zum Seccomp-Experten werden. Wenn Sie die genaue Abfolge für einen einzelnen Mandanten wünschen, verwandelt der Schritt-für-Schritt-Isolationshärtungs-Leitfaden diesen Abschnitt in Copy-Paste-Befehle.
Wann höre ich auf, Schichten hinzuzufügen, und übergebe ihnen einfach eine VM?
Hier ist der konträre Teil: Mehr Isolation ist nicht automatisch besser. VMs bieten Ihnen Isolation auf Hardware-Ebene, einen separaten Kernel und eine viel kleinere Angriffsfläche, wenn der Gast-Kernel fällt. Genau das erwarten Kunden aus dem Gesundheits- und Finanzwesen, wenn sie sagen: „Wir möchten isoliert sein.“ Aber jede VM erhöht die Kosten für Patchen, Backup und Rechenleistung und vervielfacht die Arbeit, eine Flotte aktuell zu halten. Wenn Sie jeden Kunden auf eine VM setzen, weil ein Kunde Ihnen einmal gesagt hat, dass Docker ihm Angst macht, haben Sie mit echtem Geld Sicherheitstheater gekauft.
Eine VM ist die richtige Antwort, wenn das Risiko pro Mandant höher ist als die Betriebskosten einer VM pro Mandant. Das bedeutet regulierte Daten, schriftliche Compliance-Anforderungen, unvertrauter Drittanbieter-Code oder ein Kunde, der einen lauten Nachbarn entfernt haben möchte. Es ist auch die richtige Antwort, wenn der Vertrag des Kunden wörtlich eine dedizierte Umgebung verspricht, denn „Container“ ist nicht das, was sie sich vorstellen, wenn sie „dediziert“ unterschreiben.
Aber eine VM entschuldigt keinen schlampigen Container. Eine häufige Falle besteht darin, den Kunden in eine VM zu setzen und dann die Härtung zu überspringen, weil „die VM sie schützt“. Die VM schützt den Host vor dem Mandanten, nicht den Mandanten vor seinem eigenen schlechten Image. Sie möchten auch innerhalb dieser VM weiterhin Nicht-Root, entfernte Capabilities und Seccomp. Der Hybrid-Ansatz – Container in einer VM – ist oft der Sweet Spot: Die VM bietet die Grenze für Compliance-Gespräche, und der Container bietet Ihnen den Bereitstellungs-Workflow, den Sie bereits kennen. Eine längere Version dieser Debatte finden Sie in Sollte jeder Mandant eine eigene VM bekommen?, aber die kurze Antwort lautet: Die VM ist für den Vertrag da, nicht für die Angst.
Wie mache ich das über alle Kunden hinweg wiederholbar?
Sie machen es wiederholbar, indem Sie das Stufensystem zu einer Vorlage machen, nicht zu einer Erinnerung. Halten Sie ein Verzeichnis mit Compose-Dateien bereit, eine pro Stufe: tier2-baseline, tier3-locked, tier4-vm-hybrid. Wenn ein neuer Kunde auftaucht, kopieren Sie die Vorlage, ändern Sie die Umgebungsvariablen, und Sie kennen die Isolationsform, bevor Sie auch nur eine Zeile neuer Infrastruktur geschrieben haben.
Dann schreiben Sie die Entscheidung auf. Keinen 400-seitigen Sicherheitsbericht, sondern einen kurzen Absatz im Repository des Kunden: welche Daten sie speichern, auf welcher Stufe sie stehen, warum und was sie eine Stufe höher bringen würde. Dieser Absatz ist mehr wert als hundert Firewall-Regeln, denn er ist das, was Sie dem nächsten Prüfer oder dem nächsten besorgten Kunden zeigen können. Er erspart Ihnen auch, sich merken zu müssen, warum die Bäckerei Stufe 2 und der E-Commerce-Shop Stufe 3 bekommen hat, nachdem das ursprüngliche Verkaufsgespräch verblasst ist.
Automatisieren Sie die langweiligen Prüfungen. Lassen Sie Ihre CI jedes Kunden-Image scannen und einen Build fehlschlagen, wenn es als Root läuft, wenn es alle Capabilities hat oder wenn es versucht, einen anderen Port zu veröffentlichen als die, die die Stufe erlaubt. Nichts davon ist exotisch; es stellt nur sicher, dass die Vorlage nicht versehentlich von einem wohlmeinenden Entwickler kaputtgemacht wird. Wenn Sie ohnehin den umgebenden Hosting-Workflow aufbauen, behandelt der Artikel über produktionsreife Docker-Hosting-Strategien den Teil, der nach der Definition der Container kommt.
Nichts davon ist glamourös. Kein Blogbeitrag wird „Mandantenisolation“ so aufregend klingen lassen wie ein Greenfield-Architekturdiagramm. Aber das ist der Unterschied zwischen einer Agentur, die auf „Wie isoliert sind wir?“ mit einem „völlig“ bei gekreuzten Fingern antwortet, und einer, die eine Stufe, eine Konfiguration und einen Grund vorweisen kann. Container sind keine magische Mauer. VMs sind keine Wunderwaffe. Ein Stufensystem ist nur eine Entscheidung, die Sie aufschreiben und wiederverwenden – und für eine Agentur ist Wiederholbarkeit das A und O.

