A Docker hálózatkezelése

hálózati kábel kép pixabay.com-ról

Alap szinten nem sokat kell tudni arról, hogy milyen hálózattípusok vannak a Docker konténerek esetén. Rá lehet bízni a Dockerre, hogy hozza létre, ami szükséges, hiszen neked az eredmény kell, nem az oda vezető út. Mégis érdemes kicsit elmélyedni benne, mivel több olyan kérdésre választ adhatnak, amire nem is gondolnád, hogy kíváncsi vagy. Még nem... Olyan szituációkra gondolok, hogy miért ilyen IP-t kapott a konténer, miért nem látod az IP címét, miért nem éred el úgy, mint máskor és mi az ördög az az ingress vagy overlay és miért volt baj, hogy letörölted. Ahogy próbáltam megérteni a hálózatok működését, magam is úgy jöttem rá, hogy eddig tévedésben éltem. Úgy gondolom, hogy most már tisztábban látok, és ezt fogom összegezni a következőkben.

Tartalom

Docker hálózatokról általában

[Tartalom]

Bár nem feltétlenül kell, hogy egy konténer hálózatot is kapjon, hacsak felül nem bírálod, mindegyik csatlakozik egy alapértelmezetthez. Kapnak tehát IP címet valamilyen IP tartományból. Hogy milyen címet kapnak, az több tényezőtől függ. Ettől pedig az is, hogy hogyan lehet a konténerben levő szolgáltatást, akár egy webszervert elérni. Van lehetőség egyedi hálózati interfészeket létrehozni és azokra rácsatlakozni, de vannak olyanok, amik automatikusan jönnek létre, és bizonyos esetekben az egyedi és az alapértelmezés között működésbeli különbségek vannak. Egyes hálózatfélék már a Docker telepítésével létrejönnek és használhatók, mások pedig csak a Swarm klaszternél lesznek érdekesek.

Azt is meg kell tudni oldani, hogy a konténereket kívülről is el lehessen érni, tehát szükség esetén még a szervergépek egyes portjait is át kell irányítani a szolgáltatások, illetve konténerek felé. Amíg egy kérés a felhasználótól végül eljut a konténerig, az lehet egyszerűbb, vagy komplikáltabb, hosszabb úton történő.

Több szempont alapján is megkülönböztethetők a hálózatok. Egy részt vannak lokálisak, amik csak egy Docker hosztról érhetők el, és vannak a swarm hálózatok, amik nem egy gépen, hanem több gép között értelmezendők, így biztosítva a különböző gépeken futó szolgáltatások együttműködését egy virtuális, közös hálózatban. Ezen túl többféle driver létezik, amik más-más helyzetre adnak megoldást, és ezeket a drivereket felhasználva a Docker létrehoz néhány saját hálózatot is.

Hálózatok 1 gép esetén

"null" driver , azaz nincs hálózat

[Tartalom]

A "null" driver azt jelenti, hogy nincs hálózat. Nyilván nincs értelme több "nincs hálózat"-nak, ezért ilyen, további egyedi hálózatot nem is lehet létrehozni. Egyedül a "none" néven lehet a már létezőre hivatkozni. Igen, tudom, van itt egy kis képzavar, hiszen létezik egy hálózattípus, ami azt jelenti, hogy nem létezik, de valahogy csak hivatkozni kell rá.

Ebben az esetben a konténer nem kap IP címet és nem tud sem az internetre csatlakozni, sem pedig más konténereket elérni. Mondjuk egy bash szkriptnél, aminek semmi keresnivalója nincs a neten, és főleg semmi köze ahhoz, mit csinál a többi konténer, teljesen felesleges is, hogy legyen hálózata.

"host" driver

[Tartalom]

A "host" driver azt jelenti, hogy a konténer nem kap saját net névteret. A gazda rendszer hálózatait látja. Ilyen módon nem lehetne ugyanazon a porton indítani több szolgáltatást. Legyen az akár több mysql szerver vagy több webszerver. Akkor jó, amikor el akarod kerülni a hálózat izolációját az egyszerűség kedvéért, hogy biztosan minden port elérhető legyen átirányítás nélkül. Esetleg a programnak épp az interfészekkel kell dolgoznia vagy minden konténert elérnie. Ilyen hálózatból is csak egy lehet, tehát újat nem lehet létrehozni, de nem is lenne értelme. A neve pedig a driverrel egyezően "host".

"bridge" driver

[Tartalom]

A bridge egy drivert is jelent, de az alapértelmezett, bridge típusú hálózatnak is ez a neve. Ha nem adod meg, mire csatlakozzon a konténer és le sem tiltod, hogy bármire is csatlakozzon, akkor a "bridge" nevű lesz a nyerő. Ilyenkor a konténer egyszerűen csak kap egy IP címet egy meghatározott IP tartományból. A default bridge-nél ez a 172.17.0.0/16. A kapott címen a gazda rendszerről bármelyik konténer elérhető, illetve kívülről a gazda portjai erre a címre átirányíthatók.

Van viszont egy fontos különbség az alapértelmezett bridge és az egyedileg létrehozott bridge-ek között. Az alapértelmezett bridge-re csatlakozó konténerek csak akkor tudják elérni egymást a konténer nevét használva hosztnévként, ha össze vannak linkelve. A link viszont már egy "legacy feature", ami többek között azt érte el, hogy amennyiben "web1" konténer létrehozásakor "web2" konténer linkként meg lett adva, "web2" konténer IP címe és neve bekerül "web1" konténer hosts fájljába a konténer ID-jával és az opcionális álnévvel együtt. Egyedi hálózatnál viszont az azonos hálózatba tartozó konténerek automatikusan elérhetik egymást a konténerek nevét használva, és ehhez nem kell módosítani a konténer hosts fájlját.

Amikor Docker Compose-zal indítasz szolgáltatásokat, minden Compose projekthez egy ilyen egyedi bridge hálózat jön létre. 172.18.0.0/16, 172.19.0.0/16 stb... IP tartományokban. Ráadásként ilyenkor nem csak a konténer neve, de a szolgáltatás neve is használható doménként azonos hálózatban. Ezért is kell figyelni, hogy ne legyen véletlenül rácsatlakoztatva ugyanarra az egyedi hálózatra két különböző Compose projektben levő, de azonos nevű szolgáltatás, mivel akkor a nevet doménként használva hol az egyik, hol a másik konténer IP címére mutatna.

Swarm klaszter hálózatok

[Tartalom]

Nyilván, amíg csak egy gép van, egyszerűbb a helyzet, ám klaszterbe nem csak a különböző gépeken levő konténerek kommunikációját kell megoldani, hanem a klaszter vezérlése, a Docker démonok közti "csevej" is hálózaton történik. Ennek megfelelően, ahogy a dokumentáció említi, kétféle hálózati kommunikációról beszélhetünk: "Control and management plane traffic" és "Application data plane traffic". Tehát a vezérlés közbeni forgalomról és a konténerekben futó alkalmazások kommunikációjáról van szó, ahol a vezérléssel kapcsolatos forgalom mindig titkosított.

A Swarm klaszter inicializálásakor vagy egy gép klaszterre csatlakoztatásakor újabb hálózatok jönnek létre részben a már ismert driverekkel, de egy újat is meg kell ismerni.

"overlay" driver

[Tartalom]

Az "overlay" driver lényege, hogy több Docker hoszt között alakít ki olyan hálózatot, hogy annak szereplői számára teljesen mindegy, hogy egyazon gépen vannak-e vagy fizikailag eltérő szerveren. A kapott IP cím ezt a különbséget nem tükrözi. Ebben a hálózatban résztvevő Docker hosztok lesznek a "peer"-ek. A "docker network inspect HALOZATNEVE" utasítással valami ilyesmit lehetne látni két gép esetén:

"Peers": [
     {
         "Name": "vagrant-7f2f22dd7b5a",
         "IP": "192.168.1.109"
     },
     {
         "Name": "vagrant-b7b8ebd7c3db",
         "IP": "192.168.1.149"
     }
]

Amikor a "docker stack deploy" utasítással indítod a szolgáltatásokat, akkor is ilyen hálózatok jönnek létre minden stack-hez, hogy az abban működő szolgáltatások lássák egymást bármelyik gépen is indultak el. Ez hasonló, mint a Docker Compose-nál létrejövő egyedi bridge.

A peerek között csak azok a gépek jelennek meg, amiken fut olyan szolgáltatás, amivel biztosítani kell a kapcsolatot. Ha tehát egy egyedi overlay networkre 3 gépből csak egyről csatlakozik konténer, csak annak az egy gépnek az IP címe lesz a felsorolásban.

Érdemes még azt is tudni, hogyha magad hozod létre az ilyen hálózatot valamelyik manager gépen, csak azon a gépen indíthatod el a hálózatot igénylő szolgáltatást. A többi gépen pedig csak akkor jelenik meg ez a hálózat a "docker network ls" utasítást kiadva, ha a manager gép azon is elindított konténert, ami arra csatlakozna.

"ingress" hálózat

[Tartalom]

Az "ingress" nevű hálózat egy speciális "overlay" network. Ez az, ami már a Swarm klaszter inicializálásakor létrejön. Különbség az egyedi overlay-hez képest, hogy bár futó konténerként nem látszik, de a klaszter minden node-ján megjelenik a csatlakozó konténerek között egy "ingress-sbox" azonosítójú, "ingress-endpoint" nevű elem saját IP-vel, tehát a klaszter összes node-ja megjelenik a peer-ek között.

"Containers": {
    "ingress-sbox": {
        "Name": "ingress-endpoint",
        "EndpointID": "4a016b95da2a8865f1e6440d9854a7e7376698283add013d9e842f0934e3a584",
        "MacAddress": "02:42:0a:ff:00:03",
        "IPv4Address": "10.255.0.3/16",
        "IPv6Address": ""
    }
},

Az "ingress" egyfajta belépési pont a külvilág felől a klaszter konténereibe load balancing mellett. Erre a hálózatra akkor csatlakozik egy konténer, ha az azt tartalmazó Swarm service portját publikálod, azaz a Docker hoszt nyilvános IP címén kívülről elérhetővé teszel egy portot. Ilyenkor a kérés először az "ingress" hálózatba érkezik, és az "ingress-endpoint"-ról lesz továbbítva a konténer felé. Ha egyedi overlay networkre csatlakoztatsz egy szolgáltatást, a portok akkor is az ingress-en keresztül lesznek megnyitva. Ha nincs egyedi overlay, és nincs portátirányítás, akkor az alapértelmezett bridge-en foglalnak IP-t a konténerek, és még a szolgáltatáson belüli konténerpéldányok is csak akkor látják egymást a hálózaton, ha azonos node-on indultak el véletlenül.

Megjegyzés: Jelenlegi információk szerint az ingress egyik hiányossága, hogy elrejti a HTTP kéréseknél az eredeti kérő IP címét és a webszervernél a látogatók IP-jét így nincs lehetőség a kérésből megtudni. Így tehát, még Swarm esetén is érdemes lehet egy proxy szervert használni. Erre elterjedt megoldás a Docker Flow Proxy, ami mögött HAProxy van valójában..

docker_gwbridge

[Tartalom]

Ez a hálózat speciális "bridge". Akárcsak az ingress, ez is a Swarm klaszter inicializálásakor vagy ahhoz csatlakozáskor jön létre. Emellett, ha a konténer valamilyen overlay hálózathoz van csatlakoztatva, ezen a bridge-en is kap egy IP címet. Ez Swarm service-eknél nagyjából azt jelenti, hogy ha nem a default bridge-en, akkor a "docker_gwbridge"-en kap IP-t. Feltéve persze, hogy nem a gazda hálózatát veszi igénybe a "host" network-kel.

Említettem, hogy bár konténerként nem látszik, de az ingress hálózatnál megjelenik egy "ingress-sbox" azonosítójú elem a konténerek listájában. Itt pedig egy "gateway_ingress-sbox", ami az "ingress-sbox"-ra ad egy IP címet a bridge-en. Bonyolódik már, ugye?

Hálózatok és konténerek kapcsolata

[Tartalom]

Hogy melyik hálózat micsoda, az már nagyjából kiderülhetett az előzőekből. Talán még világosabbá teszi, ha megnézzük sorban, milyen utasításoktól, hogy változnak a konténerek hálózatai.

  • A "docker container run"-nal indítva a konténer egyedi definíció nélkül az alapértelmezett "bridge" hálózaton kap helyet. "docker container inspect"-tel egyértelműen a bridge-en kapott IP-t lehet látni.

  • A "--network"-öt használva a "run" után tetszőleges, akár egyedi hálózatra lehet csatlakozni (overlay-re nem), vagy le is lehet tiltani a netet.

  • A Docker Compose-zal indítva a konténereket azok alapértelmezetten egy egyedi bridge hálózatra kerülnek projektenként.

  • A "docker service create"-tel portátirányítás és egyedi hálózat nélkül szintén a default "bridge"-ből kap IP-t a konténer a Swarm klaszterben, ami inspect-tel is látszik. A példányok nem látják egymást.

  • A create után a "--network" opcióval egyedi overlay hálózatra lehet csatlakozni, vagy a gazda hálózatára. Letiltani nem lehet. Overlay hálózatra csatlakozva a példányok már látják egymást a Swarm service-ben és a "docker_gwbridge" hálózaton is kapnak IP-t a konténerek az overlay miatt. inspect-tel a konténer IP címeként az overlay-en kapott cím látszik. A másikat csak a docker_gwbridge vizsgálatával lehet megnézni.

  • A "docker stack deploy"-jal a Docker Compose-hoz hasonlóan egyedi hálózat jön létre a stack-hez, ez viszont overlay hálózat lesz. Tehát szintén kap IP-t minden konténer a "docker_gwbridge"-en is. A stack szolgáltatásainak minden konténere látja a másikat.

  • A portok megnyitásával a külvilág felé a Swarm service konténerei a speciális, "ingress" nevű overlay hálózatra is felkerülnek függetlenül attól, csatlakoznak-e más overlay hálózathoz. Mondanom sem kell már, hogy "docker_gwbridge" hálózat... Onnan is jön egy-egy IP.

  • Ha a portokat "docker service update"-tel elveszed, a konténerek kikerülnek az ingress-ből, valamint a docker_gwbridge-ből. Ha volt egyedi overlay hálózat, akkor abban maradnak, egyébként visszakerülnek az alapértelmezett bridge-re.

Záró gondolatok

[Tartalom]

A teljes Docker hálózatkezelés lefedése ebbe a cikkbe nem fért bele, de a legfontosabb, hogy legalább nagyjából tisztában legyél az alapokkal. Az egyedi hálózatok testre is szabhatók például egyedi IP tartománnyal is, de személy szerint erre még nem volt szükségem. Fontos, hogy a Docker által létrehozott hálózatokat manuálisan ne változtasd, ne töröld, mert adott esetben a klaszter részben vagy teljesen működésképtelen lehet. Ha szükséges, akkor inkább sajátokat hozz létre. Ha az itt leírtaknál komolyabban érdekelnek a lehetőségek, akkor alább, a forrásoknál felsorolt oldalakon is informálódhatsz.

Ha hiányosságot, hibát tapasztalsz a leírtakban, kérlek, jelezd itt kommentben, vagy a Facebookon, de akár e-mailben is és szükség esetén kiegészítem, javítom a cikket.

Források

[Tartalom]

Kategóriák: 
Megosztás/Mentés