Sytuacja kobiet w IT w 2024 roku
27.04.20217 min
Studencki Festiwal Informatyczny

Studencki Festiwal Informatyczny

Nie tylko Docker - jak działają LXC, czyli Linux Containers

Poznaj LXC, albo Linux Containers, i dowiedz się jak działają, czym się charakteryzują oraz jak ich poprawnie używać.

Nie tylko Docker - jak działają LXC, czyli Linux Containers

Cześć, z tej strony Studencki Festiwal Informatyczny! Dzisiaj porozmawiamy o LXC – minimalistycznym systemie kontenerów Linux, którego używamy w naszych serwerach produkcyjnych.


Kiedy wpiszecie w wyszukiwarkę słowo „container”, prawdopodobnie pierwszym wynikiem będzie Docker. Gdzieś niżej znajdziecie zapewne Kubernetes (często również stosowany z Dockerem), kilka rozwiązań cloudowych i innych rozwiązań komercyjnych. Gdzieś na samym dole może przebije się oferta prawdziwych kontenerów transportowych lub innego transportu wielkogabarytowego, o ile w ogóle uda im się przebić przez popularność rozwiązań typu OS-level virtualization.

Jednak temat kontenerów Linux ani nie zaczyna się, ani nie kończy na Dockerze. W tym artykule zajmiemy się LXC (skrót od Linux Containers). LXC to prosty i minimalistyczny system kontenerów. Zapewnia kompletny zestaw narzędzi potrzebnych do obsługi kontenerów, jednocześnie w przeciwieństwie do Dockera, nie narzuca sposobu pracy. W działaniu jest podobny do klasycznych maszyn wirtualnych, tj. domyślnie uruchamia cały system operacyjny wewnątrz kontenera (poza rzecz jasna kernelem). LXC może odpalić nam w kontenerze dowolną instalację systemu Linux, jeśli tylko podamy mu ścieżkę do zawierającego ją katalogu/dysku. Ciekawostką jest to, że przez długi czas sam Docker bazował na LXC, zanim nie stworzono libcontainer, używając liblxc do aktywowania i zarządzania kontenerami.

Czym jest LXC?

  • Oparty na mechanizmach Namespaces i Control Groupsobecnych w standardowym jądrze systemu Linux (podobnie jak Docker).
  • Każdy kontener jest praktycznie pełnoprawnym systemem operacyjnymtak, jak normalna maszyna wirtualna (dzieli jedynie kernel z hostem).
  • Tak jak inne rozwiązania kontenerowe, w przeciwieństwie do standardowej wirtualizacji, programy pod LXC działają równie szybko jak uruchomione “natywnie”.
  • Konfiguracja opiera się na prostych plikach tekstowych,zaś do zarządzania kontenerami mamy kilka prostych komend (lxc-create, lxc-start, itd.)
  • Pozwala na bardzo szeroką integrację między hostem a kontenerem,bez problemu współdzieląc nie tylko pliki, ale i całe urządzenia, a nawet sockety (np. możemy bez problemu uruchomić aplikację w kontenerze i przekazać jej socket X11 tak, aby jej GUI wyświetlało się na ekranie hosta).
  • Zapewnia wysoki poziom bezpieczeństwa,wspierając mechanizmy takie jak Apparmor czy SELinux (jednakże nie wymaga ich do działania). Oczywiście jak każde rozwiązanie kontenerowe jest nieco mniej bezpieczny niż maszyny wirtualne, bo współdzieli kernel z hostem.
  • Polityką projektu jest pozwolić użytkownikowi na maksymalną konfigurowalność,w tym także na pozbycie się części konteneryzacji (np. współdzielenie sieci z hostem).
  • Całość jest całkowicie darmowai wydana na licencji LGPL.


Przejdźmy do praktyki. Spróbujmy stworzyć zwykły kontener LXC. Będziemy pracować pod dystrybucją Debian “buster”, lecz LXC jest dostępne pod praktycznie każdą popularną dystrybucją.

Przed całością zdobądźmy uprawnienia roota (możemy też poprzedzać wszystkie kolejne komendy poleceniem sudo)

> sudo -i


Zacznijmy od zainstalowania odpowiednich pakietów.

> apt install lxc lxc-templates


Mamy już zainstalowane LXC i możemy stworzyć nasz pierwszy prosty kontener.

> lxc-create -n nazwa-kontenera -t download


Po wykonaniu tego polecenia LXC zapyta nas jaką dystrybucję Linux chcemy zainstalować w tworzonym kontenerze. My wpisujemy kolejno debian, buster, amd64. LXC stworzył nowy kontener i zainstalował w nim wybrany przez nas system. Zobaczmy, co się tak naprawdę stało.

> cd /var/lib/lxc/nazwa-kontenera
> ls


W folderze znajdziemy dwa elementy: plik o nazwie config oraz folder rootfs. W folderze rootfs nie znajdziemy nic innego jak system plików naszego kontenera. Tak, domyślnie LXC trzyma cały system operacyjny i inne pliki naszego kontenera po prostu w jednym folderze. Oczywiście możemy wykorzystać inny sposób przechowywania (np. LVM lub ZFS), niemniej na nasze potrzeby ta opcja jest idealna. Dzięki temu będziemy mogli przenosić czy backupować wyłączony (!) kontener tak, jak inne pliki.

Drugą rzeczą jest plik config. Zawiera on konfigurację naszego kontenera. Możemy edytować go naszym ulubionym edytorem tekstu. Pełen opis plików config otrzymamy po wpisaniu polecenia:

> man lxc.container.conf


Mamy już nasz pierwszy kontener. Spróbujmy go uruchomić.

> lxc-start -n nazwa-kontenera


W tej chwili nasz kontener powinien już startować, możemy sprawdzić jego stan poleceniem:

> lxc-info -n nazwa-konera


Lub

> lxc-ls -f # wyświetli status wszystkich kontenerów


Spróbujmy teraz podłączyć się do naszego kontenera.

> lxc-attach -n nazwa-kontenera


W tym momencie powinien ukazać się nam bash lub inny shell systemu pracującego w kontenerze z uprawnieniami roota. Co możemy zrobić? Prawie wszystko, co z normalną maszyną wirtualną! (pamiętajmy tylko, że współdzielimy jeden kernel z systemem hosta, i takie rzeczy jak bezpośredni dostęp do dysku (lub innych rzeczy z /dev) się nam nie uda, o ile explicite nie pozwolimy na to w config (np. montując z opcją bind odpowiedni plik/urządzenie w kontenerze). Wychodzimy z kontenera.

> exit


Prawdopodobnie jednak (a na pewno pod debianem) nasz kontener nie będzie miał domyślnie dostępu do sieci. W config naszego kontenera znajdziemy taką linię:

lxc.net.0.type = empty


Kontener do sieci możemy podłączyć na kilka sposobów. Niestety, LXC z uwagi na swój minimalizm nie zrobi tego za nas. Dwie najbardziej popularne metody to:

  • NAT- kontenery będą używać adresu IP naszego komputera do wyjścia na świat, jednakże, aby połączyć się z nimi z zewnątrz będziemy musieli ustawić na naszym komputerze port forwarding. Jest to domyślna opcja dla np. Dockera.
  • Bridge- “spinamy” sieć kontenera z tą, do której podpięty jest nasz komputer. Kontener będzie bezpośrednio dostępny w naszej sieci LAN.


My używamy tego drugiego, jednak jeśli używacie LXC w domu, prawdopodobnie opcja NAT może być dla Was korzystniejsza. Ponieważ konfiguracja sieci jest mocno zależna od dystrybucji, której używacie, odsyłam Was do jej dokumentacji. W wielu można to zrobić nawet z GUI np, przez nm-connection-editor. Jeśli używamy też Dockera lub Libvirt, prawdopodobnie mamy już skonfigurowany NAT i po wpisaniu:

> brctl show


Pokaże nam się nazwa mostka sieciowego, który zapewni nam dostęp do internetu. Możemy też podłączyć fizyczną kartę sieciową bezpośrednio pod kontener lub skorzystać z jednego z wielu innych rozwiązań dostępnych w LXC.

Korzystając z jednej z metod, udało nam się uzyskać mostek sieciowy dający nam dostęp do internetu. Podłączmy go pod kontener. Otwieramy config naszego kontenera i wymieniamy wcześniejszą konfigurację sieci na:

lxc.net.0.type = veth
lxc.net.0.link = nazwa-mostka-sieciowego
lxc.net.0.name = eth0


Możemy też bezpośrednio ustawić adres IP kontenera w configu, dodając (oczywiście z odpowiednimi adresami):

lxc.net.0.ipv4.address = 10.20.10.120/16
lxc.net.0.ipv4.gateway = 10.20.0.1
lxc.net.0.flags = up


Następnie możemy zrestartować nasz kontener:

> lxc-stop -n nazwa-kontenera
> lxc-start -n nazwa-kontenera
> lxc-attach -n nazwa-kontenera


Teraz powinniśmy mieć już dostęp do sieci. Jeśli ustawiliśmy statyczny adres IP, pewnie będziemy musieli też zaktualizować adres serwera DNS w /etc/resolv.conf w kontenerze.

Potrafimy już tworzyć kontenery, które bez problemu zastąpią większość maszyn wirtualnych. W szczególności używając LXC możemy również przekształcić istniejącą maszynę wirtualną w kontener LXC - wystarczy, że skopiujemy jej pliki do folderu, napiszemy własny config i umieścimy wszystko w /var/lib/lxc. Nie musimy nic więcej robić, LXC sam znajdzie nowy kontener i pozwoli go nam uruchomić przez lxc-start.

Co dalej? Możemy dodatkowo zabezpieczyć nasz system tworząc kontenery typu unprivileged. Mechanizm ten pozwala zapewnić, że gdyby atakującemu udało się wydostać z kontenera LXC na zewnątrz będzie on miał zerowe uprawniania. Wystarczy, że dodamy do plików /etc/subuid/etc/subgid następującą linijkę (nasza dystrybucja mogła to zrobić za nas):

root:10000:1000000000


A do /etc/lxc/default.conf dodać:

lxc.idmap = u 0 10000 1000000000
lxc.idmap = g 0 10000 1000000000


I następny stworzony przez nas kontener będzie działać już unprivileged. Zachęcamy do tego - jest to bardzo niewielka zmiana, a znacząco podnosi bezpieczeństwo całości.

Jeśli Wasza dystrybucja używa systemu AppArmor lub SELinux możecie wykorzystać je do jeszcze lepszego zabezpieczenia kontenerów. Ubuntu robi to, na przykład, domyślnie z AppArmor, co może powodować pewne problemy z niektórymi aplikacjami w kontenerze. Oczywiście w takim przypadku najlepiej jest poprawić ustawienia AppArmor. W ostateczności możemy też dopisać do config

lxc.apparmor.profile = unconfined


co wyłączy apparmor w kontenerze.

Możliwości LXC są zdecydowanie większe, niż opisano to w tym artykule. Potrafi ono też działać na zasadzie podobnej jak docker - konteneryzować pojedyncze procesy (lxc-execute), tworzyć kontenery efemeryczne (usuwane/czyszczone do stanu startowego po każdym uruchomieniu) czy być dostępnym dla zwykłego użytkownika (a nie root, jak robiliśmy to w tym tutorialu).

LXC nie ogranicza się do przedstawionych narzędzi. Sami jego twórcy napisali wysokopoziomową nakładkę o nazwie LXD. Pozwala ona na zautomatyzowane zarządzanie wieloma kontenerami, włączając w to automatyczne migracje między maszynami czy obsługę sieci. Wartym uwagi jest również Proxmox Virtual Environment - zmodyfikowana dystrybucja Linux specjalnie do celów wirtualizacji. Obsługuje ona zarówno standardowe maszyny wirtualne (QEMU/KVM) jak i kontenery LXC, pozowalając na ich łatwe zarządzanie z poziomu przeglądarki. My jednak póki co trzymamy się “czystego” LXC, całkowicie wystarcza do naszych potrzeb.


Po więcej informacji na temat LXC odsyłam Was do strony https://linuxcontainers.org/ oraz jak zawsze niezastąpionego ArchWiki https://wiki.archlinux.org/index.php/Linux_Containers.

<p>Loading...</p>