Niezwykła migracja MongoDB do Kubernetes

Niezwykła migracja MongoDB do Kubernetes

Artykuł ten jest kontynuacją naszego niedawnego materiału na temat migracji RabbitMQ i jest poświęcony MongoDB. Obsługując wiele klastrów Kubernetes i MongoDB, doszliśmy do naturalnej potrzeby migracji danych z jednej instalacji do drugiej bez przestojów. Główne scenariusze pozostają te same: przeniesienie MongoDB z serwera wirtualnego/lub fizycznego do Kubernetes lub przeniesienie MongoDB w ramach jednego klastra Kubernetes (z jednej przestrzeni nazw do drugiej).

Nasz przepis jest przeznaczony na wypadek, gdy funkcjonuje stary klaster MongoDB (na przykład z 3 węzłami, z którego korzysta aplikacja na Kubernetes):

Niezwykła migracja MongoDB do Kubernetes

Jak zamierzamy przenieść taki klaster do nowego środowiska produkcyjnego w Kubernetes?

Teoria

Ogólny algorytm migracji jest zbliżony do opisanego w przypadku RabbitMQ.

Ważne jest, aby zauważyć, że do przeprowadzania migracji serwery z MongoDB i Kubernetes muszą znajdować się w tej samej sieci. Węzły klastra MongoDB będą komunikować się między sobą po IP starych serwerów (na których znajdują się stare instalacje MongoDB) oraz po nazwach DNS podów z MongoDB w K8s. W związku z tym na starych serwerach (z starymi instalacjami) trzeba będzie przekierować trasy do podów, a następnie skonfigurować je do korzystania z serwera DNS działającego w Kubernetes (lub wpisać potrzebne nazwy w /etc/hosts, chociaż w ogólnym przypadku lepiej unikać takiej możliwości).

Kolejnym krokiem jest uruchomienie klastra MongoDB w podach Kubernetes. W naszym przypadku klaster DB składa się z 3 węzłów, a każdy węzeł znajduje się w osobnym podzie K8s — chociaż ich liczba może być inna. W ConfigMap należy wskazać adres mastera MongoDB z starej instalacji: wtedy węzły MongoDB znajdujące się w podach w K8s od razu rozpoczną synchronizację z nim.

Gdy wszystkie pody się uruchomią, powstanie klaster MongoDB składający się z 6 węzłów:

Niezwykła migracja MongoDB do Kubernetes

Zauważ, że pody będą się długo uruchamiać, ponieważ każdy pod uruchamia się kolejno i w momencie uruchamiania synchronizuje dane z masterem.

Po tym można przełączyć aplikację na korzystanie z nowych serwerów MongoDB:

Niezwykła migracja MongoDB do Kubernetes

I pozostaje tylko usunąć stare węzły z klastra MongoDB, po czym migrację można uznać za zakończoną:

Niezwykła migracja MongoDB do Kubernetes

Tę schemę często stosujemy w środowisku produkcyjnym i dla wygody jej użycia zaimplementowaliśmy w ramach modułu k addon-operator (to narzędzie my ostatnio ogłosiliśmy), co pozwala na rozprzestrzenianie standardowych konfiguracji MongoDB na wiele klastrów. Publikację naszych modułów planujemy przeprowadzić wkrótce, a tymczasem przedstawiamy poszczególne instrukcje, z którymi można wypróbować proponowane rozwiązanie w działaniu, bez użycia addon-operator.

Rekwizyty są bardzo proste:

Wymagania

Dane kontaktowe:

  • Klaster RabbitMQ (może być zainstalowany na bare metal lub stworzony jako zwykły klaster w Kubernetes za pomocą oficjalnego Helm-chart).
  • Klaster MongoDB (może być wdrożony na bare metal lub stworzony jako zwykły klaster w Kubernetes z oficjalnego Helm-chartu).

W opisanym poniżej przykładzie stary klaster z MongoDB będzie nazwany mongo-old i zostanie zainstalowany w tym samym klastrze Kubernetes, w którym w dalszej kolejności zainstalujemy nowy (mongo-new).

Przygotowujemy stary klaster

1. Dla przykładu, który pokazuje opisaną schematykę w działaniu, stworzymy „stary” (tj. mający być migrowany) klaster MongoDB bezpośrednio w Kubernetes (w rzeczywistości może znajdować się na oddzielnych serwerach poza K8s). W tym celu pobierzemy Helm-chart:

helm fetch --untar stable/mongodb-replicaset

… i nieco go edytujemy, ustawiając autoryzację:

auth:
  enabled: true
  adminUser: mongo
  adminPassword: pa33w0rd
  # metricsUser: metrics
  # metricsPassword: password
  # key: keycontent
  # existingKeySecret:
  # existingAdminSecret:
  # existingMetricsSecret:

Można także w values.yaml ustawić certyfikaty i wiele więcej.

2. Zainstalujemy chart:

helm install . --name mongo-old --namespace mongo-old

Po tym zostanie uruchomiona testowa „stara” instalacja MongoDB:

kubectl --namespace=mongo-old get pods

Niezwykła migracja MongoDB do Kubernetes

Wejdźmy do podu z jej masterem i stwórzmy testową bazę:

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

Niezwykła migracja MongoDB do Kubernetes

Wchodząc do różnych podów, odkryłem, że masterem jest mongo-old-mongodb-replicaset-0. Jednak dla wygodniejszego rozwiązania tego problemu po instalacji Helm-chartu wyświetlana jest komenda, jak określić MASTER_POD. W moim przypadku (dla mongo-old z 3 węzłów) wygląda to tak:

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

Na tym przygotowanie starej instalacji MongoDB, których dane będą przenoszone, jest gotowe.

Migracja klastra MongoDB

Teraz rozwińmy nową instalację MongoDB, która będzie znajdować się w Kubernetes i używana przez aplikację w produkcji.

NB: Zauważam, że powinna być używana ta sama wersja MongoDB, co wcześniej. W przeciwnym razie istnieje ryzyko wystąpienia problemów z kompatybilnością.

Na podobieństwo poprzedniej sekcji (gdzie imitowaliśmy „starą” instalację MongoDB), weźmiemy już wspomniany Helm-chart (komendą helm fetch) i skonfigurujemy autoryzację oraz inne opcje, jeśli są używane. Dodatkowo poprawimy plik init/on-start.sh, tymczasowo dodając do niego w 165 linii adres głównego serwera uzyskany na poprzednim etapie (lub znany z instalacji MongoDB na oddzielnych serwerach):

peers='mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017'

Jesteśmy gotowi do stworzenia nowej instalacji MongoDB:

helm install . --name mongo-new --namespace mongo-new

Czekamy, aż wystartują wszystkie pod’y (jeśli danych jest dużo, ich uruchomienie może zająć godziny):

Niezwykła migracja MongoDB do Kubernetes

Teraz robimy exec w nowym podzie i przeglądamy listę baz:

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

Niezwykła migracja MongoDB do Kubernetes

Dwa klastry MongoDB zostały połączone w jeden składający się z 6 węzłów.

Na chwilę obecną można już przełączyć aplikację na nowy klaster, ale pozostało jeszcze kilka kroków do zakończenia migracji.

Z pliku init/on-start.sh w nowej instalacji usuwamy dodany przez nas wiersz:

peers='mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017'

Teraz przechodzimy do starego głównego serwera klastra i „obalimy” go – wówczas w klastrze zostanie wyznaczony nowy główny serwer. Wchodzimy do pod’a z głównym serwerem MongoDB:

kubectl --namespace=mongo-old exec -ti mongo-old-mongodb-replicaset-0 mongo
use admin
db.auth('mongo','password')

Po tym zmieniamy priorytety węzłów i zmieniamy główny serwer:

cfg = rs.conf()
cfg.members[5].priority = 2
rs.reconfig(cfg)
rs.stepDown(120)

Aktualny węzeł przestał być głównym serwerem – odbędą się wybory nowego. Ponieważ zmieniliśmy priorytety, głównym serwerem stanie się potrzebny nam węzeł.

NB: Domyślnie wszystkie węzły MongoDB mają priorytet równy 1. Wyżej podnosimy priorytet interesującego nas węzła do 2. W ten sposób głównym serwerem na pewno zostanie członek nowego klastra. Więcej na temat działania tych mechanizmów w MongoDB można przeczytać w dokumentacji.

Wyłączamy starą instalację MongoDB, po czym wchodzimy do nowego głównego serwera i usuwamy stare węzły:

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")

Po tym migrację można uznać za zakończoną: pomyślnie przełączyliśmy się ze starego klastra MongoDB na nowy!

Podsumowanie

Opisana procedura nadaje się praktycznie do wszystkich przypadków, gdy trzeba przenieść MongoDB lub po prostu przenieść się do nowego klastra.

Zdecydowanie najważniejszym aspektem podczas przenoszenia jest konieczność przekierowania adresów IP nowych pod’ów na serwery starej instalacji MongoDB, jeśli znajduje się ona poza K8s, oraz ich poprawnego nazywania w DNS (lub /etc/hosts). W tym przykładzie kroki te były zbędne, ponieważ migracja odbywała się między różnymi przestrzeniami nazw w obrębie tego samego klastra Kubernetes.

P.S.

Przeczytaj także na naszym blogu:

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster