Features and Kubernetes: Best Practices - Knoldus Blogs

Ushbu maqolada Kubernetes klasterida dasturni ishga tushirishni va Kubernetes ob'ektlari haqida qisqacha eslatib o'taman.

 

Maqola kimlarga mo'ljallnagan?

  • O'z ilovasini Kubernetes-da sinab ko'rmoqchi bo'lganlarga
  • Kubernetesni o'rganmoqchi bo'lganlarga

 

Boshlashdan oldin sizga kerak bo'ladi:

  • Kubernetes klasterida ishga tushirish uchun yengil ilova. Buning uchun men .NET-da yengil dastur yaratib, dastur tasvirini Docker Hub-ga joylashtirganman. Siz ham undan foydalanishingiz mumkin.
  • Kubernetes sozlangan klaster. 

 

Kubernetes-ni o’rnatish va klasterni sozlash

Kubernetes klasteri bir tugunli yoki ko’p tugunli ko’rinishida bo’lishi mumkin. Uni Kubernetes-ni o’zida yoki uning distributivlaridan biri (k3s, minikube, microk8s) yordamida sozlashingiz mumkin. Maqola kattalashib ketmasligi uchun, men bunga to’xtalib o’tmayman, qolaversa buning uchun “k3s klasterini yaratish” nomli maqolam ham bor va siz ham undan foydalanishingiz mumkin. Unda k3s Kubernetes distributivi yordamida bitta boshqaruvchi va ikkita ishchi tugunlardan iborat klaster yaratishni ko’rsatib o’tganman.

 

Klaster ishlashini tekshirish

Klaster ishlayotganligini tekshirish uchun kubectl cluster-info buyrug'idan foydalanishingiz mumkin. kubectl - bu Kubernetes bilan aloqa o’rnatish uchun CLI klient.

kubectl cluster-info
Kubernetes control plane is running at https://192.168.31.32:6443
CoreDNS is running at https://192.168.31.32:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Metrics-server is running at https://192.168.31.32:6443/api/v1/namespaces/kube-system/services/https:metrics-server:https/proxy

Natijada klaster ishlayotganini ko'rishingiz mumkin.

 

kubectl get nodes buyrug’idan foydalanib tugunlar ro’hatini tekshiramiz.

NAME         STATUS   ROLES                   	AGE    	VERSION
k3smaster1   Ready    control-plane,master 	2h   	v1.27.4+k3s1
k3sworker1   Ready    <none>                  	2h   	v1.27.4+k3s1
k3sworker2   Ready    <none>                  	2h   	v1.27.4+k3s1

Ko’rinib turganidek bizda bitta k3smaster1 nomli asosiy tugun va ikkita ishchi tugunlar mavjud. 

 

Ob'ekt haqida batafsil ma'lumot olish

Ob'ekt haqida batafsil ma'lumotni ko'rish uchun siz kubectl describe buyrug'idan foydalanishingiz mumkin:

kubectl describe node k3smaster1

ESLATMA! kubectl describe node buyrug'ini tugun nomini ko'rsatmagan holda bajarsangiz, natijada siz barcha mavjud tugunlar haqida batafsil ma’lumot olasiz.

 

Kubernetes-da dasturni ishga tushirish

Yuqorida ta’kidlaganimdek men .NET da tajriba maqsadida sodda ilova tayyorlab, uni Docker Hub tasvirlar omboriga joylashtirganman va siz ham undan foydalanishingiz mumkin. Tasvirni Docker Hub-ga qanday joylashtirish haqida qyuidagi “Dastur tasvirini Docker Hub-ga joylashtirish” havolaga o’tib ko’rishingiz mumkin.

Dasturni Kubernetes-da ishga tushirish uchun Kubernetes pod ob’ektini yaratish kerak bo’ladi.

 

Pod

Pod - Kubernetes klasteridagi abstrakt ob'ekt bo'lib, umumiy saqlash va tarmoq resurslariga ega bir yoki bir nechta konteynerlardan iborat markaziy modul. Har bir pod o'zining IP-manzili, tarmoq nomi, jarayonlari va boshqa resurslarga ega bo’lgan alohida mantiqiy mashinaga o'xshaydi.

Konteynerlar, podalar va ishchi tugunlari o'rtasidagi bog’liqlik

 

Keling endi birinchi pod ob’ektimizni yaratib olamiz. Buning uchun YAML yoki JSON faylda pod manifestini belgilash kerak bo’ladi. 

Pod manifestini yarating:

# kilova-pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: kilova
  labels:
    app: kilova
spec:
  containers:
  - name: kilova
    image: idilshod/kilova
    ports:
    - containerPort: 80
  • kind - ob’ekt turi. Kubernetes resursi
  • metadata.name - Pod nomi 
  • spec.image qismi siz ishga tushirmoqchi bo'lgan konteyner tasvirini belgilaydi 
  • spec.containers.ports.containerPort - Kubernetes-ga ilovangiz qaysi portni tinglayotganini belgilaydi.

 

Pod tavsifini qo’llash uchun qyuidagi buyruqni bajaring:

kubectl apply -f kilova-pod.yml
pod/kilova created

Pod-lar ro’yhatini ko’rish uchun kubectl get buyrug’idan foydalaning:

kubectl get pods
NAME 	READY	STATUS     RESTARTS    AGE
kilova  1/1    	Running    0           54s

READY - ustuni pod-larning tayyorlik holati va ularning sonini anglatadi.

STATUS - pod-ning holatini belgilaydi. 

Konteynerning uchta holati mavjud: 

  • Pending - kutish holati, hali ishga tushmagan hisoblanadi. Agar pod kutish holatida qotib qolsa, Kubernetes tasvirni tasvirlar omborida yuklay olmagan bo’lishi mumkin.
  • Running - to’liq ishga tushgan holati.
  • Terminated - to’xtatilish xolati

 

Yaratilgan pod haqida batafsil ma’lumot oling:

kubectl describe pod kilova
Name:              kilova
Namespace:        default
…
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  3m31s  default-scheduler  Successfully assigned default/kilova to k3sworker2
  Normal  Pulling    3m31s  kubelet            Pulling image "idilshod/kilova"
  Normal  Pulled     3m29s  kubelet            Successfully pulled image "idilshod/kilova" in 1.850840242s (1.850847957s including waiting)
  Normal  Created    3m29s  kubelet            Created container kilova
  Normal  Started    3m29s  kubelet            Started container kilova

Batafsil ma’lumotning oxirida biz Kubernetesning ichki hodisalari ro'yxatini ko'ramiz. Birinchi hodisada Kubernetes pod-ni k3sworker2 tugunga joylashtirishni tanladi. Keyingi hodisa bilan Kubernetes ushbu tugunga kerakli Docker tasvirini tortib olishni boshladi. Keyin u bizning tavsifimiz asosida konteyner yaratdi va nihoyat uni ishga tushirdi.

 

Yaratilgan pod konteyneriga kubectl exec buyrug’i yordamida kirib konteyner nimalardan tashkil topganini ko’rishingiz mumkin:

kubectl exec kilova -it -- bash
root@kilova:/app# ls
Kilova  Kilova.deps.json  Kilova.dll  Kilova.pdb  Kilova.runtimeconfig.json  appsettings.Development.json  appsettings.json  web.config

 

Mahalliy tarmoq portini pod-dagi portga yo'naltirib bog’lanish mumkin. Buni kubectl port-forward buyrug'i yordamida pod-dagi ilova haqiqatdan ishlayotganligini tekshirib ko'ramiz:

kubectl port-forward pod/kilova 8080:80
Forwarding from 127.0.0.1:8080 -> 80

Endi biz http://localhost:8080/ ni ochib server javobini ko'rishimiz mumkin:

 

kubectl logs buyrug'i yordamida konteyner jurnallarini ko'rishimiz mumkin:

kubectl logs kilova
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://[::]:80
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /app

 

Pod-larni o'chirish

kilova nomli pod-ni o’chiring:

kubectl delete pod kilova
pod "kilova" deleted

Pod-ni o’chirish orqali siz Kubernetes-ga ushbu pod-dagi barcha konteynerlarni to’xtatishni buyurasiz.

 

Label yoki yorliqlar

Ayni paytda klasterda bitta pod ishlamoqda. Lekin odatda ularning soni ancha ko’p bo’ladi.

Misol uchun, mikroservis arxitekturasida joylashtirilgan servislar soni 10 yoki undan ko'p bo'lishi mumkin. Bu komponentlar, ehtimol, bir vaqtning o'zida bir nechta versiyalar yoki relizlar bilan takrorlanadi, ya'ni bir xil komponentning bir nechta nusxalari joylashtiriladi. Bu tizimda yuzlab pod-lar paydo bo’lishi mumkin va tabiiy ravishda ularni tartiblash zarurati paydo bo'ladi.

Pod-lar va boshqa barcha Kubernetes ob'ektlari yorliqlar (label) yordamida tartibga solinadi.

Yorliq - resursga biriktirilgan ixtiyoriy kalit/qiymat juftligi bo‘lib, keyin undan yorliq selektorlari yordamida resurslarni tanlashda foydalaniladi.

 

E’tibor bergan bo’lsangiz yuqorida Pod manifestidagi metadata bo’limida biz app: kilova kalit/qiymat juftligini belgiladik. Aynan shu sababli Pod va qolgan resurslar o’rtasida o’zaro bog’liqlik paydo bo’ladi va yorliqlar yordamida resurslarni filterlash mumkin bo'ladi. Sinov tariqasida kilova-pod.yml menifestidagi Pod nomini name: kilova-v2  bilan o’zgartiring:

# kilova-pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: kilova-v2
  labels:
    app: kilova
spec:
  containers:
  - name: kilova
    image: idilshod/kilova
    ports:
    - containerPort: 80

Kiritilagan o’zgarishni qo’llang:

kubectl apply kilova-pod.yml

Buyruq bajarilgach, natichaga quyidagi xabarni ko’rasiz.

pod/kilova-v2 created

 

Yuqoridagi jarayonni yana bir marta takrorlang, faqat bu gal kilova-pod.yml menifestidagi Pod nomini name: kilova-v3  bilan o’zgartiring va uni qo'llang.

 

Pod-lar ro'hatini yorliqlar bilan ko'rish uchun kubectl get pod buyrug’iga qo’shimcha --show-labels parametrini qo’shib tekshirib ko’ring

kubectl get pods --show-labels
NAME     	READY 	STATUS 		RESTARTS   		AGE 	LABELS
kilova-v2  	1/1    	Running    	0	    		4h53m  	app=kilova
kilova-v3 	1/1    	Running    	0		    	4h53m  	app=kilova

 

Pod-larni yorliq selektorlari yordamida o’chirish

Pod-larni bittalab pod nomi bilan o’chirish o’rniga siz selector-lar yordamida bir necha pod-ni bir vaqtda o’chirishingiz mumkin:

kubectl delete po -l app=kilova
pod "kilova-v2" deleted
pod "kilova-v3" deleted

 

Yorliq selektori - bu ma'lum bir qiymatga ega bo'lgan ma'lum yorliqni o'z ichiga olgan yoki olmaganligiga qarab resurslarni filtrlaydigan mezon.

Xuddi shu tarzda yorliqlarni Kubernetes-ning barchra resurslarida qo'llash mumkin. Masalan, yorliqlar yordamida ma'lum bir pod-larni ma'lum tugunlarga joylashtirishingiz mumkin.

 

Controller-lar

Yuqorida biz pod-larni to'g'ridan-to'g'ri qo’lda yaratishni ko’rib chiqdik. Lekin real holatlarda ularni avtomatik ravishda joylashtirish talab qilinadi. Bunday holatda pod-lar to'g'ridan-to'g'ri qo’lda yaratilmaydi. Buning o'rniga, ReplicaSet yoki Deployment kontrollerlari kabi boshqa turdagi resurslar yaratiladi, ular pod-larni avtomatik yaratadi va boshqaradi. Kubernetes qanday qilib konteynerlarni holatini tekshirishi va ularni qanday qayta ishga tushirishini ko’rib chiqamiz.

 

ReplicaSet yoki replika to’plamlari

ReplicaSet - pod nusxalari to'plamlarini barqaror saqlab qolishni ta'milovchi Kubernetes resursi. Agar pod biron bir sababga ko'ra yo'qolsa, replika to’plamlari yo’qolgan pod-ni payqaydi va o'rnini yangi pod-ni yaratadi.

Replika to’plamining vazifasi pod-larning soni har doim uning yorliq selektoriga mos kelishini ta'minlashdan iborat. Agar bunday bo'lmasa, replika to’plami kerakli miqdorga moslashtirish uchun tegishli harakatni amalga oshiradi.

Replika to’plamini yaratish

Quyidagi ko’rinishdagi kilova-replicaset.yml faylini yarating:

# kilova-replicaset.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: kilova
spec:
  replicas: 3 # Pod nusxalari soni
  # selector - qaysi pod-lar ushbu replika to'plamiga tegishliligini belgilaydi
  selector:
    matchLabels:
      app: kilova
  # template - Pod-larni yaratish shabloni
  template:
    metadata:
      labels:
        app: kilova
    spec:
      containers:
      - name: kilova
        image: idilshod/kilova

Faylni qo’llaganingizda Kubernetes kilova nomli yangi replika to’plamini yaratadi va uchta pod nusxasi har doim app=kilova yorliq selektoriga mos kelishini ta'minlaydi.

Shablondagi pod yorliqlari, replika to’plamining yorliq selektoriga mos kelishi kerak, aks holda, replika to’plami cheksiz yangi pod-larni yaratadi, chunki yangi pod nusxalari soni kerakli songa teglashmaydi. Buni oldini olish uchun API server replikatsiya tekshiruvi tavsifni tekshiradi va agar u to'g'ri sozlanmagan bo'lsa, uni qabul qilmaydi.

 

kilova-replicaset.yml manifestini qo’llang:

kubectl apply -f kilova-replicaset.yml
replicaset.apps/kilova created

 

Replika to’plami haqiqatdan ham 3 ta pod nusxasini yaratganiga ishonch xosil qiling:

kubectl get po
NAME      		READY 	STATUS 		RESTARTS 	AGE
kilova-gnsnc  	1/1     Running    0           9s
kilova-gbm5z 	1/1     Running    0           9s
kilova-fcpdz  	1/1     Running    0           9s

 

Biror bir pod-ni o’chirib, replika to’plamini reaksiyasini tekshiring:

kubectl delete po kilova-gnsnc
kubectl get po
NAME           	READY    	STATUS       		RESTARTS   	AGE
kilova-fcpdz   	1/1      	Running           	0          	37s
kilova-b67rb   	1/1      	Running       		0          	37s
kubia-gnsnc  	1/1  		Terminating  		0  			30s
kilova-wsh6s   	0/1      	ContainerCreating 	0          	2s

 

Replika to’plamlari haqida ma’lumot oling:

kubectl get rs
NAME      DESIRED    CURRENT    READY    AGE
kilova    3          3          3        61s

 

Replika to’plami haqida batafsil ma’lumot oling:

kubectl describe rs kilova

 

Replika to’plamidagi pod-lar sonini o’zgarting va ularni sonini kuzating:

kubectl scale rs kilova --replicas=5
replicaset.apps/kilova scaled

Xuddi shu kabi kubectl scale rs kilova --replicas=3 buyruq yordamida pod-lar sonini kamaytiring.

 

Replika to’plamini o’chirish

Replika to’plamini o’chirish uchun quyidagi buyruqdan foydalaning:

kubectl delete rs kilova

Replika to’plamini o’chirish bilan birga ung bog’liq pod-lar ham o’chiriladi. Agar pod-larni saqlab qolmoqchi bo’lsangiz --cascade=false parametridan foydalansangiz bo’ladi.

ESLATMA: Odatda siz ReplicaSet to’gridan-to’g’ri yaratmaysiz. Buning o’rniga Deployment ob’ektidan foydalanasiz. Sababi, agar ilovani versiyasini yangilasak, ularni birin-ketin tortib pod-lar ketma ket deklarativ tarzda yangilishini xohlaymiz. ReplikaSet-lar bilan biz yangi versiya bilan ReplikaSet-ni qo'lda yaratishimiz va eskisini birdan o'chirishimiz kerak. Bu esa xavfli va noqulay. 

 

Deployment

Deployment - bu ilovalarni joylashtirish va ularni deklarativ tarzda yangilash uchun yuqori darajadagi resurs.

Deployment-ni yaratganingizda, uning ostida ReplicaSet resursi yaratiladi. Ya’ni Deployment-dan foydalanilganda, haqiqiy pod-lar to'g'ridan-to'g'ri Deployment ob'ekti tomonidan emas, balki Deployment ob'ektining replika to'plamlari tomonidan yaratiladi va boshqariladi.

 

Deployment-ni yaratish

Deployment-ni yaratish replika to'plamlarini yaratishdan farq qilmaydi.

Deplyment tavsifi:

# kilova-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kilova
spec:
  replicas: 3 # Pod nusxalari soni
  # selector - qaysi pod-lar ushbu replika to'plamiga tegishliligini belgilaydi
  selector:
    matchLabels:
      app: kilova
  # template - Pod-larni yaratish shabloni
  template:
    metadata:
      labels:
        app: kilova
    spec:
      containers:
      - name: kilova
        image: idilshod/kilova

 

Deployment tavsifini qo’llang:

kubectl apply -f kilova-deployment.yml
deployment.apps/kilova created

 

Endi klasterda bo’lgan o’garishlarni ko’rish uchun kubectl get all buyrug’idan foydalaning:

kubectl get all
NAME                           READY    STATUS               RESTARTS    AGE
pod/kilova-5686698d9d-q8r8s    0/1      ContainerCreating    0           40s
pod/kilova-5686698d9d-r8g54    1/1      Running              0           40s
pod/kilova-5686698d9d-tq7nb    1/1      Running              0           40s

NAME                  TYPE         CLUSTER-IP    EXTERNAL-IP    PORT(S)    AGE
service/kubernetes    ClusterIP    10.43.0.1     <none>         443/TCP    4d

NAME                      READY   UP-TO-DATE    AVAILABLE    AGE
deployment.apps/kilova    2/3      3             2            40s

NAME                                 DESIRED    CURRENT    READY    AGE
replicaset.apps/kilova-5686698d9d    3          3          2        40s

Aynan kutilgan narsa sodir bo'ldi: deployment yaratildi, u esa o’zini nomi bilan replikasetni yaratdi va ushbu replikaset o’zini nomi bilan ichida uchta pod yaratdi.

 

Pod resurslarini boshqarish

Biz bilamizki, har qanday dastur ishlashi uchun xotira va protsessor resurslaridan foydalanadi. Shunday vaziyatlar bo'ladiku dastur mashinadagi barcha xotira yoki protsessor resurslarini band qilib qoyishi mumkin yoki xotira yetmasligi sababli dastur qulashi mumkin. Lekin bitta konteyner butun boshli tugunni band qilishi, unchalik to'g'ri yechim emas.  Shu sababli Kubernetes-da har bir konteynerni kutilayotgan resurs iste'moli (requests)ni va maksimal resurs iste'moli (limits)ni belgilash mumkin.

 

Konteynerlarda kutilayotgan va maksimal resurs iste'molini belgilash quyidagicha tavsiflanadi: 

...
spec:
  containers:
  - name: kilova
    image: idilshod/kilova
    resources:
      requests:
        memory: "256Mi"
        cpu: "250m"
      limits:
        memory: "512Mi"
        cpu: "500m"

 

requests - bu konteyner uchun kafolatlangan xotira va protsessor miqdori. Agar ma'lum bir tugundagi konteynerlarida yetarlicha xotira va protsessor bo‘lmasa, konteyner boshqa tugunda ishga tushiriladi. 

limits - bu konteyner iste'mol qilishi mumkin bo'lgan maksimal xotira va protsessor miqdori. Agar konteynerga ko'proq xotira kerak bo'lsa va konteynerlar ishlayotga tugunda bo'sh xotira mavjud bo'lsa, unga requests da ko'rsatilganidan ko'proq xotiraga ajratilishi mumkin, lekin agar konteyner  belgilangan maksimal ko'rsatkichdan ko'proq xotira olishga harakat qilsa, ushbu konteyner o'chiriladi va o'rniga yangi ko'tariladi.

 

Yangilanish strategiyasini sozlash

Agar siz ilovangizni versiyasini yangilasangiz Kubernetes avval yangi pod yaratadi keyin eskisini o’chiradi. Eski podlarni eslab qoladi va siz xoxlagan vaziyatda oldingi versiyalarini tiklashingiz mumkin bo’ladi. Kubernetes-da ikkita maxSurge va maxUnavailable xossalari bilan yangilanish strategiyasini sozlashingiz mumkin.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kilova
spec:
  replicas: 3
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  …

maxUnavailable - yangilash jarayonida o’chirilishi mumkin bo'lgan pod-larning maksimal sonini belgilaydi. Standart qiymat 25%. 

Masalan: agar klasterda 100 ta pod mavjud bo’lsa, yangilash jarayonida faqat 25 foizi o’chirilishi mumkin. 

maxSurge -  yangi o’rnatilayotgan pod-lardan yaratilishi mumkin bo'lgan pod-larning maksimal sonini belgilaydi. Standart qiymat 25%.

Masalan: agar 100 ta pod yangilanish uchun rejalashtirilgan bo’lsa, yangilash jarayonida birin-ketin 25 foizdan yaratiladi. Baravar 100 ta pod yaratsak, klaster resursi yetmasligi mumkin.

maxSurge va maxUnavailable qiymatlarini foiz ko’rinishidan tashqari son ko’rinishida ham belgilashingiz mumkin. Masalan: maxUnavailable: 0 va maxSurge: 1 bo’lsa, bunday holatda Kubernetes avval bitta yangi pod-ni yaratadi va ushbu yangi pod tayyor bo'lgunicha kutadi va undan keyingina qolgan eski pod-lardan birini o’chiradi va bu jarayon barcha pod-lar yangilanmagunicha birin-ketin takrorlanadi. Lekin Kubernetes yangi pod-larning tayyorligini qanday biladi? Buni tiriklik (Liveness), tayyorlik (Readiness) va ishga tushirish (Startup) tekshiruvlari yordamida amalga oshiradi.

 

Tiriklik tekshiruvi. Liveness Probe

Kubernetes konteynerning ayni paytdagi tiriklik holatini livenessProbes orqali tekshirishi mumkin. Har bir konteyner uchun pod tavsifida tiriklik tekshiruvini ko'rsatilishi mumkin. Kubernetes vaqti-vaqti bilan tekshirishni amalga oshiradi va agar tekshirish muvaffaqiyatsiz bo'lsa, konteynerni qayta ishga tushiradi.

Kubernetes qyuidagi uchta mexanizmdan biri yordamida konteynerni tekshirishi mumkin:

  • HTTP tekshiruvi - siz ko'rsatgan konteynerning IP manzili, porti va yo'liga HTTP GET so'rovini bajaradi;
  • TCP soket tekshiruvi - belgilangan konteyner portiga TCP orqali ulanishga harakat qiladi. Agar ulanish muvaffaqiyatli o'rnatilgan bo'lsa, tekshirish ishlagan. Aks holda, konteyner qayta ishga tushiriladi;
  • Exec tekshiruvi - konteyner ichida ixtiyoriy buyruqni bajaradi va buyruq javob kodini tekshiradi.

 

HTTP asosidagi tiriklik tekshiruvi tavsifda quyidagicha belgilanadi:

…
spec:
  containers:
  - name: kilova
    image: idilshod/kilova
    livenessProbe:
      httpGet:
        path: /health/live
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 2

Yuqoridagi PeriodSeconds maydoni kubelet har 5 soniyada tiriklikni tekshirishni amalga oshirishi kerakligini bildiradi. initialDelaySeconds maydoni kubeletga birinchi tekshirishni amalga oshirishdan oldin 5 soniya kutish kerakligini aytadi. Tekshirishni amalga oshirish uchun kubelet konteynerda GET /health/live HTTP so’rovini bajaradi. Agar so’rov muvaffaqiyatli o’tsa va kubelet konteynerni tirik va sog'lom deb hisoblaydi va failureThreshold mayodni tekshiruv necha marta ketma-ket muvaffaqiyatsiz bajarilishi mumkinligini bildiradi. Agar muvaffaqiyatsiz tekshiruvlar soni failureThreshold ko’rsatkichiga yetsa, kubelet konteynerni o'ldiradi va uni qayta ishga tushiradi.

Shunday vaziyatlar bo’ladiki, dasturingiz trafik qabul qila olmaydi, masalan: ma’lumotar ombori nosoz holatda bo’lsa, dasturingiz ma’lumotlar ombori bilan bog’lana olmay qolishi mumkin. Bunday hollarda tiriklik tekshiruvi ish bermasligi mumkin, chunki pod-ni qayta ishga tushirgan taqdirda ham u ya’na ma’lumotlar ombori nosoz bo’lganligi tufayli unga bo’glana olmaydi va kubelet uni qayta-qayta ishga tushiraveradi. Bunday vaziyatda avval tayyorlik tekshiruvi (Readiness Probe)ni amalga ochirish kerak bo’ladi.

Kubelet konteyner ilovasi qachon boshlanganligini bilish uchun ishga tushirish tekshiruvlari (Startup Probe)dan foydalanadi. Agar bunday tekshiruv sozlangan bo'lsa, u muvaffaqiyatli yakunlanmaguncha tiriklik va tayyorlik tekshiruvlari amalga oshirilmaydi. Ushbu tekshiruvni sekin ishga tushadigan ilovalar uchun sozlasangiz bo’lad, masalan, ilovangiz birinchi marta ishga tushishi uchun 30 soniya vaqt talab qilinsa va sizning tiriklik va tayyorlik tekshiruvlaringiz 20 soniyda yakunlansa, kubelet uni qayta-qayta ishga tushiraveradi va ilovangiz hech qachon ishga tushmaydi.

 

 

Sozlamalar lug'ati (ConfigMap)

ConfigMap - bu kalit-qiymat juftliklarida faxfiy bo'lmagan ma'lumotlarni saqlash uchun ishlatiladigan Kubernetes ob'ekti. Kubernetes lug'at tarkibini konteynerlarga muhit o'zgaruvchilari yoki montaj qilingan fayllar sifatida uzatadi.

 

Sozlamalar lug'atini yaratish

Sozlamalar lug’atini minifiest ko’rinishida aniqlash:

# kilova-configmap.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: kilova-config
data:
  ASPNETCORE_ENVIRONMENT: Development
  appsettings.json: |
    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft": "Warning",
          "Microsoft.Hosting.Lifetime": "Information"
        }
      },
      "AllowedHosts": "*",
      "Settings": {
        "Foo": "Bar",
        "Bar": "Baz"
      }
    }

 

Sozlamalar lug'atini yarating:

kubectl apply -f kilova-configmap.yml

 

Sozlamalar lug'atlari ro'yhatini tekshiring:

kubectl get configmaps
NAME               DATA   AGE
kube-root-ca.crt   1      1d2h
kilova-config      2      2h

 

Muhit o'zgaruvchisi sifatida sozlamalar lug’atini dasturga uzatish

Yuqoridagi sozlamalar lug'atini dagi ASPNETCORE_ENVIRONMENT elementni bog'lashni ko'rib chiqaylik:

# kilova-pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: kilova
  labels:
    app: kilova
spec:
  containers:
  - name: kilova
    image: idilshod/kilova
    env:
    - name: ASPNETCORE_ENVIRONMENT        	  	# Muhit o'zgaruvchisi nomi
      valueFrom:
        configMapKeyRef:
          name: kilova-config  				# Sozlamalar lug’atini nomi
          key: ASPNETCORE_ENVIRONMENT       	# Sozlamalar kaliti

Pod-ni yaratib undagi muhit o'zgaruvchilarini tekshiramiz:

$ kubectl apply kilova-pod.yml
$ kubectl exec kilova -it -- bash
root@kilova:/app# env
...
ASPNETCORE_ENVIRONMENT=Development
...

 

Sozlamalar lug’atining barcha elementlarini bog’lashimiz uchun envFrom yordamida amalga oshirishimiz mumkin.

…
spec:
  containers:
  - name: kilova
    image: idilshod/kilova
    envFrom:
        configMapKeyRef:
          name: kilova-config
…

Muhit o'zgaruvchilarining kamchiligi, ular faqat pod-lar ishga tushirilganda konteynerga uzatiladi. Konteyner ishga tushgandan keyin muhit o'zgaruvchilari qayta yuklanmaydi.

 

ConfigMaps-ni konteyner fayl tizimiga biriktirish:

Muhit o'zgaruvchilaridan tashqari, biz ConfigMap elementlarini konteyner fayl tizimidagi jild (volume)ga o'rnatishimiz mumkin:

…
    spec:
      containers:
      - name: kilova
        image: idilshod/kilova
        volumeMounts:
        - name: appsettings
          mountPath: /app/appsettings.json
          subPath: appsettings.json
      volumes:
      - name: appsettings
        configMap:
          name: kilova-config
          items:
          - key: appsettings.json
            path: appsettings.json

volumeMounts.subPath xususiyati bitta faylni yoki bitta katalogni volume-dan biriktirish (montaj qilish) imkonini beradi. subPath-ning kamchiligi bor: agar siz uni ishlatsangiz va sozlamalar lug'atini o'zgartirganingizda, Kubernetes pod-larga sozlamalar o'zgargani haqida xabar bermaydi va faqat pod-larni qayta ishga tushirganingizdan keyingina, ular oxirgi o'zgartirilgan sozlamalarni qabul qiladi. Agar sizga bu muammo bo'lsa, bitta alohida fayl o'rniga butun katalogni montaj qilishingizga to'g'ri keladi. Buning uchun appsettings.json faylini alohida katalogga ko'chiraman va uni montaj qilaman.

…
    spec:
      containers:
      - name: kilova
        image: idilshod/kilova
        volumeMounts:
        - name: appsettings
          mountPath: /app/Settings
      volumes:
      - name: appsettings
        configMap:
          name: kilova-config
          items:
          - key: appsettings.json
            path: appsettings.json

mountPath: /app/Settings - Montaj qilinadigan ilovaning sozlamalar katalogi yo'li 

 

Yuqoridagi ko’rsatmalarni inobatga olgan holda Deployment tavsifini kengaytiramiz va u quyidagi ko’rinishga ega bo’ladi:

# kilova-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kilova
spec:
  replicas: 3
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  selector:
    matchLabels:
      app: kilova
  template:
    metadata:
      labels:
        app: kilova
    spec:
      containers:
      - name: kilova
        image: idilshod/kilova
        imagePullPolicy: Always
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        startupProbe:
          httpGet:
            path: /health/live
            port: http
            scheme: HTTP
          initialDelaySeconds: 5
          failureThreshold: 2
          periodSeconds: 3
        livenessProbe:
          httpGet:
            path: /health/live
            port: 80
          periodSeconds: 3
          failureThreshold: 2
        readinessProbe:
          httpGet:
            path: /health/ready
            port: 80
          periodSeconds: 3
          failureThreshold: 2
        volumeMounts:
        - name: appsettings
          mountPath: /app/Settings
      volumes:
      - name: appsettings
        configMap:
          name: kilova-config
          items:
          - key: appsettings.json
            path: appsettings.json

 

 

Service yoki xizmatlar

Kubernetes xizmati - bu efemer pod-lar ichida ishlaydigan ilovalarga tashqaridan kirish imkonini beruvchi mantiqiy abstraksiya. Biz har bir pod o'z IP-manzilini olishini maqola boshida ta'kidladik, ammo bu klaster ichki manzili hisoblanadi va tashqaridan kirish mumkin emas. Pod-ga tashqaridan kirish uchun Service ob'ekti orqali amalga oshiriladi. Kubernetes-da NodePort, ClusterIP, LoadBalancer kabi xizmat turlari mavjud.

 

LoadBalancer xizmati

LoadBalancer  - bu Kubernetes ob’ekti emas, balki ba'zi tashqi bog'liqliklarga ega bo'lgan xizmat turi xolos. 

Service tavsifini yarating:

# kilova-service.yml
apiVersion: v1
kind: Service
metadata:
  name: kilova-svc
  labels:
    app: kilova
spec:
  type: LoadBalancer
  selector:
    app: kilova
  ports:
  - name: http
    port: 5000
    protocol: TCP
    targetPort: 80

E’tibor bering biz LoadBalancer turidagi maxsus xizmatni belgiladik, chunki agar oddiy xizmat (ClusterIP yoki NodePort) yaratsak, xuddi pod kabi, unga faqat klaster ichidan kirish mumkin bo'ladi. LoadBalancer turidagi xizmatni yaratganingizda, tashqi nagruzka balansirovkasi yaratiladi va siz pod-ga umumiy IP manzil orqali ulanishingiz mumkin bo'ladi.

 

Service tavsifini qo’llash uchun qyuidagi buyruqni bajaring:

kubectl apply kilova-serivce.yml

 

Xizmatlar ro’yhatini chiqarish uchun kubectl get services buyrug'ini bajaring:

kubectl get services
NAME         TYPE          CLUSTER-IP 		EXTERNAL-IP        	PORT(S)
kubernetes   ClusterIP     10.43.0.1      	<none>              	443/TCP         
kilova-svc   LoadBalancer  10.43.30.186 	192.168.31.32,192.168.31.35,192.168.31.36   8080:30531/TCP

Eslatma! Agar siz 80-portda tinglovchi LoadBalancer xizmatini yaratmoqchi bo'lsangiz, k3s 80-port uchun klasterda bo’sh xost topishga harakat qiladi. Agar ushbu port band qilingan bo’lsa, xizmat kutish (Pending) holatda qoladi.

 

Endi dasturingizga EXTERNAL-IP ustunida ko’rsatilgan IP manzillaridan biri (masalan: http://192.168.31.32:5000) orqali tashqaridan murojaat qilsangiz bo’ladi. 192.168.31.32 or’niga o’zingizni IP manizlingizni tering, uni xizmatlar ro’yhatidagi EXTERNAL-IP ustunidan topasiz.

 

 

Ingress Controller

Muhim jixatlardan biri shundaki, har bir LoadBalancer xizmati o'zining umumiy IP-manziliga ega bo'lgan yuk balansini talab qiladi. Har bir xizmat uchun umumiy Static IP ajratish qimmatga tushishi mumkin. Ingress Controller esa  bitta yuk balansi bilan ko’plab Service-larga kirishni ta'minlaydi.

 

Ingress tavsifini aniqlang:

# kilova-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kilova
spec:
  rules:
  - host: kilova.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: kilova-svc
            port:
              number: 80

 

Ingress-ni yarating:

kubectl apply -f kilova-ingress.yml

 

Ingress IP manzilini aniqlang:

kubectl get ingresses
NAME    	CLASS 		HOSTS          	ADDRESS          PORTS 	AGE
kilova    	traefik    	kilova.local 	192.168.31.32    80       	2m

 

IP-manzilni bilganingizdan so'ng, kilova.local ni ushbu IP-manzilga bog'lash uchun DNS-serverlarni sozlashingiz yoki uni C:\windows\system32\drivers\etc\hosts (yoki Linux-da /etc/hosts) ga qo'shishingiz mumkin.

# C:\windows\system32\drivers\etc\hosts

192.168.31.32 kilova.local

Hammasi muvaffaqiyatli bajarilgan bo’lsa, endi brauzeringizda http://kilova.local manzili orqali kirishingiz mumkin:

 

 

Nom maydoni yoki Namespace

Kubernetes-da nom maydonlari bitta klaster ichidagi resurslarni guruhlarga bo’lib izolyatsiya qilish mexanizmini ta'minlaydi. Ular, resurslarni prod, dev, testing kabi muhitlarga ajratish uchun ishlatilishi mumkin. 

Biz shu paytgacha resurslarni aniq nom maydoni bilan belgilamaganingiz sababli, barcha yaratgan resurslaringiz default nom maydoni bilan ishlaydi. Qolaversa kubectl get kabi buyrularda ham nom maydonini aniq ko’rsatmaganimiz uchun kubectl bizga faqat default nom maydonidagi ob’ektlarni qaytaradi. 

 

Ma’lum nom maydoniga tegishli pod-larni chiqarish uchun qyuidagi buyruqdan foydalaning.

kubectl get po -n kube-system
NAME                                      	READY 	STATUS 		RESTARTS   	AGE
helm-install-traefik-crd-662jm            	0/1    	Completed  	0          	2h
helm-install-traefik-b8jxb                	0/1    	Completed  	2         	2h
traefik-64f55bb67d-hhns4                  	1/1    	Running    	5 			2h
svclb-traefik-6ba95d8e-72zk9              	2/2    	Running   	4 			2h
coredns-77ccd57875-kflrs                  	1/1    	Running   	6 			2h
metrics-server-648b5df564-7xvrj           	1/1    	Running   	8 			2h
local-path-provisioner-957fdf8bc-2b5jh    	1/1   	Running   	4 			2h
svclb-kilova-svc-6494edf9-p65j9     		1/1   	Running    	0         	1h

Hamma ob’ektlar ham nom maydoniga ega bo’lmaydi, masalan tugunlar. Qaysi ob’ektlar nom maydoniga emasligini bilish uchun, kubectl api-resources --namespaced=false buyrug’idan foydalaning.

 

Klasterdagi barcha nom maydonlari ro’yhatini chiqaring:

kubectl get ns
NAME               STATUS    AGE
default            Active    2h
kube-system        Active    2h
kube-public        Active    2h
kube-node-lease    Active    2h

 

Keling yangi nom maydonini yaratishdan avval, yuqoridagi barcha yaratilgan resurslarni o’chiramiz.

 

Nom maydonidagi barcha resurslarni o’chirish

kubectl delete all --all
pod "kilova-54bd855f5f-dbgb7" deleted
pod "kilova-54bd855f5f-ztrb2" deleted
pod "kilova-54bd855f5f-nx47r" deleted
service "kubernetes" deleted
service "kilova-svc" deleted
deployment.apps "kilova" deleted
replicaset.apps "kilova-596ff97fdd" deleted

Ushbu buyruqdagi birinchi all parametri barcha turdagi resurslarni o'chirayotganingizni bildiradi va --all parametri esa ularni nusxalarini o'chirib tashlashingizni bildiradi.

ESLATMA. all kalit so'zi mutlaqo hamma ob’ektlarni o'chirib tashlamaydi. Ba'zi resurslar (masalan, secret-lar) saqlanib qolgan va ular aniq belgilab o'chirilishi kerak.

ESLATMA. kubectl delete all --all buyrug'i kubernetes xizmatini ham o'chiradi, biroq u bir necha daqiqadan so'ng avtomatik ravishda qayta yaratilishi kerak.

 

Nom maydonini yaratish

Nom maydonini yaratish uchun quyidagi faylni yarating:

# dev-namespace.yml
apiVersion: v1
kind: Namespace
metadata:
  name: dev

Endi faylni Kubernetes API serveriga jo’natish uchun kubectl create dan foydalaning:

kubectl create -f dev-namespace.yml
namespace "dev" created

Eslatma! kube- prefiksi bilan nom maydoni yaratmang, chunki u Kubernetes nom maydonlari uchun ajratilgan.

 

Ob'ektlarni ma’lum nom maydonlarida boshqarish

Yaratilgangan nom maydonida resurslarni yaratish uchun har bir resurs tavsifidagi metadata bo‘limiga nom maydonini qo‘shishingiz mumkin, masalan:

apiVersion: v1
kind: Pod
metadata:
  name: kilova
  namespace: dev
…

Ikkinchi usul, ob’ektlarni yaratganingizda --namespace=dev parametrida foydalanishingiz mumkin. Keling, shu usulni qo’llab koramiz. Lekin avval asosiy fayllarimizni bitta katalog ostida yiq’ing:

 

Endi dev katalogi ostidagi barcha resurslarni yarating:

kubectl apply -f dev -n dev
configmap/kilova-config created
deployment.apps/kilova created
ingress.networking.k8s.io/kilova created
service/kilova-svc created

 

Nom maydonini va undagi barcha resurslar ro’yhatini chiqarish

Resurslar dev nom maydoni asosida yaratilganiga ishonch xosil qiling:

kubectl get all -n dev
NAME                          READY   	STATUS     RESTARTS    AGE
pod/kilova-984c9fb4f-jsj5l    1/1      Running    0           101s
pod/kilova-984c9fb4f-bxmcz    1/1      Running    0           101s
pod/kilova-984c9fb4f-58fgg    1/1      Running    0           101s

NAME                  TYPE         CLUSTER-IP       EXTERNAL-IP    PORT(S)     AGE
service/kilova-svc    ClusterIP    10.43.108.197    <none>         5000/TCP    101s

NAME                      READY    UP-TO-DATE    AVAILABLE    AGE
deployment.apps/kilova    3/3      3             3            101s

NAME                                DESIRED    CURRENT    READY    AGE
replicaset.apps/kilova-984c9fb4f    3          3          3        101s

 

Nom maydonini va undagi barcha pod-larni o'chirish

Siz quyidagi buyruq yordamida nom maydonini o’chirishingiz mumkin va pod-lar nom maydoni bilan birga avtomatik ravishda o'chiriladi:

kubectl delete ns dev
namespace "dev" deleted

 

Foydalanilgan manbalar:

 

Xulosa

Maqolada biz Kubernetes resurlari bilan tanishib chiqdik va dasturni Kubernetes-da ishlatib ko'rdik. Kubernetes-ni bitta kichkina maqola bilan to’liq yoritib bo’lmaydi, shunday bo'lsada unga kirish uchun foydali ma'lumotga ega bo'ldingiz deb umid qilaman. Kubernetes murakkab platformaligiga qaramasdan, uni sinov tariqasida o'rnatib ishlatib ko’rish unchaliq qiyin emas.