Przejdź do głównej zawartości

Docker - początek

Po wcześniejszym wprowadzeniu pora na nieco dokładniejsze spojrzenie na to czym jest Docker i co wnosi. W tym miejscu pojęcie kontener nie powinno być już tajemnicą i ogólne pojęcie o samej technologii również powinno być znane. Jeżeli tak nie jest lepiej zacząć od poprzedniego wpisu. 

Na początek może ustalimy sobie czym Docker nie jest. Otóż nie należy mylić tego rozwiązania z terminem maszyny wirtualnej. Maszyny wirtualne zawierają w sobie cały system operacyjny będący odrębną częścią , osobnym tworem niezależnym bezpośrednio od głównego systemu operacyjnego na jakim działa dany wirtualizator. W przypadku Docker'a zarówno system operacyjny jak i kontenery korzystają z tego samego jądra dzięki czemu nie zużywają tyle zasobów co maszyny wirtualne ale muszą być oparte na tym samym systemie operacyjnym. Docker nie jest również platformą chmurową choć wykazuję wiele podobieństw do takich rozwiązań jak OpenStack, CloudStack itp. W obu przypadkach chodzi o umożliwienie horyzontalnego skalowania aplikacji względem potrzeb ale Docker odpowiada jedynie za wdrożenie, uruchomienie i zarządzanie kontenerami na istniejących hostach na jakich został zainstalowany. Nie daje możliwości tworzenia nowych instancji, nowych systemów tak jak ma to miejsce w przypadku platform chmurowych. Pliki konfiguracyjne Dockera umożliwiają opisanie wyglądu danego kontenera przy kompilacji. Fakt ten może wskazywać na podobieństwo do narzędzi zarządzającymi konfiguracją takich jak Puppet, Chef i im podobne jednak w ciągu dalszego życia kontenera lepiej jednak użyć rozwiązań do tego przeznaczonych. Docker nie ma sam w sobie żadnego rozwiązania klastrowego. W celu koordynacji większych grup systemów z Dockerem powinno się zastosować dodatkowe narzędzia np.: Swarm, które umożliwią monitorowanie stanu wszystkich systemów i ich zasobów. 

Proces wdrożenia aplikacji.

W jaki sposób wygląda proces wdrożenia aplikacji ? Poniżej uproszczona lista kroków. 
  1. Dział tworzący aplikacje określa zasoby jakie wymagane są do jej uruchomienia i wnioskuje o nie do działu utrzymania.
  2. Zasoby są dostarczane programistom
  3. Instalowane są wszelkie niezbędne komponenty wymagane do działania aplikacji
  4. Osadzenie aplikacji na środowisku
  5. Testowanie i wdrażanie poprawek 
  6. Programiści odkrywają kolejne zależności wymagane dla aplikacji 
  7. Utrzymanie instaluje potrzebne dodatkowe zasoby
  8. Kroki 5,6,7 są powtarzane do osiągnięcia oczekiwanych rezultatów
  9. Wdrożenie aplikacji zostaje zakończone. 
Powyższy proces może zająć dużo czasu, co nie jest ani produktywne ani opłacalne. Twórcy oprogramowania chcąc skrócić czas potrzebny na wdrożenie np. w kroku w jakim zlecają do utrzymania doinstalowywanie kolejnych komponentów mogą pokusić się o zaszycie ich już wewnątrz samej aplikacji we własnym zakresie, by ominąć ten krok. 

Tutaj swoje zastosowanie i siłę pokazują takie narzędzia jak heroku, które często porównywane jest do standardowych metod wdrożeniowych jako bardziej efektywne.

Docker nie jest heroku ale umożliwia osiągnięcie podobnych rezultatów. Do tego stosuje troszkę inne bardziej otwarte podejście oferując swoje rozwiązania w raz z wszystkimi potrzebnymi elementami umożliwiając jednocześnie ich wymianę na inne. Punktem wyjścia jest wykorzystanie repozytorium obrazów separując tym samym odpowiedzialność za kompilacje od wdrożenia i utrzymania. 

Zakładając powyższe proces wdrożenia może wyglądać następująco: 
  1. Kompilacja obrazu 
  2. Umieszczenie obrazu w repozytorium
  3. Przekazanie informacji do działu utrzymania + konfiguracja 
  4. Wdrożenie 
  5. Wdrożona aplikacja
Pominięte zostają tu kwestie pojawiających się w trakcie standardowego wdrożenia zależności, które mogą zostać rozwiązane już w czasie programowania i testowania. Komunikacja pomiędzy działami programowania i utrzymania też jest zdecydowanie krótsza. 

Powyższe daje już wyobrażenie o korzyściach z wykorzystania tego rozwiązania. Do tego zaobserwować można też duże wsparcie dla tego projektu przez dużych graczy rynku IT. Projekt z biegiem czasu jest stale rozwijany i ulepszany. Od czerwca 2015 r. można również mówić o standaryzacji tego typu rozwiązań za sprawą The Open Container Initiative

Architektura 

Docker oferuje duże możliwości i ma zastosowanie w skomplikowanych rozwiązaniach. Sam w sobie nie jest już taki straszny i stanowi klasyczny model architektury klient - serwer. Posiada pojedynczy moduł wykonywalny obsługujący oba komponenty różnice stanowi parametr z jakim zostanie uruchomiony. 

Podczas pracy docker wykorzystuje istniejące mechanizmy jądra takie jak : 
  1. iptables 
  2. virtual bridge
  3. cgroups
  4. name spaces 
Docker klient przekazuje do docker demona zadania do wykonania i mogą to być takie operacje jak utworzenie, uruchomienie czy rozdystrybuowanie kontenera. Zarówno klient jak i serwer mogą działać na tym samym systemie lub też serwer może istnieć na osobnej maszynie. Opcjonalnie pojawia się również trzeci komponent tak zwany rejestr

Rejestr ma za zadanie przechowywać obrazy wraz z opisującymi je metadanymi. Komunikacja rozpoczyna się od klienta następnie serwery dockera mogą kierować się do rejestrów z obrazami jeżeli jest taka potrzeba. 

Docker architektura (źródło: https://docs.docker.com/engine/understanding-docker/)
Instalując Dockera otrzymujemy oba komponenty klient-serwer w postaci jednego modułu ale serwer można uruchomić jedynie w systemie Linux. Uruchomienie serwera-demona wymaga jedynie wywołania z parametrem -d. Wywołanie takie oznacza, iż program zostaje uruchomiony jako demon o nasłuchuje w oczekiwaniu nadchodzących połączeń. 

Porty sieciowe. 

Port jaki został zarejestrowany w IANA dla narzędzia Docker to 2375 TCP  do komunikacji nieszyfrowanej oraz 2376 do obsługi komunikacji szyfrowanej. 

Dodatkowe narzędzia stosowane z Dockerem



Docker Compose

Narzędzie do uruchamiania aplikacji wielo-kontenerowych. Umożliwia utworzenie pliku kompozycji (compose file) konfigurując tym samym wszystkie potrzebne serwisy jakie mają zostać uruchomione przy użyciu jednego polecenia. Dokumentacja.

Docker Machine 

Narzędzie umożliwiające zainstalowanie silnika Docker na lokalnym hoście Windows i przy jego pomocy wydawanie poleceń i obsługę istniejących w infrastrukturze hostów z zainstalowanym Dockerem. Używając poleceń docker-machine można uruchomić, sprawdzić, zatrzymać i zrestartować hosty zarządzane, podnieść wersję serwera i klienta dockera oraz wykonać zmiany konfiguracji.  Dokumentacja

Docker Swarm.

Rozwiązanie stanowiące natywny klaster dla Dockera. Umożliwia wykorzystanie puli hostów z Dockera z jednego macierzystego hosta. Ponieważ Swarm komunikuje się ze światem tym samym API co Docker możliwe jest wykorzystanie każdego narzędzia które już komunikuje się z Dockerem do korzystania z możliwości Swarm. Dokumentacja.

Klient Dockera

Najważniejszy interfejs jaki spotkamy w Docker jest klientem tekstowym napisanym w języku GO. Zadania jakie możemy wykonać za jego pomocą to : 
  • Utworzenie obrazów kontenera
  • Pobranie obrazu kontenera z istniejącego rejestru obrazów 
  • Umieszczenie utworzonych obrazów w rejestrze obrazów
  • Uruchomienie kontenera na serwerze Docekra 
  • Pobranie logów zdalnego serwera 
  • Uruchomienie wiersza poleceń wewnątrz kontenera na zdalnym serwerze

Poza komunikacją z klienta tekstowego możliwe jest również wykorzystanie interfejsu API. 
Dokumentacja APIhttps://docs.docker.com/engine/api/

Sieć

Pomimo, że procesy kontenerowe umieszczone są w samym systemie hosta ich zachowanie jest nieco odmienne niż standardowych procesów w warstwie sieci. Jako odniesienie można tu zastosować porównanie kontenerów jak pojedynczych komputerów w prywatnej sieci lokalnej. Serwer Dokera działa jako wirtualny most sieciowy, kontenery natomiast stanowią klientów połączonych za jego pomocą. Można powiedzieć, że jest to taka małą wewnętrzna sieć z podłączonymi hostami.

Każdy kontener posiada swój własny interfejs sieciowy, który jest połączony do mostka sieciowego Dockera, a następnie porty serwera łączone są z portami kontenera, co umożliwia widoczność kontenera na zewnątrz. Ruch kierowany do kontenera przechodzi przez mechanizm proxy istniejący w serwerze Dockera. Do działania wykorzystywany jest wolny blok podsieci prywatnej przypisywany do własnej sieci wirtualnej Dockera połaczony mostem z siecią lokalną używając do tego celu interfejsu docker0. Takie rozwiązanie gwarantuje również komunikacje pomiędzy kontenerami. Wyjście na zewnątrz realizowane jest przez wirtualny interfejs wirtualnego mostu docker0. 

Szczegółowa dokumentacja sieci w Docker jest dostępna pod adresem:
https://docs.docker.com/engine/userguide/networking/


Gdzie zastosować rozwiązanie Docker ?

Technologia kontenerowa oferowana przez Dockera sprawdzi się zapewne w wielu miejscach. Są jednak takie miejsca gdzie pasuje bardziej, a do innych mniej. Warto zrozumieć w jaki sposób w pełni wykorzystać dane narzędzie i zdawać sobie sprawę do czego nie będzie się nadawało.

Zastosowana architektura tego rozwiązania znakomicie sprawdzi się dla aplikacji bezstanowych lub takich gdzie dane na temat stanu trzymane są w wewnętrznych magazynach danych np.: pamięć podręczna lub baza danych. W takich przypadkach Docker wymusza niejako używanie tak zwanych dobrych praktyk programistycznych. Różnica pomiędzy aplikacjami stanowymi i bezstanowymi polega na tym, iż te stanowe przechowują istotne dane w pamięci , bazie danych. plikach płaskich i narażone są na ich utratę w momencie restartu usługi jeżeli wcześniej nie zostały trwale zapisane. Istota bezstanowych aplikacji jest taka, iż stworzone są po to by szybko reagować na pojedyncze zapytania do klientów bez przechowywania jakichkolwiek danych.

Ogólne wyobrażenie o Docker. 

Wykorzystując analogię do innych rozwiązań w przypadku Dockera należy myśleć w taki sposób jak o odrębnej przestrzeni do przechowywania pojedynczych procesów systemu Unix. Proces taki potrafi również wywołać inne procesy, a całość zamknięta jest jak gdyby w jednym odrębnym opakowaniu. Można uznać, że przypomina to maszyny wirtualne jednak kontenery mogą zostać zdecydowanie łatwiej utworzone i usunięte. Kontener w porównaniu do maszyn wirtualnych potrzebuje bardzo mało zasobów. Istnieją przykłady w jakich kontener zbudowany z istniejącego obrazu na dysku zajmuje jedynie 12 kilobajtów. Dzieje się tak dlatego ponieważ kontener w tym wypadku zawiera jedynie wskaźnik do warstwy systemu plików i metadanych  zawierających informacje o konfiguracji. Powyższe sprowadza się do tego, że prawdopodobnie nie użyto by nowej maszyny wirtualnej jedynie po to by wykonać pojedyncze zapytanie sql lub curl ale kontener nadaje się już do tego doskonale.

Choć ogólnie uważa się, że kontenery są niezależnymi odizolowanymi od siebie bytami to tak naprawdę jest to bardziej ograniczone niż można by się spodziewać. Istnieje możliwość ograniczania ich zasobów to przy zastosowaniu konfiguracji podstawowej kontenery zachowają się tak samo jak każdy proces środowiska Unix współdzieląc i rywalizując o dostępne zasoby hosta na jakim się znajdują. Dobrze jest wcześniej przewidzieć czy wiele kontenerów będzie dzieliło jedną warstwę systemu plików. Chodzi o fakt, że jeżeli dojdzie do aktualizacji obrazu jaki jest współdzielony trzeba będzie wówczas odtworzyć wiele kontenerów.

Procesy działające w kontenerach istnieją również na samym serwerze Dockera ponieważ wykorzystują to samo jądro Linuxa. Można je również zobaczyć na systemie operacyjnym hosta na jakim działa Docker używając polecenia - ps. Jest to widoczna różnica pomiędzy rozwiązaniem Docker a znanym z wirtualizacji hipernadzorcy  gdzie izolacja procesów wynika z uruchomienia ich w zupełnie odrębnym systemie operacyjnym maszyny wirtualnej.

Bezpieczeństwo
  
Domyślna konfiguracja kontenerów jest tak ustawiona, że wiele z nich do uruchamiania procesów używa UID 0, co nie budzi zastrzeżeń szczególnie, że o kontenerze mówimy jako o zamkniętym osobnym tworze. Ponieważ do działania wykorzystywane jest to samo jądra Linuxa najprostsze nawet błędy konfiguracyjne mogą umożliwić użytkownikowi  root kontenera do uzyskania dostępu do zasobów systemowych i procesów hosta na jakim kontener się znajduje.

Wcześniej pisałem, że docker najlepiej działa z aplikacjami bezstanowymi. Co jednak jeżeli taki stan musi być zapisany i przekazany ? Można w tym celu wykorzystać zmienne środowiskowe przechowywane w metadanych opisujących konfiguracje kontenera. Daje to możliwość przekazania do kontenera tej samej konfiguracji przy każdym jego restarcie. 



Komentarze

Najczęściej czytane w tym miesiącu

50 popularnych pytań dotyczących systemu Linux zadawanych na rozmowach kwalifikacyjnych. (Pytania & Odpowiedzi)

Generowanie testowych plików o określonej wielkości