History has somewhat divided the IT industry into two camps: those 'for' and those 'against'. And the subject of disputes can be absolutely arbitrary. Which OS is better: Win or Linux? On a smartphone, Android or iOS? Store everything in the cloud or upload to cold RAID storage and put the drives in a safe? Do PHP developers have the right to call themselves programmers? These debates are sometimes purely existential and have no other basis than sports interest.
It so happened that with the advent of containers and all this beloved Docker and conditional k8s kitchen, arguments 'for' and 'against' the use of new capabilities in various areas of the backend began. (Let’s clarify in advance that although Kubernetes is most often mentioned as the orchestrator in this discussion, the choice of this particular tool is not crucial. You can replace it with any other tool you find most convenient and familiar.)
And it would seem that this is just a simple debate between two sides of one coin. Just as senseless and ruthless as the eternal conflict of Win vs Linux, where reasonable people exist somewhere in between. But in the case of containerization, things are not so simple. Usually, there isn’t a right side in such disputes, but in the case of 'to use' or 'not to use' containers for database storage, everything turns upside down. Because, in a certain sense, both supporters and opponents of such an approach are right.
The Light Side
The argument of the Light Side can be briefly summarized in one phrase: 'Hello, 2k19 outside!' It sounds like populism, undoubtedly, but if you dive into the situation in detail, there are its advantages. Let’s break them down now.
Załóżmy, że masz duży projekt internetowy. Mógł on być początkowo zbudowany na podstawie podejścia mikrousługowego lub w pewnym momencie ewoluował w tym kierunku — to tak naprawdę nie jest istotne. Rozdzieliłeś nasz projekt na poszczególne mikrousługi, skonfigurowałeś orkiestrację, równoważenie obciążenia, skalowanie. A teraz z czystym sumieniem popijasz mohito w hamaku podczas efektów Habr, zamiast podnosić upadłe serwery. Jednak w każdym działaniu należy być konsekwentnym. Bardzo często konteneryzuje się tylko samo aplikację — kod. A co jeszcze mamy oprócz kodu?
Dokładnie, dane. Serce każdego projektu — to jego dane: mogą to być typowe systemy zarządzania bazą danych — MySQL, Postgre, MongoDB, a także przechowalnie używane do wyszukiwania (ElasticSearch), przechowalnie key-value do buforowania — na przykład redis, itd. Teraz nie będziemy mówić o krzywych wariantach realizacji backendu, kiedy DB pada z powodu źle napisanych zapytań, a zamiast tego porozmawiamy o zapewnieniu odporności tej bazy danych pod obciążeniem klientów. Przecież gdy konteneryzujemy naszą aplikację i pozwalamy jej swobodnie skalować, aby obsługiwać dowolną liczbę przychodzących zapytań, to automatycznie zwiększa obciążenie bazy danych.
Faktycznie, kanał dostępu do bazy danych i serwer, na którym ona działa, stają się wąskim gardłem w naszym wspaniałym konteneryzowanym backendzie. Głównym motywem wirtualizacji kontenerów jest mobilność i elastyczność struktury, które pozwalają na jak najbardziej efektywne rozłożenie szczytowego obciążenia w całej dostępnej infrastrukturze. Oznacza to, że jeśli nie konteneryzujemy i nie rozkładamy po klastrze wszystkich elementów systemu — popełniamy bardzo poważny błąd.
O wiele bardziej logiczne jest klastrowanie nie tylko samej aplikacji, ale także usług odpowiedzialnych za przechowywanie danych. Podczas klastrowania i uruchamiania niezależnych działających i rozdzielających obciążenie serwerów WWW w k8s, rozwiązujemy już problem synchronizacji danych – tych samych komentarzy do postów, jeśli przywołamy przykład jakiegoś medium lub platformy blogowej. W każdym razie tworzymy wewnętrzną, nawet jeśli wirtualną, reprezentację bazy danych jako ExternalService. Problem polega na tym, że sama baza danych nie jest jeszcze sklastrowana – uruchomione w klastrze serwery WWW pobierają informacje o zmianach z naszej statycznej bazowej bazy danych, która działa osobno.
Czujesz podstęp? Używamy k8s lub Swarm, aby rozdzielić obciążenie i uniknąć awarii głównej, serwer WWW, ale nie robimy tego dla bazy danych. Ale przecież jeśli baza danych upadnie, to w całej naszej sklastrowanej infrastrukturze nie ma sensu – co nam po pustych stronach WWW, które zwracają błąd dostępu do bazy danych?
Dokładnie dlatego należy klastrować nie tylko serwery WWW, jak to zazwyczaj się robi, ale także infrastrukturę bazy danych. Tylko w ten sposób możemy zapewnić w pełni działającą, ale jednocześnie niezależną od siebie strukturę. Nawet jeśli połowa naszego backendu „przewróci się” pod obciążeniem – reszta przetrwa, a system synchronizacji bazy danych w obrębie klastra oraz możliwość nieskończonego skalowania i uruchamiania nowych klastrów pomoże szybko osiągnąć wymagane moce – byleby były serwery w centrum danych.
Ponadto rozproszony w klastrach model bazy danych pozwala przenieść tę samą bazę danych tam, gdzie jest potrzebna; jeśli mówimy o globalnej usłudze, to dość nielogiczne jest uruchamianie klastra WWW gdzieś w rejonie San Francisco i jednoczesne przesyłanie pakietów podczas zapytań do bazy danych w Podmoskowie i z powrotem.
Ponadto konteneryzacja bazy danych pozwala zbudować wszystkie elementy systemu na tym samym poziomie abstrakcji. Co z kolei umożliwia zarządzanie tym systemem bezpośrednio z kodu przez programistów, bez aktywnego angażowania administratorów. Programiści pomyśleli, że potrzebna jest oddzielna baza danych dla nowego podprojektu – łatwo! Napisali plik yaml, załadowali go do klastra i gotowe.
Oczywiście, wewnętrzna eksploatacja znacznie się upraszcza. Powiedzcie, ile razy zamykaliście oczy, gdy nowy członek zespołu wkładał ręce do aktywnej bazy danych w pracy? Która jest, w rzeczywistości, tylko jedna i właśnie teraz działa? Oczywiście, wszyscy jesteśmy dorosłymi ludźmi i gdzieś mamy świeży backup, a jeszcze dalej — za półką z ogórkami babci i starymi nartami — jeszcze jeden backup, być może nawet w zimnym magazynie, ponieważ wasze biuro już kiedyś się spaliło. Ale mimo to, wprowadzenie nowego członka zespołu, który ma dostęp do aktywnej infrastruktury, a co za tym idzie, do aktywnej bazy danych — to prawdziwy sprawdzian dla wszystkich wokół. Kto wie, może on jest leworęczny? Straszne, zgadzacie się.
Konteneryzacja i w zasadzie rozproszona fizyczna topologia bazy danych waszego projektu pomagają uniknąć takich stresujących momentów. Nie ufacie nowicjuszowi? W porządku! Stworzymy mu własny klaster do pracy i odłączymy od pozostałych klastrów bazy danych — synchronizacja tylko przez ręczne przesyłanie i synchronizację dwóch kluczy (jeden dla lidera zespołu, drugi dla administratora). I wszyscy są zadowoleni.
A teraz nadszedł czas, aby przejść na stronę przeciwników klasteryzacji bazy danych.
Ciemna Strona
Rozważając, dlaczego nie warto konteneryzować bazy danych i kontynuować jej działania na jednym centralnym serwerze, nie zejdźmy do retoryki ortodoksów i stwierdzeń w stylu „dziadkowie używali baz danych na sprzęcie, a my też będziemy!” Zamiast tego spróbujmy wymyślić sytuację, w której konteneryzacja naprawdę przynosiłaby odczuwalne korzyści.
Zgódźcie się, że projekty, które naprawdę potrzebują bazy w kontenerze, można policzyć na palcach jednej ręki nieco gorszego frezera. W większości przypadków samo użycie k8s lub Docker Swarm bywa zbędne — do tych narzędzi często sięgają z powodu ogólnego rozgłosu technologii i nacisku „wszechmocnych” w osobach menedżerów, aby wszystko przenieść do chmur i kontenerów. No bo teraz to modne i wszyscy tak robią.
W połowie przypadków użycie Kubernetesa lub samego Dockera w projekcie jest przesadą. Problem polega na tym, że nie wszystkie zespoły lub firmy outsourcingowe zatrudnione do obsługi infrastruktury klienta zdają sobie z tego sprawę. Gorzej, gdy kontenery są narzucane, ponieważ wiąże się to z dodatkowymi kosztami dla klienta.
Ogólnie panuje przekonanie, że mafia Docker/Kubernetes po prostu zdominowuje klientów, którzy powierzają te kwestie infrastrukturalne na outsourcing. Przecież do pracy z klasterami potrzebni są inżynierowie, którzy potrafią to zrobić i rozumieją w ogóle architekturę wdrożonego rozwiązania. Opisywaliśmy już nasz przypadek z publikacją Republic – tam nauczyliśmy zespół klienta pracować w warunkach Kubernetesa i wszyscy byli zadowoleni. I to było solidne. Zazwyczaj jednak „wdrożeniowcy” K8s biorą infrastrukturę klienta jako zakładników – teraz tylko oni rozumieją, jak to wszystko działa, a po stronie klienta nie ma specjalistów.
A teraz wyobraźcie sobie, że w ten sposób oddajemy nie tylko część serwera WWW w ręce outsourcingu, ale również obsługę bazy danych. Mówiliśmy, że baza danych to serce, a jej utrata jest fatalna dla każdego żywego organizmu. Krótko mówiąc, perspektywy nie są najlepsze. Tak więc zamiast modnego Kubernetesa, wielu projektom powinno po prostu nie żałować pieniędzy na normalny plan na AWS, który rozwiąże wszystkie problemy z obciążeniem ich strony/projektu. Jednak AWS już nie jest modne, a fajerwerki są droższe od pieniędzy – niestety, także w branży IT.
Okej. Może klasteryzacja jest rzeczywiście potrzebna projektowi, ale jeśli w przypadku aplikacji stateless wszystko jest jasne, to jak zorganizować odpowiednie zapewnienie łączności sieciowej dla klasteryzowanej bazy danych?
Jeśli mówimy o bezproblemowym inżynieryjnym rozwiązaniu, jakim jest przejście na k8s, to naszą główną bolączką jest replikacja danych w skonsolidowanej bazie danych. Niektóre systemy zarządzania bazą danych początkowo dość przyjaźnie podchodzą do rozdzielania danych między swoimi instancjami. Wiele innych nie jest tak skore do współpracy. Często głównym argumentem przy wyborze systemu zarządzania bazą danych do naszego projektu nie jest wcale zdolność do replikacji przy minimalnych kosztach zasobów i inżynierii. Szczególnie jeśli projekt nie był początkowo planowany jako mikrousługa, ale ewoluował w tym kierunku.
Myślę, że nie musimy mówić o prędkości działania sieciowych dysków - są wolne. To znaczy, w przypadku konieczności, nie mamy realnej możliwości przeniesienia instancji systemu zarządzania bazą danych gdzie indziej, gdzie na przykład jest więcej mocy procesora lub wolnej pamięci RAM. Bardzo szybko napotykamy na ograniczenia wydajności wirtualizowanego systemu dyskowego. W związku z tym, system zarządzania bazą danych musi być przypisany do własnego zestawu maszyn, znajdujących się w bezpośredniej bliskości. Albo trzeba jakoś oddzielnie zorganizować wystarczająco szybką synchronizację danych na przewidywane rezerwy.
Kontynuując temat wirtualnych systemów plików: Woluminy Dockera niestety nie są bezproblemowe. Ogólnie rzecz biorąc, w sprawach takich jak długoterminowe niezawodne przechowywanie danych chcielibyśmy korzystać z jak najprostszych technicznych schematów. Dodanie nowej warstwy abstrakcji z systemu plików kontenera do systemu plików rodzica — samo w sobie stanowi ryzyko. Ale kiedy napotykamy trudności w pracy systemu zapewniającego konteneryzację przy przesyłaniu danych między tymi warstwami, to już prawdziwe kłopoty. Na obecnym etapie większość znanych problemów zdaje się być rozwiązana. Ale sami rozumiecie, im bardziej skomplikowany mechanizm, tym łatwiej się łamie.
W świetle wszystkich tych «przygod» znacznie korzystniej i łatwiej jest trzymać bazę danych w jednym miejscu, a nawet jeśli potrzebujesz konteneryzacji aplikacji — niech działa sama dla siebie i przez bramkę rozdzielającą uzyskuje równoczesne połączenie z bazą danych, która będzie odczytywana i zapisywana tylko raz i w jednym miejscu. Takie podejście minimalizuje ryzyko błędów i desynchronizacji.
Do czego zmierzamy? Do tego, że konteneryzacja baz danych ma sens tam, gdzie jest rzeczywista potrzeba. Nie można spakować bazy full-app i uruchamiać jej tak, jakbyś miał dwa tuziny mikrousług — to tak nie działa. I to trzeba jasno zrozumieć.
Zamiast wyjścia
Jeśli oczekujesz wyraźnej odpowiedzi na pytanie „wirtualizować czy nie bazy danych”, to zawiedziemy cię: nie będzie jej tutaj. Ponieważ przy tworzeniu jakiegokolwiek rozwiązania infrastrukturalnego należy kierować się nie modą i postępem, ale przede wszystkim zdrowym rozsądkiem.
Są projekty, w które zasady i narzędzia związane z Kubernetes idealnie pasują, i w takich projektach zapada pokój przynajmniej w obszarze backendu. A są projekty, które potrzebują nie konteneryzacji, a normalnej infrastruktury serwerowej, ponieważ zasadniczo nie mogą się przeskalować w model mikrousługowy, bo się nie sprawdzą.
Źródło: habr.com
