Sistemos apkrovaNamų serverio konfigūracija keitėsi ne vieną kartą. Įprastini ų programinių servisų serveris buvo paverstas virtualiųjų mašinų serveriu, tuo pačiu pasitobulinant virtualizacijos žinias bei palaipiojant ant vienokių ar kitokių grėblių. Nuo to laiko praėjo daugiau, nei metų, o kompiuterijos srityje tai labai daug - ištisa amžinybė. Per šį laiką serveryje buvo pakeistos net kelios kartos diskinių kaupiklių, daugeliu atveju dėl kaupiklių gedimų. Taip kiekvieną kartą serverio talpykla po truputį augo, senuosius diskus po vieną pakeičiant naujais didesniais kaupikliais. Duomenis visuomet pavyko išsaugoti, nors kartą berods teko atkūrinėti pabirusią failų sistemą ir prisiminti, kad rezervines kopijas galima ne tik kurti, bet ir iš jų atsistatyti duomenis.

Po paskutinės migracijos serveryje buvo likę 3 diskai, kuriuose buvo sukonfigūruoti 3 RAID5 masyvai. Jau tuomet žinojau, kad konfigūracija nėra optimali, bet sistema, kaip ir veikė. Tuo metu visi servisai jau buvo išmigruoti į Docker programinius konteinerius, o virtualios mašinos sustabdytos. Palyginus su virtualiomis mašinomis, Docker konteineriai veikė gerokai sparčiau. Taip yra dėl kelių priežasčių. Pirmiausia, konteinerio procesų virtualizavimui reikia mažiau išteklių, nes programinio konteinerio struktūra yra paprastesnė, nei viso kompiuterio virtualizavimas. Antra, Docker konteineriai tiesiog naudoja serverio failinę sistemą, todėl bendrai paėmus reikia mažiau disko I/O operacijų, kurios trunka labai ilgai (palyginus su CPU skaičiavimo operacijomis).

Taigi laikas ėjo ir vėl ėmė niežėti nagus, nes prieš keletą metų ant technologijų bangos buvęs Docker buvo išstumtas ir dabar naudojamas tik, kaip konteinerių paleidimo technologija bei kūrimo įrankis. O konteinerių infrastruktūros valdymo srityje dabar yra vienvaldis lyderis - Kubernetes. Tuo pat metu pribrendo laikas dar vienai serverio modernizacijai bei Kuberntes klasterio sukūrimui. Tiesa, kol kas klasterio dydį apribotas vienu serveriu, tačiau tai netrukdo naudoti Kubernetes privalumais. Vienas pagrindinių privalumų yra serviso teikimo užtikrinimas, kurį su Docker Compose teko spręsti įvairių Shell scenarijų ir sistemos servisų kokteiliu. Bet apie tai kitą kartą. Vos tik įdiegus Kubernetes ir numigravus pirmuosius Docker Compose servisus į Kubernetes, paaiškėjo, kad serveris ėmė veikti vėžlio greičiu, o sistemos apkrovos lygis nuolat pakildavo virš 4-5.

Atrodytų viskas turėjo būti puiku, nes Kuberntes naudoja tuos pačius Docker konteinerius, kurie naudoja tą pačią serverio failų sistemą. Bet yra vienas "bet". Klasterio konfigūracijos saugojimui Kubernetes naudoja "etcd" duomenų bazę, kuriai nuolat užklausas siunčia Kubernetes komponentai. Etcd siekia užtikrinti įrašų išlikimą ir juos išsaugo pastoviojoje atmintyje, t.y. diske. Pažiūrėjus į sistemos apkrovos ataskaitas tapo aišku, kas nutiko.

Po paskutinės serverio migracijos serveryje atsirado 3 RAID masyvai, sukurti /dev/md4, /dev/md5 ir /dev/md6 disko skirsniuose. Pirmajame RAID5 masyve yra saugomas /boot katalogo turinys - jis yra statinis ir keičiamas tik atnaujinant sistemos branduolį. Masyve /dev/md5 yra saugomi operacinės sistemos LVM tomai, o trečiajame /dev/md6 yra programų duomenys. Kol serveryje buvo naudojama tik Docker konteinerių valdymo sistema, tai diskinės operacijos buvo sutelktos į vieną RAID5 masyvą - /dev/md6. Taip yra todėl, kad Docker Compose nenaudoja aktyvios konteinerių stebėsenos ir nebando išsaugoti šios būsenos diske. Įkrovus ir kol pakanka operatyviosios atmintinės - Linux irgi nerašinėja į diską be reikalo.

Viskas pasikeitė įdiegus Kubernetes. Kadangi šis komponentas yra įdiegtas operacinės sistemos RAID masyve, tai kiekvienas Kubernetes "pirstelėjimas" yra pažymimas etcd duomenų bazėje. Tuo pačiu sistema ėmė generuoti daug disko I/O operacijų sistemos RAID masyve. 5 lygio RAID masyvas išsaugo ne tik duomenis, bet ir kontrolinę sumą, leidžiančią juos atkurti, praradus vieną iš kaupiklių. Taigi kiekviena rašymo operacija turi būti atlikta 3 diskuose. Todėl jei į diską bando rašyti ir Kubernetes valdymo sistema, ir serverio teikiamas servisas, tai Linux sistemai reikia atlikti 6 diskines operacijos, kurių kiekviena trunka keletą ar keliolika milisekundžių. Vienu metu diskas gali atlikti tik vieną diskinę operaciją ir jos metu bus blokuojamos procesoriaus komandos, t.y. procesorius lauks, kol diskas baigs savo darbą. Etcd generuoja daug skaitymo ir rašymo operacijų, nors ir nedidelių ir dėl to Linux sistema negali optimizuoti duomenų perdavimo servisų programoms. Jai reikia pertraukti servisų programų duomenų skaitymą ir nuskaityti/rašyti duomenis iš kitos disko vietos, kur saugomi Etcd duomenys.

Problemos sprendimas yra paprastas - atskirti skaitymo/rašymo duomenų srautus. Tai padaryti galima tik vienu būdu - nuperkant ir įdiegiant papildomus diskinius kaupiklius. Žinant, kad Etcd ražo dažnai ir po nedaug, tai tokiam darbui geriau tinka SSD kaupikliai. Sulaukęs prie Kalėdas užsakytos siuntos, ėmiausi serverio atnaujinimo.

Darbų planas yra toks:

  1. Naujuose diskiniuose kaupikliuose sukurti skirsnius /boot ir sistemos masyvams.
  2. Sukurti /dev/md0 ir /dev/md1 RAID1 masyvus
  3. Perkelti /boot duomenis iš /dev/md4 į /dev/md1 masyvą ir suinstaliuoti Grub įkroviklį į naujus diskus.
  4. Pridėti /dev/md1 į rootvg LVM tomų grupę.
  5. Permigruoti duomenis į naujus diskus
  6. Išmesti seną /dev/md5 iš LVM grupės.

Taigi pirmas žingsnis, sukurti du pirminius skirsnius fdisk programa ir pažymėti aktyvų skirsnį. Kadangi RAID1 masyvas yra veidrodis, tai /boot duomenims paskyriau 400MB skirsnį.

vm-serv:/etc# fdisk  -l /dev/sda
Disk /dev/sda: 223.6 GiB, 240057409536 bytes, 468862128 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x811f1967

Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 821247 819200 400M 83 Linux
/dev/sda2 821248 468862127 468040880 223.2G 83 Linux

Turėdamas skirsnius, toliau sukūriau RAID1 masyvus.

mdadm -Cv /dev/md0 -l1 -n2 /dev/sda1 /dev/sdb1
mdadm -Cv /dev/md1 -l1 -n2 /dev/sda2 /dev/sdb2

vm-serv:/etc# mdadm --detail /dev/md0
/dev/md0:
Version : 1.2
Creation Time : Mon Dec 28 13:24:43 2020
Raid Level : raid1
Array Size : 408576 (399.00 MiB 418.38 MB)
Used Dev Size : 408576 (399.00 MiB 418.38 MB)
Raid Devices : 2
Total Devices : 2
Persistence : Superblock is persistent

Update Time : Mon Dec 28 13:28:33 2020
State : clean
Active Devices : 2
Working Devices : 2
Failed Devices : 0
Spare Devices : 0

Consistency Policy : resync

Name : vm-serv:0 (local to host vm-serv)
UUID : 3224c351:d6f24e63:484cbd8f:6aa58546
Events : 17

Number Major Minor RaidDevice State
0 8 1 0 active sync /dev/sda1
1 8 17 1 active sync /dev/sdb1

Įkrovos duomenų migracijai prireiks perkelti pačius duomenis ir pakeisti įkrovos skirsnio UUID reikšmę /etc/fstab faile, kad sistema prijungtų /boot turinį iš tinkamo įrenginio.

mkfs.ext4 /dev/md0
umount /boot
# Pakeitus UUID reikšmė į naują
mount /boot
mount /dev/md4 /mnt2
rsync -avz /mnt2/ /boot/
umount /mnt2
grub-install /dev/sda
grub-install /dev/sdb

Toliau liko ilgiausiai trunkanis darbas - sulaukus, kol iki galo susikurs /dev/md1, permigruoti duomenis.

pvcreate  /dev/md1
vgextend rootvg /dev/md1

Ir galiausiai

vm-serv:/etc# pvmove /dev/md5 /dev/md1
File descriptor 7 (pipe:[217815]) leaked on pvmove invocation. Parent PID 7979: bash
/dev/md5: Moved: 0.00%
/dev/md5: Moved: 0.36%
/dev/md5: Moved: 0.79%
...
/dev/md5: Moved: 99.36%
/dev/md5: Moved: 100.00%

Duomenų migravimui prireikė maždaug 20 minučių, maždaug tiek pat, kiek ir sukurti /dev/md1. Po to jau galima buvo pašalinti /dev/md5 iš LVM tomų grupės.

vgreduce rootvg /dev/md5

Viskas, po keleto valandų sistemos apkrovos lygis atsistatė į įprastinį 1-2, o svarbiausia CPU "Wait" parametras dabar beveik visuomet yra mažiau 10%.

Papildymas: Ne ne viskas. Iki pilnos laimės dar reikia atnaujinti iinitrd atvaizdus, antraip perkrovus sistemą greičiausiai gausim ką nors panašaus į "kernel panic, unable to mount root on....". Taigi iki pilnos laimės dar trūksta maždaug tiek:

pvremove /dev/md5
mdadm --stop /dev/md4
mdadm --stop /dev/md5
mdadm --detail --scan >> /etc/mdadm.conf
#gautą failą pataisyti ir palikti tik aktualius RAID masyvus.
update-initramfs -u -k 'all'
update-grub

Tai jau turėtų būti, kaip ir viskas. O nepanaudotus 200GB kaip nors sugalvosiu, kaip prisijungti prie pagrindinio RAID, nesugriaunant viso masyvo. Kol kas vietos dar netrūksta.