Konteneryzacja - wypłyń na szerokie wody

11.02.2021 | Paweł Widera

Cloud, Containers, Microservices

W ciągu ostatnich kilku lat tematyka konteneryzacji, mikroserwisów i chmur publicznych zyskała mocno na popularności. Obecnie zagadnienia te inspirują tysiące programistów do tworzenia nowych, lepszych, szybszych i stabilniejszych rozwiązań. Coraz więcej naszych bankowych aplikacji korzysta z platformy Openshift on-premises jako orkiestratora. I właśnie o nowych możliwościach, które się przed nami otworzyły chciałem w tym artykule opowiedzieć. Zacznijmy jednak od początku – konteneryzacja.

Czym tak naprawdę ona jest? Jest to nic innego jak pomysł zamknięcia naszej aplikacji w specjalnym pudełku które nazywamy kontenerem. Będzie ono stanowiło niezależny byt uruchomieniowy (instancje) z wydzielonymi zasobami procesora, pamięci, dysku, jak również otrzyma swój własny adres IP. 


Źródło: https://www.docker.com

Obecnie na rynku istnieje wiele platform, które umożliwiają budowanie i zarządzanie kontenerami. My skupimy się na najpopularniejszym z nich czyli na Dockerze. Jest to oprogramowanie open-source, które pozwala nam tworzyć lekkie wirtualne kontenery i uruchamiać je na różnych systemach operacyjnych (np. Linux, czy Windows). Najpopularniejszy sposób tworzenia kontenerów to wykorzystanie specjalnego pliku, który nazywamy dockerfile. Po jego zbudowaniu otrzymujemy tzw. obraz  (docker image), który następnie uruchamiamy w kontenerze. W sieci istnieje bardzo duża społeczność internetowa, w której możemy znaleźć tysiące różnych plików dockerowych. Są one gotowe do użycia i oferujących nam przeróżne funkcjonalności. My jednak skupimy się na benefitach płynących z stworzenia i wykorzystywania własnego. Żeby lepiej to zobrazować posłużmy się rysunkiem przedstawiającym różnice między bardzo popularną w świecie IT wirtualizacją, a konteneryzacją.

Wirtualizacja kontra konteneryzacja


Źródło: https://www.docker.com

Główna różnica polega na tym, że w wirtualizacji istnieje tzw. gościnny system operacyjny. Oznacza to, że możemy mieć inny system operacyjny na maszynie fizycznej, a inny na maszynie wirtualnej. W przypadku konteneryzacji, kontenery działają w obrębie jądra tego samego systemu operacyjnego. Dzięki temu zużywają znacznie mniej zasobów, są lżejsze i znacznie szybciej startują w porównaniu do maszyn wirtualnych. Oczywiście zadbano również o odpowiedni poziom izolacji nie tylko od pozostałych kontenerów, ale również od samego bazowego systemu operacyjnego. 

Zadajmy sobie zatem pytanie: kto z nas nie spotkał się w swoim zawodowym życiu z sytuacją, że aplikacja działa inaczej na środowisku testowym niż na produkcyjnym? Wynikało to zazwyczaj z konfiguracji tych środowisk, jakiś zmiennych systemowych czy zainstalowanych narzędzi dodatkowych. W przypadku kontenerów jesteśmy uwolnieni od tych wyzwań. Obraz naszej aplikacji uruchomiony na naszej stacji deweloperskiej będzie działał w takim samym zamkniętym środowisku jak na środowisku produkcyjnym.

Jest to bardzo dobre rozwiązanie lecz jak to zazwyczaj w życiu bywa, wyzwania zaczynają się dopiero napiętrzać przy dużej skali. Iloma bowiem kontenerami jesteśmy w stanie ręcznie zarządzać?

Pojawia się zatem potrzeba zaprzężenia do pracy narzędzia, które mogłoby w automatyczny sposób pomóc nam orkiestrować naszymi kontenerami. Podobnie jak w przypadku platform do konteneryzacji rynek oferuje nam tutaj kilka produktów. Najpopularniejszy z nich to platforma Kubernetes. Nie musimy się jednak ograniczać do jednego rozwiązania, albowiem istnieją również produkty bazujące na samym Kubernetesie jak np. Openshift.

Orkiestracja


Źródło: https://kubernetes.io

Kubernetes to narzędzie pierwotnie stworzone przez Google, a obecnie dostępne na zasadach open-source. Platforma ta pozwala nam na zarządzanie, skalowanie i automatyzacje wdrożeń naszej aplikacji w ramach zasobów zbudowanego klastra, a dodatkowo jeśli wykorzystamy ją w połączeniu z jednym z dostawców chmury publicznej to również możemy automatycznie skalować cały klaster kiedy zajdzie takowa potrzeba. Otwiera to przed nami zupełnie nowe możliwości.

Dodatkowo Kubernetes podobnie jak Docker oferuje nam możliwość zapisania naszych zasobów w formie plików konfiguracyjnych .yaml. Dzięki temu cała nasza infrastruktura zostaje zapisana jako kod (infrastructure as a code), co z kolei przekłada się na: 

  • pełną automatyzacje procesu
  • zwiększenie szybkości wdrożeń i uproszczenie ich
  • zmniejszenie ryzyka odtworzeń
  • proces zarządzania zmianą
  • redukcje kosztów

Warto tutaj również zauważyć że Kubernetes jest dostępny w formie aplikacji desktopowej dla środowisk Windows i MacOS pod nazwą DockerDesktop. Dzięki temu możemy lokalnie budować i testować rozproszone środowisko naszej aplikacji zanim zaczniemy płacić za infrastrukturę serwerową.

Możliwości

Zostawmy jednak slogany reklamowe i zadajmy sobie właściwe pytanie. Po co nam ta cała konteneryzacja? Jakie benefity możemy czerpać z zastosowania platformy Kubernetesa?

  • Wdrożenia bezprzerwowe

    Nasi klienci cały czas oczekują, że aplikacje będą dostępne 24/7, a poprawki i funkcjonalności będą wdrażane na produkcje nawet kilka razy dziennie. Kubernetes wychodzi naprzeciw tym wymaganiom dzięki mechanizmowi rolling update. Pozwala on nam na aktualizacje deploymentu, bez przerwy w jego działaniu, dzięki krokowemu modyfikowaniu kolejnych instancji zwanych również podami.


    Źródło: https://kubernetes.io

  • historia wdrożeń

    Czasami z takich czy innych powodów nowa aktualizacja naszej aplikacji nie działa prawidłowo. Chcielibyśmy zatem w prosty sposób ją wycofać i przywrócić środowisko do poprzedniej wersji. Kubernetes rozwiązuje także ten problem, zapisując historie wszystkich naszych wdrożeń. Przy pomocy prostej komendy rollout pozwala w dowolnej chwili cofnąć się do którejś z poprzednich wersji. Co więcej, operacja ta zostanie wykonana bezprzerwowo zgodnie z opisanym wcześniej mechanizmem rolling updates.
  • Replica set

    Każdy deployment naszej aplikacji zawiera w sobie tzw. replica set. Jest to mechanizm, który gwarantuje nam uruchomienie określonej liczby replik naszej aplikacji. Platforma cały czas monitoruje status naszego deploymentu i w przypadku gdyby jedna z replik uległa uszkodzeniu, Kubernetes automatycznie powoła nową na jej miejsce. Dla przykładu poniżej przedstawiam wdrożenie nginx-deployment, w którym oczekujemy, by cały czas uruchomione były 3 repliki.

  • daemon set

    Orkiestracją podów naszej aplikacji zajmuje się za nas Kubernetes. Domyślnie nie chcemy więc wpływać na to, na których z maszyn klastra zwanymi również nodami zostaną one umieszczone. Czasami zachodzi jednak potrzeba, aby na każdym z nodów była uruchomiona kopia jakiegoś poda. Np. dla różnego rodzaju agentów czy to do logów, service discovery czy jakiś innych technicznych potrzeb. W takiej sytuacji używamy właśnie deamon set
  • autoscaling

    Kubernetes oferuje nam możliwości horyzontalnego autoskalowania instancji naszej aplikacji. Oznacza to, że w przypadku przekroczenia wybranej metryki, czy to wysycenia CPU, czy jakieś specyficznej metryki pochodzącej z aplikacji np. liczby oczekujących zdarzeń do obsługi, Kubernetes może automatycznie powołać dodatkowe pody do naszej aplikacji. Następnie po zakończonej pracy, zredukować je, aby oszczędzać zasoby. Mechanizm ten przedstawiony jest na poniższym obrazku. Domyśla wartość replik naszej aplikacji wynosi np. 2 pody, ale z czasem „pozwalamy” platformie na autoskalowanie ich do określonej liczby np. 10 podów.


    Źródło: https://kubernetes.io

  • blue/green deployment

    Wzorzec blue/green deployment polega na stworzeniu dwóch identycznych produkcyjnych środowisk, z których pierwsze dostarcza funkcjonalność klientom, a drugie wykorzystujemy do testowana nowych wdrożeń. 


    Źródło: https://kubernetes.io


    Na początku obydwa środowiska maja tą samą wersję. Następnie na środowisku testowym (green) wgrywamy nową wersje naszej aplikacji i wykonujemy na niej testy. Gdy wszystko przebiegnie prawidłowo przepinamy service w Kubernetesie ze środowiska blue na green kierując tam ruch produkcyjny. Na koniec pozostaje nam tylko wgranie nowej wersji również na środowisku blue, aby powrócić do stanu pierwotnego i powtarzać cykl wedle potrzeb.
  • canary deployment

    Wzorzec canary deployment polega na tym, aby dostarczyć nową funkcjonalność na produkcji tylko dla wybranego grona naszych klientów. W zależności od typu potrzeb może to być określona wyspecjalizowania grupa klientów lub po prostu grupa instancji naszej aplikacji. Na pierwszym rysunku widzimy rozwiązanie wagowe z instancjami, natomiast na kolejnym z użytkownikami. W obu tych przypadkach należy zastosować router, który pozwoli na sterowaniem requestami do wybranego deploymentu.


    Źródło: https://kubernetes.io

Co dalej?

Doszliśmy do sytuacji, kiedy nasza aplikacja w architekturze mikroserwisów jest hostowana na Kubernetesie. Wydaje się, że wspięliśmy się na szczyty nowoczesnej infrastruktury jak i architektury aplikacji. Pozostaje zatem pytanie: co dalej? Jak uprościć jeszcze bardziej korzystanie z naszych zasobów? Rozwiązaniem tego problemu jest wykorzystanie service mesh. Jest to sposób kontrolowania tego jak poszczególne części naszej rozproszonej aplikacji komunikują się między sobą. Jednym z najpopularniejszych obecnie rozwiązań na rynku jest rozwiązanie open-source Istio. Działa ono na zasadzie dwóch podstawowych elementów: data planecontrol plane:

  • Data plane zarządza ruchem sieciowym pomiędzy usługami w naszym klastrze. Cały ruch jest przechwytywany i przekierowywany przy pomocy obiektów proxy które są dołączane do instancji naszych aplikacji (podów). Dodatkowo zbierane są dane telemetryczne i statystyki.
  • Control plane odpowiada za zarządzanie i bezpieczeństwo data plane. Wyróżniamy w nim:
    • Pilot – zarządza regułami sieciowymi dostarczonymi przez control plane i zmienia je w konfiguracje dla obiektów proxy. 
    • Citadel – kontroluje autentykacje i zarządzanie tożsamością pomiędzy serwisami.
    • Galley – waliduje poprawność konfiguracji określonych przez użytkownika w imieniu control plane

Reasumując, dzięki Istio możemy zastąpić kod techniczny w naszych aplikacjach rozwiązaniem infrastrukturalnym. Mowa tutaj o takich obszarach jak zarządzanie ruchem, bezpieczeństwo czy monitoring.

Podsumowanie

Myślę, że nikogo nie zaskoczę stwierdzeniem, że sposób pisania nowoczesnych aplikacji zmienia się i rozwija wraz z powstawaniem nowych technologii. Interesujący jest jednak fakt, jak wraz z rozwojem chmur publicznych rozwijają się możliwości samej infrastruktury. Ostatecznie doprowadza to do sytuacji, gdzie te same powtarzające się elementy we wszystkich naszych aplikacjach przestają być rozwiązaniem zamknięty wewnątrz naszej aplikacji. Stają się natomiast elementem infrastruktury, dzięki czemu pozbywamy się dużej ilości kodu technicznego, a nasze aplikacje są lżejsze, szybsze i mniej zasobożerne. Wszystkie te zabiegi sprawiają, że tworzenie oprogramowania staje się prostsze i przyjemniejsze co bezpośrednio przekłada się na możliwość dostarczenia naszym klientom nowych oczekiwanych rozwiązań w znacznie krótszym czasie, a to z kolei podnosi konkurencyjność i umacnia pozycje naszej firmy na rynku.