singularity

From DCEwiki
Revision as of 09:12, 25 September 2019 by Keny (talk | contribs) (ROS v instanci)
Jump to: navigation, search

Singularity je nástroj pro kontejnerovou virtualizaci linuxových distribucí, napsaný v C a Go. Využívá – podobně jako naše disklessová infrastruktura – jaderný modul overlay.

Kód uveřejněný pod BSD licencí roku 2015 vytvořil tým vývojářů z Berkeley Lab pod vedením Gregory Kurtzera.

V rámci FEL ČVUT se využívá singularity v rámci disklessového linuxu na Katedře kybernetiky, ke kontejnerové virtualizaci linuxové distribuce Ubuntu, protože ta má (na rozdíl od Debianu, na kterém je diskless postaven) v distribuci předkompilované nástroje pro práci s TurtleBoty (ROS).

Jak funguje singularity

Při spuštění shellový skript singularity nejprve zavolá soubor /usr/lib/x86_64-linux-gnu/singularity/cli/shell.exec, který postupně provede následující operace:

  1. Zkontroluje jestli existují adresáře ve /var/lib/singularity.
  2. Pak, s využitím parametru offset, napíchne na loop zařízení komprimovaný datový blok ze souboru s příponou .simg (obraz disku komprimovaný přes squashfs), a toto loop zařízení následně namountuje na adresář /var/lib/singularity/mnt/container.
  3. Ten se poté použije jako podkladová vrstva do sendviče, který ji s využitím jaderného modulu overlay překryje zapisovatelnou vrstvou v RAM. Sestavený sendvič se namountuje na adresář /var/lib/singularity/mnt/final.
  4. Do něj se pak zvenčí nabindují do kontejneru vybrané soubory (passwd, localtime, aj.) – zajímavé, dosud jsem myslel, že nabindovat se dá pouze adresář.
  5. Nakonec se vytvoří přípojný bod pro domovský adresář uživatele, který se na něj namountuje.

Takto singularity připraví kontejner, do kterého lze (dokud existuje) vstupovat několika způsoby:

shell 
Použije-li se shell, tak singularity v kontejneru otevře novou konzoli, na které spustí shell. By default se spouští /bin/sh, ale tuto výchozí volbu lze přerazit, pokud se na příkazové řádce singularity předá cesta k jinému shellu parametrem --shell. V prostředí spuštěného shellu bude tato cesta uložena v proměnné SINGULARITY_SHELL.
Upozornění Pokud virtualizovaný kontejner neběží jako instance, budou – poté co konzoli opustíte všechny procesy spuštěné na pozadí ukončeny. Pokud tedy chcete v kontejneru spuštět služby, které mají běžet na pozadí, musíte použít jiný typ uživatelského přístupu (např. exec nebo run), nebo ho musíte spustit jako pojmenovanou instanci.
exec 
Přes exec lze spustit v prostředí virtualizovaného kontejneru konkrétní příkaz nebo shellový skript.
run 
Pokud se použije run, bude v prostření kontejneru spuštěn předdefinovaný skript (cesta k němu se uvede v rámci sekce %runscript ) – pokud nebude existovat, bude místo něj automaticky spuštěn shell.
test 
Volá po spuštění příkazy nakonfigurované v rámci sekce %test

Při spouštění se singularity využívá binární utilitu /usr/lib/x86_64-linux-gnu/singularity/bin/action-suid která dovoluje v rámci kontejněru realizovat operace, pro něž by jinak byla nutná rootovská práva.

Kontejner

Singularity verze 3.x podporuje – kromě kontejnerů vytvořený s využitím squashfs – také kontejnery jaké používá docker, komprimované archívy i lokální adresáře.

.simg

Kontejner, který využívá squashfs (tak jak bylo popsáno výše) je výhodný tím, že jde o kompaktní instalaci podkladové vrstvy, zabalenou do jednoho komprimovaného souboru. Jeho použití je triviální:

$ singularity shell /cesta/k/souboru.simg

Nevýhodné je, že pokud do něj chceme dostat další aplikace, musíme ho buď sestavit znova, nebo použít persistentní overlay.

Persistentní overlay

Persistentní overlay, do sendviče přidává vrstvu, jejíž obsah se po ukončení práce nezahodí. Může to být buď virtuální blokové zařízení, pro jehož vytvoření lze využít příkaz image.create[1]:

$ singularity image.create moje-data.img

…nebo adresář. Ten pak předhodíme přes parametr --overlay:

$ sudo singularity shell --overlay my-overlay.img ubuntu.simg

Tohle řešení se hodí, pokud si chce někdo doinstalovat aplikaci, která chybí v referenčním kontejneru chybí, případně potřebuje prostor pro vlastní data, s nimiž bude v kontejneru pracovat.

Poznámka Pokud byste nespustili singularity přes sudo, tak byste neměli k instalaci práva.

Nové sestavení pomocí konfiguračního souboru

Pokud chcete přidat novou aplikaci do referenčního kontejneru, musíte udělat nový build.

To lze udělat dvěma způsoby. Obvykle se nový build dělá pomocí konfiguračního souboru, tzv. "receptu" (recipe), což není nic jiného než soubor, který obsahuje několik sekcí, které se postupně zavolají během sestavení aktualizované verze kontejneru.

Výhodu je, že takhle máme podchyceno co jsme do kontejneru přidali.

Vybalení referenčního kontejneru do adresáře

Druhá možnost je vybalit referenční kontejner do lokálního adresáře, upravit, a následně z něj vytvořit aktualizovanou verzi referenčního kontejneru ve formátu .simg – pokud tedy pro vás není lepší používat rovnou tento adresář.

Konverze kontejneru do lokálního adresáře

$ singularity build --sandbox development/ production.simg
Upozornění Abyste mohli vybalený kontejner upravit, musíte do něj "vstoupit" jako uživatel root (přes sudo) s parametrem --writable
$ sudo singularity shell --writable lolcow/

Bez toho by byla překrytá základní vrtva dostupná jen pro čtení.

Sestavení nového kontejneru z aktualizovaného obsahu adresáře

$ singularity build production2 development/

Referenční kontejner

Abyste si mohli vytvořit vlastní build, musíte mít k dispozici výchozí referenční kontejner, který si pak budete upravovat.

Ten získáte buď tak, že…

  • …si odněkud stáhnete již připravený soubor s příponou .simg (lokální cesta k souboru)
  • Nebo použijete knihovnu kontejnerů (prefix library://)
  • Nebo stáhnete existující kontejner ze Singularity hub (prefix shub://)
  • Nebo zkonvertujete kontejner původně vytvořený pro Docker, tím že použijete Docker hub (prefix docker://)
  • Nebo předáte cestu k referenčnímu souboru s názvem Singularity, který získáte z repozitáře na githubu

Vlastní sestavení pak bude vypadat např. takto:

$ singularity build lokalni_kontejner.simg shub://GodloveD/lolcow
Poznámka Více o použití Singularity hub pro vytvoření výchozího buildu viz dokumentace na githubu

Instance

ROS vyžaduje, aby běžel na pozadí proces roscore. Ten sice můžete spustit přes tmux v rámci jiného okna terminálu, ale mnohem praktičtější je použití pojmenované instance, která běží na pozadí jako služba.

To můžeme realizovat následujícím způsobem

$ singularity instance start /cesta/k/image jmeno_prvni_instance

Je-li singularity kontejner spuštěn takovým způsobem, zůstane spuštěný na pozadí a přistupovat do něj můžete buď přes run, nebo exec následujícím způsobem:

$ singularity run instance://jmeno_prvni_instance

vykoná akce nakonfigurované výchozím skriptem (napž nahození roscore) a

$ singularity exec instance://jmeno_prvni_instance cat /etc/os-release

vykoná konkrétní v kontejneru konkrétní příkaz.

Pochopitelně se dá v rámci spuštěné instance otevřít i shell:

$ singularity shell instance://jmeno_prvni_instance

Spuštěných instancí stejného konktejneru může být i více – stačí je pouze jinak pojmenovat. Jaké instance jsou k dispozici si lze jednoduše vypsat:

$ singularity instance list

Suuštěnou instanci lze ukončit příkazem

$ singularity instance stop jmeno_prvni_instance
Poznámka Je-li spuštěních instancí více než jedna, můžeme použít místo jména instance parametr --all (resp. -a)

ROS v instanci

~$ singularity instance start /opt/ros jmeno_instance
INFO:   instance started successfully
~$ singularity exec instance://jmeno_instance bash -c ". /opt/ros/kinetic/setup.bash && roscore &"
~$ ... logging to /home/guest/.ros/log/2931b87c-df69-11e9-8bf6-bebebf000000/roslaunch-turtle00-45.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.

started roslaunch server http://turtle00:37091/
ros_comm version 1.12.14


SUMMARY
========

PARAMETERS
 * /rosdistro: kinetic
 * /rosversion: 1.12.14

NODES

auto-starting new master
process[master]: started with pid [55]
ROS_MASTER_URI=http://turtle00:11311/

setting /run_id to 2931b87c-df69-11e9-8bf6-bebebf000000
process[rosout-1]: started with pid [68]
started core service [/rosout]

Pokud vynecháte první krok (spuštění instance), tak se objeví následující chybová hláška:

FATAL:   no instance found with name jmeno_instance

O tom zda-li je instance spuštěná se můžete hravě přesvědčit:

~$ singularity instance list
INSTANCE NAME    PID      IMAGE
jmeno_instance   1779     /opt/ros

A nyní můžeme spustit aplikaci rviz:

~$ singularity exec instance://jmeno_instance bash -c ". /opt/ros/kinetic/setup.bash && rviz"
[ INFO] [1569397554.085427290]: rviz version 1.12.17
[ INFO] [1569397554.085610896]: compiled against Qt version 5.5.1
[ INFO] [1569397554.085727050]: compiled against OGRE version 1.9.0 (Ghadamon)
[ INFO] [1569397554.943925337]: Stereo is NOT SUPPORTED
[ INFO] [1569397554.944388205]: OpenGl version: 3 (GLSL 1.3).

Chcete-li místo spuštění aplikace rviz vstoupit na příkazovou řádku spuštěné instance, použijte:

~$ singularity shell instance://jmeno_instance

Ovšem nezapomeňte, poté spustit skript /opt/ros/kinetic/setup.bash

Upozornění Pokud spouštíte tuhle sekvenci vzdáleně, např. přes ssh s parametrem -X, bude to rovněž fungovat – dokud se neodpojíte. Technicky by v tom neměl být problém. Když z instance vyskočíte příkazem 'exit', nebo ukončením spuštěné aplikace, tak se do ní můžete kdykoliv znovu připojit, jelikož zůstane běžet na pozadí. A to i když se ze stroje odpojíte a opět připojíte později.

Ovšem prakticky, pokud aplikaci rviz ukončíte, nebo se odhlásíte bude opětovný pokus o spuštění aplikace rviz končit takto:

:~$ singularity exec instance://jmeno_instance bash -c ". /opt/ros/kinetic/setup.bash && rviz"
[ INFO] [1569398638.871181884]: rviz version 1.12.17
[ INFO] [1569398638.871348016]: compiled against Qt version 5.5.1
[ INFO] [1569398638.871442654]: compiled against OGRE version 1.9.0 (Ghadamon)
[ INFO] [1569398639.819927437]: Stereo is NOT SUPPORTED
[ INFO] [1569398639.820385385]: OpenGl version: 3 (GLSL 1.3).
bash: line 1:   188 Segmentation fault      rviz


A to i přes to, že spuštěná instance roscore stále poběží. Pak vám nezbyde než instanci ukončit a spustit znovu.

Ovšem pokud se k této instanci pokusíte připojit znovu na tomto stroji, pak nebude problém.

Ukončení instance:

~$ singularity instance stop jmeno_instance

Stopping jmeno_instance instance of /opt/ros (PID=1333)

  1. Singularity na základě tohoto příkazu vytvoří virtuální disk, formátovaný na ext3.