Dlaczego warto wykorzystywać kontenery:
W przypadku wykorzystania ich na klastrze główną zaletą jest fakt, że można postawić dowolne środowisko, które jest potrzebne. Oznacza to, że nie jest się zależnym od konfiguracji stworzonej na klastrze. Można więc wykorzystać dowolny system oraz narzędzia jakie mogą być potrzebne.
Jest to alternatywa dla użycia modułów na klastrze, która pozwala na wykorzystanie dowolnego oprogramowania, a nie tylko przygotowanych modułów. Więcej informacji o modułach znajduje się tutaj.
Apptainer uruchamia kontenery z plików obrazu SIF.
Aby uzyskać ten plik mamy głównie dwie możliwości:
Apptainer umożliwia pobranie obrazu z źródeł takich jak:
Aby pobrać dany obraz kontenera można użyć komendy:
apptainer pull [opcje] [plik docelowy] <URI>
W powyższej komendzie, jeśli nie zostanie podana nazwa pliku docelowego zostanie ona nadana automatycznie.
W przypadku pobierania jakiegokolwiek obrazu kompatybilnego z OCI zostanie on automatycznie przekonwertowany do pliku SIF.
Przykład użycia komendy:
apptainer pull docker://alpine
apptainer pull alpine.sif docker://alpine
Ważna informacja!
Przy pracy na klastrze bem2 dokonując pobierania i konwersji obrazu zalecanym jest wykonanie tych operacji przy użyciu pamięci RAM, ponieważ standardowa pamięć jest podłączona sieciowo co znacznie wydłuża czas wykonania tych operacji.
Powyższe zalecenie można wykonać dodając poniższe zmienne środowiskowe dla komendyapptainer pull
:
APPTAINER_TMPDIR=/dev/shm/$SLURM_TASK_PID APPTAINER_CACHEDIR=/dev/shm/$SLURM_TASK_PID apptainer pull [opcje] [plik docelowy] <URI>
Więcej informacji na stornie projektu Apptainer.
Drugą możliwością jest stworzenie własnego pliku definicji. W celu dokładniejszego zrozumienia jak należy tworzyć takie pliki można przeczytać dokumentację na stronie projektu Apptainer oraz informacje na temat budowania obrazów.
Można także skorzystać z możliwości konwersji pliku Dockerfile do definicji pliku Apptainer przy użyciu spython.
Następnie mając już plik definicji można go przekonwertować do obrazu kontenera za pomocą polecenia:
apptainer build [opcje] <plik docelowy> <specyfikacja build>
Przykład użycia:
apptainer build alpine.sif alpine.def
Gdzie alpine.def jest plikiem definicji.
Budowę kontenera należy wykonać w własnym środowisku, a dopiero następnie przesłać gotowy plik SIF (np. przy pomocy scp) lub umieścić obraz w repozytorium z którego będzie można go pobrać.
Możliwym jest wykorzystanie obrazu apptainer w docker, aby nie instalować oprogramowania apptainer w środowisku w którym znajduje się już docker. Przykładowy obraz który można wykorzystać https://github.com/kaczmarj/apptainer-in-docker.
Na klastrze ze względów bezpieczeństwa użytkownicy nie mają dostępu do podniesienia uprawnień, należy więc pamiętać, aby budując kontener stworzyć go w taki sposób, aby można było go wykorzystywać z poziomem uprawnień użytkownika.
--sandbox
Istnieje też możliwość stworzenia kontenera w katalogu z możliwością zapisu, można wykorzystać do tego opcje --sandbox
, która tworzy kontener w folderze zamiast w pliku SIF. Aby dokonać trwałych zmian w kontenerze sandbox należy użyć flagi --writable
przy wywołaniu kontenera. Po wprowadzeniu zmian można przekonwertować kontener sandbox do pliku SIF przy pomocy polecenia apptainer build
.
Więcej informacji na stornie projektu Apptainer.
W celu uruchomienia obrazu można użyć komend:
apptainer shell [opcje] <kontener>
apptainer exec [opcje] <kontener> <komenda>
Pierwsza z komend pozwala na otwarcie interaktywnej linii komend w kontenerze.
Druga z komend pozwala na wykonanie komendy w kontenerze, co jest przydatne przy uruchamianiu zadań wsadowych.
Więcej informacji na stornie projektu Apptainer.
Apptainer automatycznie wiąże (ang. bind) poniższe ścieżki:
$HOME
/sys:/sys
/proc:/proc
/tmp:/tmp
/var/tmp:/var/tmp
/etc/resolv.conf:/etc/resolv.conf
/etc/passwd:/etc/passwd
$PWD
Wynika z tego, że domyślnie pełen dostęp do plików w katalogu domowym w kontenerze jest zapewniony (chyba że została zmieniona konfiguracja apptainer.conf), umożliwiając użycie ścieżek względnych lub bezwzględnych. Ścieżka bezwzględna to /home/$USER, a ścieżki względne odwołują się do aktualnego katalogu roboczego.
Plik apptainer.conf
zawiera między innymi konfiguracje, które ścieżki zostaną automatycznie powiązane. Plik ten powinien należeć do użytkownika root. Oznacza to, że tylko osoby z odpowiednimi uprawnieniami mogą go edytować (administratorzy).
Aby sprawdzić jaka jest aktualna konfiguracja można użyć komendy:
cat /etc/apptainer/apptainer.conf
Warto pamiętać, że można to zrobić tylko po zarezerwowaniu zasobów i będąc w trybie pracy na klastrze.
Linie, które wskazują jakie ścieżki zostaną powiązane wyglądają w następujący sposób:
mount <mount> == yes
Aby nie pozwolić wykonać się wiązania skonfigurowanym przez administratorów w pliku apptainner.conf należy użyć flagi:
--no-mount <mount>
Wyjątkiem jest wiązanie katalogu home. Aby ten katalog nie został powiązany istnieją specjalne flagi opisane poniżej.
$HOME
Aby nie wiązać katalogu domowego mamy głównie dwie możliwości:
--no-home
Powoduje ona, że zostaje powiązany aktualny katalog roboczy, bez wiązania katalogu domowego. Jednakże jeśli aktualnym katalogiem roboczym jest katalog domowy to zostanie on powiązany.
--containall
Powoduje ona, że $HOME
nie jest montowany, a zamiast tego tworzony jest pozorny montaż wiążący na punkcie $HOME
. Jeśli więc pliki znajdują się w obrazie pod ścieżką /home/$USER
, flaga --containall
ukryje je wszystkie.
--bind
Aby przywiązać dodatkowe ścieżki można użyć opcji --bind przy uruchomianiu kontenera.
--bind <ścieżka_host:ścieżka_kontener>
Gdzie fragment przed :
opisuje katalog źródłowy hosta, natomiast ścieżka za znakiem ": opisuje docelowy punkt montażu w kontenerze. W przypadku nie podania znaku :
i ścieżki za znakiem ścieżka zostanie przypisana do takiej samej ścieżki w kontenerze. Flaga --bind
pozwala na montowanie kilku ścieżek na raz poprzez rozdzielenie ich znakiem,
.
Przykład użycia:
apptainer shell --bind /opt,/data:/mnt moj_kontener.sif
# lub
apptainer exec --bind /data:/mnt moj_kontener.sif ls /mnt
Można to samo osiągnąć ustawiając odpowiednią zmienną środowiskową
# export APPTAINER_BIND=<"ścieżka_host:ścieżka_kontener">
export APPTAINER_BIND="/data:/mnt"
--mount
Jest to bardziej rozbudowana opcja pozwalająca na zarządzanie montowaniem ścieżek, jednakże ta opcja też obsługuje jedynie montowanie ścieżek poprzez wiązania.
--mount type=bind,src=<source>,dst=<dest>
Niektórymi z funkcjonalności są:
(Znak \\
na końcu linii oznacza kontynuacje komendy w następnej linii)
--mount
w jednym poleceniu.apptainer shell --mount type=bind,src=/opt,dst=/opt \
--mount type=bind,src=/data,dst=/data \
moj_kontener.sif
$ apptainer exec \
--mount type=bind,source=/data,dest=/mnt,ro \
moj_kontener.sif touch /mnt/test
--bind
nie umie obsłużyć (np. :
).$ apptainer run \
--mount type=bind,src=/my:path,dst=/mnt \
moj_kontener.sif
Aby dodać ścieżki $SCRATCH
i $TMPDIR
należy użyć poniższych flag:
--mount type=bind,src=$SCRATCH,dst=$SCRATCH --mount type=bind,src=$TMPDIR,dst=$TMPDIR
Przykład użycia:
apptainer shell --mount type=bind,src=$SCRATCH,dst=$SCRATCH --mount type=bind,src=$TMPDIR,dst=$TMPDIR moj_kontener.sif
Dodanie tych ścieżek pozwala na korzystanie z zasobów lustre przy wykorzystaniu tych zmiennych wewnątrz kontenera.
Dokładniejsze informacje na temat montowania ścieżek znajdują się na stronie projektu Apptainer.
Opcja ta działa tylko w opcji “root-mapped user namespace” ze względów bezpieczeństwa, więc spora część opcji wykorzystujących tą flagę jest niedostępna.
Dokładniejsze wyjaśnienie znajduje się na stronie projektu Apptainer.
Jest to dodatkowa opcja pozwalająca na tworzenie "trwałych nakładek"(ang. persistent overlays) czyli nałożenie katalogu lub zapisywalnego systemu plików na niemodyfikowalny kontener tylko do odczytu, co daje iluzję dostępu do zapisu. Ze względu na wyłączoną obsługę flagi --fakeroot
opcja ta jest bardzo ograniczona.
Aby użyć opcji trwałych nakładek należy utworzyć katalog.
mkdir moj_overlay
A następnie użyć flagi --overlay
apptainer run --overlay moj_overlay moj_kontener.sif
Dokładniejsze instrukcja jak należy tworzyć nakładki znajduje się na stronie projektu Apptainer.
Aby skorzystać z kart graficznych przy użyciu Apptaninera należy użyć flagę --nv
. Instrukcja na temat uzyskania dostępu do kart graficznych znajduje się w dokumentacji na man.e-science.pl w informacjach o alokacji zasobów GPU oraz w instrukcji o węzłach z GPU na klastrze BEM2
Ściśle mówiąc, nie można dodawać pakietów do istniejącego kontenera, ponieważ nie jest on edytowalny.
Można jednak spróbować zainstalować brakujące pakiety lokalnie przy pomocy python-pip:
module load apptainer
apptainer exec <container.sif> python -m pip install --user <package>
Należy zamienić <container.sif>
na nazwę pliku kontenera oraz zamienić <package>
nazwą paczki. Żądany pakiet Python zostanie zainstalowany w katalogu domowym pod ~/.local/lib/pythonX.Y
gdzie X.Y
to wersja Python w kontenerze.
Jeśli instalacja pakietu skutkuje plikiem binarnym to najczęściej zostanie on dodany do ~/.local/bin
. Proszę pamiętać o dodaniu tej ścieżki do PATH
:
export PATH=~/.local/bin:$PATH
Po tych krokach powinna być możliwość wykorzystania nowej biblioteki/programu w kontenerze, ponieważ katalog domowy w całości jest montowany do kontenera podczas jego uruchomienia.
Instalacja może nie powieść się w bardziej skomplikowanych scenariuszach, gdzie wymagane są dodatkowe biblioteki. Jako pierwszy krok załaduj odpowiednie moduły (np. jeśli widzisz „GLIBC not found”, załaduj gcc) i spróbuj ponownie.
Zawsze możesz zwrócić się do nas o pomoc (helpdesk@e-science.pl). Aby przyspieszyć proces, poinformuj nas, co już próbowałeś/aś zrobić, i dołącz wszelkie komunikaty o błędach, które napotkałeś/aś.
Zakładając, że naszym aktualnym katalogiem roboczym /home/$USER
,można wykonać to w następujący sposób:
Należy uruchomić zadanie interaktywne:
srun -c 2 -N 1 --mem=4gb --time=00:30:00 --pty /bin/bash
Dokładne informacje na temat alokacji zasobów znajdują się tutaj.
Następnie należy wydac polecenie:
APPTAINER_TMPDIR=/dev/shm/$SLURM_TASK_PID APPTAINER_CACHEDIR=/dev/shm/$SLURM_TASK_PID apptainer pull docker://alpine
Jeżeli ilość pamięci będzie nie wystarczająca proces zostanie zabity (Komunikat
Killed
). Wykorzystując, więc inne obrazy należy przydzielić odpowiednią ilość pamięci.
Zostanie stworzony plik alpine_latest.sif
.
Aby uruchomić linie komend w kontenerze można użyć komendy:
apptainer shell alpine_latest.sif
W celu alokacji zasobów GPU, użytkownik musi posiadać nadane odpowiednie prawa dostępu. Aby je uzyskać należy napisać e-mail na adres kdm@wcss.pl.
Zakładając, że naszym aktualnym katalogiem roboczym /home/$USER
, aby wykonać zadanie wsadowe powinno się podjąć następujące kroki:
Tworzymy skrypt o nazwie create_sif.sh
.
#!/bin/bash
#SBATCH -N1 # liczba węzłów
#SBATCH -c3 # ilość rdzeni
#SBATCH --mem=40gb #ilość pamięci RAM
#SBATCH --time=00:30:00 # czas w formacie hh:mm:ss
#SBATCH --job-name=apptainer-hashcat-sif-test #nazwa
APPTAINER_TMPDIR=/dev/shm/$SLURM_TASK_PID APPTAINER_CACHEDIR=/dev/shm/$SLURM_TASK_PID apptainer pull docker://dizcza/docker-hashcat:latest
Następnie należy uruchomić zadanie wsadowe poleceniem:
sbatch create_sif.sh
Po wykonaniu zadania w katalogu domowym powinien pojawić się plik o nazwie "docker-hashcat_latest.sif".
W tym przykładzie jest to plik zawierający hash nazwany hash.txt oraz plik slownik.txt zawierający potencjalne hasła.
Można je stworzyć poleceniami:
touch hash.txt
touch slownik.txt
Następnie należy edytować pliki dowolnym edytorem (np. nano) i umieścić w nich przykładową zawartość:
b6b0d451bbf6fed658659a9e7e5598fe
rockyou
help
funforyou
Należy stworzyć skrypt o nazwie hashtest.sh
.
#!/bin/bash
#SBATCH -N1 # liczba węzłów
#SBATCH -c2 # ilość rdzeni
#SBATCH --mem=4gb # ilość pamięci RAM
#SBATCH --time=00:05:00 # czas w formacie hh:mm:ss
#SBATCH --job-name=alpine-test #nazwa
#SBATCH -p tesla # partycja
#SBATCH -q student-gpu # qos
#SBATCH -A student-gpu # account
#SBATCH --gres=gpu:tesla:1 #gpu:${nazwa_zasobu}:${ilość}
apptainer exec --nv docker-hashcat_latest.sif hashcat -m 0 hash.txt slownik.txt
Parametry w powyższym skrypcie służą jedynie jako przykłady. Użytkownik powinien dostosować parametry do swoich indywidualnych potrzeb.
Dokładne informacje na temat alokacji zasobów znajdują się tutaj.
Dokładne informacje na temat alokacji GPU znajdują się tutaj.
Następnie, aby uruchomić zadanie wsadowe należy wydać polecenie:
sbatch hashtest.sh