LXC, czy Docker? Co będzie lepsze? Jeden projekt, gdzie powiedzmy że jestem uczestnikiem (a bardziej bieda-testerem) miał pewien niezrozumiały dla mnie wybór technologii. Z tego względu chciałem porównać dwa popularne rozwiązania.
LXC, Docker, czyli konteneryzacja – co to jest?
Zacznijmy jednak od początku i od teorii. Czym są kontenery? To pojemniki, gdzie ludzie z Chin wrzucają towar. Potem te kontenery wrzucają na statek i dopływa do portu w innym kraju.
No dobra, trochę się zagalopowałem. Chodzi o kontenery w systemie operacyjnym. Najpierw zacznę od podstawowej wersji teorii. Jako użytkownik nie raz pewnie miałeś okazję aktualizować swój system operacyjny, prawda? Ile razy coś nie do końca wyszło po Twojej myśli?
Nawet użytkownicy nietechniczni mieli takie sytuacje, że po aktualizacji nie wszystko działa jak powinno. To sytuacja w warunkach domowych, niegroźna, ale denerwująca.
Przenieśmy to teraz do środowiska biznesowego. Robimy aktualizację i… nasz biznes nie działa. Co teraz? No trzeba cofnąć się do poprzedniej wersji, a nową poprawić. Wymaga to czasu, gdzie mogliśmy jako przedsiębiorcy zarabiać, a póki co tracimy wiarygodność wśród klientów, a konkurencji pomagamy 🙂
Co teraz?
To jest sytuacja niepożądana, niebezpieczna i kosztowna. Mimo testów na środowisku lokalnym danego programisty albo specjalnym środowisku testowym nie wyszły problemy związane z aplikacją. Na środowisku produkcyjnym, które zarabia na pensję programistów – nie działa. Wkurzam się ja jako klient, wkurzasz się Ty jako deweloper aplikacji. Co najważniejsze – wkurza się Twój szef przypominając sobie Twoją prośbę o podwyżkę.
Ku temu powstały kontenery, by takim sytuacjom częściowo zapobiec. Każda aplikacja wymaga jakiś bibliotek lub przygotowanego środowiska. Np.: obsługa jakiś sterowników, jakiegoś szyfrowania, gdzie między wersjami może dochodzić do różnych zmian, nie zawsze pożądanych przez biznes lub nieprzewidzianych przez programistów.
Kontenery pozwalają stworzyć własne środowisko, które będzie zawsze dostosowane do potrzeb, które będzie minimalne, lekkie i szybkie. Dodatkowo nie będzie potrzeba grzebania na systemie operacyjnym, który może wymagać innych środowisk, bibliotek itp.
Ku temu powstały tzw. virtualenv – dla Python jest to właśnie venv/pipenv, Ruby, czy PHP też mają swoje odpowiedniki. Nawet Golang posiada dep, który jakoś te problemy rozwiązuje. Jednak dalej istnieje wymóg systemowy, a zmiany nałożone przez administratorów systemu mogą być zbyt wolne.
W artykule o algorytmie hashującym wspomniałem o Argon2, który wykorzystałem w jednym z projektów opartych o Django. Jednak wymogiem tej biblioteki, był również wymóg posiadania w systemie operacyjnym odpowiedniej biblioteki, której z różnych względów nie chciałem instalować. Na ratunek przyszła konteneryzacja, która zdjęła z barków systemu operacyjnego kolejną bibliotekę.
Nie chcę się dalej rozwodzić w czym pomoże konteneryzacja. Oddam Was w ręce dużo lepiej przygotowanego artykułu, który pozwoli zrozumieć ideę kontenerów (by zobaczyć, kliknij tutaj lub tutaj).
LXC i LXD – co to?
LXC jest niczym innym jak kontenerem, korzystającym z namespace jądra systemu operacyjnego (kernel Linux) oraz cgroups. Procesy są uruchamiane „w pudełku”, czyli system operacyjny „matki” kontroluje całe środowisko. Aplikacje uruchomione w kontenerze są odizolowane od systemu operacyjnego na jakim aplikacje w kontenerze działają. Pozwala to na zarządzanie koniecznymi zasobami. Przykładowo korzystanie z własnych wersji konkretnych bibliotek, które są niezależne od tych dostępnych na fizycznym (bądź wirtualnym) serwerze.
Sam LXC to nie jest narzędzie, a bardziej technologia. Narzędziem nazywamy LXD, które pozwala na wykorzystywanie kontenerów i funkcji jądra systemu operacyjnego matki. Za pomocą „template” można uruchamiać systemy operacyjne o konkretnych zasobach i opcjach, z „własnym” interfejsem sieciowym, AppArmor itp.
Dzięki temu możemy np.: uruchomić kontener CentOS, który tak naprawdę jest uruchomiony na serwerze z Ubuntu itp.
Biblioteki systemowe, czy aplikacje również są „wirtualne”, co pozwala na dużą niezależność. Jeden fizyczny serwer może uruchamiać wiele kontenerów. Przykładowa sytuacja to moment, gdy potrzebujemy odizolować bazę danych od serwera aplikacji. Posiadamy tylko jeden fizyczny serwer, a biblioteki konieczne dla bazy danych i aplikacji „gryzą” się ze sobą.
Nazwijmy to lżejszą alternatywą dla pełnej wirtualizacji jaką jest chociażby KVM.
Docker – co to?
Docker bazuje na podobnych zasadach co LXD, ale ma nieco inne podejście. Posiada własny zestaw narzędzi przeznaczonych do parawirtualizacji. Zamiast na template bazuje na „obrazach”, czyli generowanych systemach w oparciu o plik tekstowy o nazwie Dockerfile. Przeznaczenie jest również z goła inne. LXD celuje jako zastępstwo do wirtualnych maszyn, to tak Docker celuje w jednoaplikacyjny kontener, gdzie nie mamy chociażby standardowego wsparcia dla SystemD, a dane w kontenerach Dockera nie są trwałe (chociaż to można obejść).
Jaka jest różnica?
Różnice w niskopoziomowych zagadnieniach może i nie ma, jedno i drugie to kontener, jednak różni się podejściem do pewnych założeń.
Główna różnica między kontenerami LXD i Dockerem polega na tym, że Docker koncentruje się na dostarczaniu aplikacji. Od etapu tworzenia, aż po uruchomienie produkcyjne tworzonego oprogramowania.
LXD zaś koncentruje się typowo jako kontener systemowy. Właśnie dlatego LXD ma większe szanse na konkurowanie z klasycznymi hiperwizorami, takimi jak XEN i KVM, a rzadziej z Dockerem.
LXC stara się zapewnić wrażenia podobnego do maszyn wirtualnych, jednak bez wirtualizacji sprzętu (dzięki czemu jest lżejsze).
Problemy bezpieczeństwa?
Mimo wszystko nie jest to pełna wirtualizacja, która izoluje system gościa od systemu na serwerze fizycznym, więc przeciwnicy konteneryzacji wskazują duże pole do manewru do nadużyć. Głównie w zakresie bezpieczeństwa. Niezależnie czy to Docker, czy LXD.
Co to dla nas oznacza?
Docker świetnie nadaje się do dostarczenia konkretnej aplikacji. LXD celuje bardziej w zapewnienie wirtualnej maszyny. Dzięki temu można chociażby uruchamiać kontenery Dockera w kontenerze LXC, chociaż wymaga to trochę pracy. Osobiście unikam tego, ale dla chcącego nic trudnego 🙂
LXC i Docker – Gdzie lepiej skorzystać z jednego lub drugiego?
Tutaj mógłbym przekleić połowę postów na Reddit w tej tematyce, dlatego skupię się na subiektywnej opinii autora bloga.
Docker przez swoje założenia idealnie nadaje się tam, gdzie nie posiadamy zapisywania danych. Jest to w takim razie aplikacja, gdzie za każdym razem możemy kontener usunąć i uruchomić od nowa, bez utraty danych. Jest to możliwe do obejścia prostymi sposobami jak wolumeny.
Jeśli jednak uruchamiamy bazę danych – woli mieć większą pewność, że danych nie stracimy – tutaj LXD będzie lepszym moim zdaniem wyborem.
Osobiście używam obu. Docker w miejscu, gdzie potrzebuję izolowanego środowiska dla aplikacji. LXD – tam, gdzie chcę wykorzystać zalety wirtualnej maszyny, ale aż tak bardzo nie potrzebuję pełnej wirtualizacji.
Kontener Dockera sprawia, że jak go przeniosę – zadziała na każdym systemie, gdzie działa Docker. Kontener również nie powinien przechowywać danych, by zachować jego uniwersalność i mobilność.
LXC zaś nadaje się idealnie jako zastępstwo dla wirtualnej maszyny, bez problemu przechowuje dane. Podczas jej przenoszenia na inne hosty – te dane również przenosimy. W porównaniu do wirtualnej maszyny jest lżejszy, gdyż korzysta z kernela systemu gospodarza.
Krótko podsumowując – LXC zamiast wirtualki, Docker dla konkretnej aplikacji.