Warum wird empfohlen, nur einen Prozess in einem Container auszuführen?

79

In vielen Blogeinträgen und allgemeiner Meinung gibt es ein Sprichwort, das lautet "ein Prozess pro Container".

Warum gibt es diese Regel? Warum nicht ntp, nginx, uwsgi und mehr Prozesse in einem einzigen Container ausführen, in dem alle Prozesse funktionieren müssen?

Blog-Posts, die diese Regel erwähnen:

Evgeny
quelle
Aber - wäre es in Ordnung, einen sehr "fetten" Container mit Dutzenden von Prozessen zu haben, um die Einführung und den Betrieb eines Unternehmensservers zu ermöglichen, auf dem Docker immer noch nicht verfügbar ist?
Peter
@ J.Doe es wird wohl nicht in Ordnung sein. Container unterscheiden sich von VMs. Selbst für eine kleine Anwendung gibt es mehrere kleine Probleme. Für einen Unternehmens-Rollout ist es ein zweijähriges Projekt, bei dem alles in einem Container ausgeführt wird.
Evgeny

Antworten:

65

Vergessen wir für einen Moment die hochrangigen architektonischen und philosophischen Argumente. Während es einige Randfälle gibt, in denen mehrere Funktionen in einem einzelnen Container sinnvoll sein können, gibt es sehr praktische Gründe, warum Sie als Faustregel in Betracht ziehen sollten, "eine Funktion pro Container" zu befolgen:

  • Das horizontale Skalieren von Containern ist viel einfacher, wenn der Container für eine einzelne Funktion isoliert ist. Benötigen Sie einen anderen Apache-Container? Dreh einen woanders auf. Wenn jedoch in meinem Apache-Container auch meine DB, mein Cron und andere Teile eingelassen sind, wird dies kompliziert.
  • Mit einer einzigen Funktion pro Container kann der Container problemlos für andere Projekte oder Zwecke wiederverwendet werden.
  • Außerdem ist es für Entwickler portabler und vorhersehbarer, eine Komponente aus der Produktion zu entfernen, um lokale Fehler zu beheben, anstatt eine gesamte Anwendungsumgebung.
  • Patches / Upgrades (sowohl für das Betriebssystem als auch für die Anwendung) können auf isolierte und kontrollierte Weise durchgeführt werden. Durch das Jonglieren mehrerer Bits und Bobs in Ihrem Container werden nicht nur größere Bilder erstellt, sondern auch diese Komponenten miteinander verbunden. Warum müssen Anwendung X und Y heruntergefahren werden, um Z zu aktualisieren?
    • Dies gilt auch für Code-Implementierungen und -Rollbacks.
  • Das Aufteilen von Funktionen auf mehrere Container bietet mehr Flexibilität in Bezug auf Sicherheit und Isolierung. Möglicherweise möchten (oder müssen) Dienste auf Netzwerkebene isoliert sein - entweder physisch oder in Overlay-Netzwerken -, um eine starke Sicherheitslage aufrechtzuerhalten oder Dinge wie PCI zu erfüllen.
  • Andere kleinere Faktoren, wie das Behandeln von stdout / stderr und das Senden von Protokollen an das Containerprotokoll, das Beibehalten von Containern so kurzlebig wie möglich usw.

Beachten Sie, dass ich Funktion sage, nicht verarbeiten. Diese Sprache ist veraltet. In der offiziellen Docker-Dokumentation wird nicht mehr "ein Prozess", sondern "ein Anliegen" pro Container empfohlen.

Jon
quelle
1
Dennoch scheint es, dass das Argument gegen Threads auf niedriger Ebene hier passt ... web.stanford.edu/~ouster/cgi-bin/papers/threads.pdf
jeffmcneill
Tolle, umfassende Antwort!
Rob Wells
Bedeutet die Idee, dass die Frage nicht wirklich "Prozess" im Sinne des Betriebssystems bedeutete - dass Docker und verwandte Schriften eine andere Terminologie verwendeten, die jetzt durch Umschalten auf das Wort "Funktion" geklärt wurde? Ansonsten, obwohl ich anerkenne, dass dies die akzeptierte und am höchsten bewertete Antwort ist, glaube ich nicht, dass sie die gestellte Frage beantwortet.
Tom
27

Nachdem ich vor ein paar Tagen einen Container mit "zwei Prozessen" erschlagen hatte, gab es einige Probleme, die mich veranlassten, zwei Container anstelle eines Python-Skripts zu verwenden, das zwei Prozesse startete:

  1. Docker kann abgestürzte Container gut erkennen. Das kann man nicht, wenn der Hauptprozess gut aussieht, aber ein anderer Prozess ist ein grausamer Tod. Natürlich können Sie Ihren Prozess manuell überwachen, aber warum sollten Sie das erneut implementieren?
  2. Docker-Protokolle sind viel weniger nützlich, wenn mehrere Prozesse ihre Protokolle an die Konsole senden. Auch hier können Sie den Prozessnamen in die Protokolle schreiben, Docker jedoch auch.
  3. Das Testen und Überlegen eines Containers wird immer schwieriger.
Christian Sauer
quelle
Dies sollte die akzeptierte Antwort sein.
ClintM
Einverstanden. Zwar gibt es einige andere Antworten mit einigen tollen Punkten, aber der wichtigste Punkt ist der Umgang des Hafenarbeiters mit PID 1.
Brett Wagner
13

Die Empfehlung ergibt sich aus dem Ziel und dem Design der Virtualisierung auf Betriebssystemebene

Container wurden so konzipiert, dass sie einen Prozess für andere isolieren, indem sie ihm einen eigenen Benutzerbereich und ein eigenes Dateisystem geben.
Dies ist die logische Weiterentwicklung, bei chrootder ein isoliertes Dateisystem bereitgestellt wurde. Der nächste Schritt bestand darin, Prozesse von den anderen zu isolieren, um ein Überschreiben des Speichers zu vermeiden und die Verwendung derselben Ressource (z. B. TCP-Port 8080) aus mehreren Prozessen ohne Konflikte zu ermöglichen.

Das Hauptinteresse an einem Container ist es, die benötigte Bibliothek für den Prozess zu packen, ohne sich über Versionskonflikte Gedanken zu machen. Wenn Sie mehrere Prozesse ausführen, für die zwei Versionen derselben Bibliothek im selben Benutzerbereich und Dateisystem erforderlich sind, mussten Sie mindestens LDPATH für jeden Prozess anpassen, damit die richtige Bibliothek zuerst gefunden wird und einige Bibliotheken nicht auf diese Weise angepasst werden können. Da ihr Pfad in der ausführbaren Datei zum Zeitpunkt der Kompilierung fest codiert ist, finden Sie in dieser SO-Frage weitere Informationen.
Auf Netzwerkebene müssen Sie jeden Prozess konfigurieren, um die Verwendung derselben Ports zu vermeiden.

Das Ausführen mehrerer Prozesse im selben Container erfordert einige Feinabstimmungen und kann letztendlich den Zweck der Isolation zunichte machen. Wenn Sie mehrere Prozesse im selben Benutzerbereich ausführen und dasselbe Dateisystem und dieselben Netzwerkressourcen gemeinsam nutzen können, warum sollten Sie sie dann nicht ausführen? auf dem Host selbst?

Hier ist die nicht erschöpfende Liste der starken Optimierungen / Fallstricke, die mir einfallen:

  • Umgang mit den Protokollen

    Entweder mit einem gemounteten Volume oder interleaved on stdout bringt dies etwas Management. Wenn Sie ein bereitgestelltes Volume verwenden, sollte Ihr Container einen eigenen "Platz" auf dem Host haben, oder zwei gleiche Container kämpfen um dieselbe Ressource. Wenn Sie die Vorteile von stdout nutzen docker logs, kann dies zu einem Albtraum für die Analyse werden, wenn die Quellen nicht einfach identifiziert werden können.

  • Vorsicht vor Zombieprozessen

    Wenn einer Ihrer Prozesse in einem Container abstürzt, kann Supervisord die untergeordneten Elemente in einem Zombie-Status möglicherweise nicht bereinigen, und der Host-Init erbt sie niemals. Sobald Sie die Anzahl der verfügbaren Pids erschöpft haben (2 ^ 22, also ungefähr 4 Millionen), werden einige Dinge scheitern.

  • Trennung von Bedenken

    Wenn Sie zwei getrennte Dinge ausführen, z. B. einen Apache-Server und einen Logstash im selben Container, vereinfacht dies möglicherweise die Protokollverarbeitung, Sie müssen jedoch Apache herunterfahren, um den Logstash zu aktualisieren. (In Wirklichkeit sollten Sie den Protokollierungstreiber von Docker verwenden.) Warten Sie nicht länger, bis die aktuellen Sitzungen beendet sind, oder nicht? Wenn es ein würdevoller Stopp ist, kann es einige Zeit dauern und lang werden, um die neue Version zu rollen. Wenn Sie einen Kill ausführen, haben Sie Auswirkungen auf die Benutzer eines Protokollversenders. Dies sollte meiner Meinung nach vermieden werden.

Wenn Sie über mehrere Prozesse verfügen, reproduzieren Sie ein Betriebssystem. In diesem Fall entspricht die Verwendung einer Hardwarevirtualisierung eher dieser Anforderung.

Tensibai
quelle
3
Ich finde diese Argumente nicht überzeugend. Es gibt einen großen Unterschied zwischen einem Prozess mit mehreren Containern und dem Ausführen auf dem Host. Die Erklärung der ursprünglichen Absicht von Containern ist zwar relevant, aber kein zwingender Grund, Container mit mehreren Prozessen zu vermeiden. IOW, du antwortest "warum nicht" mit "warum ja", was nicht so hilfreich ist, wie es sein könnte. Es kann sehr praktisch sein, mehrere Prozesse in einem Container auszuführen - deshalb ja. Das Warum bleibt nicht zu erklären.
Assaf Lavie
1
Sie haben die Art der Optimierung, an die Sie gedacht hatten, nicht näher erläutert. Und Sie haben nicht gedacht, dass diese Optimierung mehr Arbeit ist als das Einrichten mehrerer Container. Nehmen wir ein konkretes Beispiel: Oft sehen Sie gepackte Docker-Images, auf denen Supervisord einen Hauptprozess und einen Hilfsprozess ausführt. Dies ist sehr einfach einzurichten; wohl genauso einfach wie das trennen der behälter. zB App & Log Versender. Ich glaube, Sie müssen darüber streiten, warum dies nicht der Fall ist.
Assaf Lavie
1
Übrigens glaube ich, dass es gültige Argumente gegen Multiprozesscontainer gibt, aber Sie haben keines davon erwähnt. Aber auf jeden Fall ist es alles andere als ein klarer Fall. In einigen Fällen ist es durchaus akzeptabel, mehr als einen Prozess zuzulassen. Verdammt, einige sehr beliebte Bilder erzeugen mehrere Unterprozesse - ist das auch böse? Was ich sage, ist, dass es Kompromisse gibt und Ihre Antwort ein einseitiges Bild ergibt, dem es an Nuancen und Details mangelt.
Assaf Lavie
1
interessant ... Es hört sich so an, als hätten wir eine ähnliche (identische) Meinung dazu. Vielleicht solltest du es in diesem Fall einfach ignorieren, weil es von jemandem war, der sich das Kritiker-Abzeichen verdienen wollte ... und beschlossen hat, deine Antwort zu missbrauchen, um dieses Abzeichen zu erhalten ...
Pierre.Vriens
1
Ich "beeile" mich nicht zum Schluss ... Ich empfehle Ihnen nur, es zu ignorieren. Aber "Sie" können meine Meinung nicht ändern, was ich mit eigenen Augen darüber gesehen habe, wer der anonyme Abwähler Ihrer Antwort ist. Wie auch immer, es ist Zeit, weiterzumachen ...
Pierre.Vriens
6

Wie in den meisten Fällen ist es nicht alles oder nichts. Die Richtlinie "Ein Prozess pro Container" basiert auf der Idee, dass Container einem bestimmten Zweck dienen sollen. Beispielsweise sollte ein Container nicht gleichzeitig eine Webanwendung und ein Redis-Server sein.

In einigen Fällen ist es sinnvoll, mehrere Prozesse in einem einzigen Container auszuführen, sofern beide Prozesse eine einzige, modulare Funktion unterstützen.

Dave Swersky
quelle
2

Der Prozess, den ich hier als Service bezeichne, 1 Container ~ 1 Service . Wenn einer meiner Services fehlschlägt, drehe ich nur den entsprechenden Container hoch und innerhalb von Sekunden ist alles wieder aktiv. Es gibt also keine Abhängigkeiten zwischen den Diensten. Es wird empfohlen, die Containergröße auf weniger als 200 MB und maximal 500 MB zu beschränken (Ausnahme: Windows-native Container haben eine Größe von mehr als 2 GB). Andernfalls entspricht dies der Leistung einer virtuellen Maschine, was jedoch nicht unbedingt ausreicht. Berücksichtigen Sie außerdem einige Parameter als Skalierung, wie kann ich die Ausfallsicherheit meiner Dienste erhöhen, eine automatische Bereitstellung durchführen usw.

Und es ist nur Ihre Aufgabe, wie Sie Ihre Architekturmuster wie Micro-Service in Polygot-Umgebungen mit der Containertechnologie gestalten können, die am besten zu Ihrer Umgebung passt und die Dinge für Sie automatisiert.

mohan08p
quelle