]> gitweb.morketsmerke.org Git - mmdev.git/commitdiff
Rozpoczęcie tworzenia 16 rozdziału. Podrozdział 16.2.3.
authorxf0r3m <jakubstasinski@protonmail.com>
Thu, 2 May 2024 14:23:10 +0000 (16:23 +0200)
committerxf0r3m <jakubstasinski@protonmail.com>
Thu, 2 May 2024 14:23:10 +0000 (16:23 +0200)
articles/terminallog/Linux.Podstawy.html

index 20231b9a006f06706b810b2e8b1890b17cbea28c..e32adcfb7582cea7916e51807cf7f956235af92e 100644 (file)
@@ -12848,6 +12848,384 @@ $ patch -p0 &lt; plik_poprawki
 <pre class="code-block">
 $ patch -p1 &lt; 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
+ ---&gt; 05455a08881e
+Step 2/3 : RUN apk add bash
+ ---&gt; 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
+ ---&gt; 72784ac891aa
+Step 3/3 : CMD ["/bin/bash"]
+ ---&gt; Running in 5571f05ede12
+Removing intermediate container 5571f05ede12
+ ---&gt; 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;