Безпроблемна миграция на MongoDB в Kubernetes

Безпроблемна миграция на MongoDB в Kubernetes

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

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

Безпроблемна миграция на MongoDB в 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 възела:

Безпроблемна миграция на MongoDB в Kubernetes

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

След това можете да превключите приложението да използва новите сървъри на MongoDB:

Безпроблемна миграция на MongoDB в Kubernetes

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

Безпроблемна миграция на MongoDB в Kubernetes

Тази схема често я използваме в производство и за удобство при нейното използване сме я реализирали в рамките на модула к addon-operator (този инструмент ние току-що анонсирахме), което позволява разпространяването на типови конфигурации на 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

Безпроблемна миграция на MongoDB в Kubernetes

Ще влезем в 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

Безпроблемна миграция на MongoDB в Kubernetes

При влизането в различни 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'ове (ако данните са много, тяхното стартиране може да отнеме часове):

Безпроблемна миграция на MongoDB в Kubernetes

Сега правим exec в новия pod и виждаме списъка с бази:

kubectl --namespace=mongo-new exec -ti mongo-new-mongodb-replicaset-0 mongo

Безпроблемна миграция на MongoDB в Kubernetes

Двата кластера 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

Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри 🔥 Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри | ProHoster