
Artykuł ten jest kontynuacją naszego 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):

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:

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:

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

Tę schemę często stosujemy w środowisku produkcyjnym i dla wygody jej użycia zaimplementowaliśmy w ramach modułu k (to narzędzie 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-oldPo tym zostanie uruchomiona testowa „stara” instalacja MongoDB:
kubectl --namespace=mongo-old get pods 
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 
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())"'; doneNa 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-newCzekamy, aż wystartują wszystkie pod’y (jeśli danych jest dużo, ich uruchomienie może zająć godziny):

Teraz robimy exec w nowym podzie i przeglądamy listę baz:
kubectl --namespace=mongo-new exec -ti mongo-new-mongodb-replicaset-0 mongo 
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 .
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
