A HAProxy¶
A webszolgáltatást nyújtó konténerek egyetlen host gépen működtetése felvet egy hálózattal kapcsolatos problémát, amelynek megoldása egy újabb alkalmazás bevezetésével oldható meg. Egy ilyen szoftver a HAProxy, amit nem csak erre, hanem egyfajta terheléselosztóként is fel lehet használni – ezért érdemes alaposan megismerni. Ebben a fejezetben megismerjük a HAProxy egyik fő funkcióját és áttekintjük egy egyszerű konfigurációs beállítását leginkább ezért, hogy betekintést kapjunk annak szolgáltatási körébe és konfigurációs szabályaiba. A fejezetben az alábbi témakörökről lesz szó:
A virtuális webszerverek hálózati kommunikációjának problémája.
A HAProxy működése.
Példa konfiguráció a webszolgáltatást nyújtó konténerek működtetésére.
Szükséges eszközök: |
Linux operációs rendszerű (virtuális) számítógép, telepített Docker és HAProxy szoftverrel. A virtuális gép letölthető a dl.koczka.com oldalról (Login: |
Feldolgozási idő: |
Kb. 3 óra, a gyakorlati feladatok megoldására további 2 óra. |
A konténerek egyik tipikus alkalmazási területe a különféle website-ok egymástól független kialakítása. Egy konténerek működtetésére kialakított szervernek nem kell webszerver szoftvert vagy adatbáziskezelő-rendszert tartalmaznia, ezek kialakítása már nem a rendszert üzemeltető mérnök, hanem a devops fejlesztő feladata.
Egy webkonténereket futtató szerver kialakítása során viszont problémát jelent a bejövő web kérések továbbítása a megfelelő konténer felé. Ennek kezelése nem egyszerű, mivel a bejövő TCP csomagok fejléce nem tartalmazza a webhely nevét, csupán a 80-as (titkosítatlan http) vagy a 443-as (titkosított https) port szám alapján állapítható meg, hogy web kérésről van szó. Abban az esetben ha egy szerver csak egyetlen webhelyet szolgál ki, ez nem jelent problémát, de ha a cél egy kiszolgálón több, különböző domain néven elérhető webkonténerek működtetése, az OSI modell szállítási rétegére már nem hagyatkozhatunk: az oda érkező TCP csomagok szintjén nem lehet az egyes webhelyekre küldött kéréseket szétválasztani.
Az alkalmazás kiválasztása a port szám alapján¶
A legegyszerűbb megoldást a gyakorlatban nehezen elfogadható kompromisszum kényszer jelentené: az egyes website-ok URL-jében meg kellene adni az ahhoz tartozó port számot is valahogy így: http://www.qq.com:8081. Ez a megoldás technikai, vagy csak kevesek által használt weboldalak esetében még csak-csak elfogadható lenne, de általánosan használt oldalak esetében biztosan nem – az internet felhasználók nem tudnák/akarnák megjegyezni az egyes weboldalakhoz tartozó egyéni port számokat.
A megoldást ezért egy olyan, a 443-as és a 80-as port forgalmát fogadó alkalmazás jelenti, amely az összes bejövő web kérést fogadja, és megszünteti a névvel kapcsolatos hiányosságot: képes a csomagokból kiolvasni a címzett website nevét is, s így meg tudja állapítani, hogy a bejövő kérést melyik belső konténernek kell továbbítani. Ezzel a port számok megadását el lehet kerülni, és a megfelelő útvonal kiválasztását a domain név alapján lehet megtenni úgy, hogy a problémát sem a felhasználó, sem pedig a konténer nem érzékeli. Ezt a funkcionalitást web proxy-nak nevezik, mivel az egy köztes szolgáltatást nyújt a kliens és a szerver adatforgalmának megvalósításában.
Megjegyzés
A proxy fogalmát a Gartner IT szótára így definiálja: „A proxy-kiszolgáló egy olyan eszköz, amely közvetítőként működik a kiszolgáló erőforrásait igénylő ügyfelektől érkező kérésekhez.”
Több olyan szoftver létezik, amely az említett feladatot látja el, mi egy népszerű változat, a HAProxy működését és beállítását tekintjük át. A HAProxy nevében szereplő HA a high availability, vagyis a magas rendelkezésre állás rövidítése, ez fejezi ki a program eredeti célját. Mi viszont nem erre fogjuk használni, hanem a bejövő web kérések szétosztására a szerveren futó belső konténerek között úgy, ahogyan az alábbi ábrán látható.
A HAProxy a domain név alapján választja ki a megfelelő konténert¶
A szerver tehát minden bejövő web forgalmat (http-t és https-t) a HAProxy-nak ad át, ami az összes, eredetileg a webszervernek címmzett csomagot fogad. A proxy ezekből kiolvassa annak a cél webhely nevét, és az adatokat a saját konfigurációja alapján a megfelelő konténer belső IP címére irányítja. A proxy rögzíti a kapcsolati információkat is, így a konténer válaszait ugyanezen az úton küldi vissza el a kliens felé, ami úgy érzékeli, hogy az eredeti választ nem a konténertől, hanem a proxytól kapta.
Ezután lássuk, hogyan kell egy HAProxy szervert beállítani! A példában a konténereink futtatását eleve egy Linux operációs rendszer végzi, ezért a szoftvert arra fogjuk telepíteni, és beállítani, ami egyáltalán nem bonyolult: az apt update után az apt install haproxy parancsra van csak szükségünk.
1root@docker:/root# apt update && apt install haproxy
A sikeres telepítést követően be kell állítanunk a program működését, ehhez a /etc/haproxy/haproxy.cfg fájlt kell szerkeszteni, majd a változások érvényesítéséhez a szolgáltatást újra kell indítani a systemctl restart haproxy paranccsal. Az alábbi példa egy minimális konfigurációt tartalmaz, amelyben a HAProxy két website között végez olyan útválasztást, aminek alapja az egyes weboldalak elérésére szolgáló URL lesz. A szerveren tehát két konténerizált web alkalmazás fut, ezeket példánkban a http://web-1.pelda.hu és a http://web-2.pelda.hu nevekkel érünk el. A megoldásban mindkét website-ot a 80-as külső porton szeretnénk elérni, nem szeretnénk port számokat írni a weboldal címébe. Ez alapján tehát pusztán a megfelelő weblap URL-je lesz az, mely alapján a HAProxy a megfelelő site válaszait a kliens böngészőjének visszaadja. A HAProxy konfigurációja az alábbi lesz, az egyes részek jelentését a példa után magyarázzuk el.
1global
2 log /dev/log local0
3 log /dev/log local1 notice
4 chroot /var/lib/haproxy
5 stats socket /run/haproxy/admin.sock mode 660 level admin
6 stats timeout 30s
7 user haproxy
8 group haproxy
9 daemon
10
11defaults
12 log global
13 mode http
14 option httplog
15 option dontlognull
16 timeout connect 5000
17 timeout client 50000
18 timeout server 50000
19
20frontend http_front
21 bind *:80
22 acl host_web-1.pelda.hu hdr(host) -i web-1.pelda.hu
23 use_backend backend_web-1.pelda.hu if host_web-1.pelda.hu
24 acl host_web-2.pelda.hu hdr(host) -i web-2.pelda.hu
25 use_backend backend_web-2.pelda.hu if host_web-2.pelda.hu
26
27backend backend_web-1.pelda.hu
28 server web-1.pelda.hu 127.0.0.1:5000 check
29
30backend backend_web-2.pelda.hu
31 server web-2.pelda.hu 127.0.0.1:5001 check
A konfigurációs fájl a HAProxy esetében ún. szekciókra van felosztva, az első a global, amely a program általános beállításait tartalmazza. Ebben többek közt meghatározzuk, hogy a háttérben futó programot milyen felhasználói jogosultságokkal kell futtatni (biztonsági okokból ez nem a root, hanem a haproxy lesz). Emellett beállítjuk a program naplózási (logolási) mechanizmusát és a statisztikák képzésének módját. A defaults szekcióban alapértékek meghatározása olvasható, pl. különféle időkorlátoké (timeouts). Utóbbiak azok az idők, ameddig a HAProxy különböző eseményekre vár, ez egy kliens kérésére pl. 50.000 milliszekundum: ha ennyi időn belül a kliens nem fejezi be a kérés küldését, az erőforrások védelme érdekében a HAProxy megszakítja a kapcsolatot.
Az alapértékek beállítását a gyakorlatban egyszer szoktuk elvégezni, általában a korábbi tapasztalat alapján bevált értékeket szoktunk alkalmazni, attól általában csak valamilyen hiba, vagy eltérő körülmény miatt szoktunk eltérni.
A program frontend és backend szekciói már az egyes website-ok útválasztását definiálják. A bind *:80 azt jelenti, hogy a proxy minden, a gépbe épített hálózati kártya forgalmát figyeli (*) és a 80-as portra érkező TCP csomagokat feldolgozza. (Az egyszerűség kedvéért most a https-sel nem foglalkozunk, ehhez nem csak a port forgalmát kellene kezelni, hanem ún. tanúsítványokat is létre kellene hozni – ez túlmutat jegyzetünk keretein.) Minden egyes konténerhez három elemet kell meghatározni:
Mely bejövő kéréseket,
Melyik ún. backendhez kell továbbítani,
És az egyes kéréseket melyik belső webszerver szolgálja majd ki.
acl host_web-1.pelda.hu hdr(host) -i web-1.pelda.hu
A sor jelentése röviden: ha a bejövő kérés célja a http://web-1.pelda.hu. Az egyes részek jelentése:
- acl:
Ez a kulcsszó egy szabályt definiál, amely alapján a HAProxy döntést hoz a bejövő kérés sorsáról. Ez a szabály különböző jellemzőket vizsgálhat meg, többek közt a web kérés URL-jét, a port számot, de akár a használt protokollt is, így eltérő szabályt tudunk létrehozni a titkosítatlan
httpés a titkosítotthttpsprotokollok esetére is.- host_web-1.pelda.hu:
Minden szabálynak nevet kell adni, ez teszi lehetővé, hogy a későbbiekben hivatkozni tudjunk rá. A HAProxy esetében általános gyakorlat, hogy ez a név a
host_szöveggel kezdődik, majd az adott website URL-jével folytatódik.- hdr(host):
Ez az elem tulajdonképp egy változó, amely a bejövő kérés fejlécéből kiolvasott URL-t tartalmazza. Ez az egyes konténerek esetén különböző lesz, értéke példánkban
http://web-1.pelda.hu- -i:
Ez biztosítja, hogy az URL összehasonlítása case insensitive, azaz a kis- és nagybetűk megkülönböztetése nélkül történjen.
- web-1.pelda.hu:
A konténer elérésének URL-je, ez az a név, amelyet, ha a fejléc tartalmaz, a szabály teljesül.
A következő sor rövid jelentése: ha a host_web-1.pelda.hu szabály teljesül, használd a backend_web-1.pelda.hu nevű backendet! Az egyes elemek jelentése feltehetően egyértelmű az olvasó számára.
use_backend backend_web-1.pelda.hu if host_web-1.pelda.hu
Végül a backend definíciója következik, ami leírja, hogy a kérést melyik konténer mely portjára kell továbbítani. Az alábbi példában a backend_web-1.pelda.hu backend definíciója olvasható. Ennek első sora tulajdonképpen az előzőkben hivatkozott backend neve, a másodikban pedig a server kulcsszót és egy egyedi nevet követően azt a belső IP címét és port számát adjuk meg, ahová a kérést továbbítani kell. Ez a példánkban a helyi gép 5000-es portját használó konténer lesz:
backend backend_web-1.pelda.hu
server web-1.pelda.hu 127.0.0.1:5000 check
Bár ez a hármas konfiguráció első olvasatra bonyolultnak tűnik, valójában nem az, néhány website beállítása után a továbbiak hozzáadása rutin művelet lesz. Az egyes részfeladatok jobb megértése érdekében végezzük el az alábbi komplex feladatot!
Gyakorlat HAProxyra¶
Konfigurálj be egy Linux szervert két, egymástól függetlenül működő, konténerizált webalkalmazás működtetésére úgy, hogy azok a http://web-1.pelda.hu és a http://web-2.pelda.hu URL-ről legyenek elérhetők, és különböző tartalmakat jelenítsenek meg! Mivel a két webalkalmazást egyetlen szerver szolgálja ki, ezért azon egy HAProxy-t kell bekonfigurálni a bemutatott példa alapján. A feladat egyes lépéseit az alábbiak szerint érdemes végrehajtani:
Szerverként egy Virtualboxban futó, Ubuntu Linux 24.04LTS operációs rendszerű virtuális gépet fogunk használni, amire feltelepítjük a HAProxy-t és elvégezzük annak beállításait. A Dockert már tartalmazó virtuális gép a dl.koczka.com oldalról tölthető le (Ubuntu-24.04-LTS-Docker). Importáld a gépet a Virtualboxba, majd a hálózati beállításoknál ellenőrizd, hogy a virtuális gép hálózati interfésze a munkaállomás megfelelő fizikai interfészével legyen összerendelve!
Indítsd el a szervert, jelentkezz be a
usernévvel és azoga12Fongjelszóval, majd jegyezd fel a gép IP címét, amelyet az ip address list paranccsal lehet lekérdezni.A kényelmesebb munkavégzés érdekében jelentkezz be erre a gépre a Putty segítségével!
Indítsd el a
koczkaferenc/web-1.pelda.hu:1és akoczkaferenc/web-2.pelda.hu:1konténereket a háttérben úgy, hogy az egyes konténerek neve a kiszolgált web URL-je legyen! Az első konténer az 5000-es, a második az 5001-es porton legyen elérhető! Maguk a konténerek a 80-as belső porton működnek.Ellenőrizd le a konténerek működőképességét a
http://<szerver_ip>:5000és ahttp://<szerver_ip>:5001URL-ek megtekintésével!A szerveren a sudo -s paranccsal válts át rendszergazdai jogkörbe, és telepítsd a haproxy csomagot!
A fejezetben szereplő példa konfigurációs fájlt másold a szerver
/etc/haproxy/haproxy.cfgfájljába!Indítsd újra a haproxy szolgáltatást a
systemctl restart haproxyparanccsal!A teszteléshez a
web-1.pelda.hués aweb-2.pelda.huneveknek a virtuális gép IP címére kell mutatni, ezért azokat fel kell venni a Windows gépen aC:windowssystem32driversetchostsfájlba az alábbi alakban (avirtuális_gép_ip_címehelyére értelemszerűen a szerver gép P címét kell megadni):virtuális_gép_ip_címe web-1.pelda.hu virtuális_gép_ip_címe web-2.pelda.hu
Teszteld a
http://web-1.pelda.hués ahttp://web-2.pelda.huoldalak tartalmát! Amennyiben minden lépést sikerült végrehajtani, két különböző weboldal fog megjelenni.
Tennivaló
A megoldás folyamatát bemutató videó megtekinthető itt.
Összefoglalás¶
Az eddigi fejezetek megmutatták, hogy a konténerek egyik legjellemzőbb felhasználási területe a webalkalmazások köré csoportosul. A különféle webszerverek, webes alkalmazások, REST API kiszolgálók tipikus példák, amelyeket kifejezetten ajánlott konténerizált környezetben működtetni. Az egyes konténerek szokásos, tehát port szám megadása nélkül történő elérése egy proxy szoftver nélkül sajnos nem lehetséges, ezért ebben a fejezetben egy ilyet ismertünk meg. Egy példán keresztül végeztük el a HAProxy alapvető konfigurációját, amely során elsősorban a név alapú útválasztásra koncentráltunk.