Kubernetes klasterida dasturni ishga tushirish
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.
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 resursimetadata.name
- Pod nomispec.image
qismi siz ishga tushirmoqchi bo'lgan konteyner tasvirini belgilaydispec.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’rnigaDeployment
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:
- https://kubernetes.io/docs
- “Kubernetes in Action” Luksa, Marko kitobi
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.