Viele MongoDB-Cluster verwenden Snapshots auf Speicherebene, um schnelle und zuverlässige Backups bereitzustellen. In diesem Blogbeitrag erfahren Sie, wie Sie einen solchen Snapshot von einem herkömmlichen VM-basierten Shard-MongoDB-Cluster auf einen frisch bereitgestellten wiederherstellen Percona-Operator für MongoDB Cluster auf Kubernetes.
Hintergrundgeschichte
Ich habe kürzlich mit einem Unternehmen zusammengearbeitet, das einen großen MongoDB Enterprise Server-Datenbankcluster mit vier Shards auf VMs vor Ort betreibt und sich für die Migration auf die Google Cloud Platform entschieden hat. Nach sorgfältiger Überlegung und Pro-und-Kontra-Bewertung entschied sich der Kunde für Percona Distribution für MongoDB auf Kubernetes – insbesondere für die Verwendung von Percona Operator für MongoDB. Es gibt vier Hauptfaktoren, die zu dieser Entscheidung beigetragen haben:
- Die Gesamtbetriebskosten: Die Ressourcen von K8 sind deutlich günstiger als der Betrieb eines beliebten DBaaS in derselben Cloud
- Einfache Bereitstellung: Percona Operator für MongoDB macht den Betrieb am ersten und zweiten Tag zum Kinderspiel
- Bevorzugung von Open-Source-Tools und Cloud-nativen Lösungen: Anwendungen sind bereits auf Kubernetes migriert – der Betrieb der gesamten Lösung auf diese Weise vereinfacht den Betrieb.
- Dieser Ansatz befreit die Bereitstellung von der Bindung an die Cloud (und andere Anbieter).
Um realistische Kompatibilitäts- und Leistungstests zu starten, mussten wir die Dateisystem-Snapshot-Sicherung, die auf dem NetApp-Volume in GCP gespeichert war, in einem Google Kubernetes Engine (GKE)-Cluster wiederherstellen, auf dem Percona Operator für MongoDB ausgeführt wird. Aufgrund der Anforderungen für die Wiederherstellung einer Shard-Cluster-Sicherung in einem neuen Cluster ist dies keine triviale Aufgabe. Ich zeige Ihnen, warum und wie wir es geschafft haben.
Anforderungen
Schauen wir uns die allgemeinen Anforderungen für den Cluster an, in dem ich den Snapshot wiederherstellen möchte:
- Die gleiche Hauptversion (idealerweise auch Nebenversion) von MongoDB
- Die gleiche Anzahl an Scherben
- Der gleiche Name aller Shards
- Derselbe Name wie der Config RS
- Die gleichen Hostnamen aller Knoten (so stellt Config RS eine Verbindung zum jeweiligen Shard her)
- Dieselbe MongoDB-Konfiguration hinsichtlich der Art und Weise, wie Dateien auf der Festplatte gespeichert werden
Das scheint einfach zu sein; Bei der von Percona Operator für MongoDB kontrollierten Umgebung sind jedoch einige besondere Überlegungen zu beachten, insbesondere:
- Sie können den Namen von Config RS nicht steuern
- Sie können die Hostnamen nicht ändern und diese werden innerhalb von Kubernetes sicherlich anders sein
- Percona Operator benötigt bestimmte Benutzer in Ihrem Cluster, um ihn steuern zu können – und diese sind in Ihrem Backup nicht vorhanden.
All dies macht es unmöglich, einfach die Operator-Konfiguration anzupassen und alle Dateien aus Ihrem Snapshot-Backup in die spezifischen Volumes zu kopieren.
Planen
Der übergeordnete Plan besteht aus den folgenden Schritten:
- Stellen Sie den Cluster auf K8s bereit
- Snapshot-Dateien wiederherstellen
- Pausieren Sie den Cluster auf K8s
- Mounten Sie Speichervolumes auf einer separaten VM
- Kopieren Sie Snapshot-Dateien auf die entsprechenden Volumes
- Bereiten Sie jeden Replikatsatz im Standalone-Modus vor (Hostnamen, Sharding-Konfiguration, Benutzer).
- Starten Sie den Cluster auf K8s und initialisieren Sie jeden Replikatsatz
Der folgende Ansatz ist unabhängig davon anwendbar, welche „Variante“ von MongoDB Ihre Quellumgebung verwendet. Dies kann MongoDB Enterprise Server, MongoDB Community Edition oder Percona Server für MongoDB sein.
Schritt eins: Stellen Sie den Cluster auf K8s bereit
Um Percona Server für MongoDB (PSMDB) auf dem K8s-Cluster bereitzustellen, Folgen Sie der Dokumentation. Bevor Sie jedoch den letzten Schritt (Bereitstellen von cr.yaml) ausführen, stellen Sie sicher, dass Sie die folgenden Elemente der Konfiguration anpassen. Dadurch wird der Cluster „passend“ zu dem Cluster, von dem wir das Backup erstellt haben.
- Satz spec.image zu einer bestimmten Bildversion. Es muss die Version sein, die mit der Hauptversion des Quellclusters übereinstimmt, zum Beispiel:
spec: image: percona/percona-server-mongodb:5.0.11-10
- Erstellen Sie so viele Shard-Replikatsätze wie im Quellcluster. Kopieren Sie die Standardreplikatsatzdefinition (gesamter Abschnitt) in spec.replsets(). Wenn Ihr Quellcluster beispielsweise über zwei Shards mit den Namen „shard1“ und „shard2“ verfügt (die Namen müssen mit denen des Quellclusters übereinstimmen):
replsets: - name: shard size: 3 (...) - name: shard2 size: 3 (...)
Leider können Sie den Namen von Config RS nicht festlegen. Wir kümmern uns später darum.
- Wenn die WiredTiger-Konfiguration Ihres Quellclusters von der Standardkonfiguration abweicht, passen Sie die Mongod-Konfiguration jedes Replikatsatzes entsprechend an. Insbesondere sind zwei MongoDB-Konfigurationselemente von entscheidender Bedeutung: storage.directoryPerDB Und storage.wiredTiger.engineConfig.directoryForIndexes. Sie können dies folgendermaßen tun:
replsets: - name: shard1 size: 3 configuration: | storage: directoryPerDB: true wiredTiger: engineConfig: directoryForIndexes: true
- Speichern Sie die Änderungen und starten Sie den Cluster mit den geänderten cr.yaml Datei
Schritt zwei: Snapshot-Dateien wiederherstellen
Ihr Cluster sollte zu diesem Zeitpunkt gestartet werden und es ist wichtig, dass alle dafür erforderlichen PersistentVolumes erstellt werden. Sie können Ihren Clusterstatus mit überprüfen kubectl holt sich psmdb, Alle bereitgestellten Pods anzeigen mit kubectl holt Pods, oder PVs mit überprüfen kubectl bekommt pv. In diesem Schritt müssen Sie Volumes aller Ihrer Datenbankknoten auf einer unabhängigen VM bereitstellen, da wir Änderungen im MongoDB-Standalone-Modus vornehmen. Sie benötigen diese VMs vorübergehend, um die erforderlichen Vorgänge auszuführen.
- Pausieren Sie den PSMDB-Cluster auf K8s durch Einstellung spec.pause: wahr in deinem cr.yaml Datei. Dadurch wird der gesamte Cluster angehalten und es ist möglich, Volumes an anderer Stelle bereitzustellen.
- Überprüfen Sie die Zonen, in denen Ihre PerstistentVolumes erstellt wurden. Sie können verwenden kubectl beschreibt pv pv_name oder finden Sie es in der Cloud-Konsole.
- Erstellen Sie in jeder Zone eine VM und mounten Sie dann Volumes, die PersistentVolumes entsprechen, auf einer VM in ihrer Zone. Es ist wichtig, dass Sie den Zweck des Volumes leicht erkennen können (auf welchen Replikatsatz in Ihrem MongoDB-Cluster es sich bezieht und auf welchen Knoten – primär oder sekundär). So können Sie beispielsweise ein Volume auf Ihrer VM bereitstellen gcloud-API:
# attach disk to an instance gcloud compute instances attach-disk vm_name --disk disk_name --zone=us-central1-a # check volume on vm sudo lsblk # create a mountpoint sudo mkdir -p /dir_name (e.g. rs0-primary) # mount the volume sudo mount -o discard,defaults /dev/sdb /dir_name
- Löschen Sie alle Dateien von jedem Volume, das auf Ihren VMs gemountet ist – Primär- und Sekundärvolumes.
- Kopieren Sie Dateien aus dem Snapshot auf das entsprechende Volume, direkt in das Hauptverzeichnis des gemounteten Volumes. Tun Sie dies nur für Volumes, die sich auf primäre Knoten beziehen (lassen Sie sekundäre Knoten leer).
- Installieren Sie Percona Server für MongoDB auf jeder Ihrer VMs. Überprüfen Installationsanleitung und installieren Sie die gleiche Version wie Ihr Mongo-Cluster auf K8s. Starten Sie den Server noch nicht!
Schritt drei: Bereiten Sie jeden Replikatsatz im Standalone-Modus vor
Jetzt müssen Sie PSMDB für jedes Volume mit Daten (jedes Primärteil jedes Replikatsatzes, einschließlich Config RS) separat starten. Anschließend melden wir uns bei der Mongo-Shell an und bearbeiten die Cluster-Konfiguration manuell, sodass, wenn wir Volumes mit Daten zurück zu Kubernetes bringen, dieser erfolgreich gestartet werden kann.
Führen Sie die folgenden Schritte für jeden Replikatsatz aus, einschließlich Config RS:
- Wenn Ihr primäres Config RS-Volume auf der VM gemountet ist, nehmen Sie die Bearbeitung vor /etc/mongod.conf. Konkret anpassen storage.dbPath (in das Verzeichnis, in dem Sie das Volume gemountet haben), storage.directoryPerDB, Und storage.wiredTiger.engineConfig.directoryForIndexes.
- Starten Sie PSMDB mit sudo mongod –config /etc/mongod.conf
- Stellen Sie eine Verbindung zu PSMDB her mit Mongo Befehl (Authentifizierung ist nicht erforderlich). Sobald Sie sich erfolgreich angemeldet haben, können wir mit der Durchführung von Änderungen an der Clusterkonfiguration beginnen.
- Löschen Sie die Konfiguration des lokalen Replikatsatzes mit den folgenden Befehlen:
use local; db.dropDatabase();
- (Dieser Schritt gilt nur für Config RS)
Ersetzen Sie die Shards-Konfiguration. Führen Sie den folgenden Befehl für jeden Shard separat aus (Sie können sie alle mit db.shards.find() auflisten). Ersetzen Sie in der folgenden Zeichenfolge: Shard-Name, Cluster-Name, Namespace-Name durch Werte, die für Ihren Cluster spezifisch sind:
use config; db.shards.updateOne( { "_id" : "shard_name" }, { $set : { "host" : "shard_name/cluster_name-shard_name-0.cluster_name-shard_name.namespace_name.svc.cluster.local:27017,cluster_name-shard_name-1.cluster_name-shard_name.namespace_name.svc.cluster.local:27017,cluster_name-shard_name-2.cluster_name-shard_name.namespace_name.svc.cluster.local:27017"} });
- (Dieser Schritt gilt nur für Shard RS) Shard-Metadaten löschen
use admin db.system.version.deleteOne( { _id: "minOpTimeRecovery" } )
- (Dieser Schritt gilt nur für Shard RS) Ersetzen Sie die Config RS-Verbindungszeichenfolge in ShardIdentity mit dem folgenden Befehl. Ersetzen Clustername, namespace_name mit deinen Werten.
use admin db.system.version.updateOne( { "_id" : "shardIdentity" }, { $set : { "configsvrConnectionString" : "cfg/cluster_name-cfg-0.cluster_name-cfg.namespace_name.svc.cluster.local:27017,cluster_name-cfg-1.cluster_name-cfg.namespace_name.svc.cluster.local:27017,cluster_name-cfg-2.cluster_name-cfg.namespace_name.svc.cluster.local:27017"} });
- Percona MongoDB Operator erfordert, dass MongoDB-Benutzer auf Systemebene in einer Datenbank vorhanden sind. Wir müssen diese Benutzer für den Betreiber erstellen, da sie in unserem Backup nicht vorhanden sind. Wenn Sie die Standardeinstellung nicht geändert haben Geheimnisse.yaml Während der Bereitstellung des Clusters finden Sie Standardkennwörter entweder in der Datei oder hier im Dokumentation. Um erforderliche Benutzer und Rollen zu erstellen, verwenden Sie die folgenden Mongo-Befehle:
use admin; //drop user in case they already exist in your backup db.dropUser("userAdmin"); db.dropUser("clusterAdmin"); db.dropUser("clusterMonitor"); db.dropUser("backup"); db.dropUser("databaseAdmin"); //create missing role db.createRole({"role" : "explainRole", "privileges" : ({"resource": {"db" : "","collection" : "system.profile"}, "actions" : ("collStats","dbHash","dbStats","find","listCollections","listIndexes")}), roles: ()}); //create system users db.createUser({ user: "userAdmin", pwd: "userAdmin123456", roles: ( { role: "userAdminAnyDatabase", db: "admin" }) }); db.createUser({ user: "clusterAdmin", pwd: "clusterAdmin123456", roles: ( { role: "clusterAdmin", db: "admin" }) }); db.createUser({ user: "clusterMonitor", pwd: "clusterMonitor123456", roles: ({ role: "explainRole", db: "admin" }, { role: "read", db: "local" }, { role: "clusterMonitor", db: "admin" }) }); db.createUser({ user: "databaseAdmin", pwd: "databaseAdmin123456", roles: ({ role: "readWriteAnyDatabase", db: "admin" }, { role: "readAnyDatabase", db: "admin" }, { role: "dbAdminAnyDatabase", db: "admin" }, { role: "backup", db: "admin" }, { role: "restore", db: "admin" }, { role: "clusterMonitor", db: "admin" },) }); db.createUser({ user: "backup", pwd: "backup123456", roles: ({ role: "backup", db: "admin" }, { role: "restore", db: "admin" }, { role: "clusterMonitor", db: "admin" }) });
- Fahren Sie den Server jetzt herunter db.shutdownServer();
- Der Operator führt den Mongod-Prozess mit dem Benutzer „mongodb“ aus (nicht als Standard-„mongod“!). Daher müssen wir die Berechtigungen korrigieren, bevor wir das Volume aushängen. Fügen Sie die folgende Zeile zu Ihrer /etc/passwd-Datei hinzu:
mongodb:x:1001:0:Default Application User:/home/mongodb:/sbin/nologin
- Berechtigungen festlegen:
cd /your_mountpoint sudo chown -R mongodb:1001 ./
- Hängen Sie das Volume aus und trennen Sie es von der VM. So können Sie beispielsweise ein Volume von Ihrer VM aushängen gcloud-API:
sudo umount /dir_name gcloud compute instances detach-disk vm_name --disk disk_name --zone=us-central1-a
Schritt vier: Starten Sie den Cluster auf K8s und initialisieren Sie jeden Replikatsatz
Sie sind bereit, zu K8s zurückzukehren. Starten Sie den Cluster (er startet mit zuvor verwendeten Volumes). Es befindet sich im Status „Ausstehend“, da wir Replikatsätze (absichtlich) beschädigt haben. Es wird nur ein Pod pro Replikatsatz gestartet. Sie müssen Replikatsätze einzeln initialisieren.
Um die Pause des PSMDB-Clustersatzes aufzuheben spec.pause: falsch in deinem cr.yaml Datei und wenden Sie sie mit kubectl an. Wiederholen Sie dann die folgenden Schritte für alle Replikatsätze, beginnend mit Config RS.
- Melden Sie sich mit bei der Shell von „Pod 0“ des Replikatsatzes an kubectl exec –stdin –tty Clustername-cfg-0 – /bin/bash (für Config RS)
- Melden Sie sich mit bei PSMDB an Mongo Befehl
- Authentifizieren als ClusterAdmin mit dem folgenden Befehl (vorausgesetzt, Sie haben Standardkennwörter verwendet):
use admin; db.auth("clusterAdmin", "clusterAdmin123456");
- Initialisieren Sie den Replikatsatz wie folgt. Ersetzen Clustername Und namespace_name Und Shard_Name mit deinen eigenen Werten.
# version for Config RS rs.initiate( { _id: "cfg", members: ( { _id: 0, host : "cluster_name-cfg-0.cluster_name-cfg.namespace_name.svc.cluster.local:27017" }, { _id: 1, host : "cluster_name-cfg-1.cluster_name-cfg.namespace_name.svc.cluster.local:27017" }, { _id: 2, host : "cluster_name-cfg-2.cluster_name-cfg.namespace_name.svc.cluster.local:27017" }, ) } ); # version for other RS (shards) rs.initiate( { _id: "shard_name", members: ( { _id: 0, host : "cluster_name-shard_name-0.cluster_name-shard_name.namespace_name.svc.cluster.local:27017" }, { _id: 1, host : "cluster_name-shard_name-1.cluster_name-shard_name.namespace_name.svc.cluster.local:27017" }, { _id: 2, host : "cluster_name-shard_name-2.cluster_name-shard_name.namespace_name.svc.cluster.local:27017" }, ) } );
- Nach einigen Sekunden wird Ihr Knoten PRIMÄR. Sie können den Zustand des Replikatsatzes mithilfe von überprüfen rs.status() Befehl. Denken Sie daran, dass der anfängliche Synchronisierungsprozess bei einem großen Datensatz lange dauern kann (wie bei jeder MongoDB-Bereitstellung).
Das ist es! Sie haben nun erfolgreich einen Snapshot wiederhergestellt Sicherung in Percona Server für MongoDB, bereitgestellt auf K8s mit Percona Operator. Um zu überprüfen, ob Sie diesen Lauf erfolgreich durchgeführt haben kubectl holt Pods oder kubectl holt sich psmdb – Die Ausgabe sollte der folgenden ähneln.
$ kubectl get psmdb NAME ENDPOINT STATUS AGE my-cluster-name my-cluster-name-mongos.ns-0.svc.cluster.local ready 156m
Die Percona Kubernetes-Operatoren automatisieren die Erstellung, Änderung oder Löschung von Mitgliedern in Ihrer Percona Distribution für MySQL-, MongoDB- oder PostgreSQL-Umgebung.
Erfahren Sie mehr über Percona Kubernetes-Operatoren