Ist dieser Prozess sicher? Ich kann ein Multicontainer-Setup in einer Entwicklungsumgebung problemlos betreiben, aber wenn ich es in einer Produktionsumgebung verwende, während Nutzer auf den alten Container zugreifen und der neue Container initialisiert wird und den Schritt der Datenbankmigration durchführt, werden Anfragen an den alten Container weiterhin die alte Backend-Logik verwenden und Daten speichern, wie sie in der vorherigen Version definiert waren – selbst nachdem der Schritt der Datenbankmigration abgeschlossen ist (aber bevor der gesamte Initialisierungsprozess beendet ist).
Obwohl ich weiß, dass dies kein Problem ist, das spezifisch für Discourse ist (eine Umgebung mit mehreren Replikaten könnte dieses Problem haben, wenn ein Replikat vor dem anderen aktualisiert wird, es sei denn, man stoppt alle vor dem Upgrade, was wahrscheinlich nicht der Fall sein wird, wenn man hohe Verfügbarkeit anstrebt), ist der von Ihnen beschriebene Prozess dennoch allgemein sicher?
Etwas, an das ich denken kann, ist sicherzustellen, dass Discourse immer aktuell gehalten wird, um die minimalen Datenbankmigrationen zwischen Neubauten zu haben. Aber in jedem Fall ist dies immer noch nicht ideal, und Probleme könnten auch in diesem Fall auftreten.
Das Multicontainer-Setup scheint einer der empfohlenen Ansätze zu sein (obwohl nicht der Standardansatz mit nur einem Container), daher denke ich, dass es sicher sein sollte, und ich denke nur zu viel nach.
Wissen Sie, ob es auf Produktionsseiten einwandfrei funktioniert (wobei die Initialisierung in einem Container durchgeführt wird, während ein anderer läuft)? Ich frage nur, um von Leuten zu hören, die dies bereits auf Produktionsseiten gemacht haben, um ein Feedback zu erhalten und zu wissen, ob es auch nach mehreren Neubauten einwandfrei funktioniert, ob es Fallstricke gibt usw. Wie gesagt, in einer Entwicklungsumgebung funktioniert es einwandfrei.
Ja. In den meisten Fällen gibt es keine Migrationen, die den laufenden Container unterbrechen.
Du kannst es auch so einrichten, dass Migrationen in der web_only.yml deaktiviert sind. Sobald der neue Container läuft, kannst du dann im laufenden Container etwas wie folgt ausführen:
cd /var/www/discourse;SKIP_POST_DEPLOYMENT_MIGRATIONS=0 rake db:migrate
Anschließend wählen wir den Container aus, der live sein soll, indem wir eine symbolische Verknüpfung zum tatsächlichen Socket erstellen, wie folgt:
Angenommen, wir möchten, dass der socket2-Container live ist:
ls -sf /var/discourse/shared/socket2/nginx.http.sock /var/run/nginx.http.sock
Angenommen, wir möchten eine Änderung an socket1 vornehmen und socket1 live schalten:
cd /var/discourse
./launcher rebuild socket1
ls -sf /var/discourse/shared/socket1/nginx.http.sock /var/run/nginx.http.sock
Beachte: Es gibt keinen Grund, den socket1-Container nur zu bootstrap, da der Container über einen Unix-Domain-Socket in seinem eigenen freigegebenen Verzeichnis bzw. Volume exponiert ist. Daher können beide dieser „Web-App“-Container gleichzeitig laufen:
Es gibt hier keine „Port-Binding-Kollision“ wie bei der Exposition eines TCP/IP-Container-Ports. Aus diesem Grund exponiere ich in der Produktion nur einen Unix-Domain-Socket (keinen TCP/IP-Port).
Natürlich kannst du bootstrap ausführen, wenn du möchtest:
cd /var/discourse
./launcher bootstrap socket1
./launcher start socket1
ls -sf /var/discourse/shared/socket1/nginx.http.sock /var/run/nginx.http.sock
Das liegt bei dir, aber beachte: Wenn du beide Container gleichzeitig laufen lässt, führen beide sidekiq aus und führen geplante Jobs aus. Das ist unsere Erfahrung; daher synchronisieren wir gelegentlich unsere Uploads in beiden Containern.
Das funktioniert für uns einwandfrei, und wir können eine Web-App-Container neu aufbauen und mit praktisch null Ausfallzeit live schalten. Wir nehmen Ausfallzeiten in der Produktion sehr ernst und vermeiden sie, wann immer möglich.
Hinweis:
Diese Methode (oben) ist für den Web-App-Teil der Lösung konzipiert, nicht für den Data-Container. Ich habe keine ähnliche Lösung für den Data-Container erstellt; aber wer weiß, vielleicht werde ich eines Tages etwas Zeit investieren und etwas Ähnliches (aber natürlich anderes) für den Data-Container bauen (eine Art „zwei Data-Container, DBs synchronisieren“-Methode, die in meinem Kopf noch völlig offen ist).
Ich mache also eigentlich das Gegenteil davon:
Wie gesagt, in einer Entwicklungsumgebung funktioniert es einwandfrei.
Ich richte das in der Entwicklung in der Regel nicht ein, da es länger dauert und in der Entwicklung nicht notwendig ist, da eine kurze Ausfallzeit in Ordnung ist, da es nur „mich und den Code“ betrifft (nicht live mit Benutzern und Bots, die auf die Site zugreifen). Außerdem verwende ich in der Entwicklung (auf dem Desktop) kein Docker.
Hoffentlich hilft das weiter.
**Mit „Entwicklung“ meine ich die Software- (z. B. Plugin-) Entwicklung; nicht einfach nur das „Staging“ einer Discourse-Installation, was ich als „Staging“ und nicht als „Entwicklung“ bezeichne (nur zur Klarheit).
Danke, das wusste ich nicht. Das ist ein großartiges Feature und ich kann mir vorstellen, dass es Probleme wie das zuvor erwähnte vermeidet (obwohl dies Änderungen der Logik bei bereits existierenden Spalten nicht verhindert, aber das sollte ein seltenerer Fall sein).
Danke für die Antwort. SKIP_POST_DEPLOYMENT_MIGRATIONS scheint das zu sein, was @riking erwähnt hat, und genau das suchte ich, um zu verhindern, dass Migrationen Vorgänge im laufenden Container stören.
Danke für die Erklärung. Das scheint mir ein guter Ansatz zu sein, bei dem zwischen zwei Containern abgewechselt wird (damit immer ein Container läuft, während der andere hochfährt).
Mit „Dev-Umgebung“ meinte ich eine Remote-Entwicklungsumgebung, die ich zum Testen des Multicontainer-Setups verwendet habe (sowohl auf derselben Maschine als auch mit Containern auf verschiedenen Maschinen).
Ich habe „Dev“ und nicht „Staging“ gesagt, weil ich in einer Staging-Umgebung die YML-Dateien mit denselben Plugins und eine Sicherungskopie der Produktionsdatenbank zum Testen verwenden würde. Aber stimmt, wenn ich einfach nur eine Dev-Umgebung einrichten möchte, würde ich in den meisten Fällen den Ansatz mit einem Container verwenden.
Soweit ich das beurteilen kann, besteht dieser Leitfaden aus vielen Worten um folgende Punkte:
Sichern
Eine völlig neue Discourse-Instanz erstellen, mit mehr Worten, aber denselben Ergebnissen wie das bloße Ausführen von discourse_setup 2container
Wiederherstellen
Warum verschieben oder kopieren Sie nicht einfach /var/discourse/shared/standalone/{postgres,redis}* nach /var/discourse/shared/data, nachdem Sie sauber heruntergefahren haben, und starten dann zwei neue Container aus separaten containers/*.yml-Dateien? Ein Backup/Wiederherstellung scheint ein sehr schwerfälliger Weg zu sein, um all diese Daten zu verschieben, und fügt dem Prozess unnötig Stunden hinzu. Übersehe ich hier etwas Offensichtliches?
Ich habe diesen Prozess gerade an meinem Test-Discourse ausprobiert und dabei auch Redis ausgelagert, nur um sicherzugehen, dass ich alle Aspekte abdecke. Edit: Ich habe die Beschreibung in ein neues Thema verschoben:
Die Seite scheint ohne einen Backup/Wiederherstellungs-Zyklus einwandfrei zu funktionieren. Gibt es etwas Nicht-Offensichtliches, das ich überprüfen sollte?
Ich habe denselben Prozess für ein relativ großes Discourse durchgeführt, und es funktioniert einwandfrei. Ich habe beschlossen, dass ich in der Produktion meinen neuen web_only-Container app nennen werde, damit meine Finger automatisch das Richtige tun. Nachdem ich die neuen container/*.yml-Dateien geschrieben hatte, betrug die Ausfallzeit für die gesamte Migration 12 Minuten, weit schneller als es bei einem Backup/Wiederherstellungs-Zyklus der Fall gewesen wäre.
Es ist nur so, dass dies etwas mehr Aufwand und ein Verständnis dafür erfordert, wie die Dinge funktionieren. Die Wiederherstellung aus einem Backup ist fehlertoleranter.
Ich schätze, wir sind dann einfach verschiedener Meinung. Ich würde denken, dass jemand, der in der Lage ist, mehrere Container zu verwalten, auch ein paar Befehle ausführen kann. Und ich glaube nicht, dass diese Befehle schwieriger zu tippen sind als bin/rails c und dann Ruby-Befehle hier zu tippen, oder dass sie deutlich mehr oder andere Fähigkeiten erfordern als die Nutzung mehrerer Container. Ich werde den Inhalt jedoch in einen separaten neuen Beitrag verschieben, anstatt ihn hier in einem Kommentar zu belassen.
Das ist ein vernünftiges Argument. Vielleicht würde es diejenigen, die nicht über die nötigen Fähigkeiten verfügen, davon abhalten, es zu versuchen, wenn das Verfahren noch abschreckender wirken würde.
Und falls sie einen Fehler machen, gibt es vor einer Migration nichts Besseres als ein Backup! Ich hoffe, ich habe das in meinem oben verlinkten Artikel klar gemacht!
Das ist der Fehler in deinem Argument. Das Hinzufügen von 2container zu ./discourse-setup beinhaltet keine Maßnahme für Kompetenz. Es gibt viele Leute, die zwei Container betreiben, einfach weil sie Themen wie dieses sehen und annehmen, es gäbe ein geheimes Rezept oder es sei die „richtige Sache zu tun".
Das Thema zu Postgres 12 sollte als warnendes Beispiel für die hinzugefügte Komplexität dienen. Die Verwendung eines Backups als Zwischenschritt zwischen Zuständen ermöglicht es einem Benutzer, durch Umbenennen einer einzigen Datei zu einem einzelnen Container zurückzukehren. Sobald man jedoch beginnt, Ordner zu verschieben, geht diese Einfachheit verloren.
@Stephen Es gibt einen Fehler in deiner Argumentation: Die Beschreibung für Multi-Container ist voller Warnungen, dass du für Updates selbst verantwortlich bist und verstehst, wie es funktioniert, und die lange Beschreibung oben ist so verschleiert, dass wahrscheinlich jeder, der sie betrachtet, ohnehin aufgeben würde. Lies dir bitte meinen Beitrag unter Migrate quickly to separate web and data containers durch und sag mir dann, dass dies die Leute nicht abschrecken wird, die Schwierigkeiten haben werden, ihm zu folgen, oder dass er die Notwendigkeit von Backups und die Fähigkeit, im Fehlerfall auf ein Backup zurückzugreifen, nicht ausreichend betont!
Ich war zutiefst unglücklich, als ich kurz nach der Migration auf einen leistungsfähigeren Server (für ein Sicherheitsupdate) den Befehl ./launcher rebuild app ausgeführt habe und meine Seite für eine empörend lange Zeit offline war, wobei ein Großteil dieser Zeit für den Neuaufbau der PostgreSQL-Teile des Containers aufgewendet wurde. In diesem Moment habe ich die 2-Container-Dokumentation und diese Dokumentation gefunden und wollte wirklich nicht weitere 4 Stunden Ausfallzeit für eine Migration in Kauf nehmen, also habe ich weiterhin lange Ausfallzeiten für ./launcher rebuild app in Kauf genommen, um die 4 Stunden Ausfallzeit einer Wiederherstellung zu vermeiden. Als vage kompetente Person war ich lange Zeit sehr verärgert darüber, dass diese Konfiguration effektiv versteckt war.
Das Thema zu PostgreSQL 12 ist eine großartige Referenz, weil die Leute am Ende mehr Ausfallzeit haben, weil sie die gesamte App mehrfach neu aufbauen müssen, obwohl sie nur den PostgreSQL-Container zweimal neu aufbauen müssten. Ich kann nicht sagen, dass ich den gesamten Thread gelesen habe, wegen der automatischen Löschung nach 6 Tagen, aber es ist für mich keineswegs offensichtlich, dass inkompetente Multi-Container-Bereitstellungen das große Problem dort sind, oder auch nur ein großes Problem.
(Entschuldigung, manchmal werde ich ein wenig müde von der Haltung „alle Benutzer sind inkompetent
Das mag für Sie vielleicht keinen Sinn ergeben, aber für diejenigen von uns, die seit 6 oder 7 Jahren hier im Meta-Bereich aktiv sind und in Support Unterstützung bieten, wird eine Rollback-Strategie immer sinnvoll sein.
Fehler gelangen gelegentlich auch in Tests-passed-Umgebungen; manchmal beeinträchtigen RubyGems-Ratenlimits Neubuilds, und selbst GitHub hatte schon einmal eine kleine Schwankung. Allein aus diesem Grund sehe ich keinen Wert darin, einen Zustand zu ändern, der es erschwert, einfach eine Datei umzubenennen und ./launcher start app auszuführen.
Ihr Risikobereitschaft mag anders sein; in diesem Fall können Sie einen anderen Weg wählen. Für diejenigen, die regelmäßig bei der Aufräumarbeit helfen, funktioniert der aktuelle Leitfaden gut.
Ich habe den Eindruck, du hast den von mir verfassten Prozess tatsächlich nicht gelesen, da du so schreibst, als hätte ich die Notwendigkeit der Wiederherstellungsfunktion nicht betont. Lies ihn bitte durch und kehre dann zurück, um zu überlegen, deinen Text so zu ändern, dass er eine wahre Aussage über meine Anweisungen trifft. So, wie es jetzt ist, habe ich das Gefühl, du machst mir den Vorwurf, ohne mir die Höflichkeit zu erweisen, dir die Mühe zu machen, zu lesen, was ich geschrieben habe.
Dennoch habe ich viele weitere zusätzliche Warnungen hinzugefügt, darunter eine ganz oben, die über die Warnungen in diesem Beitrag hinausgehen, der seit fünf Jahren besteht und weiterhin die kanonische Quelle für Anweisungen zu diesem Migrationsprozess ist.
Ich habe kürzlich ein selbstgehostetes Discourse-Forum auf einem VPS eingerichtet. Uploads werden auf Wasabi gespeichert, ebenso wie Backups. Alles wird bei Linode gehostet.
Ich habe die Standalone-Vorlage verwendet und die Einrichtung war im Vergleich zu anderer Software eine echte Erleichterung. Es war einfach großartig! Eine pure Freude. Ich wünschte, jedes Open-Source-Projekt würde so viel Aufmerksamkeit auf Installation und Einrichtung legen wie Discourse.
Hier kommt aber der Haken: Ich habe einen dedizierten PostgreSQL-Server, der auf einem separaten Server läuft und nur über eine RFC-1918-Adresse erreichbar ist, die nicht aus dem Internet zugänglich ist. Diesen möchte ich für Discourse nutzen. Ich bin kein großer Fan davon, dass Datenbankserver auf demselben Server wie der Web-/Anwendungsserver laufen.
Gibt es also eine Möglichkeit, die Standalone-Datenbank zu trennen und auf meinen dedizierten Datenbankcluster zu verlegen?
Ich gehe davon aus, dass ich nur einen pgdump der Discourse-Datenbank durchführen, diesen auf meinen dedizierten Datenbankserver übertragen und wiederherstellen muss, gefolgt von einem „postgres vacuum analyze all tables
Wenn für die integrierte PostgreSQL-Datenbank normalerweise keine Anmeldeinformationen erforderlich sind, gibt es dann eine Möglichkeit, mit pg_dump eine Sicherung der Datenbank aus dem eigenständigen Container zu erstellen?