Przejdź do treści
Administracja·~18 min czytania

virsh w praktyce: zarządzanie maszynami wirtualnymi z terminala

Listowanie, adresy, dostęp przez konsolę i pulpit graficzny, zasilanie, dyski i sieci - oraz kilka pułapek, na których łatwo stracić wieczór.

Autor: Zespół LinuxLab

W LinuxLab maszyny wirtualne obsługujemy z terminala, nie z okienka. Powód jest prozaiczny: na serwerze nie ma pulpitu, a przez SSH i tak trzeba umieć sprawdzić, czy maszyna żyje, jaki ma adres i dlaczego nie wstaje. To wszystko robi jedno narzędzie.

W tym artykule przechodzimy przez codzienną pracę z virsh: od wypisania maszyn, przez odczyt ich adresów i stanu, dostęp przez konsolę szeregową oraz pulpit graficzny, po zasilanie, dyski, sieci i migawki. Wszystkie polecenia były uruchomione na działającym hoście, a nie przepisane z dokumentacji. Nazwy maszyn w przykładach są z naszego labu i możesz je podmienić na swoje.

Spis treści

  1. Czym jest virsh
  2. Dwa światy: system i sesja
  3. Listowanie maszyn
  4. Co maszyna ma w środku
  5. Adres maszyny
  6. Konsola szeregowa
  7. Pulpit graficzny i virt-viewer
  8. Zasilanie maszyny
  9. Podgląd i zmiana konfiguracji
  10. Dyski, pule i wolumeny
  11. Sieci i dzierżawy
  12. Migawki i ich ograniczenia
  13. Pułapki, które kosztują czas
  14. Ściągawka

Czym jest virsh

virsh to narzędzie wiersza poleceń do libvirt - warstwy, która ujednolica zarządzanie maszynami wirtualnymi. Sama libvirt nie uruchamia maszyn; robi to hipernadzorca pod spodem, najczęściej QEMU wraz z KVM, czyli wirtualizacją wbudowaną w jądro Linuksa. Libvirt daje temu wszystkiemu jeden zestaw pojęć i jeden interfejs.

Praktyczna konsekwencja jest taka, że virsh, graficzny virt-manager i narzędzia w rodzaju virt-install to różne twarze tego samego stanu. Maszyna utworzona w okienku będzie widoczna w terminalu i odwrotnie. Nie ma tu dwóch osobnych rejestrów, które trzeba by synchronizować.

Wersje użyte w tym artykule to libvirt 10.0.0 na Ubuntu 24.04. Pełny opis poleceń zawiera podręcznik virsh, a model obiektów - dokumentacja libvirt. Polecenia są stabilne od lat, ale przy starszych wydaniach część flag może nie istnieć.

Do pracy bez uprawnień administratora konto musi należeć do grupy libvirt:

id -nG | tr ' ' '\n' | grep libvirt

Jeżeli nic nie wypisze, dodaj się do grupy przez sudo usermod -aG libvirt "$USER" i zaloguj ponownie. Bez tego każde polecenie będzie kończyć się odmową dostępu albo - co bardziej mylące - pokaże pustą listę maszyn, o czym za chwilę.

Dwa światy: system i sesja

To jest pierwsza rzecz, która potrafi zmylić, i warto ją znać, zanim zacznie się szukać zaginionych maszyn. Libvirt ma dwa niezależne zestawy maszyn, opisane adresem połączenia:

AdresCzyje maszynyTypowe użycie
qemu:///systemmaszyny hosta, prowadzone przez usługę systemowąserwery, laby, wszystko co ma działać niezależnie od zalogowanego użytkownika
qemu:///sessionmaszyny konkretnego użytkownikamaszyny doraźne, bez uprawnień do zasobów hosta

Na naszym hoście widać to wprost - w jednym świecie jest dwanaście maszyn, w drugim ani jednej:

$ virsh -c qemu:///system  list --all --name | grep -c .
12
$ virsh -c qemu:///session list --all --name | grep -c .
0

Stąd bierze się klasyczne „przecież ta maszyna istniała”. Jeżeli virsh list --all zwraca pustkę, a jesteś pewien, że maszyny są, prawie zawsze pytasz nie ten świat. Które połączenie jest domyślne, sprawdzisz jednym poleceniem:

virsh uri

Domyślne można ustawić na stałe zmienną środowiskową LIBVIRT_DEFAULT_URI, a doraźnie przełączyć flagą -c. Ta sama flaga obsługuje host zdalny przez SSH, co bywa wygodniejsze od logowania się na serwer:

virsh -c qemu+ssh://uzytkownik@serwer/system list --all

Listowanie maszyn

Najczęściej używane polecenie w całym zestawie. Bez żadnej flagi pokazuje tylko maszyny działające:

$ virsh list
 Id   Name          State
 -----------------------------
 7    vm-code-ai2   running
 9    awx           running
 10   ubu2204       running
 12   deb13         running

To jest źródło drugiego częstego nieporozumienia: maszyna wyłączona po prostu tu nie występuje, co łatwo wziąć za jej zniknięcie. Pełny obraz daje dopiero:

virsh list --all

Kolumna Id ma znaczenie tylko dla maszyn działających i zmienia się przy każdym uruchomieniu - wyłączone mają w tym miejscu myślnik. Do wszystkiego, co ma być trwałe, używaj nazwy albo identyfikatora UUID, nigdy numeru.

Do skryptów przydają się dwie flagi. Filtr stanu zawęża listę, a --name zwraca same nazwy, bez ramek i nagłówków:

# same działające, tylko nazwy - gotowe do pętli
virsh list --state-running --name

# same wyłączone
virsh list --state-shutoff --name

# ile maszyn w ogóle
virsh list --all --name | grep -c .

Stan pojedynczej maszyny, bez przeszukiwania całej listy:

$ virsh domstate deb13
running

Co maszyna ma w środku

Podsumowanie parametrów jednej maszyny:

$ virsh dominfo deb13
Id:             12
Name:           deb13
UUID:           16d6bd44-dfc7-4555-9f82-a416e4fd572e
State:          running
CPU(s):         2
Max memory:     2097152 KiB
Used memory:    2097152 KiB
Persistent:     yes
Autostart:      disable
Managed save:   no
Security model: apparmor

Cztery pola z tego wydruku warto umieć czytać:

  • Persistent - czy maszyna ma zapisaną definicję. yes znaczy, że przetrwa restart hosta jako definicja. no oznacza maszynę ulotną, która po zatrzymaniu zniknie bez śladu.
  • Autostart - czy wstaje razem z hostem. Osobna rzecz od Persistent: definicja może istnieć, a maszyna i tak nie ruszy sama.
  • Managed save - czy leży zapisany stan pamięci, do którego maszyna wróci przy starcie. Jeżeli maszyna „startuje w dziwnym stanie”, sprawdź to pole najpierw.
  • Used memory - pamięć przydzielona, w kibibajtach. Tu 2097152 KiB, czyli 2 GiB.

Dyski i interfejsy sieciowe maszyny:

$ virsh domblklist deb13
 Target   Source
 ------------------------------------------------
 vda      /var/lib/libvirt/images/deb13.img
 vdb      /var/lib/libvirt/images/deb13-seed.img

$ virsh domiflist deb13
 Interface   Type      Source   Model    MAC
 ----------------------------------------------------------
 vnet9       network   lab      virtio   52:54:00:3a:a3:8a

Kolumna Source przy dyskach to ścieżka do pliku - stąd wiadomo, co sprawdzić przez qemu-img info. Przy interfejsach Source mówi, do której sieci maszyna jest podpięta, co bywa pierwszym tropem, gdy „nie ma łączności”.

Bieżące zużycie zasobów, bez logowania się do maszyny:

virsh domstats deb13 --balloon --vcpu

Adres maszyny

Najczęstsze pytanie w codziennej pracy brzmi: pod jaki adres się połączyć. Są dwa sposoby i różnią się wiarygodnością.

# 1. Odczyt z tablicy dzierżaw DHCP - działa zawsze, bywa nieaktualny
virsh domifaddr deb13

# 2. Zapytanie systemu w środku maszyny - wiarygodne, wymaga agenta
virsh domifaddr deb13 --source agent

Pierwszy wariant pokazuje, co serwer DHCP (od angielskiego Dynamic Host Configuration Protocol, czyli usługa rozdzielająca adresy w sieci) kiedyś przydzielił. Jeżeli maszyna dostała potem inny adres, ma skonfigurowany adres stały albo dzierżawa wygasła, wynik będzie mylący. Drugi pyta system operacyjny gościa o jego rzeczywistą konfigurację, więc mówi prawdę - pod warunkiem, że w maszynie działa qemu-guest-agent. Jeżeli go nie ma, polecenie zwróci pustkę i trzeba wrócić do wariantu pierwszego.

Odczyt przez agenta zwraca wszystkie adresy, także te, które Cię nie interesują:

$ virsh domifaddr awx --source agent
 ... 127.0.0.1/8
 ... 192.168.122.103/24
 ... 10.42.0.1/24

Tu widać pętlę zwrotną, adres z sieci hosta oraz adres wewnętrzny klastra kontenerów działającego w tej maszynie. Ten, którego szukasz, to zwykle adres z zakresu sieci libvirt - w domyślnej instalacji 192.168.122.0/24.

Jeżeli agenta nie ma i dzierżawy też nie, zostaje jeszcze jedna droga: adres sprzętowy interfejsu z virsh domiflist i przeszukanie tablicy sąsiedztwa na hoście.

Konsola szeregowa

Konsola szeregowa jest tym, po co sięga się, gdy maszyna nie odpowiada po sieci - bo pokazuje to, co dzieje się od momentu startu, razem z komunikatami firmware, programu rozruchowego i jądra. Jest więc jedynym miejscem, gdzie zobaczysz, dlaczego maszyna nie wstała.

virsh console deb13

Zapamiętaj, jak wyjść, zanim wejdziesz. Konsola przejmuje terminal i Ctrl+C trafia do maszyny, a nie do virsh. Wyjście to Ctrl+] - domyślnie sekwencja znana z telnetu. Można ją zmienić flagą -e, na przykład virsh -e ^X console deb13. Bez tej wiedzy jedynym wyjściem bywa zamknięcie okna terminala.

Dwie flagi warte znajomości. --force odłącza sesję, która już zajmuje konsolę - przydatne, gdy ktoś zostawił otwarte połączenie albo poprzednia sesja się urwała. --safe łączy się tylko wtedy, gdy hipernadzorca gwarantuje wyłączność.

Jeżeli konsola nie pokazuje nic poza pustym ekranem, przyczyną zwykle nie jest sama libvirt, tylko brak konfiguracji po stronie gościa: system musi kierować komunikaty na port szeregowy. W definicji maszyny odpowiada za to element konsoli, który sprawdzisz przez virsh dumpxml.

Pulpit graficzny i virt-viewer

Gdy maszyna ma pulpit, terminal nie wystarczy. Adres wyświetlacza podaje:

$ virsh domdisplay deb13
spice://127.0.0.1:5904

Zwróć uwagę na adres: 127.0.0.1. Wyświetlacz jest domyślnie wystawiony tylko lokalnie na hoście, i tak ma być - protokół pulpitu bez dodatkowych zabezpieczeń nie powinien słuchać na wszystkich adresach.

Do połączenia służy virt-viewer. Uruchomiony z nazwą maszyny sam odpyta libvirt o adres:

# na hoście z pulpitem graficznym
virt-viewer deb13

# poczekaj aż maszyna wstanie i połącz się automatycznie
virt-viewer --wait --reconnect deb13

Z innego komputera nie podawaj adresu wyświetlacza wprost, tylko każ narzędziu połączyć się przez SSH - wtedy ruch idzie tunelem, a nie otwartym portem:

virt-viewer -c qemu+ssh://uzytkownik@serwer/system deb13

Maszyna wyłączona nie ma wyświetlacza. Sprawdziliśmy to wprost: dla działających maszyn virsh domdisplay zwraca adres, a dla wyłączonej nie zwraca nic, choć jej definicja zawiera kompletną konfigurację grafiki. Pusty wynik nie znaczy więc „ta maszyna nie ma pulpitu”, tylko „ta maszyna nie działa”. Kolejność jest jedna: najpierw virsh start, potem domdisplay.

Jeżeli wolisz jedno okno na wszystkie maszyny, tym samym stanem zarządza graficzny virt-manager. Nie jest alternatywą dla virsh, tylko inną twarzą tego samego - maszyny widać w obu miejscach.

Zasilanie maszyny

Tu jedno nieporozumienie potrafi kosztować dane, więc zacznijmy od tabeli. Nazwy poleceń są mylące i nie odpowiadają temu, co sugerują po polsku:

PolecenieCo naprawdę robiOdpowiednik w świecie fizycznym
virsh starturuchamia maszynę z zapisanej definicjinaciśnięcie przycisku zasilania
virsh shutdownprosi system gościa o zamknięciewybranie „zamknij system” w menu
virsh rebootprosi system gościa o ponowne uruchomieniewybranie „uruchom ponownie”
virsh destroyodcina zasilanie, nie kasuje niczegowyrwanie kabla z gniazdka
virsh resettwardy reset bez pytania gościaprzycisk reset w obudowie
virsh undefinekasuje definicję maszynywyrzucenie komputera

Nazwa destroy jest tu najgorsza z możliwych, bo brzmi jak usunięcie. Opis w samej pomocy narzędzia mówi wprost: „Forcefully stop a given domain, but leave its resources intact” - czyli zatrzymaj siłowo, ale zostaw zasoby nietknięte. Dysk, definicja i konfiguracja zostają. To jest odpowiednik wyrwania kabla, ze wszystkimi konsekwencjami dla systemu plików gościa, ale bez utraty maszyny.

Maszynę usuwa dopiero undefine, i to on ma flagi, przy których trzeba uważać:

# kasuje samą definicję, dyski ZOSTAJĄ na miejscu
virsh undefine deb13

# kasuje definicję RAZEM ze wszystkimi dyskami - nie ma odwrotu
virsh undefine deb13 --remove-all-storage

Praktyczna kolejność przy wyłączaniu wygląda tak: najpierw shutdown, potem obserwacja przez virsh domstate, a dopiero gdy maszyna nie reaguje przez kilka minut - destroy. Sięganie od razu po to drugie to zwykłe wyrywanie kabla.

Czy maszyna ma wstawać razem z hostem, ustawia się osobno:

virsh autostart deb13              # włącz
virsh autostart --disable deb13    # wyłącz

Jest też pośredni tryb, przydatny gdy chcesz zwolnić pamięć, ale wrócić dokładnie do tego, co było. managedsave zapisuje stan pamięci na dysk i zatrzymuje maszynę; najbliższy start odtworzy ją w tym samym miejscu, razem z otwartymi programami:

virsh managedsave deb13
virsh start deb13                  # wraca do zapisanego stanu

To wyjaśnia pole Managed save z dominfo. Jeżeli maszyna uparcie wraca do stanu, którego się nie spodziewasz, prawie na pewno leży taki zapis - usuwa go virsh managedsave-remove.

Do wstrzymania bez zapisu na dysk służą suspend i resume - maszyna zostaje w pamięci, przestaje dostawać czas procesora.

Podgląd i zmiana konfiguracji

Cała konfiguracja maszyny to dokument XML. Podgląd:

virsh dumpxml deb13

# tylko to, co Cię interesuje
virsh dumpxml deb13 | grep -E '<memory|<vcpu|<disk|<interface'

Do edycji nie otwieraj pliku w katalogu libvirt bezpośrednio - zmiany wprowadzone poza narzędziem bywają nadpisywane, a błąd składni potrafi uszkodzić definicję. Właściwa droga sprawdza XML przed zapisem:

virsh edit deb13

Otwiera edytor ze zmiennej $EDITOR, a po zamknięciu waliduje dokument i odrzuca zmianę, jeżeli jest niepoprawna. Większość zmian - pamięć, liczba rdzeni, dyski - zadziała dopiero po pełnym zatrzymaniu i uruchomieniu maszyny. Samo reboot z wnętrza gościa nie wystarczy, bo proces maszyny nadal działa ze starą konfiguracją.

Do zmian skryptowych, bez otwierania edytora, służy virt-xml:

virt-xml deb13 --edit --memory 4096
virt-xml deb13 --edit --vcpus 4

Dyski, pule i wolumeny

Libvirt grupuje pliki dysków w pule, czyli katalogi lub inne miejsca składowania. Przegląd:

$ virsh pool-list --all
 Name     State    Autostart
 ------------------------------
 golden   active   yes
 images   active   yes

$ virsh vol-list images
$ virsh vol-info --pool images deb13.img

Powiększenie dysku działającej maszyny robi się w dwóch krokach, o czym łatwo zapomnieć. Najpierw rośnie plik po stronie hosta:

virsh vol-resize --pool images deb13.img 30G

Ale system w środku nadal widzi starą wielkość, bo tablica partycji i system plików nic o zmianie nie wiedzą. Drugi krok wykonuje się w gościu, narzędziami w rodzaju growpart i resize2fs. Sam vol-resize niczego w maszynie nie powiększy.

Obowiązuje przy tym zasada „tylko w górę”. Zmniejszenie dysku, na którym jest system plików z danymi, to prosta droga do jego uszkodzenia - libvirt pozwoli, system plików nie wybaczy.

Sieci i dzierżawy

$ virsh net-list --all
 Name      State    Autostart   Persistent
 --------------------------------------------
 default   active   yes         yes
 lab       active   yes         yes

$ virsh net-dhcp-leases default
$ virsh net-dumpxml lab | grep -E '<forward|<ip |<range'

Wydruk definicji sieci odpowiada na dwa pytania naraz: w jakim trybie sieć pracuje i jaki ma zakres adresów. Tryb translacji adresów oznacza, że maszyny widzą świat, ale świat ich nie - żeby dostać się do usługi z innego komputera, potrzebny jest tunel albo przekierowanie portu.

Sieć da się zatrzymać i uruchomić niezależnie od maszyn, co bywa potrzebne po zmianie jej definicji:

virsh net-destroy lab      # zatrzymuje sieć, nie kasuje jej
virsh net-start lab

Nazewnictwo jest tu tak samo mylące jak przy maszynach: net-destroy zatrzymuje, a kasuje dopiero net-undefine.

Własna sieć: definicja i adresacja

Sieć opisuje się tak samo jak maszynę - dokumentem XML. Poniżej najprostsza sensowna definicja: własna adresacja, brama na hoście i serwer DHCP rozdający adresy gościom.

<network>
  <name>projekt-a</name>
  <forward mode='nat'/>
  <bridge name='virbr-proja' stp='on' delay='0'/>
  <ip address='192.168.130.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.130.10' end='192.168.130.100'/>
    </dhcp>
  </ip>
</network>

Trzy rzeczy warto tu rozumieć. address to adres, który weźmie host - staje się bramą dla maszyn w tej sieci. Zakres DHCP celowo zaczyna się od .10, żeby zostawić kilka adresów na maszyny konfigurowane ręcznie. Nazwa mostka może być dowolna, ale musi być unikalna w systemie i mieścić się w limicie długości nazw interfejsów.

virsh net-define projekt-a.xml     # zapisuje definicję
virsh net-start projekt-a          # uruchamia
virsh net-autostart projekt-a      # ma wstawac razem z hostem

Te trzy kroki są rozdzielone celowo: definicja może istnieć bez działającej sieci, a sieć uruchomiona bez autostartu zniknie po restarcie hosta.

Trzy sieci: dwie połączone, jedna osobna

To jest częsty scenariusz - kilka środowisk na jednym hoście, z których jedno ma być odcięte. Zanim jednak zaczniesz planować reguły, sprawdź, co dzieje się domyślnie. My sprawdziliśmy, budując trzy sieci i mierząc łączność między nimi.

Wynik jest jednoznaczny i dla wielu osób zaskakujący:

SprawdzenieWynik
Maszyna w sieci A do maszyny w sieci B (obie z translacją adresów)nie widzi
Kierunek odwrotny, B do Anie widzi
Maszyna w sieci A na zewnątrzwychodzi
Host do maszyn w obu sieciachwidzi obie
Maszyna w sieci izolowanej do swojej bramywidzi
Maszyna w sieci izolowanej do innej sieci i na zewnątrznie widzi

Czyli dwie osobne sieci na tym samym hoście są domyślnie wzajemnie odcięte, mimo że host ma nogę w każdej z nich, a przekazywanie pakietów w jądrze jest włączone. Zadbały o to reguły filtrowania, które libvirt zakłada przy uruchamianiu sieci: przepuszczają ruch danej sieci na zewnątrz, ale nie do sąsiedniej.

Praktyczny wniosek jest wygodny: samo umieszczenie maszyn w osobnych sieciach już je od siebie oddziela. Nie trzeba nic dokładać, żeby środowiska się nie widziały.

Sieć naprawdę odcięta

Jeżeli maszyny mają nie mieć wyjścia w ogóle, wystarczy jedna różnica w definicji - pomijasz element forward:

<network>
  <name>projekt-c</name>
  <!-- brak elementu forward: siec izolowana -->
  <bridge name='virbr-projc' stp='on' delay='0'/>
  <ip address='192.168.132.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.132.10' end='192.168.132.100'/>
    </dhcp>
  </ip>
</network>

Sprawdziliśmy, jak taka sieć się zachowuje. Maszyna dostaje adres z DHCP, rozmawia z innymi maszynami w tej samej sieci i widzi bramę na hoście - ale nie wychodzi nigdzie dalej. Zapytanie do adresu w Internecie po prostu nie wraca.

To dobre miejsce na maszyny, które mają być odizolowane od świata: analiza podejrzanego oprogramowania, środowisko z danymi, których nie wolno wypuścić, albo test aktualizacji, który nie ma prawa dotknąć niczego produkcyjnego. Odcięcie wynika z definicji sieci, a nie z konfiguracji w gościu, więc nie da się go wyłączyć przez pomyłkę wewnątrz maszyny.

Różnicę widać jednym poleceniem:

$ virsh net-dumpxml projekt-a | grep forward
  <forward mode='nat'>

$ virsh net-dumpxml projekt-c | grep forward
  (nic - i o to chodzi)

Gdy dwie sieci mają się jednak widzieć

Skoro domyślnie są odcięte, połączenie ich wymaga świadomej decyzji. Są dwie drogi i różnią się miejscem, w którym powstaje przejście.

Pierwsza to maszyna z nogą w obu sieciach. Podpinasz jej drugi interfejs i ta jedna maszyna widzi oba środowiska:

virsh attach-interface --domain MASZYNA \
  --type network --source projekt-b --model virtio --live

Flaga --live dokłada interfejs działającej maszynie; bez --config zmiana zniknie po jej wyłączeniu, co przy testach bywa zaletą. W gościu trzeba potem podnieść nowy interfejs i pobrać adres. Żeby maszyny z jednej sieci sięgały przez taką maszynę do drugiej, musi ona jeszcze przekazywać pakiety i trzeba dodać trasy - to już budowanie routera i warto wiedzieć, że się na to piszemy.

Druga droga to reguły filtrowania na hoście, przepuszczające ruch między mostkami obu sieci. Daje przejście dla wszystkich maszyn naraz, ale trzeba je odtwarzać po restarcie sieci, bo libvirt zakłada swoje reguły od nowa przy każdym net-start.

Dwie pułapki, na które trafiliśmy przy tym teście. Pierwsza: maszyna z dwoma interfejsami dostaje dwie trasy domyślne o tym samym koszcie. Pakiet wysłany z adresem źródłowym jednej sieci może wtedy wyjść drugim interfejsem i nie wrócić. Objawia się to jako „sieć nie działa”, choć działa - to kwestia trasowania w gościu, nie definicji sieci. Sprawdzając łączność wskazuj interfejs wprost, na przykład ping -I enp8s0.

Druga: liczba interfejsów, które można dołożyć działającej maszynie, jest ograniczona. Przy próbie podpięcia trzeciego dostaliśmy No more available PCI slots. Kolejny interfejs wymaga wtedy zatrzymania maszyny i zmiany jej definicji, a nie dokładania na gorąco.

Na koniec sprzątanie po eksperymencie, w tej samej kolejności co przy maszynach - najpierw zatrzymanie, potem usunięcie definicji:

virsh detach-interface --domain MASZYNA --type network --mac 52:54:00:aa:bb:cc --live
virsh net-destroy projekt-a
virsh net-undefine projekt-a

Migawki i ich ograniczenia

Migawka pozwala wrócić do stanu sprzed zmiany i jest naturalnym odruchem przed ryzykowną operacją. Warto jednak wiedzieć, że są dwa różne rodzaje migawek i że format dysku decyduje o tym, który z nich zadziała.

RodzajGdzie trzyma daneWymaga
Wewnętrznaw samym pliku dyskuformatu qcow2
Zewnętrznaw nowym pliku nakładki nad dotychczasowymdziała także na dysku surowym

Sprawdziliśmy to na plikach roboczych: qemu-img snapshot -c tworzy migawkę w pliku qcow2, a na pliku surowym nie ma jej gdzie zapisać. Jeżeli więc dyski Twoich maszyn są surowe - a bywa tak w konfiguracjach nastawionych na wydajność albo wymuszonych przez narzędzie tworzące maszyny - migawki wewnętrzne odpadają.

Zostaje wariant zewnętrzny. Tworzy on nowy plik, do którego trafiają wszystkie kolejne zapisy, a dotychczasowy dysk staje się niezmienną podstawą:

virsh snapshot-list deb13
virsh snapshot-create-as deb13 przed-zmiana --disk-only --atomic
virsh snapshot-revert deb13 przed-zmiana

Po takiej migawce virsh domblklist pokaże już nie ten plik, co wcześniej, tylko nakładkę. To normalne, ale bywa zaskoczeniem, gdy ktoś w międzyczasie szuka „swojego” dysku.

Powrót do stanu bez migawki polega na scaleniu nakładki z podstawą. Robi to operacja blokowa, wykonywana na działającej maszynie:

virsh blockcommit deb13 vda --active --pivot --wait

Zapisy z nakładki trafiają wtedy do pliku podstawowego, a maszyna zostaje przełączona z powrotem na niego. Trzeba to powtórzyć dla każdego dysku maszyny osobno - jeżeli ma ich dwa, jedno wywołanie zostawi drugi nadal na nakładce.

Uwaga na flagę, która wygląda jak tryb próbny, ale nim nie jest. Pisząc ten artykuł sprawdzaliśmy zachowanie migawek i użyliśmy --validate w przekonaniu, że to bezpieczne sprawdzenie. Nie jest. Opis w pomocy narzędzia brzmi „validate the XML against the schema” - flaga sprawdza poprawność dokumentu i mimo to tworzy migawkę. Trybem próbnym jest --print-xml, opisane jako „print XML document rather than create”. Skutek był łatwy do naprawienia scaleniem nakładek, ale kosztował kwadrans, którego można było uniknąć, czytając opis flagi zamiast zgadywać z nazwy.

Pułapki, które kosztują czas

Zebrane w jednym miejscu, bo każda z nich potrafi wysłać w złą stronę na dłużej niż powinna.

ObjawCo się dzieje naprawdęCo zrobić
Lista maszyn jest pusta, choć maszyny istniejąpytasz nie ten świat: session zamiast system, albo brak Cię w grupievirsh uri, potem -c qemu:///system
Maszyna „zniknęła”virsh list pokazuje tylko działającevirsh list --all
Nie mogę wyjść z konsolikonsola przejęła terminal, Ctrl+C idzie do gościaCtrl+]
domdisplay nic nie zwracamaszyna jest wyłączona, wyświetlacz istnieje dopiero przy działającejnajpierw virsh start
Adres z domifaddr nie odpowiadaodczyt z dzierżaw DHCP bywa nieaktualnydodać --source agent
Zmiana pamięci nie działareboot w gościu nie tworzy procesu maszyny od nowapełne shutdown i start
Dysk powiększony, gość widzi stary rozmiarvol-resize rusza tylko plik na hościepowiększyć partycję i system plików w gościu
Migawka utworzona mimo „sprawdzenia”--validate waliduje, ale tworzyużywać --print-xml
Maszyna wraca do dziwnego stanuleży zapisany stan pamięcidominfo, potem managedsave-remove

Jedna wspólna zasada wychodzi z tej listy: nazwy poleceń w libvirt opisują operację na obiekcie, a nie skutek widziany przez człowieka. destroy niszczy proces maszyny, nie maszynę. net-destroy zatrzymuje sieć, nie kasuje jej. Kiedy nazwa brzmi groźnie albo zbyt łagodnie, szybciej jest sprawdzić opis niż zgadywać:

virsh help destroy
virsh help undefine

Ściągawka

# --- rozeznanie -----------------------------------------------------------
virsh uri                            # które połączenie jest domyślne
virsh list                           # tylko działające
virsh list --all                     # wszystkie
virsh list --state-shutoff --name    # same nazwy wyłączonych
virsh domstate MASZYNA               # stan jednej

# --- co maszyna ma w środku -----------------------------------------------
virsh dominfo MASZYNA                # pamięć, rdzenie, autostart, managed save
virsh domblklist MASZYNA             # dyski i ścieżki do plików
virsh domiflist MASZYNA              # interfejsy i sieć
virsh domifaddr MASZYNA --source agent   # adres, wiarygodnie

# --- dostęp ---------------------------------------------------------------
virsh console MASZYNA                # konsola szeregowa, wyjście Ctrl+]
virsh domdisplay MASZYNA             # adres pulpitu (tylko gdy działa)
virt-viewer MASZYNA                  # pulpit graficzny
virt-viewer -c qemu+ssh://uzytkownik@serwer/system MASZYNA

# --- zasilanie ------------------------------------------------------------
virsh start MASZYNA
virsh shutdown MASZYNA               # grzecznie, przez system gościa
virsh destroy MASZYNA                # siłowo, jak wyrwanie kabla zasilającego
virsh autostart --disable MASZYNA
virsh managedsave MASZYNA            # zapisz stan i zatrzymaj

# --- konfiguracja ---------------------------------------------------------
virsh dumpxml MASZYNA
virsh edit MASZYNA                   # z walidacją przed zapisem
virt-xml MASZYNA --edit --memory 4096

# --- magazyn i sieć -------------------------------------------------------
virsh pool-list --all
virsh vol-list images
virsh vol-resize --pool images DYSK.img 30G    # potem growpart w gościu
virsh net-list --all
virsh net-dhcp-leases default

# --- pomoc ----------------------------------------------------------------
virsh help                           # grupy tematycznie
virsh help snapshot                  # polecenia jednej grupy
virsh help POLECENIE                 # opis i flagi

Ostatnia linia jest tą, która najbardziej się opłaca. Pomoc w virsh jest podzielona tematycznie - domain, monitor, network, pool, volume, snapshot i kilka innych - a opis pojedynczego polecenia zawiera wszystkie flagi razem z tym, co naprawdę robią. Wystarczy przeczytać jedno zdanie, żeby nie potraktować walidacji jako trybu próbnego.

Potrzebujesz opieki nad infrastrukturą wirtualną?

Projektujemy i utrzymujemy środowiska na libvirt i KVM - od pojedynczego hosta z maszynami testowymi po produkcję opisaną kodem, z backupem i sprawdzonym odtworzeniem.