Hlavní navigace

OpenVZ: přidělování zdrojů fyzického stroje

18. 9. 2012
Doba čtení: 9 minut

Sdílet

Ve třetím díle našeho seriálu o OpenVZ se seznámíme s počítadly fazolek – UserBeanCounters – tedy s mechanizmem, pomocí kterého OpenVZ řídí a účtuje, kolik procesů, souborů a obecně paměti může virtuální server spotřebovat. Podíváme se také na přidělování a účtování využití procesorového času.

Se zdroji fyzického stroje je to jednoduché - kolik paměti a jak výkonný procesor si koupíte, tolik máte. S virtuálními servery je to složitější. Některé virtualizační technologie to správci hodně zjednoduší a umožní virtuálnímu serveru přidělit paměť, počet procesorů, a tím to končí. Jiné, jako OpenVZ, poskytují správci mnohem jemnější kontrolu nad přidělovanými zdroji.

V předchozích dílech seriálu jsem se opomněl zmínit, že je velmi vhodné použít na VE0 64bitový kernel. Pokud zvolíte 32bitový, musíte počítat s tím, že některé zdroje musí OpenVZ alokovat z prvních 832 MB RAM. To je totiž prostor, který je vždy namapovaný do adresového prostoru kernelu, ostatní paměť je pak přístupná pomocí stránkování, což přístup zpomaluje. Pokud se vás to týká, přečtěte si obecné informace o tzv. Low Memory na LWN.net, a poté o dopadech na OpenVZ. Potřebujete-li provozovat 32bitový software uvnitř CT, není to problém na 64bitovém hostiteli. Problémy mohou nastat jen při kompilaci, pokud si autor ušetřil práci a parsuje výstup uname.

Přidělování a správa zdrojů v OpenVZ

OpenVZ přiděluje zdroje hostitele (VE0) pomocí čtyř mechanismů User BeanCounters, CPU Fair-Share plánovače, diskové quoty, a nakonec priority a accounting I/O operací. První dva mechanismy se vám pokusím vysvětlit v tomto dílu seriálu.

UBC aneb User BeanCounters

UBC jsou základní komponentou řízení zdrojů. Obsahují řadu parametrů, které definují, kolik a jakých zdrojů může container použít. Parametry ovládají především dostupnou paměť, a to i nepřímo, např. v podobě maximálního počtu otevřených souborů.

Rychlý přehled o jednotlivých zdrojích získáte zobrazením souboru /proc/user_beancounters. Ten je k dispozici nejen uvnitř containeru, ale i na VE0. Jen na VE0 je soubor poněkud nepřehledný, protože obsahuje informace o všech CT. Přehlednější informace jsou k dispozici v souboru /proc/bc/<CTID>/resources. Uvádím příklad z containeru:

root@deb6:/# cat /proc/user_beancounters
Version: 2.5
   uid  resource        held  maxheld   barrier                limit  failcnt
 1000:  kmemsize     2134853  2355374  14372700             14790164        0
        lockedpages        0        0       256                  256        0
        privvmpages     2658     2707     65536                69632        0
        shmpages           0        0     21504                21504        0
        dummy              0        0         0                    0        0
        numproc           11       13       240                  240        0
        physpages       2047     2047         0  9223372036854775807        0
        vmguarpages        0        0     33792  9223372036854775807        0
        oomguarpages    2047     2047     26112  9223372036854775807        0
        numtcpsock         3        3       360                  360        0
        numflock           3        4       188                  206        0
        numpty             1        1        16                   16        0
        numsiginfo         0        1       256                  256        0
        tcpsndbuf      52320        0   1720320              2703360        0
        tcprcvbuf      49152        0   1720320              2703360        0
        othersockbuf  138720   147176   1126080              2097152        0
        dgramrcvbuf        0        0    262144               262144        0
        numothersock     163      166       360                  360        0
        dcachesize    200772   208494   3409920              3624960        0
        numfile          338      373      9312                 9312        0
        dummy              0        0         0                    0        0
        dummy              0        0         0                    0        0
        dummy              0        0         0                    0        0
        numiptent         10       10       128                  128        0

Sloupec resource představuje název jednotlivých parametrů, sloupec held aktuálně držené množství prostředků a maxheld hodnotu maximálně držených prostředků od startu virtuálního serveru. Sloupce barrierlimit jsou nastavené limity pro jeden každý parametr. Některé parametry využívají obě hodnoty, jiné jen jednu a některé žádnou, ty pak slouží pouze pro accounting. Např. u parametru vmguarpages představuje hodnota limit maximální počet stránek paměti, které smí container alokovat, a hodnota barrier je garantovaný počet stránek, které jsou containeru k dispozici. Mělo by platit barrier <= limit.

Poslední sloupec failcnt je počítadlo, kolikrát nebyl požadavek containeru na ten který zdroj uspokojen. Z uživatelského hlediska je právě on tím nejdůležitějším. Když vidíte, že některý z nich roste, je pravděpodobné, že virtuální server strádá nějakým nedostatkem. V ten okamžik nastává moment, kdy je nutné se ponořit do dokumentace UBC a nastudovat, jestli je nutné s parametrem hýbat. Hodnota failcnt se nedá snadno vynulovat, ale existuje program vzubc, který umožňuje UBC zobrazovat relativně.

prvním článku jsem vytvořil první virtuální server příkazem:

root@ve0:~# vzctl create 1000 --ostemplate debian-6-amd64 --ipadd 172.16.206.100 --hostname deb6

Neuvedl jsem parametr –config, takže mu byly přiděleny limity ze souboru /etc/vz/conf/ve-basic.conf-sample. Jsou relativně nízké a je docela pravděpodobné, že se uživatel takto připraveného CT seznámí s přibývajícími fazolkami ve sloupci failcnt hodně rychle.

Záleží hodně na účelu, pro který virtuální server vytváříte. Z vlastní zkušenosti vám ale nedoporučuji používat uvedené minimální limity. Jsou celkem nízké. Hodně ořezaný virtuální server znamená, že uživateli severu leccos nebude fungovat. Bude vás kontaktovat a vy to budete muset řešit. No a ve finále skončíte s tím, že budete mít řadu CT s hodně rozdílnými parametry.

Většina parametrů je nějakým způsobem závislá na dostupné operační paměti, zkuste tedy limity nastavit podle toho, kolik operační paměti by zamýšlený virtuální server potřeboval na fyzickém HW. Pro spočtení hodnot jednotlivých parametrů slouží program vzsplit. Např. máte-li fyzický server s 16 GB RAM a předpokládáte-li, že virtuálnímu serveru postačí 1 GB, zadejte:

ve0:~# vzsplit -n 16 -f 1G_RAM
Config /etc/vz/conf/ve-1G_RAM.conf-sample was created

vzsplit vytvořil konfigurační soubor /etc/vz/conf/ve-1G_RAM.conf-sample, v němž jsou parametry odpovídající jedné šestnáctině zdrojů hostitele. V uvedeném příkladu má hostitel 16 GB RAM. Virtuální server vytvořený podle tohoto konfiguračního souboru bude mít 1 GB paměti. Použití předpřipraveného souboru je snadné:

root@ve0:~# vzctl create 1010 --config 1G_RAM --ostemplate debian-6-amd64 --ipadd 172.16.206.110 --hostname deb6

Porovnání hodnot pro konfigurační soubor basic1G_RAM:

parametr soubor basic soubor 1G_RAM
barier limit barier limit
numproc 240 240 5124 5124
numtcpsock 360 360 5124 5124
numothersock 360 360 5124 5124
vmguarpages 33792 9223372036854775807 677212 9223372036854775807
kmemsize 14372700 14790164 209884672 230873139
tcpsndbuf 1720320 2703360 48973653 69961557
tcprcvbuf 1720320 2703360 48973653 69961557
othersockbuf 1126080 2097152 24486826 45474730
dgramrcvbuf 262144 262144 24486826 24486826
oomguarpages 26112 9223372036854775807 677212 9223372036854775807
privvmpages 65536 69632 2459586 2705544
lockedpages 256 256 10248 10248
shmpages 21504 21504 245958 245958
physpages 0 9223372036854775807 0 9223372036854775807
numfile 9312 9312 81984 81984
numflock 188 206 1000 1100
numpty 16 16 512 512
numsiginfo 256 256 1024 1024
dcachesize 3409920 3624960 45847363 47222784
numiptent 128 128 125 125

Nastavení limitů hodně ovlivňuje účel, pro který jste si OpenVZ vybrali. Mé zkušenosti, s nimiž píšu tento seriál, vychází z potřeby redukovat množství low end fyzických serverů a koncentrovat služby na kvalitních serverech vyšší třídy s tím, že služby ani jejich správci nemají být příliš omezováni. Limity pak nastavuji tak, aby virtuální server, na který probíhá DoS, nespotřeboval veškeré zdroje platformy. Když virtuální server potřebuje větší zdroje, po žádosti správce je obvykle dostane.

Dostanete-li se do situace, že budete chtít upravit jednotlivé parametry virtuálního serveru, použijte příkaz vzctl, syntaxe:

# vzctl set <ctid> --save --<parametr> <barier>:<limit>

Důležité je nezapomenout parametr –save. Bez něj se hodnoty parametru neuloží do konfiguračního souboru a po restartu CT se vrátí na původně nastavenou hodnotu. Po změně parametru se vyplatí nechat si zkontrolovat závislosti s ostatními parametry. K tomuto účelu slouží program vzcfgvalidate, použití je prosté:

root@ve0:~# vzcfgvalidate /etc/vz/conf/1000.conf
Validation completed: success

V případě chyby vypíše srozumitelně, co je třeba změnit, uvádím příklad z našeho produkčního serveru (kterým bych se asi moc chlubit neměl):

# vzcfgvalidate /etc/vz/conf/<CTID>.conf
Warning: dcachesize.lim should be > 1536000 (currently, 1097728)
Error: tcpsndbuf.lim-tcpsndbuf.bar should be > 409600 (currently, 1000000-700000=300000)
Error: othersockbuf.lim-othersockbuf.bar should be > 1280 000 (currently, 1200000-500000=700000)
Warning: tcprcvbuf.lim-tcprcvbuf.bar should be > 409600 (currently, 1000000-700000=300000)
Error: limit should be = 9223372036854775807 for physpages (currently, 2147483647)

Měl bych tedy zvýšit limit dcachesize, ale hlavně upravit barier a limit u tcpsndbuf, tcprcvbufothersockbuf. Když jsou tyto hodnoty příliš nízké, dochází k zamrzání síťových spojení.

Jakmile začnete s hodnotami jednotlivých UBC parametrů manipulovat, studiu dokumentace se nevyhnete. Dokumentace rozděluje parametry do tří skupin, vychází z vnitřní struktury OpenVZ, takže rozdělení nemusí být na první pohled zřejmé:

primární parametry
Jejich hodnota ovlivňuje hodnoty sekundárních parametrů. Jedná se o numproc, numtcpsock, numothersockvmguarpages. Nejčastěji je třeba upravit numproc (maximální počet procesů) a numtcpsock (maximální počet TCP socketů).
sekundární parametry
Hodnota těchto parametrů je ovlivňována hodnotou příslušných primárních parametrů, vztahy jsou uvedeny v dokumentaci. Jmenovitě se jedná o kmemsize, tcpsndbuf, tcprcvbuf, othersockbuf, dgramrcvbuf, oomguarpagesprivvmpages. Je skutečně třeba dodržovat doporučené limity, ale i tak občas v praxi narážím na narůstající failcnttcprcvbuf, případně tcpsndbuf, obvykle ve spojení s nedobrým výkonem TCP spojení, a velmi zřídka dokonce se zamrzáváním spojení. Pomáhá zvýšení hodnoty nad minimální doporučenou hodnotu.
doplňkové parametry
O těchto parametrech dokumentace říká, že ovlivňují bezpečnost a stabilitu celého systému, že zlepšují to, jak se aplikace uvnitř containeru vyrovnávají s případným nedostatkem zdrojů. Je jich poměrně hodně: lockedpages, shmpages, physpages, numfile, numflock, numpty, numsiginfo, dcachesize, numiptent, swappages. V praxi se setkáte se situací, že aplikace, která nedostane to, co potřebuje, prostě zkolabuje. Nejčastěji upravuji shmpages (sdílená paměť, Apache ji používá rád a hodně), numfile (počet otevřených souborů) a numiptent (počet položek IP firewallu).

Jednotky, ve kterých se parametr měří, jsou naznačeny v jeho názvu. Parametry obsahující num jsou počty položek. Parametry obsahující v názvu page jsou paměťové stránky, velikost stránky se liší podle systému, na x86 and x86_64 je to 4096 B a na IA64 je stránka velká 16384 B.

Monitoring UBC

V praxi můžete narazit na fakt, že budete potřebovat znát časovou závislost vývoje spotřeby jednotlivých parametrů u konkrétního CT. Mně se hodně osvědčil Munin. Výhodu spatřuji v tom, že jednou nastavím server, který sbírá data z jednotlivých uzlů (hostitelů virtuálních serverů), a jednotliví hostitelé virtuálních serverů pak sami předávají informace o UBC jednotlivých CT, které na nich běží. Před několika lety jsem pro Munin připravil plugin, který používám dodnes. Grafy, které produkuje, se výborně hodí, když je třeba zpětně řešit nějaký problém.

Příklad vývoje velikosti buferů pro jednotlivé sockety:

CPU Fair-Share plánovač

Plánovač OpenVZ zajišťuje přidělování času procesoru ve dvou úrovních. V první úrovni přiděluje čas procesoru jednotlivým CT. Při této činnosti se řídí hodnotou parametru cpuunits, který je přidělen každému jednomu virtuálnímu serveru. Po tomto rozhodnutí je řízení předáno standardnímu linuxovému plánovači, který na základě priorit procesů rozhodne, kterému procesu přidělí čas.

Hodnota cpuunits nemá přímou vazbu na cykly procesoru. Jedná se o poměrnou hodnotu, která získává význam až v poměru vůči součtu všech cpuunits na systému. Jinými slovy můžete použít hodnoty 1 1 1 nebo 200 200 200 a nebo 8888 8888 8888 - a CT dostanou stejný díl času. Pokud uděláte toto:

# vzctl set 1001 --cpuunits 1000 --save
# vzctl set 1002 --cpuunits 2000 --save
# vzctl set 1003 --cpuunits 3000 --save

pak CT 1001 dostane 1000/6000, neboli 17 % času, CT 1002 dostane 2000/6000, neboli 33 % času a CT 1003 dostane 3000/6000, neboli 50 % času. Toto platí ale pouze tehdy, pokud všechny CT vyžadují čas procesoru. Pokud CT 1003 nevyžaduje CPU, jeho díl se rozdělí mezi ostatní CT, pokud ty CPU potřebují.

Je-li z nějakého důvodu potřeba omezit maximální spotřebovaný čas procesoru určitým CT, je k dispozici parametr cpulimit. Ten udává, kolik procent z jednoho CPU může CT využít, takže hodnota může být větší než 100, pokud chcete přidělit víc než jedno jádro. Dalším parametrem je cpus, kterým můžete omezit počet jader, k nimž bude mít CT přístup (nastavení ovlivňuje i obsah /proc/cpuinfo, a lze ho provádět za běhu).

Bohužel tato možnost je k dispozici pouze v kernelu verze 2.6.18. Mám ji otestovanou na RHEL 5.5 s kernelem 2.6.18–128.2.1.el5.028stab064.8. Na Debian Squeeze s kernelem 2.6.32–5-openvz-amd64 to nefunguje. V roce 2005 jeden z vývojářů přiznal, že opustili svůj plánovač a používají defaultní linuxový.

Soubor /proc/vz/vestat obsahuje statistiku o využití procesoru jednotlivými CT. Sloupce user, nice, system, uptime jsou v jiffies. idle, uptime (druhý výskyt) a used jsou v cyklech procesoru. Pro zajímavost uvádím část výpisu z našeho produkčního serveru:

# cat /proc/vz/vestat
Version: 2.2
   VEID       user        nice      system       uptime                idle  strv             uptime              used  maxlat  totlat  numsched
   1001    2377472       12039      778289   1407929044   23347007112226694     0   2956770446265516     8340747864432       0       0
   1002   11562678    79207885    51819967   3228189174   53062117348749001     0   6779471159378854   301530700545860       0       0
   1003  100462869  2428380224  1060215341   6164220823   93118401848819349     0  12945386729084366  7515216979094341       0       0
   1004    1440440           0     1739857   6515373490  102929127518504858     0  13682837124463623     7311914244470       0       0
   1005   10318933       90338     8912664  12214370580  202231032930022943     0  25651214571771123    50665663063448       0       0
   1006    5331847           0    21646446  12539606845  204930997400964221     0  26334238322678234    61678306608473       0       0
   1007   78940070      144485     8389905  15102223064  253238230150021975     0  31715949818023758   197645192017021       0       0
   1008   35402455      109889    10527892  15103160860  252992838415551643     0  31717919269130391   141679427381790       0       0
   1009    4493092        6810     4185957  15133369749  253628805278848224     0  31781360499479364    58063096149059       0       0
   1010   21377827      103323    34991401  15133429525  253216433063174771     0  31781486032310792   128684994932897       0       0
   1011   45970735     9108323    42381841  15133819159  248486749910943882     0  31782304297116858   209358507834538       0       0
   1012    3313472       31764     3609644  15133856927  252897634907919124     0  31782383614523084    48816716280752       0       0
   1013    6422412           0    14667208  15133884769  250767746840303880     0  31782442084703238    53807557319602       0       0
...

Pro reálné použití účtování CPU budete muset do OpenVZ trochu proniknout nebo se zeptat v konferenci. Přiznávám, že jsem takhle detailní accounting nikdy v praxi nepotřeboval.

CS24 tip temata

Zjištění příslušnosti procesu k CT

OpenVZ umožňuje správci nahlédnout do útrob jednotlivých CT, a tak se při správě virtualizačního serveru nemusíte omezovat jen na přidělování a počítání cyklů procesoru. Pomocí klasických linuxových nástrojů můžete procesy monitorovat. Když už identifikujete proces, který spotřebovává víc, než by měl, budete potřebovat zjistit, ke kterému CT patří. K tomu účelu slouží program vzpid. Jeho použití je jednoduché:

root@ve0:~# ps aux --sort pcpu |tail -5
2000 24516 56.6 0.1 12004 10468 ? RN 08:23 80:24 dnetc -hide -ini /usr/local/dnetc/dnetc.ini
2000 24519 57.0 0.1 12016 10468 ? RN 08:23 80:56 dnetc -hide -ini /usr/local/dnetc/dnetc.ini
2000 24517 58.5 0.1 12008 10468 ? RN 08:23 83:04 dnetc -hide -ini /usr/local/dnetc/dnetc.ini
2000 24518 58.6 0.1 12012 10468 ? RN 08:23 83:15 dnetc -hide -ini /usr/local/dnetc/dnetc.ini
2000 24514 60.1 0.1 11996 10464 ? RN 08:23 85:25 dnetc -hide -ini /usr/local/dnetc/dnetc.ini
root@ve0:~# vzpid 24514
Pid VEID    Name
24514   1001    dnetc

Tímto se s vámi dnes rozloučím a za domácí úkol vám nechám vyřešení tohoto zbytečného pálení energie uživatelem CT 1001. Příští díl seriálu bude o diskové kapacitě a zálohování.

Autor článku

Jan Tomášek v současnosti pracuje pro CESNET, z. s . p. o. jako vývojář v oblasti PKI a správy uživatelských identit. Ve volném čase se věnuje krajinné fotografii a geocachingu.