Nasze doświadczenie w tworzeniu sterownika CSI w Kubernetes dla Yandex.Cloud

Nasze doświadczenie w tworzeniu sterownika CSI w Kubernetes dla Yandex.Cloud

Z przyjemnością informujemy, że Flant rozszerza swój wkład w narzędzia Open Source dla Kubernetes wydając wersja alfa sterownika CSI (Interfejs przechowywania kontenerów) dla Yandex.Cloud.

Zanim jednak przejdziemy do szczegółów wdrożenia, odpowiedzmy sobie na pytanie, dlaczego jest to w ogóle potrzebne, skoro Yandex ma już usługę Usługa zarządzana dla Kubernetes.

Wprowadzenie

Dlaczego to?

W naszej firmie od samego początku wykorzystania Kubernetesa w produkcji (tj. już od kilku lat) rozwijamy własne narzędzie (deckhouse), które notabene planujemy wkrótce udostępnić również jako projekt Open Source . Za jego pomocą jednolicie konfigurujemy i konfigurujemy wszystkie nasze klastry, a obecnie jest ich już ponad 100, na szerokiej gamie konfiguracji sprzętowych i we wszystkich dostępnych usługach chmurowych.

Klastry korzystające z nadbudówki posiadają wszystkie komponenty niezbędne do działania: balansery, monitorowanie za pomocą wygodnych wykresów, metryk i alertów, uwierzytelnianie użytkowników za pośrednictwem zewnętrznych dostawców w celu uzyskania dostępu do wszystkich dashboardów i tak dalej. Nie ma sensu instalować tak „napompowanego” klastra w rozwiązaniu zarządzanym, ponieważ często jest to albo niemożliwe, albo będzie prowadzić do konieczności wyłączenia połowy komponentów.

NB: Takie jest nasze doświadczenie i jest ono dość specyficzne. W żadnym wypadku nie sugerujemy, że każdy powinien samodzielnie wdrażać klastry Kubernetes, zamiast korzystać z gotowych rozwiązań. Nawiasem mówiąc, nie mamy prawdziwego doświadczenia w obsłudze Kubernetesa od Yandex i nie będziemy oceniać tej usługi w tym artykule.

Co to jest i dla kogo?

Mówiliśmy już o nowoczesnym podejściu do przechowywania w Kubernetesie: jak działa CSI? и jak pojawiła się społeczność do tego podejścia.

Obecnie wielu dużych dostawców usług w chmurze opracowało sterowniki umożliwiające używanie ich dysków w chmurze jako woluminów trwałych w Kubernetes. Jeśli dostawca nie posiada takiego sterownika, ale wszystkie niezbędne funkcje udostępniane są poprzez API, to nic nie stoi na przeszkodzie, aby samodzielnie zaimplementować sterownik. Tak właśnie stało się z Yandex.Cloud.

Przyjęliśmy jako podstawę rozwoju Sterownik CSI dla chmury DigitalOcean i kilka pomysłów z sterowniki do GCP, ponieważ interakcja z API tych chmur (Google i Yandex) ma wiele podobieństw. W szczególności API i GCPoraz Yandex zwrócić obiekt Operation do śledzenia statusu długotrwałych operacji (na przykład tworzenia nowego dysku). Aby współdziałać z interfejsem API Yandex.Cloud, użyj Zestaw SDK Yandex.Cloud Go.

Wynik wykonanej pracy opublikowane na GitHubie i może być przydatny dla tych, którzy z jakiegoś powodu korzystają z własnej instalacji Kubernetes na maszynach wirtualnych Yandex.Cloud (ale nie z gotowego klastra zarządzanego) i chcieliby korzystać (zamawiać) dyski poprzez CSI.

realizacja

Najważniejsze cechy

Obecnie sterownik obsługuje następujące funkcje:

  • Uporządkowanie dysków we wszystkich strefach klastra zgodnie z topologią węzłów w klastrze;
  • Usuwanie wcześniej zamówionych płyt;
  • Zmiana rozmiaru dysków offline (Yandex.Cloud nie wspieraj zwiększenie liczby dysków zamontowanych na maszynie wirtualnej). Informacje na temat modyfikacji sterownika, aby zmiana rozmiaru była jak najbardziej bezbolesna, można znaleźć poniżej.

W przyszłości planujemy wdrożyć obsługę tworzenia i usuwania migawek dysków.

Główna trudność i sposób jej pokonania

Brak możliwości zwiększania dysków w czasie rzeczywistym w Yandex.Cloud API to ograniczenie, które komplikuje operację zmiany rozmiaru dla PV (Persistent Volume): w tym przypadku konieczne jest zatrzymanie aplikacji korzystającej z dysku, co może powodować przestoje aplikacji.

Według Specyfikacje CSI, jeśli kontroler CSI zgłosi, że może zmieniać rozmiar dysków tylko „offline” (VolumeExpansion.OFFLINE), to proces zwiększania dysku powinien przebiegać następująco:

Jeśli wtyczka ma tylko VolumeExpansion.OFFLINE możliwości rozbudowy i tom są aktualnie publikowane lub dostępne w węźle ControllerExpandVolume NALEŻY wywołać TYLKO po:

  • Wtyczka posiada kontroler PUBLISH_UNPUBLISH_VOLUME zdolności i ControllerUnpublishVolume został pomyślnie wywołany.

ALBO

  • Wtyczka NIE posiada kontrolera PUBLISH_UNPUBLISH_VOLUME możliwości, wtyczka ma node STAGE_UNSTAGE_VOLUME możliwości i NodeUnstageVolume został pomyślnie zakończony.

ALBO

  • Wtyczka NIE posiada kontrolera PUBLISH_UNPUBLISH_VOLUME możliwości ani węzła STAGE_UNSTAGE_VOLUME możliwości i NodeUnpublishVolume zakończyło się pomyślnie.

Zasadniczo oznacza to, że musisz odłączyć dysk od maszyny wirtualnej przed jej rozszerzeniem.

Jednak niestety wdrożenie Specyfikacja CSI z przyczepami bocznymi nie spełnia tych wymagań:

  • W kontenerze z przyczepą boczną csi-attacher, który powinien odpowiadać za obecność wymaganej przerwy pomiędzy mocowaniami, ta funkcjonalność po prostu nie jest zaimplementowana w przypadku zmiany rozmiaru offline. Rozpoczęto dyskusję na ten temat tutaj.
  • Czym dokładnie jest kontener z wózkiem bocznym w tym kontekście? Sama wtyczka CSI nie wchodzi w interakcję z API Kubernetes, a jedynie odpowiada na wywołania gRPC wysyłane do niej przez kontenery sidecar. Najnowszy są rozwijane przez społeczność Kubernetes.

W naszym przypadku (wtyczka CSI) operacja powiększenia dysku wygląda następująco:

  1. Otrzymujemy wywołanie gRPC ControllerExpandVolume;
  2. Próbujemy zwiększyć dysk w API, ale pojawia się błąd o niemożności wykonania operacji, ponieważ dysk jest zamontowany;
  3. Identyfikator dysku przechowujemy na mapie, która zawiera dyski, dla których należy wykonać operację zwiększania. Poniżej dla zwięzłości będziemy nazywać tę mapę jako volumeResizeRequired;
  4. Ręcznie usuń moduł korzystający z dysku. Kubernetes uruchomi go ponownie. Aby dysk nie miał czasu na zamontowanie (ControllerPublishVolume) przed zakończeniem operacji zwiększania przy próbie zamontowania sprawdzamy, czy dany dysk nadal jest na swoim miejscu volumeResizeRequired i zwróć błąd;
  5. Sterownik CSI próbuje ponownie wykonać operację zmiany rozmiaru. Jeśli operacja się powiodła, wyjmij dysk z volumeResizeRequired;
  6. Ponieważ Brak identyfikatora dysku volumeResizeRequired, ControllerPublishVolume przechodzi pomyślnie, dysk jest zamontowany, kapsuła uruchamia się.

Wszystko wygląda dość prosto, ale jak zawsze są pułapki. Powiększa dyski zewnętrzny-resizer, co w przypadku błędu podczas operacji korzysta z kolejki z wykładniczym wzrostem czasu oczekiwania do 1000 sekund:

func DefaultControllerRateLimiter() RateLimiter {
  return NewMaxOfRateLimiter(
  NewItemExponentialFailureRateLimiter(5*time.Millisecond, 1000*time.Second),
  // 10 qps, 100 bucket size.  This is only for retry speed and its only the overall factor (not per item)
  &BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)},
  )
}

Może to okresowo powodować wydłużenie operacji rozszerzania dysku o ponad 15 minut, a tym samym niedostępność odpowiedniego zasobnika.

Jedyną opcją, która w miarę łatwo i bezboleśnie pozwoliła nam skrócić potencjalne przestoje, było zastosowanie naszej wersji zewnętrznego-resizera z maksymalnym limitem czasu w 5 sekund:

workqueue.NewItemExponentialFailureRateLimiter(5*time.Millisecond, 5*time.Second)

Nie uznaliśmy za konieczne pilnego wszczynania dyskusji i łatania zewnętrznego narzędzia zmiany rozmiaru, ponieważ zmiana rozmiaru dysków w trybie offline to powrót do przeszłości, który wkrótce zniknie ze wszystkich dostawców usług w chmurze.

Jak zacząć z niego korzystać?

Sterownik jest obsługiwany na platformie Kubernetes w wersji 1.15 i wyższej. Aby kierowca mógł pracować muszą być spełnione następujące wymagania:

  • Flaga --allow-privileged ustawić na wartość true dla serwera API i kubelet;
  • Dołączony --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=true dla serwera API i kubelet;
  • Propagacja wierzchowców (propagacja wierzchowców) musi być włączona w klastrze. Podczas korzystania z Dockera demon musi być skonfigurowany tak, aby zezwalał na wspólne montowanie.

Wszystkie niezbędne kroki do samej instalacji opisane w README. Instalacja polega na utworzeniu obiektów w Kubernetesie z manifestów.

Aby sterownik działał, potrzebne będą:

  • Określ identyfikator katalogu w manifeście (folder-id) Yandex.Cloud (zobacz dokumentację);
  • Do interakcji z API Yandex.Cloud sterownik CSI korzysta z konta usługi. W manifeście należy przekazać Sekret autoryzowane klucze z konta usługi. W dokumentacji opisane, jak założyć konto w serwisie i zdobyć klucze.

W sumie - spróbuji będziemy szczęśliwi, jeśli otrzymamy informację zwrotną i nowe problemyjeśli napotkasz jakiekolwiek problemy!

Dalsze wsparcie

W rezultacie pragniemy zaznaczyć, że wdrożyliśmy ten sterownik CSI nie z wielkiej chęci dobrej zabawy przy pisaniu aplikacji w Go, ale z powodu pilnej potrzeby wewnątrz firmy. Utrzymywanie własnej implementacji nie wydaje nam się praktyczne, więc jeśli Yandex wykaże zainteresowanie i zdecyduje się na dalsze wspieranie sterownika, chętnie przeniesiemy do niego repozytorium.

Ponadto Yandex prawdopodobnie posiada własną implementację sterownika CSI w zarządzanym przez siebie klastrze Kubernetes, który można udostępnić w formacie Open Source. Również tę opcję rozwoju postrzegamy jako korzystną – społeczność będzie mogła skorzystać ze sprawdzonego sterownika od usługodawcy, a nie od zewnętrznej firmy.

PS

Przeczytaj także na naszym blogu:

Źródło: www.habr.com

Dodaj komentarz