Kubernetes Service-ek: ClusterIP, NodePort és LoadBalancer
Korábban már írtam olyan kiemelten fontos Kubernetes témáról, mint: hogyan kapcsolódnak a Pod-ok a Volume-okhoz, mire jó a PersistentVolume és a PersistentVolumeClaim, és hogyan automatizálja ezt a StorageClass a Dynamic Provisioning-on keresztül. Legutóbb pedig a Secret és a ConfigMap rejtelmeibe avattalak be Titeket. Most nézzünk egy másik alapvető fogalmat, ami nélkül a Kubernetes cluster gyakorlatilag használhatatlan lenne: a Service-eket.
Miért van szükség a Service-re?
A Kubernetes architektúrája arra épül, hogy a Pod-ok ideiglenesek. Bármelyik Pod bármikor megszűnhet, és egy újjal helyettesítődik – más IP-vel. Ha egy alkalmazás közvetlenül egy Pod IP-jére hivatkozna, minden újraindításnál elromlana a kapcsolat. A
pontosan ezt a problémát oldja meg: label-ek (címkék) alapján összeköti a Pod-okat egymással, vagy elérhetővé teszi őket a cluster-en kívülről is. Amikor egy Pod lecserélésre kerül, a Service – egy Endpoint objektumon keresztül – automatikusan az új Pod-hoz irányítja a forgalmat.
Hogyan irányítja a forgalmat a kube-proxy
A háttérben a kube-proxy figyeli a Kubernetes API-t, és minden node-on reagál az új Service-ekre és Endpoint-okra. Véletlenszerű portokat nyit, figyeli a forgalmat a ClusterIP:Port címen, és onnan irányítja tovább a generált endpoint-okhoz. A Service automatikus load balancingot biztosít a label query alapján, session affinity IP alapján konfigurálható, és létezik úgynevezett headless service is, amelynek nincs fix IP-je és load balancingja. Az egyedi IP-ket a Service-ek az etcd adatbázison keresztül kapják, a forgalomirányítást pedig jellemzően iptables vagy ipvs végzi.

A négy alapvető típus
| Típus | Mire jó |
|---|---|
| ClusterIP | Alapértelmezett típus, csak belső elérést biztosít a cluster-en belül |
| NodePort | Debugoláshoz vagy statikus IP-hez hasznos, például tűzfalon átengedett porthoz |
| LoadBalancer | A cloud provider (pl. GKE, AWS) felé küld kérést egy load balancer létrehozására |
| ExternalName | Nincs selectora, se portja – DNS szinten ad vissza egy aliast egy külső erőforráshoz |
Fontos tisztázni egy gyakori félreértést: a LoadBalancer típus önmagában nem hoz létre load balancert. Először egy NodePort-ot készít, majd aszinkron kérést küld a load balancer létrehozására. Ha van olyan komponens, ami reagál erre a kérésre – ahogy ez publikus cloud környezetben történik –, akkor létrejön a load balancer. Ha nincs ilyen figyelő komponens, a Service állapota Pending marad.
Hogyan frissül egy Service működés közben
A label-ek (címkék) határozzák meg, mely Pod-ok kapják meg a forgalmat egy Service-től. Az alapértelmezett frissítési minta a rolling deployment: az új verziójú Pod-ok bekerülnek, és az automatikus load balancing miatt a régi verzióval együtt kapnak forgalmat. Ha a különböző verziók nem kompatibilisek egymással, érdemes verziószámot is tartalmazó, specifikusabb label-t használni a deploymenthez. Amikor a deployment létrehozza az új replicaSet-et a frissítéshez, a label nem fog egyezni – így csak azután áll át rá a forgalom, hogy manuálisan módosítjuk, mihez kapcsolódjon a Service. Ez minimalizálja a verziók közötti összezavarodást a kliens oldalon.
Egy példán keresztül
A leggyorsabb módja annak, hogy egy meglévő deploymenthez Service-t rendeljünk, a kubectl expose parancs:
kubectl expose deployment/nginx --port=80 --type=NodePort
kubectl get svc
Ez létrehoz egy Service-t, amely a 80-as portot használja, és véletlenszerű portot generál minden node-on. A port és a targetPort explicit is megadható, ha nem szeretnénk véletlenszerű értékeket – a targetPort alapból megegyezik a porttal, de akár egy Pod-on belüli port nevére is hivatkozhat.
DNS és a Service-ek
A CoreDNS az alapértelmezett DNS megoldás v1.13 óta. Induláskor egy szervert futtat a konfigurált zónákhoz, és plugin láncokat tölt be a további funkciókhoz – a beépített, körülbelül harminc plugin fedi le a leggyakoribb igényeket, például metrikák szolgáltatását Prometheus felé, hibalogolást vagy TLS tanúsítványkezelést. A klienseknek a kube-dns service-en keresztül van elérésük ehhez. Ha a DNS regisztrációt szeretnénk ellenőrizni, a legegyszerűbb módszer egy shell-t és hálózati eszközöket (nslookup, dig, nc) tartalmazó Pod indítása, majd a Service-en keresztüli lekérdezés – a /etc/resolv.conf fájl, a label-ek, a selector-ok és a Network Policy-k is befolyásolhatják az eredményt.
Amit szándékosan kihagytunk
Ebben a cikkben nem tértünk ki az Ingress controllerre, ami külön, a szolgáltatásokra épülő komponens, és a forgalmat URL alapján irányítja a megfelelő Service felé – ez önálló témát érdemel. Szintén nem foglalkoztunk a monitoringgal vagy a high availability beállításokkal, mert ezek külön réteget jelentenek a Service-ek alapműködése fölött.
Amire érdemes figyelni
Azure, AWS, Google Cloud és általában a felhőszolgáltatóknál a LoadBalancer típusú Service-eknél sokan elfelejtik, hogy ez valódi, fizetős cloud erőforrást hoz létre a háttérben. Teszteléskor könnyű több ilyen Service-t is létrehozni, majd elfeledkezni róluk – ez ugyanolyan felesleges költséget generál, mint egy éjszakára bekapcsolva hagyott fejlesztői VM. Érdemes rendszeresen átnézni, mely Service-ek futnak LoadBalancer típussal, és amelyikre nincs szükség, azt törölni.
