Instalacja i konfiguracja kontenerów LXC
Dawno temu na tej stronie zajmowałem się tematem instalacji LXD, czyli kontenerów, będących alternatywą dla maszyn wirtualnych, gdzie możemy korzystać z zalet VM-ek, ale nie potrzebujemy pełnej wirtualizacji. Po mimo tego, że mówiliśmy tam o LXD, to tak naprawdę całym mechanizmem kontenerów zajmowało się LXC - temat tego artykułu. LXD nawet nie robi tego samego co LXC, ale LXD daje nam możliwość skonfigurowania LXC i zarządania kontenerami tej technologii w bardziej przystępny sposób. Można uznać LXD za frontend dla LXC. W tym przypadku, będziemy ciąć niepotrzebne bajery i przygotujemy do pracy LXC do pracy z kontenerami nieuprzywilejowanymi - uruchamianymi z uprawnieniami zwykłego użytkownika w jego przestrzeni. Kontenery uprzywilejowane - uruchamiane z uprawnieniami superużytkownika - działają od razu po zainstalowaniu LXC w systemie.
Na nieuprzywilejowanych kontenerach nie będziemy mogli:
- Zamontować większości wykorzystywanych systemów plików.
- Tworzyć nowych węzłów urządzeń.
- Wykonać żadanej operacji po za tymi dozwolnymi dla użytkownika, którego identyfikatory zostały zmapowane do użytkownika root wewnątrz kontenera.
W momencie gdy tworzenie i zarządzanie uprzywilejowanymi kontenerami sprowadza się do poprzedzenia poleceń LXC, poleceniem sudo, to konfiguracja LXC w celu uruchamiania nieuprzywilejowanych kontenerów wymaga już nieco więcej zachodu.
Sam ten materiał powstał w oparciu o różne strony zajmujące się instalacją i konfiguracją LXC, nie mniej jednak zebrano i zweryfikowano różne rozwiązania, aby zapewnić konkretne, działające rozwiązanie. Wiele rozwiązań, prezentowanych nawet na głównej stronie projektu nie zawsze okazuje się prawidłowe dla naszego środowiska. W tym materiale skupiłem się na dystrybucji GNU/Linux Debian i to dla niej dedytkowane są poniższe rowiązania.
- Konfigurację rozpoczynamy od zainstalowania pakietu LXC z
repozytorium.
xf0r3m@lxc-host:~$ sudo apt install lxc -y
- Wiążemy użytkownika, który będzie uruchamiał kontenery z dodatkowym
UID oraz GID. Te identyfikatory natomiast będą powiązane z
użytkownikiem root wewnątrz kontenera, ale na początku system
musi wiedzieć, z którym z użytkowników je powiązać. Do tego służą pliki
/etc/subuid oraz /etc/subgid.
xf0r3m@lxc-host:~$ echo "xf0r3m:100000:65536" | sudo tee -a /etc/subuid xf0r3m:100000:65536 xf0r3m@lxc-host:~$ echo "xf0r3m:100000:65536" | sudo tee -a /etc/subgid xf0r3m:100000:65536
- Tworzymy przydział możliwych do utworzenia urządzeń sieciowych
(uruchomionych jednocześnie kontenerów) przez nieuprzywilejowanego
użytkownika. Utworzenie takiego przydziału wymaga dodanie wpisu do
pliku /etc/lxc/lxc-usernet.
xf0r3m@lxc-host:~$ echo "xf0r3m veth lxcbr0 50" | sudo tee -a /etc/lxc/lxc-usernet xf0r3m veth lxcbr0 50
Liczba 50, na końcu polecenie wskazuje ile będzie można uruchomić jednocześnie kontenerów (wpiętych do sieci). - Tworzymy katalog lxc użytkownika. Do niego kopiujemy
globalny plik konfiguracyjny LXC (/etc/lxc/default.conf) oraz
wiążemy superużytkownika kontenera z użytkownikiem systemowym za pomocą
wcześniej zdefiniowanych dodatkowych identyfikatorów UID oraz GID.
xf0r3m@lxc-host:~$ mkdir -p ~/.config/lxc xf0r3m@lxc-host:~$ cp /etc/lxc/default.conf ~/.config/lxc/default.conf xf0r3m@lxc-host:~$ echo "lxc.idmap = u 0 100000 65536" >> ~/.config/lxc/default.conf xf0r3m@lxc-host:~$ echo "lxc.idmap = g 0 100000 65536" >> ~/.config/lxc/default.conf
- LXC w celu zapewnienia odpowiedniego poziomu bezpieczeństwa
wykorzystuje AppArmor. Przynajmniej korzysta z jego profili. Wpis,
który znajduje się w pliku domyślnej konfiguracji kontenerów
nieuprzywilejowanych lub użytkownika (~/.config/lxc/default.conf),
zawiera profil, którego zwykły użytkownik nie może użyć. Dlatego też
trzeba go zmienić oraz usunąć możliwość zagnieżdzania
(w celach bezpieczeństwa).
xf0r3m@lxc-host:~$ sed -i 's/generated/unconfined/' ~/.config/lxc/default.conf xf0r3m@lxc-host:~$ sed -i '6d' ~/.config/lxc/default.conf xf0r3m@lxc-host:~$ cat -n ~/.config/lxc/default.conf 1 lxc.net.0.type = veth 2 lxc.net.0.link = lxcbr0 3 lxc.net.0.flags = up 4 5 lxc.apparmor.profile = unconfined 6 lxc.idmap = u 0 100000 65536 7 lxc.idmap = g 0 100000 65536
Jeśli będziemy wprowadzać zmiany w tym plików i mają mieć one wpływ na obecne kontenery, to... Nie będą miały. Zmiany będą miały tylko wpływ na nowe kontenery. - W najnowszych dystrybucjach Debiana, katalogi domowe mają domyślne
uprawnienia o wartości 700. Aby można było uruchamiać kontenery,
których, roofs jest ukryty gdzieś w dotdirs.
Potrzbne są co najmniej możlwości uruchomienia i takie uprawnienia
trzeba nadać inaczej kontenery się nie uruchomią.
xf0r3m@lxc-host:~$ chmod +x .
- Ostatnią czynnością, którą musmy wykonać jest dodanie ścieżki do
polecenia
apparmor_parser
do zmiennej PATH, która odpowiada z wyszukiwanie poleceń w systemie. Tą konfigurację musimy nadać na stałe więc dodamy linię do naszego pliku ~/.bashrc.echo "export PATH=${PATH}:/usr/sbin/apparmor_parser" >> ~/.bashrc;
- Jeśli już dodajemy ochoczo linię do ~/.bashrc to możemym
dodać aliasy, które umożlwią nam szybsze tworzenie, uruchamianie oraz
podłączanie się pod kontenery.
echo 'alias unpriv-lxc-create="systemd-run --user --scope -p "Delegate=yes" -- lxc-create"' >> ~/.bashrc; echo 'alias unpriv-lxc-start="systemd-run --user --scope -p "Delegate=yes" -- lxc-start"' >> ~/.bashrc; echo 'alias unpriv-lxc-attach="systemd-run --user --scope -p "Delegate=yes" -- lxc-attach"' >> ~/.bashrc;
Po wykonaniu tych czynności warto się wylogować i zalogować ponownie, chociażby po to, aby ponownie wczytać plik ~/.bashrc. Zarządzanie takimi kontenerami wygląda w następujący sposób:
- Tworzenie nowego kontenera:
xf0r3m@lxc-host:~$ unpriv-lxc-create --name c1 --template download -- --dist debian --release bookworm --arch amd64 Running scope as unit: run-r8ff0d41124ac4ec4bf8b156dedd6e443.scope Downloading the image index Downloading the rootfs Downloading the metadata The image cache is now ready Unpacking the rootfs --- You just created a Debian bookworm amd64 (20241015_05:24) container. To enable SSH, run: apt install openssh-server No default root or user password are set by LXC.
- Uruchamianie kontenera:
xf0r3m@lxc-host:~$ unpriv-lxc-start -n c1 Running scope as unit: run-r1a78035bc74149f29a9d0978c11d1f7f.scope
- Podłączanie się do kontenera:
xf0r3m@lxc-host:~$ unpriv-lxc-attach -n c1 Running scope as unit: run-rb5dd458fd5a947e69d7a5e02a00e7f16.scope root@c1:/#
- Więcej informacji o kontenerze (podsumowanie):
xf0r3m@lxc-host:~$ lxc-info -n c1 Name: c1 State: RUNNING PID: 12192 IP: 10.0.3.65 Link: veth1000_nsuN TX bytes: 1.92 KiB RX bytes: 1.99 KiB Total bytes: 3.91 KiB
- Lista utworzonych kontenerów, ze szczegółami:
xf0r3m@lxc-host:~$ lxc-ls --fancy NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED c1 RUNNING 0 - 10.0.3.65 - true
W taki o to sposób możemy skonfigurować LXC do działania bez potrzeby instalacji LXD, który był przez dłuższy czas niedostępny w dystrybucji Debian i trzeb było go instalować przez Snap. Powyższe polecenia, instalująco-konfigurujące możemy zapisać za pomocą skryptu, zapisać go, nadać uprawnienia i uruchomić.
#!/bin/bash sudo apt install lxc -y; echo "${USER}:100000:65536" | sudo tee -a /etc/subuid; echo "${USER}:100000:65536" | sudo tee -a /etc/subgid; echo "${USER} veth lxcbr0 50" | sudo tee -a /etc/lxc/lxc-usernet; mkdir -p ${HOME}/.config/lxc; cp /etc/lxc/default.conf ${HOME}/.config/lxc/default.conf; echo "lxc.idmap = u 0 100000 65536" >> ${HOME}/.config/lxc/default.conf; echo "lxc.idmap = g 0 100000 65536" >> ${HOME}/.config/lxc/default.conf; sed -i 's/generated/unconfined/' ${HOME}/.config/lxc/default.conf; sed -i '6d' ${HOME}/.config/lxc/default.conf; chmod +x ${HOME}; echo "export PATH=${PATH}:/usr/sbin/apparmor_parser" >> ${HOME}/.bashrc; echo 'alias unpriv-lxc-create="systemd-run --user --scope -p "Delegate=yes" -- lxc-create"' >> ${HOME}/.bashrc; echo 'alias unpriv-lxc-start="systemd-run --user --scope -p "Delegate=yes" -- lxc-start"' >> ${HOME}/.bashrc; echo 'alias unpriv-lxc-attach="systemd-run --user --scope -p "Delegate=yes" -- lxc-attach"' >> ${HOME}/.bashrc;
Źródła:
- Linux Containers - LXC - Getting started
- Known Debian problems with Debian package 4.0.2-1~1
- About lxd and lxc
- Docker vs LXC – czym to się różni?
~xf0r3m