Wzorce przechowywania danych w Kubernetes

Wzorce przechowywania danych w Kubernetes
Cześć, Habr!

Przypominamy, że wydaliśmy kolejną wyjątkowo ciekawą i przydatną książkę o wzorcach Kubernetes. Wszystko zaczęło się jeszcze od "Wzorców" Brandona Burnsa, a zresztą, prace w tym segmencie u nas wrze. Dziś proponujemy Ci przeczytać artykuł z bloga MinIO, który w skrócie przedstawia tendencje i specyfikę wzorców przechowywania danych w Kubernetes.

Kubernetes zasadniczo zmienił tradycyjne wzorce rozwoju i wdrażania aplikacji. Teraz zespoły mogą potrzebować zaledwie kilku dni na rozwój, testowanie i wdrażanie aplikacji — w różnych środowiskach, i to wszystko w ramach klastrów Kubernetes. Tego rodzaju prace z technologiami poprzednich pokoleń zazwyczaj zajmowały całe tygodnie, jeśli nie miesiące.

Takie przyspieszenie stało się możliwe dzięki abstrakcji oferowanej przez Kubernetes — to znaczy, dzięki temu, że Kubernetes sam zarządza interakcją z niskopoziomowymi detalami fizycznych lub wirtualnych maszyn, pozwalając użytkownikom deklarować między innymi potrzebny procesor, odpowiednią ilość pamięci, liczbę instancji kontenerów. Ponieważ wsparciem Kubernetes zajmuje się ogromna społeczność, a jego zastosowania stale się rozszerzają, z dużą przewagą prowadzi on wśród wszystkich platform orkiestracji kontenerów.

W miarę jak wzrasta zastosowanie Kubernetes, rośnie również zamieszanie dotyczące stosowanych w nim wzorców przechowywania danych..

W sytuacji, gdy konkurencja o kawałek tortu Kubernetes (to znaczy, o magazyn danych) jest tak intensywna, podczas rozmów o przechowywaniu danych sygnał ten ginie w silnym hałasie.
Kubernetes wciela nowoczesny model rozwoju i wdrażania aplikacji, a także ich zarządzania. Taki nowoczesny model oddziela przechowywanie danych od obliczeń. Aby w pełni zrozumieć to oddzielenie w kontekście Kubernetes, należy także zrozumieć, czym są aplikacje działające z zachowaniem stanu i bez tego, a także jak z tym związane jest przechowywanie danych. Tutaj podejście REST API używane przez S3 ma wyraźne przewagi w porównaniu z podejściem POSIX/CSI, charakterystycznym dla innych rozwiązań.

W tym artykule porozmawiamy o wzorcach przechowywania danych w Kubernetes oraz osobno omówimy spór dotyczący aplikacji działających z przechowywaniem stanu i bez niego, aby dokładnie zrozumieć, na czym polega różnica między nimi i dlaczego jest ona ważna. Następnie w tekście zostaną omówione aplikacje i stosowane w nich wzorce przechowywania danych w świetle najlepszych praktyk pracy z kontenerami i Kubernetes.

Kontenery bez stanu

Kontenery są z natury lekkie i efemeryczne. Można je łatwo zatrzymywać, usuwać lub wdrażać na innym węźle – wszystko to zajmuje tylko kilka sekund. W dużym systemie orkiestracji kontenerów takie operacje odbywają się nieustannie, a użytkownicy nawet nie zauważają tych zmian. Jednak przemieszczenia są możliwe tylko wtedy, gdy kontener nie ma żadnych zależności od węzła, na którym się znajduje. O takich kontenerach mówi się, że działają bez stanu.

Kontenery ze stanem

Jeśli kontener przechowuje dane na lokalnie podłączonych urządzeniach (lub na urządzeniu blokowym), to przechowywanie danych, na którym się znajduje, będzie musiało zostać przeniesione na nowy węzeł razem z samym kontenerem — w przypadku awarii. To ważne, ponieważ w przeciwnym razie aplikacja uruchomiona w kontenerze nie będzie mogła prawidłowo funkcjonować, ponieważ musi mieć dostęp do danych przechowywanych na lokalnych nośnikach. O takich kontenerach mówi się, że działają ze stanem.

Z czysto technicznego punktu widzenia, kontenery ze stanem również można przenosić na inne węzły. Zwykle odbywa się to za pomocą rozproszonych systemów plików lub blokowych sieciowych magazynów danych, które są podłączane do wszystkich węzłów, na których działają kontenery. Dzięki temu kontenery uzyskują dostęp do wolumenów do przechowywania danych, a informacje są przechowywane na dyskach rozmieszczonych w całej sieci. Tę metodę nazywam „kontenerowym podejściem ze stanem”, i tak będę ją nazywał w dalszej części artykułu dla zachowania spójności.

Wzorce przechowywania danych w Kubernetes

W typowym podejściu kontenerowym z zachowaniem stanu wszystkie pody aplikacji są przypisane do jednego rozproszonego systemu plików – powstaje w ten sposób pewnego rodzaju współdzielona przestrzeń, w której przechowywane są wszystkie dane aplikacji. Chociaż możliwe są pewne wariacje, to jest to podejście na wysokim poziomie.

Teraz zajmijmy się tym, dlaczego podejście kontenerowe z zachowaniem stanu w świecie zorientowanym na chmurę jest antywzorem.

Projektowanie aplikacji zorientowanych na chmurę

Tradycyjnie aplikacje wykorzystywały bazy danych do strukturalnego przechowywania informacji oraz lokalne dyski lub rozproszone systemy plików, do których zrzucano wszystkie nieustrukturyzowane lub nawet półstrukturyzowane dane. W miarę wzrostu ilości danych nieustrukturyzowanych, programiści zdali sobie sprawę, że POSIX jest zbyt 'rozgadany', wiąże się z znacznych kosztami i ostatecznie utrudnia działanie aplikacji przy przejściu do rzeczywiście dużych skali.

To w głównej mierze przyczyniło się do powstania nowego standardu przechowywania danych, czyli chmurowych magazynów, działających głównie na podstawie REST API i uwalniających aplikację od uciążliwego zarządzania lokalnym magazynem danych. W takim wypadku aplikacja przechodzi faktycznie w tryb pracy bez zachowania stanu (ponieważ stan znajduje się w zdalnym magazynie). Wsp współczesne aplikacje są budowane od podstaw z uwzględnieniem tego czynnika. Zazwyczaj każda nowoczesna aplikacja zajmująca się danymi różnego rodzaju (logi, metadane, bloby itp.) jest zbudowana w oparciu o chmurową paradygmatę, gdzie stan jest przenoszony do specjalnie przeznaczonego do jego przechowywania systemu oprogramowania.

Podejście kontenerowe z zachowaniem stanu zmusza całą tę paradygmatę do powrotu do tego, od czego się zaczęła!

Kiedy aplikacje korzystają z interfejsów POSIX do przechowywania danych, działają w ten sam sposób, jak gdyby zapisywały stan, przez co odstępują od najważniejszych zasad projektowania chmurowego, to znaczy od możliwości zmiany rozmiaru wątków roboczych aplikacji w zależności od obciążenia, przechodzenia na nowy węzeł, gdy aktualny węzeł zawiedzie, i tak dalej.

Przyglądając się tej sytuacji bliżej, odkrywamy, że przy wyborze magazynu danych wciąż napotykamy dylemat „POSIX kontra REST API”, ALE z dodatkowym pogorszeniem problemów związanych z POSIX, spowodowanym rozproszoną naturą środowisk Kubernetes. W szczególności,

  • POSIX jest gadatliwy: semantyka POSIX wymaga skojarzenia z każdą operacją metadanych i uchwytów plików, które pomagają utrzymać stan operacji. To prowadzi do znacznych kosztów, które nie mają żadnej realnej wartości. API do przechowywania obiektów, w szczególności API S3, pozbyło się tych wymagań, pozwalając aplikacji działać, a następnie „zapomnieć” o wywołaniu. Odpowiedź systemu przechowywania danych wskazuje, czy dane działanie zakończyło się sukcesem, czy też nie. W przypadku niepowodzenia aplikacja może spróbować ponownie.
  • Ograniczenia sieciowe: W rozproszonej systemie zakłada się, że może istnieć wiele aplikacji próbujących zapisać dane na tym samym podłączonym nośniku. Dlatego, oprócz tego, że aplikacje będą konkurować między sobą o pasmo sieciowe (aby wysłać dane na nośnik), sam system przechowywania danych będzie konkurować o to pasmo, rozdzielając dane między fizyczne dyski. Z powodu gadatliwości POSIX liczba wywołań sieciowych wzrasta kilkakrotnie. Z drugiej strony, API S3 zapewnia wyraźne rozgraniczenie wywołań sieciowych między tymi, które pochodzą z klienta do serwera, a tymi, które zachodzą w obrębie serwera.
  • Bezpieczeństwo: Model bezpieczeństwa POSIX zakłada aktywne uczestnictwo człowieka: administratorzy konfigurują konkretne poziomy dostępu dla każdego użytkownika lub grupy. Taka paradigma jest trudna do zaadoptowania w chmurowym świecie. Nowoczesne aplikacje polegają na modelach bezpieczeństwa związanych z API, gdzie prawa dostępu definiowane są jako zestaw polityk, wyróżnione konta serwisowe, tymczasowe dane logowania itd.
  • Zarządzanie: Kontenery z zachowaniem stanu niosą za sobą pewne koszty związane z zarządzaniem. Chodzi o synchronizację równoległego dostępu do danych, zapewnienie spójności danych, co wymaga starannego przemyślenia, jakie wzorce dostępu do danych zastosować. Trzeba instalować, kontrolować i konfigurować dodatkowe programy, nie mówiąc już o dodatkowych wysiłkach, jakie trzeba włożyć w rozwój.

Interfejs kontenera przechowywania danych

Podczas gdy interfejs kontenera przechowywania danych (CSI) znakomicie ułatwił dystrybucję poziomu wolumenów Kubernetes, częściowo przekazując go zewnętrznym dostawcom przechowywania danych, przypadkowo również wspierał przekonanie, że podejście kontenerowe z zachowaniem stanu jest zalecanym sposobem przechowywania danych w Kubernetes.

CSI został opracowany jako standard dostarczania dowolnych systemów blokowego i plikowego przechowywania danych dla systemów dziedziczonych podczas pracy z Kubernetes. Jak wykazano w tym artykule, jedyną sytuacją, w której podejście kontenerowe z zachowaniem stanu (i CSI w obecnej formie) jest uzasadnione, jest wtedy, gdy samo aplikacja jest systemem dziedziczonym, w którym niemożliwe jest dodanie wsparcia dla API obiektowego przechowywania danych.

Ważne jest, aby zrozumieć, że korzystając z CSI w jego obecnej formie, to znaczy montując wolumeny podczas pracy z nowoczesnymi aplikacjami, napotkamy zbliżone problemy, które występowały w systemach, gdzie przechowywanie danych zorganizowane było w stylu POSIX.

Bardziej jakościowe podejście

W tym przypadku ważne jest zrozumienie, że większość aplikacji nie jest zasadniczo przystosowana do pracy z zachowaniem stanu lub bez zachowania stanu. Takie zachowanie zależy od ogólnej architektury systemu oraz od konkretnych opcji wybranych podczas projektowania. Porozmawiajmy nieco o aplikacjach, które zachowują stan.

Zasadniczo wszystkie dane aplikacji można podzielić na kilka szerokich typów:

  • Dane logów
  • Dane znaczników czasowych
  • Dane transakcji
  • Metadane
  • Obrazy kontenerów
  • Dane blobów (dużych obiektów binarnych)

Wszystkie te typy danych są bardzo dobrze wspierane na nowoczesnych platformach przechowywania danych, a istnieje kilka chmurowych platform przystosowanych do dostarczania danych w każdym z tych konkretnych formatów. Na przykład dane transakcji i metadane mogą znajdować się w nowoczesnej chmurowej bazie danych, takiej jak CockroachDB, YugaByte itd. Obrazy kontenerów lub dane blobów mogą być przechowywane w rejestrze dockera opartym na MinIO. Dane znaczników czasowych mogą być przechowywane w bazie danych szeregów czasowych, takiej jak InfluxDB itd. Nie będziemy tutaj wdawać się w szczegóły każdego typu danych i odpowiadających im aplikacji, ale ogólna idea polega na unikaniu trwałego przechowywania danych opartego na lokalnym montowaniu dysków.

Wzorce przechowywania danych w Kubernetes

Ponadto, często okazuje się, że efektywne jest udostępnienie poziomu tymczasowego buforowania, który służy aplikacjom jako rodzaj magazynu plików tymczasowych, ale aplikacje nie powinny polegać na tym poziomie jako źródle prawdy.

Magazyn dla aplikacji z zachowaniem stanu

Podczas gdy w większości przypadków korzystne jest utrzymywanie aplikacji bez zachowania stanu, te aplikacje, które są przeznaczone do przechowywania danych – na przykład bazy danych, magazyny obiektowe, magazyny kluczy i wartości – powinny zachować stan. Przyjrzyjmy się, dlaczego te aplikacje są uruchamiane w Kubernetes. Weźmy jako przykład MinIO, ale podobne zasady można zastosować do wszelkich innych dużych chmurowych systemów przechowywania danych.

Aplikacje oparte na chmurze projektowane są z myślą o maksymalnie efektywnym wykorzystaniu elastyczności charakterystycznej dla kontenerów. Oznacza to, że nie zakłada się żadnych warunków dotyczących środowiska, w którym będą wdrażane. Na przykład, w MinIO stosowany jest wewnętrzny mechanizm kodyfikacji redundantnej (erasure coding), który zapewnia systemowi wystarczającą odporność, aby pozostał funkcjonalny nawet przy awarii połowy dysków. MinIO zarządza także integralnością i bezpieczeństwem danych, wykorzystując własne haszowanie i szyfrowanie po stronie serwera.

Dla takich aplikacji opartych na chmurze jako lokalne archiwum najwygodniejsze są lokalne trwałe wolumeny (PV). Lokalny PV zapewnia możliwość przechowywania surowych danych, podczas gdy aplikacje działające na tych PV same zbierają informacje pozwalające na skalowanie danych i zarządzanie rosnącymi wymaganiami.

To podejście jest znacznie prostsze i lepiej skaluje się w porównaniu do PV na bazie CSI, które wprowadzają do systemu własne poziomy zarządzania danymi i redundancji; problem polega na tym, że te poziomy zazwyczaj kolidują z aplikacjami zaprojektowanymi według zasady zachowania stanu.

Pewny krok w kierunku oddzielenia danych od obliczeń

W tym artykule omówiliśmy, jak aplikacje przekształcają się na pracę bez zachowania stanu, a innymi słowy, przechowywanie danych jest oddzielone od obliczeń nad nimi. Na zakończenie przyjrzymy się kilku rzeczywistym przykładom tego trendu.

Spark, słynna platforma do analizy danych, tradycyjnie była używana z zachowaniem stanu i wdrażana w systemie plików HDFS. Jednak wraz z przejściem Sparka do chmurowego świata, ta platforma coraz bardziej wykorzystywana jest bez zachowania stanu z użyciem `s3a`. Spark stosuje s3a do przesyłania stanu do innych systemów, podczas gdy same kontenery Spark działają całkowicie bez zachowania stanu. Inni ogromni gracze z branży analizy dużych danych, w szczególności, Vertica, Teradata, Greenplum również przechodzą na pracę z oddzieleniem przechowywania danych i obliczeń nad nimi.

Podobne wzorce można również zauważyć na innych dużych platformach analitycznych, takich jak Presto, Tensorflow do R, Jupyter. Eksportując stan do zdalnych chmurowych systemów przechowywania danych, znacznie łatwiej jest zarządzać aplikacją i skalować ją. Ponadto sprzyja to przenośności aplikacji w różnych środowiskach.

Ź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