
Тази статия продължава нашия за миграцията на RabbitMQ и е посветена на MongoDB. Тъй като обслужваме множество клъстери Kubernetes и MongoDB, пристъпихме към необходимостта да мигрираме данни от една инсталация в друга без да има престой. Основните сценарии остават същите: прехвърляне на MongoDB от виртуален/физически сървър в Kubernetes или прехвърляне на MongoDB в рамките на един и същи клъстер Kubernetes (от едно пространство на имената в друго).
Нашата рецепта е предназначена за случаи, когато функционира стар клъстер MongoDB (например, от 3 възела и намиращ се или в K8s, или на стари сървъри), с който работи приложение, разположено в Kubernetes:

Как ще прехвърлим такъв клъстер в новото производство в Kubernetes?
Теория
Общият алгоритъм за миграция е подобен на описания в ситуацията с RabbitMQ.
Важно е да се отбележи, че за възможността за преместване, сървърите с MongoDB и Kubernetes трябва да бъдат в една и съща мрежа. Възлите на клъстера MongoDB ще комуникират помежду си по IP адресите на старите сървъри (където се намират старите инсталации на MongoDB) и по DNS-имената на pod-овете с MongoDB в K8s. Затова на физическите сървъри (със старите инсталации) ще трябва да се пренасочат маршрути до pod-овете, а след това да се настроят да използват DNS-сървър, работещ в Kubernetes (или да се впишат необходимите имена в /etc/hosts, въпреки че в общия случай е по-добре да се избягва такава възможност).
Следващата стъпка е да се издигне клъстерът MongoDB в pod-ове на Kubernetes. В нашия случай, базата данни се състои от 3 възела и всеки възел е в отделен pod на K8s — въпреки че техният брой може да бъде различен. В ConfigMap трябва да се посочи адресът на майстора MongoDB от старата инсталация: тогава възлите на MongoDB, намиращи се в pod-овете в K8s, незабавно ще започнат синхронизация с него.
След като всички pod-ове се стартират, ще се образува клъстер MongoDB от 6 възела:

Обърнете внимание, че pod-овете ще се стартират бавно, тъй като всеки pod се стартира последователно, а в момент на стартиране синхронизира данните с майстора.
След това можете да превключите приложението да използва новите сървъри на MongoDB:

Остава само да се премахнат старите възли от клъстера MongoDB, след което преместването може да се счита за завършено:

Тази схема често я използваме в производство и за удобство при нейното използване сме я реализирали в рамките на модула к (този инструмент ние ), което позволява разпространяването на типови конфигурации на MongoDB в множество клъстери. Публикацията на нашите модули планираме да осъществим в скоро време, а засега представяме отделни инструкции, с които можете да изпробвате предложеното решение в действие и без използването на addon-operator.
Опитваме в практиката
Изисквания
Реквизити:
- Клъстер Kubernetes (подходящ и minikube);
- Клъстер MongoDB (може да бъде разположен и на bare metal, и да бъде създаден като обикновен клъстер в Kubernetes от официалния Helm график).
В описания по-долу пример старият клъстер с MongoDB ще бъде наречен mongo-old и ще бъде инсталиран в същия клъстер Kubernetes, където по-късно ще инсталираме и новия (mongo-new).
Подготвяме стария клъстер
1. За примера, демонстриращ описаната схема в действие, ще създадем "стар" (т.е. подлежащ на миграция) клъстер MongoDB директно в Kubernetes (в действителност той може да се намира и на отделни сървъри извън K8s). За целта ще изтеглим Helm графика:
helm fetch --untar stable/mongodb-replicaset… и малко ще го редактираме, настройвайки авторизацията:
auth:
enabled: true
adminUser: mongo
adminPassword: pa33w0rd
# metricsUser: metrics
# metricsPassword: password
# key: keycontent
# existingKeySecret:
# existingAdminSecret:
# exisitingMetricsSecret: Също в values.yaml може да се настроят сертификати и много друго.
2. Ще инсталираме графика:
helm install . --name mongo-old --namespace mongo-oldСлед това ще бъде стартирана тестова "стара" инсталация на MongoDB:
kubectl --namespace=mongo-old get pods 
Ще влезем в pod с нейния мастер и ще създадем тестова база:
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 
При влизането в различни pod’ове, установих, че мастърът е mongo-old-mongodb-replicaset-0. Впрочем, за по-удобно решаване на този въпрос след инсталирането на Helm графика се извежда команда, как да определим MASTER_POD. В моя случай (за mongo-old от 3 възли) тя изглежда така:
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С това подготовката на старата инсталация на MongoDB, данните от която ще бъдат прехвърлени, е готова.
Миграция на клъстера MongoDB
Сега ще разположим нова инсталация на MongoDB, която ще бъде в Kubernetes и ще бъде използвана от приложението в продукция.
NB: Обръщам внимание, че трябва да се използва същата версия на MongoDB, както преди. В противен случай съществува риск от проблеми със съвместимостта.
По аналогия с предишния раздел (където имитирахме "старата" инсталация на MongoDB), ще вземем вече споменатия Helm чарт (с командата helm fetch) и ще настроим автентикацията, както и други параметри, ако те се използват. Освен това, ще коригираме файла init/on-start.sh, временно добавяйки в него на ред 165 адреса на мастера, получен на предишния етап (или известен ви от инсталацията на MongoDB на отделни сървъри):
peers='mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017'Готови сме за създаване на нова инсталация на MongoDB:
helm install . --name mongo-new --namespace mongo-newИзчакваме, докато стартират всички pod'ове (ако данните са много, тяхното стартиране може да отнеме часове):

Сега правим exec в новия pod и виждаме списъка с бази:
kubectl --namespace=mongo-new exec -ti mongo-new-mongodb-replicaset-0 mongo 
Двата кластера MongoDB са обединени в един, състоящ се от 6 възела.
В момента вече можем да превключим приложението към новия кластер, но за завършване на миграцията остават няколко стъпки.
От файла init/on-start.sh в новата инсталация премахваме добавения от нас ред:
peers='mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017'Сега влизаме в стария мастер на клъстера и "сваляме" него — тогава в клъстера ще бъде назначен нов мастер. Влизаме в pod с мастера MongoDB:
kubectl --namespace=mongo-old exec -ti mongo-old-mongodb-replicaset-0 mongo
use admin
db.auth('mongo','password')След това променяме приоритетите на възлите и сменяме мастера:
cfg = rs.conf()
cfg.members[5].priority = 2
rs.reconfig(cfg)
rs.stepDown(120)Текущият възел спира да бъде майстор — ще се проведат избори за нов. Понеже променихме приоритетите, мастером ще стане желаният от нас възел.
NB: По подразбиране приоритетът на всички възли MongoDB е 1. По-горе повишаваме приоритета на желания от нас възел до 2. Така общият мастер става член на новия клъстер. Повече за това как функционират тези механизми в MongoDB може да прочетете в .
Деактивираме старата инсталация на MongoDB, след което влизаме в мастера на новата и премахваме старите възли:
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")След това миграцията може да се счита за завършена: успешно сме преминали от стария кластер MongoDB към новия!
Резюме
Описание на схемата е подходящо за почти всички случаи, когато трябва да пренесем MongoDB или просто да се преместим в нов клъстер.
Вероятно, най-важният нюанс при прехвърлянето е необходимостта от пробросване на IP адресите на новите pod’ове към сървърите на старата инсталация на MongoDB, ако тя се намира извън K8s, и правилното им наименоване в DNS (или /etc/hosts). В примера тези стъпки не бяха необходими, тъй като миграцията се извършваше между различни пространства от имена на един и същ Kubernetes клъстер.
P.S.
Прочетете също в нашия блог:
- «»;
- «»;
- «».
Източник: habr.com
