<pre class="code-block">
$ patch -p1 < plik_poprawki;
</pre>
+ <h1 id="16.virtualisation">16. Wirtualizacja</h1>
+ <p>
+ Same pojęcie tego, że coś jest <em>wirtualne</em> odności się do
+ translacji warstwy bazowej do postaci uproszczonego interfejsu, z
+ którego może korzystać wielu odbiorców. Z pojęciem wirtualizacji
+ zapoznaliśmy się pośrednio przy poznawaniu zagadnienia
+ pamięci wirtualnej, oferującej procesom duży odizolowany obszar
+ pamięci operacyjnej. W tym przpadku skupimy się nieco szerszym
+ aspekcie możliwości wirtualizacyjnych pozwalających na tworzenie
+ izolowanych środowisk umożliwiających uruchomienie wielu systemów
+ operacyjnych bez powstawania konfliktu miedzy nimi.
+ </p>
+ <h2 id="16.1.virtualmachines">16.1. Maszyny wirtualne</h2>
+ <p>
+ Maszyny wirtualne obejmują całość sprzętu komputerowego, za pomocą
+ oprogramowania, wydzielane są zasoby fizycznego hosta oraz
+ tworzone nowe urządzenia aby powstała zupełnie nowa maszyna. Z
+ terminu <em>maszyna wirtualna</em>, korzysta się od wielu lat,
+ dlatego też w celach rozróżnienia (przecież spotkaliśmy się z
+ maszyną wirtualną Javy) dla maszyn tworzących izolowane środowiska
+ zdolne do uruchamiania systemów operacyjnych, które podwzględem
+ programowym nie różnią się niczym od fizycznych komputerów używa
+ się sformuowania <strong>systemowa maszyna wirtualna</strong>.
+ </p>
+ <p>
+ Żeby tego było mało, to możemy wróżnić jeszcze maszyny oparte
+ całkowicie na oprogramowania, czyli <strong>emulatory</strong>. Przy
+ użyciu tego rozwiązania możemy uruchamiać np. programy nieprzeznaczone
+ domyślnie na wykorzystywaną przez nas architetkurę. Dla przykładu
+ mamy obecnie dostępne emulatory konsol do gier czy smartfonów.
+ </p>
+ <h3 id="16.1.1.hypervisors">16.1.1 Hipernadzorcy</h3>
+ <p>
+ Programy pozwalające nam na kontrolowanie maszyn wirtualnych i
+ wchodzenie w interakcje z nimi (chociażby po to, aby zainstalować
+ system operacyjny) nazywane jest <strong>hipernadzorcą</strong>.
+ Istnieją dwa typy oprogramowania hipernadzorcy.
+ Z <strong>typem 2</strong>, każdy
+ mógł mieć styczność są to takie środowiska virtualizacji jak
+ Oracle VirtualBox czy VMware Player lub Workstation. Hipernadzorcami
+ drugiego typu jest najczęściej oprogramowanie instalowane
+ <strong>zawierające pełen pakiet wirtualizacji</strong>. Inaczej jest
+ w przypadku <strong>typu 1</strong>, gdzie instalujemy na fizycznym
+ komputerze
+ specjalny system operacyjny pełniący rolę hipernadzorcy. Pozostają
+ również rozwiązania zawieszone pomiędzy pierwszym a drugim typem,
+ np. rozwiązanie KVM z dystrybucji Linuksa. Pozwala ono zamienić
+ normalną dystrybucję w hipernadzorcę typu 1.
+ </p>
+ <p>
+ Po omówieniu roli hipernadzorcy, możemy wprowadzić odpowiednią
+ nomenklaturę dla zagadnienia maszyn wirtualnych. Mianowicie komputer,
+ który udostępnia maszyny wirtualne lub ma możliwość ich tworzenia
+ nazywany jest <strong>hostem</strong>, natomiast maszyna wirtualna
+ <strong>gościem</strong>.
+ </p>
+ <h3 id="16.1.2.vmhardware">16.1.2. Sprzęt maszyny wirtualnej</h3>
+ <p>
+ Istnieje wiel różnic między sprzętem fizycznym a tym z którego
+ korzystają maszyny - wirtualny. Wynikają one najczęściej z
+ umożliwienia gościom bardziej bezpośredniego dostępu do zasobów
+ hosta. Wykorzystywany jest mechnizm <strong>parawirtualizacji</strong>,
+ który pozwala na pomięcie sprzetu wirtualnego między składnikami
+ wirtualizacji (hostem a gościem). Tego typu rozwiązanie najczęściej
+ stosowane jest w przypadku urządzeń blokowych (pamięci masowych)
+ oraz interfejsów sieciowych.
+ </p>
+ <p>
+ Niezależnie od wykorzystywanych mechanizmów, celem wirtualizacji
+ zawsze będzie takie dostosowanie zasobów, a żeby gośćie mogli
+ trakotować te urządzenia jak swóje własne. Zapewni to stabilność
+ działania uruchmianego na maszynach oprogramowanie, to dzięki tego
+ typu rozwiązaniom możemy np. normalnie alokować przestrzeń pamięci
+ masowych, czy formatować partycje.
+ </p>
+ <p>
+ Innym ważnym zagadnieniem związanym z maszynami wirtualnymi jest
+ dostęp do procesora. Jak pamiętamy w systemie operacyjnym mamy dwa
+ trybu dystępu do procesora. Tryb <em>jądra</em> - pozwalający na
+ wykonanie dowolnych czynności oraz tryb <em>użytkownika</em> -
+ najprościej rzecz ujmując - ograniczony. Jeśli mamy uruchmiać na
+ maszynach systemy operacyjne, to hipernadzorcy powinni być
+ uruchamiani w trybie jądra. I tu jest mały problem, tryb jądra jest
+ zarezerwowany <strong>tylko dla jądra</strong>. Hipernadzorca
+ działa w trybie użytkownika (jak każdy inny proces, po za procesami
+ jądra). Jedną z koncepcji, która działa przez jakiś czas było
+ wychwytywanie przez hipernadzorcę wszystkich ograniczonych instrukcji
+ i emulowanie ich działania. To rozwiązanie zostało wyparte przez
+ rozszerzenia procesorów <strong>VT-x</strong> (Intel) oraz
+ <strong>AMD-V</strong> (AMD), które udostępniają odpowiednie zestawy
+ instrukcji, które zapewniają gościom bardziej swobodny dostęp do
+ procesora.
+ </p>
+ <h3 id="16.1.3.vmusege">16.1.3. Użycie maszyn wirtualnych</h3>
+ <p>
+ Jak wielkrotnie było wspomniane w tym rozdziale maszyny wirtualne
+ tworzą odizolowanie środowisko, zatem ich zastosowaniami mogą być
+ wszelkiego rodzaju testy. Np. jeśli korzystamy z dystrybucji Linuksa
+ na naszych komputerach codziennego użytku, to mogliśmy wykorzystać
+ maszyny wirtualne to testowania przykładów z tego materiału, lub
+ np. dostosowania konfiguracji systemowych do własnych potrzeb. Wiele
+ systemów wirtualizacji posiada mechnizm <strong>migawek</strong>,
+ które umożliwiają zapisanie stanu maszyny i poźniej ewentualnego
+ cofnięcia się do tego zapisu w razie ewentualnych problemów.
+ </p>
+ <p>
+ Drugim zastosowaniem maszyn może byc sztywne wydzielenie zasobów dla
+ konkretnych środowisk. Przydzielenie takiej a takiej ilośći pamięci
+ operacyjnej, tyle i tyle rdzeni procesora oraz takiej wielkości
+ dysk twardy znajdujący się np. na macierzy.
+ </p>
+ <h2 id="16.2.containers">16.2. Kontenery</h2>
+ <p>
+ Kontenery w przeciwieństwie do maszyn wirtualnych nie są tak
+ odizolowane systemu hosta. Często swoą wykorzystywane jako prostsza
+ alternatywa. Kontenery korzystają z rozwiązań dostępnych już
+ w systemie, aby zapewnić swój rodzaj wirtualizacji. Najczęściej
+ korzystają zmożliwości zmiany katalogu głównego (<em>chroot</em>)
+ oraz określenia limitów jądra (<em>rlimit</em>).
+ <strong>Kontener</strong> można określić jako ograniczone środowisko
+ uruchomieniowe przeznaczone dla zbioru procesów. Oznacza to, że mogą
+ one nie mieć dostępu do niczego poza obrębem swojego środowiska.
+ Tego typu wirtualizację określa się mianem
+ <strong>wirtualizacji na poziomie systemu operacyjnego</strong>.
+ </p>
+ <p>
+ Warto dodać, że nie ważna jest liczba kontenerów dalej host będzie
+ dysponowować tylko własnym bazowym jądrem. Natomiast procesy
+ użytkownika mogą pochodzić z innych dystrybucji niż bazowa.
+ </p>
+ <p>
+ Kontenery są ograniczne za pomocą kilku opcji jądra, przez co one:
+ </p>
+ <ul>
+ <li>Mają własne groupy <em>cgroup</em></li>
+ <li>Mają własne urządzenia i systemy plików</li>
+ <li>Nie mogą uzyskać dostępu do jakichkolwiek innych procesów w
+ w systemie ani prowadzić z nimi interakcji.</li>
+ <li>Mają własne interfejsy sieciowe</li>
+ </ul>
+ <p>
+ Mimo iż jest to możliwe, rzadko kto zadaje sobie tyle trudu aby
+ poustawiać te wszystkie aspekty ręcznie. Dlatego też korzysta się
+ z uproszczonych systemów konteneryzacji takich jak
+ <strong>Docker</strong>. Nie mniej jednak za pomocą takie systemu
+ <em>LXC</em> mamy możliwość własnoręcznego skonfigurowania tych
+ zagadanień. W tym rozdziale nacisk położono na Docker, ale system
+ LXC również po krótce omowiono.
+ </p>
+ <h3 id="16.2.1.dockerandpodman">16.2.1. Docker i Podman</h3>
+ <p>
+ Docker jest jednym z podstawowych narzędzi kontenerowych, jest on
+ bardzo łatwy do instalacji z strony projektu. Wymaga do korzystania
+ z kontenerów procesu serwera oraz przywilejów superużytkownika aby
+ uzyskać dostęp do opcji jądra.
+ </p>
+ <p>
+ Alternatywą dla dockera jest <strong>Podman</strong>. Nie wymaga on
+ do swojego działania procesu serwera. Podman może zostać uruchomiony
+ z uprawnieniami zwykłego użytkownika (ang. <em>rootless</em>),
+ wówczas stosowane są inne mechanizmy do uzyskania izolacji. Jeśli
+ uruchomimy Podman z uprawnieniami administratora to użyje on
+ rozwiązań stosowanych przez Docker. Podman jest kompatybilny pod
+ względem wiersza polecenia z Dockerem. Oczywiście występują różnice
+ w implementacji, szczególnie gdy Podman działa z uprawnieniami
+ zwykłego użytkownika. Jeśli gdzieś zajdzie taka potrzeba rożnice
+ między tymi systemami zostaną wyraźnie zaznaczone.
+ </p>
+ <p>
+ W tym materiale skupie się na <em>Docker</em>-ze. Podmana z resztą już omawiałem
+ w tym rozdziale materiału o RHCSA: <a href="https://morketsmerke.github.io/articles/terminallog/RedHat_-_RHCSA.html#23.containers">https://morketsmerke.github.io/articles/terminallog/RedHat_-_RHCSA.html#23.containers</a>
+ </p>
+ <h3 id="16.2.2.dockerusage">16.2.2. Użycie Dockera</h3>
+ <p>
+ Zamieszczony w tym podrozdziale przykład użycia <em>Docker</em>-a
+ przestawia
+ podstawowe elementy ukazujące działanie kontenerów. Na początku
+ niezbędne może być utworzenie obrazu składającego się z systemu
+ plików oraz innych elementów definiujących kontener. Obraz ten będzie
+ bazować na obrazie pobranym z repozytorium. Jest to standardowe
+ zachowanie. Przez sam <strong>obraz</strong> można rozumieć jako
+ system plików kontenera. Obraz naszego kontenera przygotujemy do
+ uruchomienia za pomocą
+ pliku <em>Dockerfile</em>. Oczywiście nie zawsze takie działanie
+ jest wymagane, ponieważ moglibyśmy utworzyć kontener ręcznie,
+ zalogować się do jego powłoki i zainstalować powłokę BASH. Za pomocą
+ pliku <em>Dockerfile</em> utworzymy obraz, z którego będziemy mogli
+ uruchamiać wiele kontenerów.
+ </p>
+<pre class="code-block">
+xf0r3m@debian:~/lp_test$ cat Dockerfile
+FROM alpine:latest
+RUN apk add bash
+CMD ["/bin/bash"]
+</pre>
+ <p>
+ Po zapisaniu zmian w pliku <em>Docker</em>-a, wydajemy poniższe
+ polecenie.
+ Opcja <code class="code-inline">-t lp_test</code> wskazuje na
+ identyfikator obrazu. Później łatwiej będzie go lokalizować,
+ ewentualnie wykorzystać do utworzenia nowego kontenera.
+ </p>
+<pre class="code-block">
+xf0r3m@debian:~/lp_test$ docker build -t lp_test .
+Sending build context to Docker daemon 2.048kB
+Step 1/3 : FROM alpine:latest
+latest: Pulling from library/alpine
+4abcf2066143: Pull complete
+Digest: sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b
+Status: Downloaded newer image for alpine:latest
+ ---> 05455a08881e
+Step 2/3 : RUN apk add bash
+ ---> Running in ad8a95239176
+fetch https://dl-cdn.alpinelinux.org/alpine/v3.19/main/x86_64/APKINDEX.tar.gz
+fetch https://dl-cdn.alpinelinux.org/alpine/v3.19/community/x86_64/APKINDEX.tar.gz
+(1/4) Installing ncurses-terminfo-base (6.4_p20231125-r0)
+(2/4) Installing libncursesw (6.4_p20231125-r0)
+(3/4) Installing readline (8.2.1-r2)
+(4/4) Installing bash (5.2.21-r0)
+Executing bash-5.2.21-r0.post-install
+Executing busybox-1.36.1-r15.trigger
+OK: 10 MiB in 19 packages
+Removing intermediate container ad8a95239176
+ ---> 72784ac891aa
+Step 3/3 : CMD ["/bin/bash"]
+ ---> Running in 5571f05ede12
+Removing intermediate container 5571f05ede12
+ ---> 9abc76076917
+Successfully built 9abc76076917
+Successfully tagged lp_test:latest
+</pre>
+ <p>
+ Zwróćmy uwagę na informacje zwracane przez Docker podczas przetwarzania
+ pliku <em>Dockerfile</em>. Na początku pobierany jest oficjalny
+ obraz kontenera dystrybucji Alpine Linux
+ (id: <code class="code-inline">05455a08881e</code>) na jego podstawie
+ tworzony jest kontener
+ (id: <code class="code-inline">ad8a95239176</code>) w którym to
+ uruchamiany jest proces menedżera pakietów, które zdaniem jest
+ zainstalowanie powłoki BASH
+ (<code class="code-inline">RUN apk add bash</code>), jest to druga
+ linia pliku <em>Dockerfile</em>. Na podstawie tego kontenera
+ tworzony jest obraz (id: <code class="code-inline">72784ac891aa</code>).
+ Następnie z tego obrazu tworzony jest kontener, który uruchamia proces
+ powłoki (id: <code class="code-inline">5571f05ede12</code>). Ten
+ kontener finalnie posłuży nam za wzorzec dla naszego obrazu - wyniku
+ pliku <em>Dockerfile</em>. Po między kolejnymi czynnościamy odczytanymi
+ z pliku, pośrednie kontenery są usuwane. Wynik działania polecenia
+ możemy również zobaczyć na liście dostępnych obrazów. Dostęp do niej
+ możemy uzyskać za pomocą polecenia:
+ <code class="code-inline">docker images</code>.
+ </p>
+<pre class="code-block">
+xf0r3m@debian:~/lp_test$ docker images
+REPOSITORY TAG IMAGE ID CREATED SIZE
+lp_test latest 9abc76076917 5 minutes ago 11.6MB
+alpine latest 05455a08881e 3 months ago 7.38MB
+</pre>
+ <p>
+ Na uruchomienie naszego kontenera mamy dwa sposoby:
+ <strong>nieinteraktywny</strong>, który dobry byłby gdybyśmy mieli
+ uruchomić jakiś skrypt powłoki. Próba uruchomienia naszego kontenera
+ w tym trybie wygląda w następujący sposób:
+ </p>
+<pre class="code-block">
+xf0r3m@debian:~/lp_test$ docker run lp_test
+xf0r3m@debian:~/lp_test$
+</pre>
+ <p>
+ Ze względu na to, że nie było żadnego polecenia dla powłoki, proces
+ zamknął się natychmiastowo. Na potwierdzenie możemy wyświetlić listę
+ wszystkich procesów (kontenerów), nawet wykonanych za pomocą
+ polecenia <code class="code-inline">docker ps -a</code>, polecenie
+ bez opcji <code class="code-inline">-a</code> spowoduje wyświetlenie
+ działających kontenerów.
+ </p>
+<pre class="code-block">
+xf0r3m@debian:~/lp_test$ docker ps -a
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+d4e8739ee569 lp_test "/bin/bash" 2 seconds ago Exited (0) 2 seconds ago modest_ardinghelli
+6f5067c97eb9 lp_test "/bin/bash" About a minute ago Exited (0) About a minute ago great_tharp
+</pre>
+ <p>
+ Jak możemy wywnioskować po pierwszym wpisie, to coś się działo.
+ Jednak nie wiele z tego użyliśmy. Jeśli chcelibyśmy uruchomić
+ kontener w drugim trybie <strong>interaktywnym</strong> to wówczas
+ musimy do podpolecenia <code class="code-inline">run</code> opcje
+ <em>-it</em>, czyli <em>-i</em> - praca interaktywna oraz <em>-t</em>
+ - podłączenien terminala.
+ </p>
+<pre class="code-block">
+xf0r3m@debian:~/lp_test$ docker run -it lp_test
+1d87aa6e43e7:/#
+</pre>
+ <p>
+ Dopóki pozostawimy tę sesje powłoki uruchomioną, doputy kontener
+ pozostanie uruchiomy. A w ten sposób prezentuje się lista procesów,
+ które są uruchomione na kontenerze:
+ </p>
+<pre class="code-block">
+1d87aa6e43e7:/# ps
+PID USER TIME COMMAND
+ 1 root 0:00 /bin/bash
+ 203 root 0:00 ps
+</pre>
+ <p>
+ Proces uruchomionej powłoki (a co za tym idzie, kontenera) możemy
+ rownież zobaczyć wyświetlając listę procesów hosta:
+ </p>
+<pre class="code-block">
+root 2369 0.0 0.1 2612 2360 pts/0 Ss+ 14:42 0:00 /bin/bash
+</pre>
+ <p>
+ Za tego typu zachowanie odpowiedzialna jest jedna z opcji jądra
+ wykorzystywana na potrzeby kontenerów - <strong>przestrzenie nazw</strong>
+ Dzięki tej funkcji proces może utworzy zupełnie nowy zestaw
+ identyfikatorów dla siebie oraz swoich procesów potomnych zaczynająć
+ do PID-u 1. Procesy te będą wówczas miały dostęp tylko do tego
+ identyfikatora.
+ </p>
+ <p>
+ Jeśli mamy na to ochotę to po skończonej zabawie możemy usunąć
+ nieaktywne już kontenery za pomocą polecenia
+ <code class="code-inline">docker rm identyfikator</code>:
+ </p>
+<pre class="code-block">
+xf0r3m@debian:~/lp_test$ docker ps -a
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+1d87aa6e43e7 lp_test "/bin/bash" 2 hours ago Exited (0) 19 minutes ago mystifying_gauss
+31808ed62e2a hello-world "/hello" 3 hours ago Exited (0) 3 hours ago elegant_davinci
+xf0r3m@debian:~/lp_test$ docker rm 1d87aa6e43e7
+1d87aa6e43e7
+xf0r3m@debian:~/lp_test$ docker ps -a
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+31808ed62e2a hello-world "/hello" 3 hours ago Exited (0) 3 hours ago elegant_davinci
+</pre>
+ <h4>Nakładkowy system plików</h4>
+ <p>
+ Inną funkcją jądra wykorzystywaną przez kontenery jest
+ <strong>nakładkowy system plików</strong>. Opcja ta pozwala na
+ utworzenie systemu plików po przez połącznie istniejących katalogów
+ jako warstw, wówczas zmiany przechowywane są w jednym miejscu.
+ Ten mechanizm składa się z trzech warstw:
+ </p>
+ <ul>
+ <li><strong>Dolnego katalogu</strong> (<em>lowerdir</em>) -
+ zawierającego bazowy system plików.</li>
+ <li><strong>Górnego katalogu</strong> (<em>upperdir</em>) -
+ zawierającego
+ wszelkie zmiany dokonane na bazowym systemie plików w trakcie
+ działania systemu.</li>
+ <li><strong>Katalogu roboczego</strong> (<em>workdir</em>) -
+ katalog przejściowy, w którym sterownik systemu plików realizuje
+ swoje działania przed zapisaniem zmian w górnym katalogu.</li>
+ </ul>
+ <p>
+ W przypadku Podmana bez uprawnień, wykorzystywany nakładkowy system
+ plików w wersji FUSE.
+ </p>
+ <h4>Obsługa sieci</h4>
+ <p>
+ W przypadku <em>Docker</em>-a istnieje kilka metod na zapewnienie
+ łączności kontenerom. Najczęściej stosowanym rozwiązaniem jest
+ sieć z mostem wykorzystującym siecią przestrzeń nazw (<em>netns</em>).
+ Serwer <em>Docker</em>-a tworzy w systemie hosta interfejs sieciowy
+ zazwyczaj o nazwie <em>docker0</em> przypisanym pierwszym adresie
+ z podsieci prywatnej 172.17.0.0/16 - 172.17.0.1/16. Ten interfejs
+ wykorzystywany do komunikacji miedzy hostem a kontenerami.
+ <em>Docker</em> wykorzystuje dodatkowe interfejsy w sieciowej
+ przestrzeni nazw oraz mechnizm NAT aby zapewnić kontenerom dostęp do
+ sieci zewnętrznych (w tym sieci lokalnej) hosta, w tym do Internetu.
+ </p>
+ <p>
+ Podman bez uprawnień wykorzystuje natomiast interfejsy TAP oraz
+ mechanizmy przekazujące w postacji daemon <em>slirp4netns</em>, aby
+ uzyskać dostęp do sieci zewnętrznych. To rozwiązanie ma jeden
+ minus, kontenery niestety nie mogą łączyć się ze sobą.
+ </p>
</div>
<p style="margin: 15px; padding: 0; outline: 0;">
2024; COPYLEFT; ALL RIGHTS REVERSED;