OpenBSD: Terhelés-elosztó web szerver készítése CARP-pal

Címkék

Az OpenBSD-vel foglalkozó előző írásaimban megismerkedhettünk az OpenBSD 3.5 telepítésének menetével, elvégeztük a rendszer alapvető beállítását, lefordítottuk a saját, az OpenBSD csapat által támogatott kernelünket, majd megpróbáltunk magas rendelkezésre-állású failover web szervert készíteni az OpenBSD 3.5-ben bemutatkozó CARP segítségével.

Az elkészült web szerverünk szépen tette is a dolgát egy ideig. Szerencsére sikerült olyan web tartalommal feltölteni, amelyre sokan voltak kíváncsiak.

Egyszer csak azt vettük észre, hogy a web szerverünk folyamatosan lassult, majd először csak délutánonként nem volt elérhető, a későbbiekben pedig rendszeresen kiszolgálási gondjaink akadtak. Főleg olyankor, amikor egy-egy sokat látogatott oldalon linkelték a mi web oldalunkat, és hirtelen nagy számú kérés érkezett felénk, amelyet a web szerverünk nem tudott kiszolgálni. Az interneten a fent leírt jelenséget Slashdot effektusnak nevezik. A Slashdot effektus, vagy egyéb nagy webes terhelés ellen egy ideig harcolhatunk úgy, hogy nagyobb teljesítményű processzort, több memóriát, gyorsabb merevlemezt építünk a gépünkbe, de egy idő után rá kell jönnünk, hogy az ilyen típusú terhelések ellen egy géppel nem vehetjük fel sikerrel a harcot.Szóval két dolgot tehetünk, az egyik, hogy felfele, vertikálisan skálázzuk a rendszerünket, a másik pedig az, hogy horizontálisan bővítjük azt. Lássuk, hogy melyik típusú skálázás mit jelent.

Fel skálázás (scale-up):

------------------------

Pár évvel ezelőtt még de facto szabvány eljárásnak volt tekinthető a felfele történő skálázás akkor, ha egy rendszer teljesítményét növelni kellett. A recept egyszerű volt, vegyél még nagyobb, még erősebb vasat, tömj bele egy marék processzort, egy zsák memóriát, SCSI merevlemezeket, gyors hálózati csatolót. Ha ez egy idő után kevés lesz, akkor tegyél bele ezekből kétszer annyit, vagy kétszer gyorsabbat. A piacra egyre gyorsabb és gyorsabb processzorok érkeztek - egy ideig szinte követve Moore híres törvényét - így biztosított volt, hogy egyre nagyobb teljesítmény zsúfolhassunk egy darab rendszerbe. Aztán a szabványnak tekinthető elgondolás megdőlt, több okból is kifolyólag: egy idő után képtelenség felfele skálázni, mert nem tudunk több és gyorsabb eszközt beleépíteni a gépbe. A gép egymaga nem képes redundáns működésre, így ha meghibásodik, akkor a rajta futó szolgáltatások elérhetetlenné váltak. Ezért megszületett az új elgondolás, az oldal irányba történő skálázás.

Ki skálázás (scale-out):

------------------------

Az oldal irányban skálázott rendszerek is sokkal nagyobb teljesítményt nyújtanak, mint egy szóló rendszer, de teljesen más megközelítésből. Clusterezéssel, vagy egyéb más eljárással feldaraboljuk a rendszerre irányuló terhelést, azokat elosztjuk több kisebb teljesítményű szerver között, így az egyes szerverek képesek megbirkózni a nagy terhelés rájuk háruló kisebb részeivel. Magyarul a munkát nem egy nagy vas (szaknyelven előforul big iron néven is) végzi, hanem több kisebb szerver, amelynek az összegzett teljesítménye azonban meghaladja az egy nagy szerver teljesítményét. Már most látszik, hogy ennek az elképzelésnek sok előnye van az előzőhöz képest. Az egyik a redundáns működés. Ha a rendszerünk egyik tagja kiesik mondjuk meghibásodás miatt, akkor a többi szerver függetlenül a leállt tagtól, tovább tud szolgáltatni. A jelenség annyi lesz, hogy a kiesett tag feladata a többi szerverre hárul, és azokon elosztva annyival nagyobb workload jelentkezik, amennyit a kiesett szerver végzett. A másik előnye ennek a megközelítésnek, az, hogy szinte a végtelenségig bővíthető, szemben a big iron megközelítéssel. Tegyük fel, hogy a 4 node-ból álló webszerverünk már nem képes kiszolgálni a kéréseket. Mit teszünk? Egyszerűen üzembe helyezünk egy újabb node-ot, és a probléma meg van oldva. Ha egy nem elég, akkor beüzemelünk még egyet, kettőt, vagy éppen ahányra szükségünk van.

Tehát a mai jelszó a oldal irányú skálázás! Már csak azért is mert a cikksorozat az OpenBSD köré épül, és ha akarnám se tudnám a rendszert felfele skálázni, annál az egyszerű oknál fogva, hogy az OpenBSD nem képes felfele növekedni. Hogy miért? Mert nem támogatja az SMP-t (több processzoros működést), és egy processzornál többet nem képes (jelenleg) kezelni.

Szóval scale-out. Nézzük mi jöhet szóba:

RR DNS:

-------

Az első ami eszembe jut, az a szegény ember load-balancer-je a Round Robin DNS (hívják LB DNS-nek is). A RR DNS lényege, hogy az egy web oldalra irányuló kéréseket több gépre osztjuk el úgy, hogy a hosthoz több bejegyzést készítünk a DNS szerverben. Tételezzük fel, hogy a hup.hu zónafile-jában az alábbi bejegyzéseket készítjük a (BIND) DNS szerverünkön:

www 60 in A 195.228.252.138

www 60 in A 195.228.252.139

Mostantól ha valaki lekéri a www.hup.hu IP címét a DNS szerverektől, akkor az esetek felében a 195.228.252.138-as címet, míg az esetek másik felében a 195.228.252.139-es címet fogja visszakapni.

# host www.hup.hu

www.hup.hu has address 195.228.252.138

www.hup.hu has address 195.228.252.139

majd utána:

# host www.hup.hu

www.hup.hu has address 195.228.252.139

www.hup.hu has address 195.228.252.138

Az alkalmazasok nagy része csak az elsőnek visszakapott számot használja fel, így a dolog szépen működik. Kb. az esetek felében a kérés az egyik szerverre, míg az esetek másik felében a masik szerverre érkezik. A DNS konfigban a TTL (Time To Live) értéket lehetőleg alacsonyan kell tartanunk, hogy az útban levő cache DNS szerverek ne tartsák sokáig gyorsítótárban az IP címeket és ne ``ragadjanak le'' az egyiknél. Így a terhelés szépen közelítőleg 50-50%-ban eloszlik a két gép között.

``Hurrá, megcsináltuk!" - kiálthatnánk fel, és itt véget is érne a cikk. Igen megcsináltuk, de ha ilyen egyszerű lenne, akkor nem lennének komoly berendezések, amelyek ezt a funkciót biztosítják. Ennek a megoldásnak vagy egy nagy hátránya. Ha az egyik szerver kiesik, akkor a DNS feloldások felében a kliens gépek egy olyan szerver IP címét adják vissza, amely már nem él. Ez komoly probléma lehet. A megoldás ilyenkor, az lehet, hogy 1.) módosítjuk a DNS konfigurációt, és megvárjuk míg az elterjed a többi DNS szerver között, 2.) ``gányolunk'', és ping, shell, és arp manipuláló segédprogramokat felhasználva a meghalt gép IP-címét átvesszük az élő gépre. Vagy kitalálunk valami mást...

Van egy másik (olcsó) megoldás is (drága van több is), mégpedig az, hogy munkába fogjuk az OpenBSD-t és a CARP-ot.

A múlt alkalommal felépítettünk egy failover CARP rendszert, amelynek egyik hibája az volt, hogy nem biztosított terhelés-elosztást. Ezt fogjuk most tovább fejlesztni.

Tehát a kiindulási alap ugyanaz, mint a múltkor. Ahhoz, hogy egy ARP elosztott virtuális hostot létre tudjunk hozni, mind a két fizikai hostra (Puffy és Rock) konfigurálni kell egy virtuális hostot, amely majd válaszolni fog az ARP kérésekre, és ez által kezelni fogja a webes forgalmat.

Először felállítjuk a carp csatoló-felületeket a Puffy névre hallgató gépen:

# ifconfig carp0 create

# ifconfig carp0 vhid 1 pass foobar 192.168.5.100

(eddig jutottunk a múltkot, és most folytatjuk)

# ifconfig carp1 create

# ifconfig carp1 vhid 2 advskew 100 pass foobar 192.168.5.100

Majd felállítjuk a carp csatoló-felületeket a Rock névre hallgató gépen is:

# ifconfig carp0 create

# ifconfig carp0 vhid 1 advskew 100 pass foobar 192.168.5.100

(itt eddig jutottunk a múltkor, és innen folytatjuk)

# ifconfig carp1 create

# ifconfig carp1 vhid 2 pass foobar 192.168.5.100

Ha ez kész, akkor az ARP balancing funkciót engedélyezni kell mindegyik hoston:

# sysctl net.inet.carp.arpbalance=1

(reboot után is maradandó beállítást a /etc/sysctl.conf fileban kell elkövetni)

Amikor a hostok ARP kérést kapnak a 192.168.5.100-as címre, a kérés IP címe alapján kiválasztódik az egyik virtuális host. A virtuális host azon tagja fog válaszolni a kérésre, amelyik a MASTER, a többi pedig ignorálja a kérést. Mivel mindig az a host lesz a MASTER a virtuális hostok közül, amelyik gyakoribb időközönként hirdeti magát, abban az esetben, ha az 1-es számú virtuális host (vhid 1) választódik ki, akkor a Puffy névre hallgató gép fog a kérésre válaszolni, mert a vhid 1-ben ő a MASTER. Ebből következik, hogy a 2-es számú virtuális host (vhid 2) kiválasztódása esetén a Rock névre hallgató gép fog válaszolni, hiszen a vhid 2-vel jelölt virtuális hostban a Rock a MASTER.

A konfiguráció az alábbiak szerint néz ki a Puffy-ról nézve:

és a Rock-ról nézve:

A fenti konfigurációból az következik, hogy az ARP kérések eloszlanak (a kérés forrásának címe alapján) a virtuális (vhid 1 és vhid 2) hostok között, melynek az eredménye az lesz, hogy a webes forgalom is eloszlik a hostok között. Ha az egyik host meghal, akkor a másik magához ragadja a virtuális MAC address-t, és az fog a továbbiakban a kérésekre válaszolni.

A fenti konfigurációnak is van hátránya természetesen. Az egyik, hogy csak akkor működik az ARP balancing, ha a csoport tagjai egy fizikai subnet-en helyezkednek el. A CARP-ban implementált load balancing magában sajnos nem tökéletes. Mivel a CARP a kérést indító IP címének HASH-e alapján dönti el, hogy melyik virtuális host fogja a kérést lekezelni, sokat nem várhatunk tőle. Például abban az esetben, ha le szeretnénk tölteni egy file-t a szerverről, és azzal egy időben még böngészni is szeretnénk a web szerveren, akkor sajnos ugyanattól a szervertől fogjuk kapni az adatokat.

Bővebb információt a carp(4), sysctl(3), inet(4), ifconfig(8), sysctl(8) oldalakon kaphatsz.

Jó barkácsolást!

Hozzászólások

Van opensource eszkoz a load alapjan valo szervervalasztashoz? Vagyis, hogy ahhoz a szerverhez menjen a keres amelyiknek a legkisebb volt a load-ja az lekerdezes elott.

Az otlet trivialias, kell egy kicsi php oldal, ami a /proc/loadavg tartalmat adja vissza. Igy megvan az alkalmazas szintu ping-is, es a load is visszajon. Ezt kell lekerni a DNS szerverrol mondjuk 5sec-enkent, es ez alakjan sulyozni egy veletlen valasztast a szerverek kozott(ha mindegyiknek azonos a loadja, akkor egyenlo valoszinuseggel kapjak a kovetkezo lekerest)

A kerdesem az volt, hogy _uzembiztos_, _tesztelt_, _kiprobalt_ megvalositas van-e opensource-ben?

Az ipvs-ben (linux nat-csicsa modul) van olyan, hogy az aktiv kapcsolatok szamanak aranyat (sulyt) adhatsz meg webserverenkent. Igy ha vmely webserver belassul barmi okbol kifolyolag, akkor az aktiv kapcsolatok aranyanak tartasa eppen a masik webserverhez valo nat-ot eredmenyezi. Ez egyebkent inkabb terheleselosztasra jo, nem rendelkezesreallas-javitasra.

Érdekes és ügyes megoldás.

A cikkel kapcsolatban: miért is jpeg a konzol screenshot?

Ejnye. Irgumburgum. És egyebek.

>>>A DNS konfigban a TTL (Time To Live) értéket lehetőleg alacsonyan kell tartanunk, hogy az útban levő cache DNS szerverek ne tartsák sokáig gyorsítótárban az IP címeket és ne ``ragadjanak le'' az egyiknél. Így a terhelés szépen közelítőleg 50-50%-ban eloszlik a két gép között.

-----------------------

egy kis pontositas:

a DNS cachekben mindket A record benne lesz, tehat nem "ragadnak be". Minden egyes (kozbulso) DNS szepen round-robinolni fog.

A TTL-t csak akkor kell alacsonyan tartani, ha a rekordot a kozeljovoben valtoztatni akarod.

Nem kell feleslegesen terhetli a DNS-t.

hostmaster@fsn.hu-nak:

Ez peldaul felesleges:

portal.fsn.hu. 0 IN A 195.228.252.138

Honapok ota igy all.

udv

>a DNS cachekben mindket A record benne lesz, tehat nem "ragadnak be". Minden egyes (kozbulso) DNS szepen round-robinolni fog.

Olvass el par RR DNS leirast. Ahanyat en olvastam, az osszes javasolja a TTL ertek alacsonyan tartasat.

1.) "We set the TTL low (to 60 seconds) to prevent any intervening caching DNS servers from hanging onto one sort order for too long"

2.) " The TTL value should be kept to a low value, so that the DNS cache is refreshed faster."

3.) "Reducing the TTL value on the individual records can mitigate the caching problem at the expense of DNS transactions."

sorolhatnam meg.

>hostmaster@fsn.hu-nak:

Ez peldaul felesleges:

portal.fsn.hu. 0 IN A 195.228.252.138

Honapok ota igy all.

Teves. 2 eve igy all. :-D (de ezt mar megbeszeltuk).

>Olvass el par RR DNS leirast. Ahanyat en olvastam, az osszes javasolja a TTL ertek alacsonyan tartasat.

Akkor tevesek a leirasok.

Probald ki pl a www.google.com-ot.

A kozbulso DNS az a szolgaltatod nameserver-e lesz, es megsem ragad be csak az egyik IP-re. (es a TTL nem 0, hanem 300)

>Teves. 2 eve igy all. :-D (de ezt mar megbeszeltuk).

ahh:)

>A kozbulso DNS az a szolgaltatod nameserver-e lesz, es megsem ragad be csak az egyik IP-re. (es a TTL nem 0, hanem 300)

Hol lattal te 0-as TTL-t? A cikkben az van irva, hogy tartsuk alacsonyan (60 van benne).

Azert ezt a linket atolvasnam a helyedben:

Round Robin low TTL @ Google [www.google.com]

(4870 oldal tevedne?)

"Understanding DNS and its load-balancing capabilities

By setting a low TTL, administrators can use DNS to help achieve load balancing. A low TTL forces clients and local servers to query the authoritative server frequently, giving the authoritative server the opportunity to reply with a different IP... "

:-D

A cikk szuper, már csak _Joel és kisza kifogásaira várok... ;-P

A végéhez hozzáfűznék még egy gondolatot: webszervernél, de úgy általában, bármilyen Internetes szervernél a fenti megoldás teljességgel használhatatlan terheléselosztásra.

Hogy miért? Mert az Ethernet keretekben a forrás MAC cím mindig ugyanaz lesz (a router MAC címe), így a forgalom csak az egyik gép felé fog menni, a másik felé csak akkor, ha az elsővel valami gond van.

Pont errol irtam. Nem arrol volt szo, hogy magas TTL-lel nem fog mukodni a RR. Hanem arrol, hogy celszeru alacsony ertekel uzemeltetni.

Ha megall az egyik host, es valamilyen modon kiveszuk a halott host IP cimet, akkor gyorsabban vezetodnek at a valtozasok. Megsutheted ebben az esetben, ha magas ertekekkel nyomatod a TTL-t.

BTW mit jelent az RR DNS-nel, hogy csak akkor kell alacsonyra venni, ha valtoztatni akarom? Tudom elore, hogy mikor fog meghalni az egyik host? :-D

A cikk jo! Az egesz sorozat tetszik. Orulok, hogy foglalkoztok a temaval!

Viszont en inkabb a CARP-ot routerre vagy tuzfalra hasznalnam. Ket olcsobb, kissebb teljesitmenyu gepet raknek be tuzfalnak CARP-al megoldva a magas rendelkezesreallast es pf-el forwardolnam a kereseket a kiszolgalok fele. Pfsync-el meg a ket fuzfal kozott a state tabla megosztast.

Szerintem ezzel a modszerrel lehet elerni a legjobb load balancingot. Nagyobb biztonsagot is ad es gyorsabban lehet skalazni a rendszert.

Szerintem ez a megoldás a való világban nem nagyon állja meg a helyét.. ha az ARP kérést intéző forrás IP címe alapján dől el, milyen ARP választ adunk, akkor bukott az egész... interneten lévő szervernél ugyanis ARP kérés nagy valószínűséggel egy, és csakis egy IP felől fog érkezni, mégpedig a gatewaytől, aki ráadásul el is cacheli szépen a választ. De lehet, hogy valamit nem jól értelmezek a cikkben, ennyire az OpenBSD-sek se lehetnek hülyék, vagy lehet, hogy inkább ez a dolog nem is load balancera akar szolgálni, hanem csak fail overre. De akkor meg a cikknek nincs értelme.

A tema irant melyebben erdeklodoknek figyelmebe ajanlom az ftp://ftp.hit.bme.hu/sys/anonftp/jereb/teljanal

konyvtarban levo pdf file-okat..:)