Kubernetes (K8s) planer često koristi jednostavna pravila zasnovana na dostupnosti resursa kako bi smestio podove na nodove (čvorove).
To je sasvim u redu za mnoge slučajeve i upotrebu uopšte. Međutim, ponekad možda možemo da idemo korak dalje od jednostavnog planiranja zasnovanog na resursima.
Na primer, šta ako želimo da rasporedimo podove na određene nodove?
Ili, recimo želimo da izbegnemo postavljanje određenih podova na iste nodove?
Znam, zvuči zamršeno.
Tu dolaze do izražaja dva koncepta u Kubernetesu – Affinity i AntiAffinty ( npr. afinitet i anti-afinitet) .
Ova dva koncepta su naredne tehnike planiranja u Kubernetesu koje nam mogu pomoći da kreiramo fleksibline takozvane politike planiranja.
Uopšteno govoreći, Affinity omogućava planeru Kubernetes-a da postavi pod na grupu nodova ili pod u odnosu na postavljanje drugih podova.
Da bismo kontrolisali postavljanje poda na grupu nodova, korisnik mora koristiti pravila afiniteta nodova.
Za razliku od toga, pravila afiniteta poda ili anti-afiniteta poda omogućavaju kontrolu postavljanja poda u odnosu na druge podove.
Dakle, da vidimo prvo detaljno šta su Affinity i AntiAffinity u Kubernetesu.
U Kubernetesu, Affinity i Antiaffinity su koncepti koji se koriste za upravljanje rasporedom aplikacija i resursa u klasteru.
- Affinity se odnosi na preferenciju koju jedna aplikacija ili resurs ima prema drugoj aplikaciji ili resursu u smislu njihove lokacije u klasteru.
- Na primer, ako imate dva mikroservisa koji često komuniciraju međusobno, možda ćete želeti da ih držite na istom fizičkom ili virtualnom serveru kako bi se smanjilo vreme prenosa podataka i povećala brzina odziva.
- Affinity se takođe može koristiti za balansiranje opterećenja između čvorova u klasteru, ili za postavljanje aplikacija na određenim vrstama hardvera ili resursa.
S druge strane, Antiaffinity se odnosi na želju da se dva resursa drže razdvojeno i ne smeju biti smešteni zajedno na istom fizičkom ili virtualnom serveru.
- Ovo se može koristiti, na primer, ako su dve aplikacije kritične za poslovanje i postoji rizik od istovremene greške ili prekida rada ako su smeštene zajedno na istom serveru.
- Antiaffinity se takođe može koristiti za sprečavanje dva ista servisa ili aplikacije da se izvršavaju na istom čvoru u klasteru.
U Kubernetesu, Affinity i Antiaffinity se primenjuju pomoću etiketa (labels) i selektora (selectors), kojima se označavaju nodovi i resursi u klasteru.
Ovo omogućava Kubernetesu da upravlja rasporedom aplikacija i resursa na različitim nodovima u klasteru, u skladu sa definisanim Affinity i Antiaffinity pravilima.
Affinity i Antiaffinity su, dakle, ključni koncepti za upravljanje Kubernetes klasterom i omogućavaju bolju skalabilnost, performanse i otpornost na greške.
U ovom članku, kako biste brzo krenuli sa afinitetom Kubernetes-a, detaljno ćemo razmotriti napredne metode planiranja, duboko uroniti u različite vrste K8s afiniteta i pružiti demo afiniteta čvora kako biste mogli praktično da se bavite naprednim planiranjem Kubernetes-a.
Napredne tehnike planiranja podova u Kubernetes-u
Pre nego što se upustimo u Kubernetes afinitet, vratimo se korak unazad i pregledajmo različite prilagođene tehnike planiranja podova koje su nam dostupne.
U tabeli ispod možete videti pregled različitih naprednih metoda planiranja, uključujući Afinitet nodova i Anti-Afinitet poda.
Koncept | Opis i značenje |
---|---|
Taints i Tolerations | Dozvoljavanje nodu da kontroliše koje će se podovi izvršavati na njemu i koje će biti odbijeni |
NodeSelector | Dodeljivanje Poda određenom nodu pomoću oznaka (Labels). |
Node Affinity | Slično NodeSelector-u, ali izražajnije i fleksibilnije kao što je dodavanje „Required“ i „Preferred“ pravila |
Pod Affinity i Anti-Affinity | Zajedničko lociranje modula ili postavljanje modula dalje jedan od drugog na osnovu pravila o Affinity i Anti-Affinity |
Sada ćemo da pogledamo bliže o čemu se radi ovde.
K8s Taints i Tolerations
Sa Taints-ima, nodovi imaju kontrolu nad postavljanjem podova.
Taints omogućavaju nodovima da definišu koji podovi mogu da se postave na njih, a koji su podovi odbijeni od njih.
Na primer, pretpostavimo da imamo node sa posebnom hardverskom opremom i želimo da planer (scheduler) raspoređuje samo podove koji zahtevaju tu posebnu hardversku opremu.
Možemo koristiti Toleracije za Taintove nodova da bismo ispunili ovaj zahtev.
Podovi koji zahtevaju posebnu hardversku opremu moraju definisati toleranciju za Taints na tim nodovima. Sa Tolerancijama, nodovi će omogućiti pokretanje podova na njima.
K8s NodeSelector
NodeSelector je najjednostavniji način za raspoređivanje podova na nodovima.
Radi tako što se definiše oznake za node, a zatim se veže pod za taj node odgovaranjem oznake u specifikaciji poda.
Ovo je jednostavan pristup koji funkcioniše u nekim slučajevima. Međutim, nije dovoljno fleksibilan za kompleksno planiranje podova.
Node Affinity
Pravila afiniteta noda koriste oznake na nodovima i selektore oznaka u fajlu specifikacije poda.
Nodovi nemaju kontrolu nad postavljanjem.
Ako planer postavi pod koristeći pravilo afiniteta noda i pravilo kasnije više nije važeće (npr. zbog promene oznaka), pod će i dalje raditi na tom nodu.
Postoji mnogo korisnih slučajeva za afinitet nodova, uključujući postavljanje poda na grupu nodova sa specifičnim CPU/GPU i postavljanje podova na nodove u određenoj dostupnoj zoni.
Primer zakazivanja Kubernetes poda korišćenjem afiniteta noda.
Postoje dva tipa pravila za Node afinitet :
- Obavezno „Required“
- Poželjno „Preffered“
Dakle, Afinitet noda može biti obavezan ili poželjan.
Za postavljanje poda, pravilo afiniteta noda koje je obavezno, mora biti zadovoljeno, dok sa pravilom afiniteta koje je poželjno, planer će pokušati da pravilo primeni, ali ne garantuje primenu.
Pod Afinitet i Anti-Afinitet – omogućavaju kreiranje pravila koja kontrolišu gde će biti postavljeni podovi u odnosu na druge podove.
Korisnik mora označiti nodove i koristiti selektore oznaka u specifikaciji poda.
Pod Afinitet i Anti-Afinitet omogućavaju podu da specifikuje afinitet (ili anti-afinitet) prema skupu podova.
Kao i kod afiniteta noda, node nema kontrolu nad postavljanjem poda.
Pravila afiniteta funkcionišu na osnovu oznaka.
Pomoću pravila afiniteta, planer može postaviti pod na isti node kao i drugi podovi, ako se oznaka na novom podu podudara sa oznakom na drugom podu.
Primer raspoređivanja Kubernetes poda uz upotrebu Pod Affinity-a.
- Anti-Afinitet pravilo govori planeru da ne raspoređuje novi pod na isti node ako oznaka na novom podu odgovara oznaci na drugom podu.
- Takođe, omogućava vam da držite podove udaljene jedan od drugog.
- Uvođenje Anti-affinity je korisno u slučajevima kao što su izbegavanje postavljanja poda koji će uticati na performanse postojećeg poda na istom nodu.
Primer raspoređivanja Kubernetes podova korišćenjem Anti-Affinity pravila.
Kao i pravila Node Affinity-ja, pravila Pod Affinity-ja takođe imaju „Obavezni“ i „Preferirani“ režim rada.
U „Obaveznim“ pravilima, pravilo mora biti ispunjeno da bi scheduler postavio pod.
U „Preferiranom“ režimu, raspoređivanje zasnovano na pravilu nije garantovano.
Primer Node Affinity-a
Sada kada razumete Kubernetes afinitete, pređimo na naš demo Node Affinity-a.
U ovom primeru, proći ćemo korak po korak kroz instrukcije:
- Hajde da objasnimo kako Node Affinity pravila funkcionišu označavanjem nekih nodova u klasteru
- Zatim ćemo da napravimo deployment sa Node Affinity pravilom u pod specifikaciji
- Na kraju ćemo da vidimo da su pod-ovi postavljeni na nodove sa datim oznakama.
Prvo da vidimo listu nodova u klasteru:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-node-master-1 Ready controlplane,etcd 3d v1.15.12
k8s-node-master-2 Ready controlplane,etcd 3d v1.15.12
k8s-node-master-3 Ready controlplane,etcd 3d v1.15.12
k8s-node-worker-1 Ready worker 3d v1.15.12
k8s-node-worker-2 Ready worker 3d v1.15.12
k8s-node-worker-3 Ready worker 3d v1.15.12
k8s-node-worker-4 Ready worker 3d v1.15.12
Označite dva noda za Node Affinity primer tako da se podovi mogu postaviti na označene nodove prema pravilima privrženosti nodovima:
$ kubectl label node k8s-node-worker-3 app=frontend node/k8s-node-worker-3 labeled
$ kubectl label node k8s-node-worker-4 app=frontend node/k8s-node-worker-4 labeled
Zatim kreirajte namespace test za ovaj demo:
$ kubectl create ns test
namespace/test created
Zatim kreirajte sledeći deployment fajl sa nodeАffinity
u specifikaciji pod-a:
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-affinity
namespace: test
spec:
replicas: 4
selector:
matchLabels:
run: nginx
template:
metadata:
labels:
run: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: Always
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: app
operator: In
values:
- frontend
Sada kreirajte deployment koristeći YAML datoteku:
$ kubectl create -f deployment-node-affinity.yml
deployment.apps/node-affinity created
Sledeći korak je da se proveri da li je deployment uspešno kreiran. Ovde vidimo komanu za deploy u namespace-u test.
$ kubectl get deploy -n test
NAME READY UP-TO-DATE AVAILABLE AGE
node-affinity 4/4 4 4 10s
Zatim tražimo da vidimo sve podove izlistane.
$ kubectl get pods -n test
NAME READY STATUS RESTARTS AGE
node-affinity-8fd8f3f23f-dng7b 1/1 Running 0 30s
node-affinity-8fd8f3f23f-frsxz 1/1 Running 0 30s
node-affinity-8fd8f3f23f-nn6jl 1/1 Running 0 30s
node-affinity-8fd8f3f23f-wpc66 1/1 Running 0 30s
Dalje, da bismo proverili da li je pravilo afiniteta za nodove funkcionisalo, otvaramo listu podova na nodovima i proveravamo da li su podovi smešteni na nodovima sa oznakom app=frontend
, tj. worker3
, worker4
u ovom slučaju:
$ kubectl get pod -o=custom-columns=NODE:.spec.nodeName,NAME:.metadata.name -n test
NODE NAME
k8s-node-worker-4 node-affinity-8fd8f3f23f-dng7b
k8s-node-worker-4 node-affinity-8fd8f3f23f-frsxz
k8s-node-worker-3 node-affinity-8fd8f3f23f-nn6jl
k8s-node-worker-3 node-affinity-8fd8f3f23f-wpc66
Na kraju, očistite resurse demo primera:
$ kubectl delete ns test --cascade
namespace "test" deleted
Pod Affinity i Anti-Affinity
Sada ćemo da pretpostavimo da imamo Redis keš za web aplikacije i potrebno je pokrenuti tri replike Redis-a, ali je potrebno da se svaka replika pokreće na drugom čvoru.
Koristi se anti-affinity pravilo u ovom slučaju.
Deployment Redis-a sa pravilom pod anti-affinity, tako da svaka replika završi na drugom čvoru:
cat redis.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-cache
namespace: test
spec:
selector:
matchLabels:
app: store
replicas: 3
template:
metadata:
labels:
app: store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: redis-server
image: redis:3.2-alpine
Kreirajte deployment koristeći yaml fajl iznad:
kubectl create -f redis.yaml deployment.apps/redis-cache created
Proverite da li je deployment pokrenut.
$ kubectl -n test get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
redis-cache 3/3 3 3 11s
Proverite da li svaki pod radi na različitom čvoru:
$ kubectl get pod -o=custom-columns=NODE:.spec.nodeName,NAME:.metadata.name -n test
NODE NAME
k8s-node-worker-3 redis-cache-58786cc745-yzxtr
k8s-node-worker-1 redis-cache-58786cc745-bmkpc
k8s-node-worker-2 redis-cache-58786cc745-lehut
Dakle, ovde vidimo da se svaki pod pokreće na drugom nodu.
Idemo dalje, sada pretpostavimo da imamo pokrenut veb server i da moramo da se uverimo da se svaki modul veb servera nalazi zajedno sa svakim Redis keš modulom, ali u isto vreme, moramo da se uverimo da dva modula veb servera ne rade na istom nodu, da bi se ovo desilo koristimo pod affinity i pod anti-affinity kao što je prikazano u nastavku.
Kreirajte datoteku za implementaciju sa pravilima pod affinity i pod anti-affinity:
cat web-server.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
namespace: test
spec:
selector:
matchLabels:
app: web-store
replicas: 3
template:
metadata:
labels:
app: web-store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-store
topologyKey: "kubernetes.io/hostname"
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: web-app
image: nginx:1.12-alpine
Ovde pravimo deployment.
$ kubectl create -f web-server.yaml
deployment.apps/web-server created
Izlistajte podove zajedno sa nodovima i proverite da li su postavljeni prema pravilima:
$ kubectl get pod -o=custom-columns=NODE:.spec.nodeName,NAME:.metadata.name -n test
NODE NAME
k8s-node-worker-3 redis-cache-58786cc745-yzxtr
k8s-node-worker-1 redis-cache-58786cc745-bmkpc
k8s-node-worker-2 redis-cache-58786cc745-lehut
k8s-node-worker-1 web-server-84b9456f9b-dhd9x
k8s-node-worker-3 web-server-84b9456f9b-lf6xs
k8s-node-worker-2 web-server-84b9456f9b-zbjq2
Dakle, ovde vidimo da se svaki web pod nalazi u istom nodu kao i jedan Redis pod, i da nijedna dva web noda ne rade na istoj mašini, što je postignuto upotrebom pravila za pod Affinity i Anti-Affinity.
Zaključak
Kocenpti afinitet i anti-afinitet pružaju fleksibilne načine za zakazivanje pods-ova na nodovima ili postavljanje pod-ova u odnosu na druge pod-ove.
Možete koristiti pravila afiniteta za optimizaciju raspoređivanja pod-ova na radnim nodovima za performanse, toleranciju na greške ili druge složene zahteve raspoređivanja.
Primeri koji su navedeni mogu da se urade na Kubernetes klasteru na Linode Cloud-u, koji je svakako najjeftiniji i najbrže se podiže.
Ukoliko ste zaintersovani za ovo testiranje možete otvoriti nalog ovde i uraditi probu.
Nemojte zaboraviti da na kraju testiranja ugasite i obrišete komplet nodove sa mašine.
Srećna plovidba.
Napišite komentar