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

Come trasferiremo questo cluster in un nuovo production in Kubernetes?
Teoria
L'algoritmo generale di migrazione è simile a quello descritto nella situazione con RabbitMQ.
È importante notare che per poter migrare, è necessario che i server con MongoDB e Kubernetes siano nella stessa rete. I nodi del cluster MongoDB comunicheranno tra loro attraverso gli IP dei vecchi server (dove si trovano le precedenti installazioni di MongoDB) e attraverso i nomi DNS dei pod con MongoDB in K8s. Pertanto, sui server fisici (con le vecchie installazioni) sarà necessario instradare le rotte verso i pod e poi configurarli per utilizzare un server DNS che opera in Kubernetes (oppure inserire direttamente i nomi necessari in /etc/hosts, sebbene in generale sia 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, anche se il loro numero potrebbe essere diverso. Nel ConfigMap è necessario indicare l'indirizzo del master MongoDB dall'installazione precedente: così i nodi MongoDB presenti nei pod in K8s inizieranno subito la sincronizzazione con esso.
Una volta che tutti i pod saranno avviati, si formerà un cluster MongoDB di 6 nodi:

Si prega di notare che i pod impiegheranno più tempo ad avviarsi, poiché ogni pod viene avviato uno dopo l'altro e durante il loro avvio sincronizzano i dati con il master.
Dopo di ciò, puoi passare all'utilizzo dei nuovi server MongoDB:

Rimane solo da eliminare i vecchi nodi dal cluster MongoDB, dopodiché la migrazione può essere considerata completata:

Questa configurazione viene spesso utilizzata in produzione e, per facilitarne l'uso, l'abbiamo implementata nel modulo k (questo strumento lo abbiamo ), il che consente di distribuire configurazioni standardizzate di MongoDB su molti cluster. Prevediamo di pubblicare i nostri moduli a breve, ma nel frattempo presentiamo delle istruzioni separate per provare la soluzione proposta in azione senza utilizzare l'addon-operator.
Proviamo nella pratica
Requisiti
Dettagli:
- Cluster Kubernetes (va bene anche minikube);
- Cluster MongoDB (può essere implementato su bare metal o creato come un normale cluster in Kubernetes utilizzando l'Helm chart ufficiale).
Nell'esempio descritto qui di seguito, il vecchio cluster con MongoDB sarà chiamato mongo-old e installato nello stesso cluster Kubernetes dove successivamente installeremo il nuovo (mongo-new).
Prepariamo il vecchio cluster
1. Per esempio, per dimostrare il schema descritto in azione, creeremo un 'vecchio' cluster MongoDB (cioè da migrare) direttamente in Kubernetes (nella realtà potrebbe trovarsi anche su server separati al di fuori di K8s). Per fare ciò, scaricheremo il chart Helm:
helm fetch --untar stable/mongodb-replicaset… e faremo alcune modifiche, configurando l'autenticazione:
auth:
enabled: true
adminUser: mongo
adminPassword: pa33w0rd
# metricsUser: metrics
# metricsPassword: password
# key: keycontent
# existingKeySecret:
# existingAdminSecret:
# existingMetricsSecret: Inoltre, in values.yaml puoi configurare certificati e molto altro.
2. Installeremo il chart:
helm install . --name mongo-old --namespace mongo-oldDopo ciò, verrà avviata un'installazione ‘vecchia’ di prova di MongoDB:
kubectl --namespace=mongo-old get pods 
Entriamo nel pod con il suo master e creiamo un database di test:
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 
Interrogando diversi pod, ho scoperto che il master è mongo-old-mongodb-replicaset-0. Tuttavia, per risolvere questa questione in modo più conveniente, dopo l'installazione del chart Helm viene visualizzato un comando per determinare MASTER_POD. Nel mio caso (per mongo-old di 3 nodi) appare così:
for ((i = 0; i < 3; ++i)); do kubectl exec --namespace mongo-old mongo-old-mongodb-replicaset-$i -- sh -c 'mongo --eval="printjson(rs.isMaster())"'; doneLa preparazione della vecchia installazione di MongoDB, i cui dati saranno migrati, è completa.
Migrazione del cluster MongoDB
Ora implementeremo una nuova installazione di MongoDB, che si troverà in Kubernetes e sarà utilizzata dall'applicazione in produzione.
NB: È importante utilizzare la stessa versione di MongoDB di prima. In caso contrario, ci sono rischi di problemi di compatibilità.
Analogamente alla sezione precedente (dove abbiamo simulato la "vecchia" installazione di MongoDB), utilizzeremo il già menzionato chart Helm (con il comando helm fetch) e configureremo l'autenticazione, così come gli altri parametri, se necessari. Inoltre, modificheremo il file init/on-start.sh, aggiungendo temporaneamente alla riga 165 l'indirizzo del master, ottenuto nel passaggio precedente (o quello conosciuto dall'installazione di MongoDB su server singoli):
peers='mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017'Siamo pronti per creare la nuova installazione di MongoDB:
helm install . --name mongo-new --namespace mongo-newAspettiamo che tutti i pod siano avviati (se ci sono molti dati, il loro avvio potrebbe richiedere ore):

Ora eseguiamo exec in un nuovo pod e vediamo l'elenco dei database:
kubectl --namespace=mongo-new exec -ti mongo-new-mongodb-replicaset-0 mongo 
Due cluster MongoDB sono uniti in uno composto da 6 nodi.
Attualmente è già possibile passare l'applicazione al 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'Ora accediamo al vecchio master del cluster e 'deponiamolo' — in questo modo verrà nominato un nuovo master nel cluster. Entriamo nel pod con il master MongoDB:
kubectl --namespace=mongo-old exec -ti mongo-old-mongodb-replicaset-0 mongo
use admin
db.auth('mongo','password')Dopo di che cambiamo le priorità nei nodi e cambiamo il master:
cfg = rs.conf()
cfg.members[5].priority = 2
rs.reconfig(cfg)
rs.stepDown(120)Il nodo attuale ha smesso di essere master — si svolgeranno le elezioni per un nuovo master. Poiché abbiamo cambiato le priorità, il nodo richiesto diventerà il master.
NB: Per impostazione predefinita, la priorità di tutti i nodi MongoDB è 1. Qui sopra innalziamo a 2 la priorità del nodo che ci interessa. In questo modo, il membro del nuovo cluster diventa sicuramente il master. Per saperne di più su come funzionano questi meccanismi in MongoDB, puoi leggere .
Disattiviamo la vecchia installazione di MongoDB, dopodiché accederemo al master nuovo e rimuoveremo i vecchi nodi:
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 questo, la migrazione può dirsi conclusa: siamo riusciti a passare dal vecchio cluster MongoDB al nuovo!
Risultati
Lo schema descritto è adatto praticamente a tutti i casi in cui è necessario trasferire MongoDB o semplicemente spostarsi in un nuovo cluster.
Probabilmente, il principale aspetto da considerare durante il passaggio è la necessità di mappare gli indirizzi IP dei nuovi pod ai server della vecchia installazione di MongoDB, se questa si trova al di fuori di K8s, e il loro corretto naming nel DNS (o /etc/hosts). Nell'esempio, questi passaggi non sono stati necessari, poiché la migrazione è avvenuta tra diversi spazi dei nomi dello stesso cluster Kubernetes.
P.S.
Leggete anche nel nostro blog:
- «»;
- «»;
- «».
Fonte: habr.com
