Kubernetes umrežavanje

Umrežavanje u Kubernetes okruženju je prilično kompleksna tema. Za samo 30 minuta, ovaj članak će vam kroz praktične primere pružiti osnovna znanja koja će poslužiti kao čvrst temelj za dalje usavršavanje u ovoj oblasti.

Za osnovne informacije o samom Kubernetes-u, njegovim komponentama i arhitekturi, možete pročitati ovaj blog članak.

Pregled sadržaja

Evo šta nas očekuje u narednim sekcijama:

  1. Šta je potrebno za praktični rad? Videćemo šta ćemo od alata koristiti za rad i proći ćemo kroz korake instalacije kako bismo postavili okruženje za rad.
  2. Slojevi umrežavanja: Sagledaćemo kako možemo da raščlanimo i pojednostavimo umrežavanje u Kubernetes-u, koristeći slojeviti pristup. Svaki od slojeva će biti analiziran u zasebnoj sekciji. Počećemo od toga kako da umrežimo najniže komponente sistema, dok na kraju ne dođemo do umrežavanja celokupnog sistema.
  3. Umrežavanje kontejnera: Proučićemo šta se dešava unutar pojedinačnog Pod-a – kako su umreženi kontejneri unutar njega i koja je to komponenta koja omogućava komunikaciju između kontejnera unutar Pod-a.
  4. Umrežavanje Pod-ova: Videćemo kako funkcioniše sistem s mnoštvom Pod-ova – kako kontejneri unutar jednog Pod-a mogu komunicirati s kontejnerom u sasvim različitom Pod-u. Razmotrićemo slučajeve kada su to Pod-ovi unutar istog čvora i kada su Pod-ovi raspoređeni na različitim čvorovima (serverima). Navešćemo i koji su to neophodni elementi za pouzdano funkcionisanje ovakve mreže.
  5. Povbezivanje Pod-ova i Servisa: Uvešćemo pojam servisa i reći koja je njihova uloga i zašto su ključni elementi za umrežavanje svih Pod-ova unutar klastera. Pokazaćemo primer korišćenja servisa u komunikaciji.
  6. Umrežavanje spoljnih klijenata sa servisima: Proučićemo još dva tipa servisa koji omogućavaju komunikaciju sa spoljnim klijentima i na koje načine može da se pristupi Pod-ovima unutar klastera kada se zahtevi šalju sa lokacije van klastera. Videćemo i prednosti svakog od ova dva servisa.

Šta je potrebno za praktični rad?

Da bi praktično isprobali ono o čemu će biti reč u narednim sekcijama, potrebno je prvo da podesimo okruženje za rad. Koristićemo:

  • VirtualBox
  • Minikube
  • kubectl

Instalacija VirtualBox-a je preduslov, jer će naš eksperimentalni Kuberenetes klaster raditi na virtuelnoj mašini.

Minikube nam je bitan jer predstavlja open-source alat pomoću koga možemo da postavimo i pokrenemo jedan čvor Kubernetes klastera na našem lokalnom računaru. Posebno je koristan za razvoj, testiranje i učenje, jer nam omogućava da eksperimentišemo sa Kubernetes-om bez potrebe za pravim produkcionim okruženjem.

Dostupan je za različite operativne sisteme, ali za potrebe ovog članka, fokusiraćemo se na uputstva za instalaciju na Linux operativnom sistemu.

Za instalaciju Minikube-a, izvršavamo dve komande:

> curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
> sudo install minikube-linux-amd64 /usr/local/bin/minikube

kubectl je interfejs komandne linije (CLI) koji se koristi za interakciju sa Kubernetes klasterima. On nam je ključan alat, jer bez njega ne bismo mogli da vršimo bilo kakvu orkestraciju aplikacija u Kubernetes-u.

Za instalaciju kubectl-a pokrećemo:

> curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

Validiranje binarnog fajla (opciono):

> curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256"

> echo "$(cat kubectl.sha256)  kubectl" | sha256sum --check

Ako je validan, na izlazu bi trebalo da ispiše: kubectl: OK

Na kraju, izvršavamo sledeću komandu:

> sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

Nakon uspešnih instalacija (koje možemo proveriti pokretanjem komandi minikube i kubectl koje bi trebalo da nam vrate listu dostupnih komandi), sada možemo kreirati i pokrenuti klaster nad kojim ćemo raditi u nastavku. Klaster pokrećemo komandom:

> minikube start --driver=virtualbox

Potrebno je sačekati koji trenutak dok se klaster prvi put podesi za rad. Takođe, sam Docker je instaliran u okviru Minikube-a, tako da o tome ne treba brinuti.

Slojevi umrežavanja

Umrežavanje u Kubernetes-u je izuzetno važna tema. S obzirom da mu je uloga da orkestrira kontejnerima, Kubernetes je odgovoran za veliki broj kontejnera koji se izvršavaju u klasteru. Ovi kontejneri moraju biti u mogućnosti da međusobno komuniciraju, kao i da komuniciraju sa drugim delovima infrastrukture, poput spoljnih servisa i bazom podataka. Kubernetes-ova mrežna infrastruktura omogućava da se ova komunikacija odvija pouzdano i efikasno.

Da bi bilo jasnije kako stvari funkcionišu, mrežnu komunikaciju ćemo posmatrati kroz navedene slojeve (od nižih ka višim delovima arhitekture):

  1. Umrežavanje kontejnera
  2. Umrežavanje Pod-ova
  3. Umrežavanje Pod-ova i Servisa
  4. Umrežavanje spoljnih klijenata sa Servisima

Umrežavanje kontejnera

Ako ne bismo koristili Kubernetes, naš server bi imao veliki broj (npr. stotinu) kontejnera koji bi bili pokrenuti direktno na njemu. Aplikacije pokrenute unutar kontejnera bi slušale na portu koji je vezan za port hosta. Došlo bi do problema, jer bi bilo potrebno pratiti ogroman broj pokrenutih aplikacija i znati na kojim portovima su one aktivne. Mogao bi da se javi konflikt ukoliko bismo pokušali da pokrenemo novu aplikaciju na portu koji je već zauzet. Pored toga, postalo bi teško ispratiti koji su portovi slobodni. Iz tog razloga, uvodi se apstrakcija Pod-a.

Svaki Pod ima jedinstvenu IP adresu, network namespace i virtuelnu ethernet konekciju (veth0 na slici). Pod predstavlja izolovani virtuelni host na kome je pokrenut jedan ili više kontejnera. Time je obezbeđeno da možemo da imamo aplikacije koje su sve pokrenute na portu 5432 unutar 10 različitih Pod-ova i neće biti konflikta jer se nalaze na izolovanim virtuelnim hostovima.

Prikaz Pod-a i umreženih kontejnera

U ovom trenutku, možemo i kod nas na klasteru da kreiramo Pod-ove kako bismo demonstrirali primer.

Napravićemo dva Pod-a i svaki će unutar sebe sadržati kontejner sa slikom Postgres baze podataka. Da bi kreirali Pod, potrebno je da informacije o njemu smestimo u yaml konfiguracioni fajl pod nazivom postgres.yaml.

apiVersion: v1
kind: Pod
metadata:
  name: postgres
  labels:
    app: postgres
spec:
  containers:
  - name: postgres
    image: postgres:9.6.17
    ports:
    - containerPort: 5432
    env:
    - name: POSTGRES_PASSWORD
      value: "pwd"  

Unutar fajla dodeljujemo informacije o tome koji je tip komponente u pitanju (kind: Pod), metapodatke o Pod-u (ime i labele u ovom slučaju) i informacije o samom kontejneru koji će biti pokrenut unutar Pod-a (ime, image i port na kome je pokrenuta aplikacija u kontejneru).

Pod se zatim kreira pokretanjem komande:

> kubectl apply -f postgres.yaml

Nakon toga, status kreiranih Pod-ova proveravamo uz:

> kubectl get pods -o wide

Ovo je komanda koja se koristi za prikazivanje liste svih trenutno pokrenutih Pod-ova u Kubernetes klasteru. Dobijamo informacije o stanju Pod-ova, kao što su njihova imena, status (na primer, „Pending“, „Running“ ili „Error“), IP adrese, vreme pokretanja i druge relevantne informacije.

Sad ćemo kreirati i drugi Pod. Možemo iskoristiti već postojeći yaml fajl, jedino ćemo modifikovati ime Pod-a u postgres-2 (name: postgres-2). Ponavljamo isti proces i pokrećemo istu komandu kao i za kreiranje prvog Pod-a.

Sada kada pokrenemo komandu za proveru statusa Pod-ova, dobićemo izlaz kao na slici:

Ukoliko želimo da pogledamo detalje o nekom od pokrenutih Pod-ova (npr. o prvom izlistanom Pod-u na slici), to možemo uraditi komandom:

> kubectl describe pod postgres

Komanda će nam izlistati opšte informacije o Pod-u, kao što su ime, namespace u kojem se nalazi, stanje, IP adresa i vreme pokretanja, kao i informacije o tome koje kontejnere sadrži taj Pod, uključujući njihova imena, trenutni status, i portove na kojima su pokrenuti.

Ovom demonstracijom pokazali smo vrlo realan i praktičan primer gde imamo više replika istog kontejnera unutar više različitih Pod-ova.

Ovakva praksa je česta u realnim sistemima kako bi se osiguralo da, ako jedan od kontejnera prestane da radi, korisnici i dalje mogu pristupiti bazi podataka jer postoji kopija tog kontejnera u drugom Pod-u.

Sada se postavlja drugo pitanje – Ukoliko imamo više kontejnera unutar jednog Pod-a, kako oni komuniciraju među sobom?

Kontejneri unutar istog Pod-a dele zajednički network namespace. To znači da međusobno mogu da komuniciraju putem localhosta i određenog porta. Na primer, ako imamo kontejner na kome je pokrenut nginx i sluša na portu 80, i drugi kontejner na kome je pokrenut curl, drugi kontejner može da se poveže sa prvim kontejnerom preko localhost:80.

Za ovaj primer, možemo kreirati novi Pod koji će biti konfigurisan na ovaj način:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80
  - name: curl-container
    image: curlimages/curl
    command: ["/bin/sh"]
    args: ["-c", "echo Hello from the sidecar container; sleep 300"] 

Vidimo da sada unutar ključa containers navodimo dva kontejnera. Nakon što kreiramo Pod sa ovakvom konfiguracijom, komandama kubectl-a možemo da uđemo unutar drugog kontejnera i obratimo se prvom kontejneru na kome je pokrenut nginx server.

> kubectl exec -it nginx -c curl-container -- /bin/sh

Kada nam se prikaže komandna linija unutar curl kontejnera, poslaćemo poslati zahtev ka nginx kontejneru komandom curl localhost:80

Kao odgovor, dobijamo podrazumevanu stranicu nginx servera.

Da bi ovakva komunikacija bila moguća, Kubernetes mora da u svakom Pod-u sadrži poseban kontejner čiji je jedini cilj da obezbedi mrežni interfejs za ostale kontejnere u Pod-u. Ti kontejneri su nazvani pause kontejneri jer su pokrenuti komandom pause.

Procesi unutar ovog kontejnera su obustavljeni dok ne prime signal, tako da ovi kontejneri ne rade ništa osim što su u stanju mirovanja dok im Kubernetes ne pošalje signal za završetak (SIGTERM). Bez obzira na svoju neaktivnost, pause kontejner je glavna komponenta Pod-a, pružajući virtuelni mrežni interfejs koji će svi drugi kontejneri koristiti kako bi komunicirali međusobno i sa spoljnim svetom.

Prikaz Pod-a uz pause kontejner

Umrežavanje Pod-ova

Da bismo imali sistem koji funkcioniše, nije dovoljno da samo kontejneri unutar jednog Pod-a mogu međusobno da komuniciraju, već je bitno da svi Pod-ovi budu umreženi i mogu da komuniciraju jedni sa drugima, bez obzira da li se nalaze na istoj mašini ili ne.

Da bi razmatrali komunikaciju između Pod-ova, potrebno je da posmatramo viši nivo arhitekture koji je zasnovan na čvorovima (nodes) unutar klastera. Klaster sadrži jedan ili više radnih čvorova, a unutar čvorova su smešteni Pod-ovi.

Kao što je već napomenuto, svim Pod-ovima unutar Kubernetes klastera su dodeljene jedinstvene IP adrese i mogu pristupiti svakom drugom Pod-u putem IP adrese. Sada ćemo objasniti kako.

Da bi dva Pod-a koja se nalaze unutar istog čvora komunicirala, dovoljno je da unutar čvora postoji most (bridge) koji povezuje Pod-ove sa različitim adresama. U Kubernetes-u, ovaj most se naziva cbr0 (custom bridge). Na prethodnoj slici, most je bio predstavljen kao docker0. Kao što vidimo na slici ispod, adrese Pod-ova će biti dodeljenje unutar iste podmreže.

Međutim, šta se dešava ukoliko su Pod-ovi na različitim čvorovima? Kada most pita Pod-ove unutar čvora da li imaju odgovarajuću IP adresu, neće je pronaći.

Ono što je bitno da znamo je da Kubernetes ima određeni adresni prostor za sve čvorove u klasteru. Svaki čvor će dobiti određeni opseg IP adresa. Na primer, na sledećoj slici vidimo da je levi čvor dobio opseg IP adresa 100.68.1.xxx, a desni čvor opseg 100.68.2.xxx. Pod-ovima unutar tih čvorova će biti dodeljene IP adrese iz tih opsega.

Drugo, na nivou klastera postoji tabela (route table) koja mapira opsege IP adresa ka različitim čvorovima. Dodaju se ruting pravila na gateway koja mu govore kako da rutira pakete namenjene svakom čvoru, odnosno prema kojem eth0 interfejsu čvora se može pristupiti njegovom mostu. Ovakva kombinacija virtuelnih mrežnih interfejsa, mostova i rutirajućih pravila obično se naziva overlay mreža.

Kada se ciljana IP adresa ne može pronaći unutar čvora, most koristi gateway. Taj gateway se nalazi na nivou klastera i pomoću ruting pravila, traži kom opsegu adresa pripada ta IP adresu tj. na koji čvor je potrebno proslediti paket dalje.

Glavna karakteristika Pod-ova je to da su kratkog životnog veka. Mogu da budu uništeni i ponovo kreirani u svakom trenutku. To stvara problem u mrežnom saobraćaju, jer Pod-ovi ne dobijaju iste IP adrese svaki put kada se ponovo kreiraju. Nepouzdano je koristiti IP adresu Pod-a kao endpoint jer ne postoji garancija da se adresa neće promeniti u bilo kom trenutku.

Umrežavanje Pod-ova i Servisa

Glavna karakteristika Pod-ova je to da su kratkog životnog veka. Mogu da budu uništeni i ponovo kreirani u svakom trenutku. To stvara problem u mrežnom saobraćaju, jer Pod-ovi ne dobijaju iste IP adrese svaki put kada se ponovo kreiraju. Nepouzdano je koristiti IP adresu Pod-a kao endpoint jer ne postoji garancija da se adresa neće promeniti u bilo kom trenutku.

Kako onda da obezbedimo stalnu komunikaciju sa bilo kojim Pod-om? Dizajneri Kubernetesa su rešili ovaj problem na elegantan način pomoću servisa.

Servis je tip Kubernetes objekta pomoću koga je konfigurisan proxy tako da prosleđuje zahteve određenom skupu Pod-ova. Takođe, obezbeđuje DNS imena za skup Pod-ova. To omogućava drugim aplikacijama da komuniciraju sa Pod-ovima koristeći doslednu adresu, čak i kada se sami Pod-ovi uništeni i ponovo kreirani.

Servis obezbeđuje usmeravanje saobraćaja preko neke vrste reverse-proxy-a U Kubernetes-u ta komponenta se zove kube-proxy, a reći ćemo nešto o njoj u nastavku. Klijenti se povezuju na proxy, a proxy je odgovoran za održavanje liste Pod-ova na koje će prosleđivati zahteve. To znači da proxy mora sam biti stabilan i otporan na otkaze, mora imati listu Pod-ova na koje može prosleđivati zahteve i mora imati način da utvrdi da li određeni Pod radi i da li može da odgovori na zahteve.

Postoji više tipova servisa, ali u ovom sloju će nas najviše zanimati ClusterIP servisi. To je podrazumevani tip servisa koji je namenjen za komunikaciju aplikacija unutar klastera. Tip servisa možete videti pokretanjem komande „kubectl describe services“ sa dodatim imenom servisa.

Kako funkcioniše ClusterIP servis?

Kada se kreira ClusterIP servis, dobija statičku IP adresu koja se nikada ne menja tokom trajanja servisa. Umesto da se direktno povezuju sa Pod-ovima, klijenti se povezuju sa servisom putem njegove IP adrese. IP adresa koju servis dobija ne pripada istoj mreži na kojoj se nalaze Pod-ovi i čvorovi klastera (nodes). Mreža određena ovim adresnim prostorom naziva se „mreža servisa„. Svaki ClusterIP servis će dobiti IP adresu na ovoj mreži.

Mreža servisa je takođe virtuelna, ali ono po čemu se razlikuje od mreže Pod-ova i čvorova je to što ne postoje uređaji konfigurisani sa adresama na ovoj mreži. Možete pregledati tabelu (route table) na gateway-u koji povezuje sve čvorove i nećete pronaći rute za ovu mrežu. Mreža servisa ne postoji, barem ne kao povezani interfejsi. Ipak, moguće je da zahtev stigne do serverskog Pod-a. Pogledajmo primer da bismo shvatili o čemu je reč.

Na slici su prikazana dva čvora, gateway koji ih povezuje i tri Pod-a: dva na prvom čvoru (serverski i klijentski) i jedan na drugom (serverski). Klijent šalje HTTP zahtev servisu koristeći DNS ime. DNS sistem prevodi to ime u IP adresu servisa 10.3.241.152, klijentski Pod kreira HTTP zahtev i dolazi do slanja paketa ka toj IP adresi.

Prvi interfejs koji vidi pakete u ovom primeru je virtuelni ethernet interfejs unutar klijentskog Pod-a (veth1). Taj interfejs pripada mreži Pod-ova i ne poznaje uređaj sa adresom 10.3.241.152, pa preusmerava paket na svoj gateway, tj. most cbr0. Mostovi su prilično jednostavni i umeju samo da prosleđuju saobraćaj, tako da most šalje paket do interfejsa čvora.

Interfejs čvora (eth0) takođe ne poznaje uređaje sa adresom 10.3.241.152, pa bi se onda desilo ono što se obično dešava – paket bi bio prosleđen do gateway-a ovog interfejsa. Umesto toga, ono što se zapravo dešava je da se paket presreće u letu i preusmerava ka jednom od aktivnih serverskih Pod-ova.

Komponenta koja obezbeđuje ovakvo ponašanje jeste kube-proxy koji radi na svakom čvoru unutar klastera.

Komponenta koja obezbeđuje ovakvo ponašanje jeste kube-proxy koji radi na svakom čvoru unutar klastera.

Kubernetes koristi framework linux kernela nazvan netfilteri interfejs user space-a za njega nazvan iptables. Ukratko, netfilter je mehanizam za obradu paketa zasnovan na pravilima. Radi u kernel space-u i pregleda svaki paket. Upoređuje pakete sa pravilima i kada pronađe pravilo koje odgovara, preduzima navedenu akciju. Među mnogim akcijama koje može preduzeti je i preusmeravanje paketa na drugu destinaciju.

U ovakvom režimu kube-proxy otvara port (npr. 10400 kao na slici) na lokalnom interfejsu čvora (eth0), kako bi slušao zahteve upućene servisu. Takođe, postavlja netfilter pravila kako bi preusmerio pakete namenjene IP adresi servisa na svoj port, a potom te zahteve prosleđuje Pod-u.

Postoji još jedan režim u kome može da radi kube-proxy, a to je iptables režim. U ovom režimu, kube-proxy gubi ulogu proxy-ja, delegira zahtev netfilter-u i to se odvija u kernel space-u. U ovom slučaju, uloga kube-proxy-ja je uglavnom ograničena na održavanje sinhronizacije netfilter pravila.

Možemo sada izvesti i praktični primer kojim ćemo demonstrirati rad servisa. Napravićemo isti primer kao i gore, kreiraćemo dva serverska Pod-a. Njih možemo kreirati ovakvom konfiguracijom:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: service-test
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test_pod
  template:
    metadata:
      labels:
        app: test_pod
    spec:
      containers:
      - name: simple-http
        image: python:3.10
        imagePullPolicy: IfNotPresent
        command: ["/bin/bash"]
        args: ["-c", "echo \"Hello from $(hostname)\" > index.html; python -m http.server 8080"]
        ports:
        - name: http
          containerPort: 8080

Kreiramo dve replike serverskih Pod-ova koji će unutar sebe imati pokrenute HTTP servere na portu 8080. Naravno, pokrećemo komandu kubectl apply za kreiranje ova dva Pod-a, možemo videti da su Pod-ovi pokrenuti u klasteru. Da ponovimo, možemo da pogledamo njihove IP adrese komandom:

> kubectl get pod -o wide

Kada smo sigurni da su Pod-ovi aktivni, možemo kreirati servis, pa i klijentski Pod.

Za kreiranje servisa, yaml fajl treba ovako da izgleda:

kind: Service
apiVersion: v1
metadata:
  name: service-test
spec:
  selector:
    app: test_pod
  ports:
  - port: 80
    targetPort: http

Skup Pod-ova koji će primati saobraćaj određuje se putem selektora koji se poklapa sa selektorima dodeljenim Pod-ovima prilikom njihovog kreiranja. Nakon što kreiramo servis, možemo videti da mu je dodeljena IP adresa i da će prihvatati zahteve na portu 80.

> kubectl get service service-test

Vidimo i tip servisa, koji iako nigde nije bio naglašen u našem konfiguracionom fajlu, postavljen je na podrazumevani ClusterIP.

Ostalo je još da kreiramo klijentski Pod. Čim se kreira, on pokuša da se obrati serverskom Pod-u preko servisa. Ovo će biti konfiguracija za klijentski Pod:

apiVersion: v1
kind: Pod
metadata:
  name: service-test-client
spec:
  restartPolicy: Never
  containers:
  - name: test-client
    image: alpine
    command: ["/bin/sh"]
    args: ["-c", "echo 'GET / HTTP/1.1\r\n\r\n' | nc service-test 80"]

Zahtevi se mogu slati direktno na IP adresu servisa, ali bilo bi bolje koristiti hostname koje se prevodi u IP adresu pomoću DNS-a.

Nakon kreiranja ovog Pod-a, primetićemo ubrzo u listi Pod-ova da je status ovog Pod-a „Completed“, što znači da je poslao zahtev i uspešno završio. Ono što smo dobili kao odgovor od serverskog Pod-a, možemo videti pokretanjem komande:

> kubectl logs service-test-client
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.10.13
Date: Tue, 07 Nov 2023 19:52:41 GMT
Content-type: text/html
Content-Length: 48
Last-Modified: Tue, 07 Nov 2023 19:16:04 GMT

Hello from service-test-7bc64bc78b-pjtvh

Umrežavanje spoljnih klijenata sa Servisima

Prošli smo sve slojeve umrežavanja unutar klastera. Međutim, u mnogim slučajevima takođe je potrebno da se spoljnim klijentima omogući pristup servisima unutar klastera. Izlaganjem servisa spoljnim klijentima, omogućava im se pristup aplikaciji, čak i ako se nalaze izvan mreže klastera.

Postoji nekoliko načina za izlaganje servisa spoljnim klijentima u Kubernetesu. Mi ćemo u ovom članku dotaći se dva načina, a to su:

  1. NodePort servisi
  2. LoadBalancer servisi
NodePort servisi

Pored podrazumevanog ClusterIP servisa, postoji još jedan tip servisa – NodePort. Evo primera konfiguracije jednog NodePort servisa.

kind: Service
apiVersion: v1
metadata:
  name: service-test
spec:
  type: NodePort
  selector:
    app: test_pod
  ports:
  - port: 80
    targetPort: http

Kada Kubernetes kreira NodePort servis, kube-proxydodeljuje port u opsegu 30000–32767 i otvara ovaj port na eth0 interfejsu SVIH ČVOROVA KLASTERA (otuda naziv „NodePort„). Sav saobraćaj koji stiže na ovaj port se prosleđuje adresi ClusterIP servisa. Ako kreiramo ovakav servis i izvršimo sledeću komandu:

> kubectl get svc service-test

možemo videti informacije o našem NodePort servisu, na primer – na kom portu sluša servis.

NodePort servis izlaže „običan“ interni servis spoljnom svetu. Saobraćaj se kreće ovako:

Spoljni klijent -> IP čvora (eth0 interfejs) -> NodePort -> ClusterIP servis -> Pod

Važno je napomenuti da NodePort servis ne pruža load balancing između čvorova. Sav dolazni saobraćaj ide do čvora čija je IP adresa ciljana. Ovo može dovesti do neujednačene raspodele saobraćaja među čvorovima i potencijalno prouzrokovati preopterećenost određenih čvorova, dok drugi nisu dovoljno iskorišćeni.

LoadBalancer servisi

LoadBalancer servis je treći tip servisa u Kuberenetes-u i jedan od načina da se saobraćaj raspodeli prema više čvorova u klasteru. Može usmeravati neke zahteve na više različitih čvorova, pokušavajući da ne preoptereti ni jedan pojedinačni čvor. Evo primera konfiguracije jednog LoadBalancer servisa.

kind: Service
apiVersion: v1
metadata:
  name: service-test
spec:
  type: LoadBalancer
  selector:
    app: test_pod
  ports:
  - port: 80
    targetPort: http

Saobraćaj koji dolazi sa spoljnog izvora prolazi kroz ovu putanju:

Spoljni klijent -> Load balancer -> IP čvora (eth0 interfejs) -> NodePort -> ClusterIP servis -> Pod

Međutim, da bi LoadBalancer servis zaista radio kako je zamišljeno, potrebno je koristiti Kubernetes u oblaku koji podržava ovaj tip servisa. Na primer, ako pokrećete Kubernetes klaster u oblaku poput AWS-u, možete kreirati LoadBalancer servis koji zatim kreira Elastic Load Balancer za usmeravanje saobraćaja prema čvorovima.

Važno je imati na umu da će logika balansiranja opterećenja biti implementirana od strane provajdera oblaka, a ne od strane Kubernetes-a.

Zaključak

Upoznali smo se sa umrežavanjem u Kubernetes-u i videli da je to ključni aspekt za implementaciju i upravljanje kontejnerizovanim aplikacijama. Umrežavanje smo razložili na slojeve kako bi lakše shvatili kako svaka komponenta komunicira i funkcioniše u sistemu.

Iako može biti obimna i kompleksna tema, nadamo se da ovaj članak u nekom meri doprnosi rasvetljavanju osnovnih pojmova.

Korisni linkovi

Autor: Milica Stevanović

Studentkinja završne godine osnovnih studija Informatike na Prirodno-matematičkom fakultetu u Kragujevcu. U toku studija, radila sam kao demonstator na fakultetu i sticala dodatno iskustvo kroz prakse u dve IT kompanije.

Milica Stevanović

Studentkinja završne godine osnovnih studija Informatike na Prirodno-matematičkom fakultetu u Kragujevcu. U toku studija, radila sam kao demonstator na fakultetu i sticala dodatno iskustvo kroz prakse u dve IT kompanije.