Virtualizacija yra puikus būdas išnaudoti serverio išteklius, nes dažnai nemaža dalis tarnybinės stoties išteklių lieka nepanaudota, o kompiuteris vis viena eikvoja elektros energiją ir užima vietą. Žinoma, į vieną tarnybinę stotį galima įdiegti keletą servisų, tačiau ne visuomet tai yra paranku.

Pasitelkus virtualizaciją, iš vienos fizinės mašinos galima nesunkiai padaryti 2, 3 ar net daugiau sistemų, tinkle matomų, kaip savarankiški serveriai. O su įvertinus apkrovą ir itinkamai bei tinkamai paskirsčius išteklius - tarnybinių stočių teikiamų paslaugų spartos sumažėjimas nebus pastebimas. Apie tai, kaip įdiegti ir suderinti virtualizacijos programinę įrangą - galima rasti XEN, KVM, „Virtual Box“ ar „VMWare Server“ autorių tinklalapiuose ir daugelyje kitų Wiki ar tinklaraščių puslapiuose. Bet yra vienas niuansas, apie kurį šiuose vadovuose paprastai užsimenama tik keletu žodžių ir neatkreipus dėmesio į tai, kur bus saugomos virtualios mašinos - pirmieji virtualizacijos įspūdžiai gali būti labai ne kokie.

Nors straipsnyje bus rašoma apie XEN virtualizacijos sistemą Linux terpėje, tačiau tie patys principai galioja ir diegiant virtualius kompiuterius kitose OS.

Disko posistemio veiklos diagnostika

Kuriant virtualius kompiuterius, jų virtualūs diskiniai kaupikliai vienokiu ar kitokiu būdu turi būti įrašyti į realias fizinės mašinos laikmenas. Beveik visuose virtualių sistemų diegimo vadovuose (išskyrus, nebent, į „Enterprise“ lygio sistemas orientuotų programų) nurodoma galimybė sukurti virtualių diskinių kaupiklių konteinerius paprastuose failuose ar jų grupėje. Tai yra pats paprasčiausias būdas - tiesiog sukuriamas diskinio kaupiklio atvaizdo failas, kuriame virtualios mašinos procesas sukuria diskinio kaupiklio turinį. Ir dažniausiai pats prasčiausias.

Deja, tokia konfigūracija dažnai yra tinkama nebent principinei virtualizavimo galimybei patikrinti, bet jokiu būdu ne sistemos darbui ar, tuo labiau, virtualaus serverio našumui įvertinti! Problema ta, jog kuriant virtualų diskinį kaupiklį faile, susidaro failų sistemų „sumuštinis“. Virtuali mašina tvarko savo failų sistemą ir rašo failų duomenis į failų sistemą virtualaus kaupiklio skirsnyje, registruodama failų sistemos operacijas savame žurnale. Savo ruožtu fizinė mašina perima šias rašymo operacijas ir jas vėl pakartoja fizinės mašinos failų sistemoje ir atžymi operacijas failų sistemos operacijų žurnale. Grubiai, vienam virtualios mašinos duomenų bloko rašymui reikės 9 įvesties/išvesties operacijų fizinėje mašinoje, kurios papildomai apkraus procesorių. To pasėkoje procesorius užuot apdorojęs duomenis, tiesiog laukia, kol jie bus įrašyti ar nuskaityti iš kaupiklio.

Ypač tai pastebima, jei virtualus serveris atlieka daug mažų failinių operacijų, atlikdamas daug pakeitimų dideliuose failuose. Nors bendras rašomų skaitomų duomenų srautas nebus didelis (0.5-2 MBps), tačiau Linux sistema bus labai užsiėmusi, tvarka failinės sistemos įvykių žurnalą. Kažkiek gali padėti žaidimas su failų sistemos prijungimo parametrais, tokiais kaip noatime ar data=writeback, bet didelio pagerėjimo nebus.

Tokią situaciją galima nesunkiai atpažinti: sistema iš pažiūros lyg ir nėra apkrauta ir komandos įvykdomos sparčiai, tačiau reikia ilgokai palaukti, kol komanda bus pradėta vykdyti. Gerokai sulėtėja net ir nedidelių failų atvėrimas ar katalogo turinio parodymas. Serverio būklę tiksliai galima įvertinti pasitelkus iostat ir sar (sysstat paketo dalis) programas.

Komanda iostat 3 10, kas 3 sekundes parodys įvesties išvesties operacijų skaičių kiekvienam blokiniam įrenginiui ir bendrus sistemos apkrovos rodiklius. Jei kompiuteris atlieka daug įvesties ir išvesties operacijų  parametras iowait bus gerokai didesnis už 0. Taip yra todėl, kad įvesties ir išvesties operacijos vykdomos labai ilgai, palyginus su kitomis instrukcijomis. Procesorius tiesiog laukia, kol duomenys bus įrašyti ar nuskaityti.

vm-serv:~# iostat 3 10
Linux 2.6.26-2-xen-amd64 (vm-serv)     2010.05.05     _x86_64_    (1 CPU)
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0,02    0,00    0,04   42,55    1,06   56,32
Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda              14,81        99,58       378,45  271387618 1031415098
sdb               0,09         3,31        10,65    9021638   29026500
dm-0              0,22         2,51         1,55    6841834    4223704
dm-1              0,00         0,00         0,00       2298       2536
dm-2              0,00         0,00         0,00       3672       2768
dm-3             36,88        91,10       286,31  248275050  780294952
dm-4              0,01         0,27         0,51     746794    1394200
dm-5              0,10         0,13         5,29     343488   14419374
dm-6              2,31         5,31        84,79   14475468  231076968
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0,33    0,00    0,00    0,00    1,98   97,69
Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda               7,59        29,04        89,77         88        272
sdb               0,00         0,00         0,00          0          0
dm-0              0,00         0,00         0,00          0          0
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0,00    0,00    0,00    0,33    0,00   99,67
Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda               9,30         5,32       441,20         16       1328
sdb               0,00         0,00         0,00          0          0
dm-0              0,00         0,00         0,00          0          0
dm-1              0,00         0,00         0,00          0          0
dm-2              0,00         0,00         0,00          0          0
dm-3             31,89         0,00       255,15          0        768
dm-4              0,00         0,00         0,00          0          0
dm-5              0,00         0,00         0,00          0          0
dm-6              3,99         5,32       186,05         16        560

Jei iostat renka tik įvesties ir išvesties operacinjų statistiką, tai sar gali pateikti tiek realaus laiko duomenis (nurodant sekundes ir kiek matavimų atlikti), tiek ataskaitų rinkmenose sukauptus duomenis, naudingus įvertinti sistemos darbo pokyčius. Komanda sar -u parodo per dieną surinktus kompiuterio CPU apkrovos rodiklius.

vm-serv:~# sar -u
Linux 2.6.26-2-xen-amd64 (vm-serv) 2010.05.05 _x86_64_ (1 CPU)

00:00:01 CPU %user %nice %system %iowait %steal %idle
00:05:01 all 0,02 0,00 0,03 0,01 0,22 99,72
00:15:01 all 0,02 0,00 0,02 0,01 0,18 99,77
00:25:01 all 0,02 0,00 0,02 0,01 0,26 99,69
00:35:01 all 0,02 0,00 0,02 0,01 0,16 99,79
00:45:01 all 0,02 0,00 0,02 0,01 0,14 99,80
00:55:01 all 0,01 0,00 0,01 0,02 0,17 99,78
01:05:01 all 0,02 0,00 0,02 0,01 0,23 99,72
01:15:01 all 0,02 0,00 0,02 0,01 0,18 99,77
...
05:05:01 all 0,01 0,00 0,02 0,02 0,18 99,77
05:15:01 all 0,01 0,00 0,02 0,01 0,18 99,78
05:25:01 all 0,02 0,00 0,02 0,01 0,21 99,75
05:35:01 all 0,01 0,00 0,02 0,02 0,21 99,74
05:45:02 all 0,02 0,00 0,02 0,01 0,21 99,73
05:55:01 all 0,02 0,00 0,02 0,01 0,21 99,75
06:05:01 all 0,01 0,00 0,02 0,01 0,18 99,77
...

...
19:45:01 all 0,01 0,00 0,02 0,01 0,15 99,80
19:55:01 all 0,02 0,00 0,01 0,01 0,22 99,73
20:05:01 all 1,02 0,00 0,66 10,13 1,32 86,88
20:15:01 all 3,70 0,00 1,00 12,92 4,11 78,26
20:25:01 all 0,37 0,00 0,19 0,02 0,61 98,81
20:35:01 all 0,04 0,00 0,03 0,01 0,74 99,19
20:45:01 all 0,02 0,00 0,03 0,02 0,58 99,36
20:55:01 all 0,01 0,00 0,02 0,02 0,24 99,71
21:05:01 all 0,12 0,00 0,04 0,07 0,39 99,38
21:15:01 all 0,02 0,00 0,02 0,02 0,29 99,64
Average: all 0,06 0,00 0,03 0,21 0,26 99,44
vm-serv:~#

Nurodžius parametrą -f galima pasiimti seniau sukauptus duomenis iš paskutinių 30 dienų archyvo:

vm-serv:~# sar -u -f /var/log/sysstat/sa01
Linux 2.6.26-2-xen-amd64 (vm-serv)     2010.05.01     _x86_64_    (1 CPU)

00:00:01        CPU     %user     %nice   %system   %iowait    %steal     %idle
00:05:01        all      1,73      0,00      0,48     78,06      1,71     18,03
00:15:01        all      2,04      0,00      1,78     15,27      0,72     80,20
00:25:01        all      3,26      0,00      1,97     21,06      0,60     73,12
00:35:01        all      2,39      0,00      3,10     29,96      0,84     63,71
00:45:01        all      0,03      0,00      0,09     42,30      3,35     54,22
00:55:01        all      0,01      0,00      0,04     30,95      1,82     67,17
01:05:01        all      0,02      0,00      0,07     46,05      0,33     53,54
01:15:01        all      0,03      0,00      0,05     61,50      0,24     38,18
...
05:05:01        all      0,01      0,00      0,03     50,09      1,17     48,70
05:15:01        all      0,01      0,00      0,04     60,37      1,34     38,25
05:25:01        all      0,01      0,00      0,04     51,09      1,16     47,71
05:35:01        all      0,01      0,00      0,03     44,97      0,95     54,04
...
21:15:01        all      0,02      0,00      0,23     78,62      0,80     20,33
21:25:01        all      0,01      0,00      0,07     98,75      0,74      0,43

21:25:01        CPU     %user     %nice   %system   %iowait    %steal     %idle
21:35:01        all      0,02      0,00      0,10     83,22      0,62     16,04
21:45:01        all      0,01      0,00      0,09     68,67      0,64     30,59
21:55:01        all      0,01      0,00      0,09     79,92      0,47     19,51
22:05:01        all      0,01      0,00      0,09     93,31      0,72      5,87
22:15:01        all      0,01      0,00      0,03     96,77      0,82      2,36
22:25:01        all      0,01      0,00      0,04     98,55      1,22      0,18
22:35:01        all      0,01      0,00      0,03     95,33      0,79      3,84
22:45:01        all      0,02      0,00      0,06     98,74      1,18      0,00
22:55:01        all      0,02      0,00      0,07     56,43      2,23     41,26
23:05:01        all      0,01      0,00      0,04     51,37      2,14     46,44
23:15:01        all      0,01      0,00      0,05     57,03      2,41     40,50
23:25:01        all      0,02      0,00      0,04     68,07      2,48     29,39
23:35:01        all      0,01      0,00      0,05     69,98      2,35     27,61
23:45:01        all      0,02      0,00      0,04     73,77      2,42     23,75
23:55:01        all      0,02      0,00      0,03     65,78      2,65     31,52
23:59:01        all      0,03      0,00      0,05     89,52      1,94      8,46
00:00:01        all      0,02      0,00      0,05     15,15      0,98     83,80
Average:        all      0,07      0,00      0,09     57,77      1,44     40,64

Pavyzdžiuose matomas akivaizdus skirtumas tarp to, kiek procentų laiko procesorius praleisdavo laukdamas diskinių operacijų mėnesio pirmą dieną, kol virtualios mašinos buvo saugomos failiniuose konteineriuose ir kiek jam tenka lūkuriuoti dabar. Atsisakius failinių konteinerių tiek virtuali mašina, tiek fizinė sistema tiesiog atsigavo ir komandų vykdymo ar katalogo turinio nebereikėjo laukti po 10 sekundžių.


LVM

Kaip ir daugelis kitų šiuolaikinių OS, Linux turi savo LVM („Logical Volume Manager“) disko tomų valdymo sistemos versiją. LVM yra naudingas tuo, jog leidžia labai lanksčiai išnaudoti ir valdyti diskinę ervdę. Diskinio kaupiklio skirsniai yra statinės struktūros, kurias po sukūrimo yra sunku pakeisti. Tuo tarpu LVM leidžia veikiant sistemai perkelti loginį tomą iš vieno diskinio kaupiklio į kitą, padidinti ar sumažinti tomo dydį, pridėti ar pašalinti kaupiklius iš tomų grupės ir t.t. Visa tai galima atlikti kompiuteriui veikiant ir jei tomuose sukurtos failų sistemos numato tokių pakeitimų galimybę - visiškai netrikdyti kompiuterio darbo.

Pasitelkus LVM galima padaryti aktyvių duomenų rezervines kopijas, kas kartais labai praverčia administruojant duomenų bazes ar kitus sparčiai kintančius duomenis.  LVM yra geras dar ir tuo, kad šis papildomas „sluoksnis“ beveik nelėtina diskinių operacijų.

Išsamų LVM vadovą galima rasti šiuose puslapiuose:

Taigi, 1 TB kaupiklis buvo suskaidytas į 3 skirsnius: įkrovos /boot ir du skirsnius LVM tomų grupėms. Vienas paskirtas pačiai Linux sistemai, kitas duomenims.

vm-serv:~# fdisk -l /dev/sda

Disk /dev/sda: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x000eb383

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          25      200781   83  Linux
/dev/sda2              26        3849    30716280   8e  Linux LVM
/dev/sda3            3850      121601   945842940   8e  Linux LVM
vm-serv:~#
vm-serv:~# pvdisplay -C
  PV         VG     Fmt  Attr PSize   PFree 
  /dev/sda2  rootvg lvm2 a-    29.28G  11.56G
  /dev/sda3  datavg lvm2 a-   902.00G 238.06G
vm-serv:~#

Visi LVM tomai yra pasiekiami, kaip /dev/mapper/tomugrupe-tomovardas blokiniai įrenginiai. Taigi jei turime tokius tomus LVM tomų grupėse:

vm-serv:~# lvdisplay -C
  LV                VG     Attr   LSize   Origin Snap%  Move Log Copy%  Convert
  storage           datavg -wi-ao 390.62G                                     
  vmhold            datavg -wi-ao 195.31G                                     
  xen-freenet-disk0 datavg -wi-ao   8.00G                                     
  xen-freenet-disk1 datavg -wi-ao  70.00G                                     
  root              rootvg -wi-ao  11.72G                                     
  swap              rootvg -wi-ao   4.00G                                     
  tmp               rootvg -wi-ao   2.00G                                     
vm-serv:~#

Tai sistemoje bus pasiekiami štai tokie blokiniai „įrenginiai“, kuriuos galima sužymėti, kaip savarankiškas failų sistemas ar pateikti, kaip virtualios mašinos talpyklą XEN virtualizavimo sistemai:

vm-serv:~# ls /dev/mapper/
control        datavg-vmhold            datavg-xen--freenet--disk1    rootvg-swap
datavg-storage    datavg-xen--freenet--disk0  rootvg-root            rootvg-tmp
vm-serv:~#

Sukūręs papildomus du tomus freenet virtualios mašinos kaupikliams - ėmiausi migracijos.


Virtualių mašinų migracija

Jei XEN virtualios mašinos kaupiklis buvo kuriamas, kaip vienas diskas, tai migracija yra gerokai paprastesnė. Tam tiesiog reikia sukurti identiško dydžio loginį tomą ir dd komandos pagalba perkopijuoti failo turinį į loginį tomą maždaug taip: dd if=/vm/domains/serveris/disk0.img of=/dev/mapper/datavg-server1--disk0. Visos rinkmenoje buvusios failinės srtuktūros bus sėkmingai atkartotos loginiame tome. Gana išsamus paaiškinimas, kaip tai padaryti yra šiame „HowTo Forge“ puslapyje.

Deja, mano XEN mašinos buvo aprašytos, nei kaip vienas diskas, o kaip skirsnių rinkinys, todėl vienai virtualiai mašinai man būtų reikėję sukurti 6 loginius tomus - po vieną kiekvienam skirsniui šioje XEN mašinoje. Numigravus antrą mašiną į LVM tomus, o vėliau eksperimentams susikūrus dar ir trečią - gautųsi jau gana didelis „zoologijos sodas“, kuriame sunku susigaudyti. Todėl buvo nuspręsta supaprastinti sistemą ir migruoti kiek kitaip. Nors šis būdas nėra labai elegantiškas, tačiau jis visai efektyvus.

Pirmiausia nauji LVM tomai, kurių dydis buvo parinktas pagal realių duomenų apimtį, buvo prijungti prie XEN mašinos, kaip papildomi diskiniai kaupikliai.

root        = '/dev/sda2 ro'
disk        = [
'file:/home/VM/domains/freenet/swap.img,sda1,w',
'file:/home/VM/domains/freenet/root.img,sda2,w',
'file:/home/VM/domains/freenet/var.img,sda3,w',
'file:/home/VM/domains/freenet/tmp.img,sda4,w',
'file:/home/VM/domains/freenet/home.img,sda5,w',
'phy:/dev/mapper/datavg-xen--freenet--disk0,sdb,w',
'phy:/dev/mapper/datavg-xen--freenet--disk1,sdc,w'
]

Perkrovus virtualią mašiną, diskiniai kaupikliai /dev/sdb ir /dev/sdc buvo suskaidyti į norimus skirsnius ir šie skirsniai buvo sužymėti ext3 failų sistemomis. Tuomet skirsniai buvo prijungti /mnt ir /mnt/home kataloguose ir sustabdžius aktyvias programas, visa Linux sistema su visais duomenimis buvo tiesiog perkopijuota į /mnt katalogą, kuriame buvo prijungti nauji diskai. Kopijuojant buvo nurodoma išsaugoti esamas failų nuosavybės teises. kadangi kopijuoti reikia ne viską, tai operacijos supaprastinimui viskas buvo daroma iš mc aplinkos. Kuria buvo palikti nepažymėti /proc, /sys ir aišku /mnt katalogai. Tiesa, failų sistemos buvo sužymėtos su specialiais parametrais. Namų katalogo skirsnis /dev/sdb1 buvo sužymėtas be vietos rezervavimo root vartotojui - tai naudinga tik sisteminiams skirsniams, o duomenų saugojimo skirsniuose tai tik veltui išmesti 5 proc. vietos. Taip pat šiems skirsniams buvo aktyvuotas writeback ext3 žurnalo darbo režimas, leidžiantis spartesnes failines operacijas duomenų saugojimo patikimumo sąskaita. Jei nesupratote apie ką čia -- data=writeback nuostatos nenaudokite. ;)

mkfs.ext3 -m 0 /dev/sdb1
mkfs.ext3 /dev/sda1
tune2fs -o journal_data_writeback /dev/sda1
tune2fs -o journal_data_writeback /dev/sdb1

Perkopijavus, buvo pataisytas /mnt/etc/fstab failas, iš kurio buvo išmesti visi nereikalingi skirsnių prijungimo taškai, nes naujoje sistemoje visa Linux sistema bus viename /dev/sda1 skirsnyje, o /home prijungtas, kaip /dev/sdb1. Galutinis fstab turinys atrodė štai taip:

freenet:~# cat /etc/fstab 
# /etc/fstab: static file system information.
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
proc            /proc           proc    defaults        0       0
/dev/sda2 none swap sw 0 0
/dev/sda1 /         ext3 async,noatime,data=writeback,errors=remount-ro,commit=30 0 1
/dev/sdb1 /home     ext3 async,noatime,nodev,nosuid,data=writeback,commit=30 0 1

Po visų šių operacijų /mnt/home ir /mnt buvo atjungtos ir virtuali mašina išjungta shutdown -h now komanda. Beliko tik pakeisti XEN virtualios mašinos aprašą ir pradėti naudoti naujus „kaupiklius“. Virtualios mašinos konfigūracijos failo diskinių kaupiklių dalis buvo pakeista taip:

root        = '/dev/sda1 ro'
disk        = [
                  'phy:/dev/mapper/datavg-xen--freenet--disk0,sda,w',
                  'phy:/dev/mapper/datavg-xen--freenet--disk1,sdb,w'
              ]

Kadangi XEN savo Linux virtualioms mašijoms OS branduolį „sustumia“ iš fizinės mašinos, tai OS migracijai visiškai pakako paprasčiausiai perkopijuoti failus ir pakeisti sistemos įkrovos įrenginį. Jei tai būtų kokia KVM ar Virtual Box mašina, tai po perkopijavimo tektų pažaisti su chroot komanda bei įkrovos tvarklyklės (GRUB arba LILO) diegimu į naują kaupiklį, antraip jos paprasčiausiai neįsikrautų.

Po šios operacijos XEN virtualios mašinos visiškai atlaisvino CPU ir laisvo laiko pakako paskirstytųjų skaičiavimų klientui įdiegti. Kviečiu ir jus prisidėti prie šių visuomeninių projektų ir paskirti nepanaudotą CPU laiką mokslinių tyrimų duomenims apdoroti. Berklio universiteto sukurta paskirstytųjų skaičiavimų sistema BOINC šiuo metu vienyja daugiau nei pusę milijono kompiuterių, kurie apdoroja dešimčių projektų duomenis. Tokių projektų pavyzdžiais gali būti „World Community Grid“ ar garsusis SETI@Home  (https://www.launchknowledge.com/seti-at-home-alternatives/ SETI@Home užsidarė).