Безпроблемна миграция на 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-a трябва да се посочи адреса на мастера 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 и ще се използва от приложението в production.

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