
Questo articolo prosegue il nostro sulla migrazione di RabbitMQ e dedicato a MongoDB. Poiché gestiamo numerosi cluster Kubernetes e MongoDB, è emersa la necessità di migrare i dati da un'installazione all'altra senza downtime. Gli scenari principali rimangono: spostare MongoDB da un server virtuale/fisico a Kubernetes, oppure trasferire MongoDB all'interno di un singolo cluster Kubernetes (da uno spazio dei nomi a un altro).
La nostra ricetta è destinata ai casi in cui è attivo un vecchio cluster MongoDB (ad esempio, composto da 3 nodi e già presente in K8s o su vecchi server), con cui lavora un'applicazione ospitata in Kubernetes:

Come tradurremo questo cluster nel nuovo ambiente di produzione in Kubernetes?
Teoria
L'algoritmo generale di migrazione è simile a quello descritto nella situazione con RabbitMQ.
È importante notare che per consentire il trasferimento, i server con MongoDB e Kubernetes devono trovarsi nella stessa rete. I nodi del cluster MongoDB comunicheranno tra loro utilizzando gli IP dei vecchi server (dove si trovano le vecchie installazioni di MongoDB) e i nomi DNS dei pod con MongoDB in K8s. Pertanto, sui server fisici (con le vecchie installazioni) sarà necessario instradare i percorsi verso i pod e poi configurarli per utilizzare il server DNS funzionante in Kubernetes (o specificare i nomi necessari in /etc/hosts, anche se in generale è meglio evitare questa possibilità).
Il passo successivo è avviare il cluster MongoDB nei pod di Kubernetes. Nel nostro caso, il cluster DB è composto da 3 nodi e ogni nodo si trova in un pod K8s separato, anche se il loro numero può essere diverso. In ConfigMap, è necessario specificare l'indirizzo del master MongoDB dell'installazione precedente: in questo modo, i nodi MongoDB presenti nei pod in K8s inizieranno immediatamente a sincronizzarsi con esso.
Dopo che tutti i pod sono stati avviati, si formerà un cluster MongoDB di 6 nodi:

Si noti che i pod impiegheranno tempo a avviarsi, poiché ogni pod si avvia a turno e al momento dell'avvio sincronizza i dati con il master.
Dopo di ciò, è possibile passare l'applicazione all'utilizzo dei nuovi server MongoDB:

E rimarrà solo da rimuovere i vecchi nodi dal cluster MongoDB, dopo di che il trasferimento può essere considerato completato:

Utilizziamo spesso questo schema in produzione e per comodità l'abbiamo implementato all'interno del modulo a (questo strumento lo ), che consente di distribuire configurazioni standard di MongoDB su più cluster. Pianifichiamo di pubblicare i nostri moduli a breve, ma nel frattempo presentiamo istruzioni dettagliate con cui è possibile testare la soluzione proposta in azione e senza utilizzare l'addon-operator.
Proviamo nella pratica
Requisiti
Dettagli:
- Un cluster Kubernetes (va bene anche minikube);
- Cluster MongoDB (può essere distribuito su bare metal o creare un cluster normale in Kubernetes utilizzando l'Helm chart ufficiale).
Nell'esempio descritto di seguito, il vecchio cluster con MongoDB sarà chiamato mongo-old e installato nello stesso cluster Kubernetes dove installeremo anche il nuovo (mongo-new).
Prepariamo il vecchio cluster
1. Per esempio, per dimostrare lo schema descritto in azione, creeremo un "vecchio" cluster MongoDB (cioè soggetto a migrazione) direttamente in Kubernetes (in realtà può trovarsi anche su server separati al di fuori di K8s). Per questo, scaricheremo l'Helm chart:
helm fetch --untar stable/mongodb-replicaset… e modificheremo un po' il file, configurando l'autenticazione:
auth:
enabled: true
adminUser: mongo
adminPassword: pa33w0rd
# metricsUser: metrics
# metricsPassword: password
# key: keycontent
# existingKeySecret:
# existingAdminSecret:
# exisitingMetricsSecret: Inoltre, è possibile configurare certificati e molto altro. values.yaml 2. Installeremo il chart:
helm install . --name mongo-old --namespace mongo-old
Dopo questo, verrà avviata una "vecchia" installazione di test di MongoDB:kubectl --namespace=mongo-old get pods
Accediamo al pod del suo master e creiamo un database di prova: 
kubectl --namespace=mongo-old exec -ti mongo-old-mongodb-replicaset-0 mongo use admin db.auth('mongo','password') use music db.artists.insert({ artistname: "The Tea Party" }) show dbs
Accedendo a diversi pod, ho scoperto che il master è 
mongo-old-mongodb-replicaset-0. In ogni caso, per una soluzione più conveniente a questo problema, dopo l'installazione dell'Helm chart viene fornito un comando per determinareMASTER_POD. Nel mio caso (persu 3 nodi) appare in questo modo: mongo-old for ((i = 0; i < 3; ++i)); do kubectl exec --namespace mongo-old mongo-old-mongodb-replicaset-$i -- sh -c 'mongo --eval="printjson(rs.isMaster())"'; done
Con questo, la preparazione della vecchia installazione di MongoDB, i cui dati saranno trasferiti, è pronta.Migrazione del cluster MongoDB
Ora procederemo a distribuire una nuova installazione di MongoDB, che si troverà in Kubernetes e sarà utilizzata dall'applicazione in produzione.
: Si noti che deve essere utilizzata la stessa versione di MongoDB di prima. In caso contrario, c'è il rischio di problemi di compatibilità.
NBAnalogamente alla sezione precedente (dove abbiamo simulato la "vecchia" installazione di MongoDB), utilizzeremo l'Helm chart già menzionato (con il comando
helm fetch helm fetch) e configureremo l'autenticazione, così come altri parametri, se necessari. Inoltre, correggeremo il file init/on-start.sh, aggiungendo temporaneamente alla riga 165 l'indirizzo del master, ottenuto nella fase precedente (o conosciuto da voi con l'installazione di MongoDB su server separati):
peers='mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017'Siamo pronti per la creazione di una nuova installazione di MongoDB:
helm install . --name mongo-new --namespace mongo-newAspettiamo che tutti i pod partano (se ci sono molti dati, il loro avvio può richiedere ore):

Adesso facciamo exec nel nuovo pod e controlliamo l'elenco dei database:
kubectl --namespace=mongo-new exec -ti mongo-new-mongodb-replicaset-0 mongo 
Due cluster MongoDB sono stati uniti in uno, composto da 6 nodi.
Attualmente, è già possibile commutare l'applicazione sul nuovo cluster, ma ci sono ancora alcuni passaggi da completare per terminare la migrazione.
Dal file init/on-start.sh nella nuova installazione rimuoviamo la riga che abbiamo aggiunto:
peers='mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017'Adesso andiamo sul vecchio master del cluster e 'sconfiggiamo' — in questo modo verrà nominato un nuovo master nel cluster. Entriamo nel pod con il master di MongoDB:
kubectl --namespace=mongo-old exec -ti mongo-old-mongodb-replicaset-0 mongo
use admin
db.auth('mongo','password')Dopo di ciò cambiamo le priorità dei nodi e modifichiamo il master:
cfg = rs.conf()
cfg.members[5].priority = 2
rs.reconfig(cfg)
rs.stepDown(120)Il nodo corrente ha smesso di essere master — si svolgeranno le elezioni di un nuovo master. Poiché abbiamo modificato le priorità, il nodo desiderato diventerà master.
NB: Per impostazione predefinita, tutte le priorità dei nodi MongoDB sono uguali a 1. In precedenza, abbiamo aumentato a 2 la priorità del nodo desiderato. In questo modo, un membro del nuovo cluster diventa sicuramente il master. Maggiori informazioni su come funzionano questi meccanismi in MongoDB possono essere letti in .
Disattiveremo la vecchia installazione di MongoDB, dopodiché entreremo nel master nuovo e rimuoveremo i nodi obsoleti:
rs.remove("mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017")
rs.remove("mongo-old-mongodb-replicaset-1.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017")
rs.remove("mongo-old-mongodb-replicaset-2.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017")Dopo di ciò, la migrazione può essere considerata completata: ci siamo spostati con successo dal vecchio cluster MongoDB al nuovo!
Conclusioni
Lo schema descritto si adatta praticamente a tutti i casi in cui è necessario trasferire MongoDB o semplicemente spostarsi in un nuovo cluster.
Probabilmente, il principale accorgimento durante il trasferimento è la necessità di mappare gli indirizzi IP dei nuovi pod sui server della vecchia installazione di MongoDB, se questa si trova al di fuori di K8s, e di una corretta denominazione nei DNS (o /etc/hosts). Nell'esempio questi passaggi non sono stati necessari poiché la migrazione avveniva tra diversi spazi dei nomi dello stesso cluster Kubernetes.
P.S.
Leggi anche nel nostro blog:
- «»;
- «»;
- «».
Fonte: habr.com
