22 β Pod, Deployment, Service¶
β¬ οΈ Oldingi: 21 β Nega Kubernetes: arxitektura va lokal klaster Β· π README Β· Keyingi: 23 β Production Kubernetes β‘οΈ
Bu bobda: 21-bobda nega Kubernetes kerakligini va lokal klaster (
minikube/kind) ko'targan edik β endi unda ishlaydigan asosiy obyektlarni o'rganamiz. Kubernetes'ning eng kichik birligi Pod (bir yoki bir necha konteyner, umumiy tarmoq va storage) ekanini, Pod ephemeral (o'tkinchi) ekanini ko'ramiz; ReplicaSet bir xil Pod nusxalarini ushlab turishini; Deployment (apps/v1) esa ReplicaSet'ni deklarativ boshqaribreplicas,selector,templateorqali self-healing va masshtablash berishini o'rganamiz. K8s'ning bog'lash mexanizmi β label va selector β ni alohida puxta ko'ramiz: Deployment va Service Pod'larni IP orqali emas, label orqali topadi. So'ng Service (v1) β ephemeral Pod'lar ustidan barqaror tarmoq nuqtasi va load balancing β va uning uch turi (ClusterIP, NodePort, LoadBalancer) farqini ko'ramiz. Oxirida konfiguratsiyani koddan ajratuvchi ConfigMap va Secret (v1) ni, va namuna "vazifalar" ilovasi uchun to'liq Deployment + Service + ConfigMap manifestinikubectl apply -fbilan deploy qilishni o'rganamiz.
Muammo: "konteynerni qo'lda ishlatish" yetarli emas¶
21-bobda lokal klaster ko'tardik. Endi unga namuna vazifalar API ilovamizni (kitob bo'ylab ishlatib kelayotgan kichik Node.js ilova) joylashtirmoqchimiz. Birinchi xayolga keladigan narsa β Docker'dagidek bitta konteyner ishga tushirish:
# Bitta Pod'ni qo'lda ishga tushirish (illustrativ - keyin nega yomonligini ko'ramiz)
kubectl run vazifalar --image=ghcr.io/foydalanuvchi/vazifalar-api:latest
Ishladi β bitta Pod ko'tarildi. Lekin shu zahoti uchta jiddiy savol tug'iladi:
- Pod qulasa-chi? Ilova kodida xato bo'lib konteyner yiqilsa, uni kim qayta ko'taradi?
kubectl runbilan ko'tarilgan yakka Pod o'lsa β o'lik qoladi. - Yukni qanday ko'taramiz? Bitta Pod yetmasa, 3 ta bir xil nusxa kerak. Ularni qo'lda 3 marta
kubectl runqilamizmi va birini boshqaramizmi? - Pod'ga qanday murojaat qilamiz? Pod'ning IP manzili bor, lekin Pod o'lib qayta yaratilsa IP o'zgaradi. Brauzer yoki boshqa servis qaysi manzilga ulanadi?
Bu uchta savolning javobi β bu bobning uchta asosiy obyekti: Deployment (qulasa tikla, masshtabla), label/selector (bog'lash) va Service (barqaror manzil). Ularni quyidan yuqoriga, Pod'dan boshlab quramiz.
π Kubernetes'da deyarli hech qachon Pod'ni yoki konteynerni to'g'ridan qo'lda ishlatmaysiz. Buning o'rniga deklarativ ravishda "men 3 ta shunday Pod xohlayman" deb YAML'da yozasiz, klaster esa shu holatga o'zini keltiradi va ushlab turadi. Bu β 21-bobdagi "kerakli holatni e'lon qilasan, K8s amalga oshiradi" tamoyilining amaliyoti.
Pod: K8s'ning eng kichik birligi¶
Docker'da eng kichik ish birligi β konteyner. Kubernetes'da esa Pod. Pod β bir yoki bir necha konteynerni o'rab turuvchi qobiq. Bir Pod ichidagi konteynerlar:
- bitta tarmoq (network namespace) ni baham ko'radi β ya'ni
localhostorqali bir-biriga ulanadi, bitta IP manzilga ega; - storage (volume) ni baham ko'rishi mumkin;
- har doim birga rejalashtiriladi (bir node'da turadi), birga ko'tariladi va birga o'ladi.
Oddiy o'xshatish: Pod β bitta kvartira, konteynerlar β undagi xonadoshlar. Xonadoshlar bitta manzilni (IP) baham ko'radi, bitta eshikdan kiradi va birga ko'chib chiqadi. Aksar hollarda kvartirada bitta xonadosh bo'ladi (1 Pod = 1 konteyner = sizning ilovangiz); ikkinchi konteyner faqat asosiy ilovaga yordamchi ("sidecar") bo'lganda qo'shiladi (masalan log yig'uvchi).
π‘ Amalda eng keng tarqalgan holat: 1 Pod = 1 konteyner. "Bir necha konteyner" β bu istisno, oddiy qoida emas. Boshlovchi sifatida har doim "1 Pod = mening ilovam" deb tasavvur qiling, sidecar'ni keyinroq kerak bo'lganda qo'shasiz.
Pod ephemeral β bu eng muhim xususiyat¶
Pod o'tkinchi (ephemeral). U o'ladi va o'rniga yangi Pod yaratiladi β eski Pod tiklanmaydi, balki butunlay yangisi tug'iladi, yangi nom va yangi IP bilan. Pod o'lishi mumkin: konteyner qulasa, node yangilansa, klaster Pod'ni boshqa node'ga ko'chirsa. Shuning uchun:
- Pod'ning IP'siga tayanmang β u istalgan vaqtda o'zgaradi (Service shuning uchun kerak).
- Pod ichidagi diskka muhim ma'lumot yozmang β Pod o'lsa yo'qoladi (doimiy ma'lumot uchun PersistentVolume kerak, 24-bobda).
Pod'ni quyidagicha tasvirlash mumkin β bu eng oddiy K8s manifesti:
# pod.yaml - eng oddiy Pod (odatda buni TO'G'RIDAN ishlatmaymiz)
apiVersion: v1
kind: Pod
metadata:
name: vazifalar
labels:
app: vazifalar
spec:
containers:
- name: api
image: ghcr.io/foydalanuvchi/vazifalar-api:latest
ports:
- containerPort: 3000
Har K8s manifestida to'rt asosiy maydon bor (buni har obyektda ko'rasiz):
apiVersionβ obyekt qaysi API guruh/versiyaga tegishli (Pod uchunv1).kindβ obyekt turi (Pod,Deployment,Service...).metadataβ nom (name) va labellar (pastda muhim rol o'ynaydi).specβ kerakli holat: qaysi image, qaysi port, nechta nusxa va h.k.
Pod bilan ishlash buyruqlari (Docker'dagi docker ps/logs/exec ning K8s ekvivalenti):
kubectl apply -f pod.yaml # manifestdan Pod yaratish
kubectl get pods # Pod'lar ro'yxati va holati
kubectl describe pod vazifalar # batafsil: hodisalar, xatolar, IP
kubectl logs vazifalar # konteyner loglari (docker logs kabi)
kubectl exec -it vazifalar -- sh # Pod ichiga kirish (docker exec kabi)
kubectl delete pod vazifalar # Pod'ni o'chirish
kubectl get pods chiqishi taxminan shunday:
READY 1/1 β Pod'dagi 1 konteynerdan 1 tasi tayyor; STATUS Running β ishlayapti.
β οΈ
kubectl run/pod.yamlbilan yakka Pod yaratsangiz va u o'lsa, hech kim uni qayta yaratmaydi β o'lik qoladi. Yakka Pod'da self-healing YO'Q. Shuning uchun production'da Pod'ni hech qachon to'g'ridan ishlatmaymiz; uni Deployment orqali boshqaramiz. Yuqoridagipod.yamlfaqat "Pod nima" ni ko'rsatish uchun.
ReplicaSet va Deployment: self-healing va masshtablash¶
Yakka Pod'ning kamchiligini (o'lsa tiklanmaydi, ko'paytirib bo'lmaydi) ikki qatlam hal qiladi.
ReplicaSet β vazifasi bitta: belgilangan sondagi (replicas) bir xil Pod'ni doimo ushlab turish. Agar 3 ta so'ralgan bo'lsa-yu, bittasi o'lsa β ReplicaSet darhol yangisini yaratadi (3 ta bo'lib qoladi). Bu β self-healing.
Lekin ReplicaSet'ni to'g'ridan ishlatmaymiz. Uning ustida yana bir qatlam β Deployment β turadi, chunki ReplicaSet yangilanish (yangi image'ga o'tish) ni boshqara olmaydi. Deployment esa: yangi versiyaga rolling update (bosqichma-bosqich), rollback (orqaga qaytish) va masshtablashni boshqaradi.
Ierarxiya quyidagicha: siz Deployment yozasiz, u ReplicaSet yaratadi, u esa Podlarni yaratadi.
Namuna vazifalar ilovamiz uchun Deployment manifesti:
# deployment.yaml
apiVersion: apps/v1 # DIQQAT: Deployment apps/v1 (Pod v1 emas)
kind: Deployment
metadata:
name: vazifalar
labels:
app: vazifalar
spec:
replicas: 3 # 3 ta bir xil Pod nusxasi xohlaymiz
selector:
matchLabels:
app: vazifalar # qaysi Pod'larni "meniki" deb hisoblaydi
template: # yaratiladigan Pod'ning shabloni (qolipi)
metadata:
labels:
app: vazifalar # selector.matchLabels bilan AYNAN bir xil
spec:
containers:
- name: api
image: ghcr.io/foydalanuvchi/vazifalar-api:latest
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: production
Asosiy maydonlar:
replicas: 3β kerakli nusxa soni. Klaster doimo aynan shuncha Running Pod ushlab turadi.selector.matchLabelsβ Deployment qaysi Pod'larni boshqarishini label bo'yicha aniqlaydi. Bu Pod IP'siga emas, labelga tayanadi.templateβ yaratiladigan har bir Pod'ning qolipi: aslidatemplate.metadata+template.specβ bu yuqoridagipod.yamlning ichki qismi.
π Eng muhim qoida (xatolarning 90 foizi shu yerda): Deployment'da
spec.selector.matchLabelsvaspec.template.metadata.labelsaynan bir xil bo'lishi SHART. Selector "men shu label'li Pod'larni boshqaraman" deydi, template esa "men shu label'li Pod'lar yarataman" deydi β ular mos kelmasa, Deployment o'zi yaratgan Pod'ni "meniki" deb tanimaydi va xato beradi. Yuqorida ikkalasi hamapp: vazifalar.
Deployment bilan ishlash:
kubectl apply -f deployment.yaml # deploy qilish (yoki yangilash)
kubectl get deploy # Deployment'lar holati
kubectl get pods # 3 ta Pod ko'rinadi
kubectl scale deploy/vazifalar --replicas=5 # 3 -> 5 ga masshtablash
kubectl rollout status deploy/vazifalar # yangilanish holati
kubectl delete -f deployment.yaml # o'chirish
kubectl get deploy va kubectl get pods chiqishi:
NAME READY UP-TO-DATE AVAILABLE AGE
vazifalar 3/3 3 3 40s
NAME READY STATUS RESTARTS AGE
vazifalar-7c9f8d6b5-2xklm 1/1 Running 0 40s
vazifalar-7c9f8d6b5-9wq4t 1/1 Running 0 40s
vazifalar-7c9f8d6b5-mn7pz 1/1 Running 0 40s
E'tibor bering: Pod nomlari avtomatik generatsiya qilingan (Deployment nomi + ReplicaSet hash + tasodifiy qism). Pod nomini siz tanlamaysiz β chunki ular o'tkinchi.
π‘ Self-healing'ni sinab ko'ring: Pod'lardan birini ataylab o'chiring β
kubectl delete pod vazifalar-7c9f8d6b5-2xklm. Bir necha soniyadakubectl get podsga qarang: ReplicaSet o'rniga yangi Pod (yangi nom) yaratgan bo'ladi, jami yana 3 ta. Hech qanday qo'lda aralashuvsiz β bu 19-bobdagi systemdRestart=ga o'xshash, lekin butun klaster miqyosida. (Bu jonli klasterda bajariladi.)
Label va selector: K8s'ning bog'lash mexanizmi¶
Bu β Kubernetes'ni tushunishdagi eng muhim tushuncha. Agar shuni o'zlashtirsangiz, qolgan hamma narsa joyiga tushadi.
Kubernetes obyektlari bir-birini IP yoki nom orqali emas, label orqali topadi. Label β bu obyektga (asosan Pod'ga) yopishtirilgan oddiy kalit: qiymat yorlig'i, masalan app: vazifalar yoki tier: backend. Selector β "menga shu label'lari mos keladigan obyektlarni top" degan so'rov.
Oddiy o'xshatish: label β kiyimdagi bayroqcha/yorliq, selector β "qizil yorliqli hamma narsani ber" degan filtr. Pod'lar to'plamida turli yorliqlar bor; selector kerakligini yorliq bo'yicha ajratib oladi.
Nega bu shunchalik muhim? Chunki Pod'lar o'tkinchi β IP va nomlari doim o'zgaradi. Agar Deployment yoki Service Pod'ni IP bo'yicha qidirsa, Pod qayta yaratilishi bilan bog'lanish uziladi. Label esa barqaror: yangi Pod ham xuddi shu app: vazifalar label bilan yaratiladi, demak selector uni baribir topadi.
Yuqoridagi Deployment misolida shu mexanizm ikki marta ishladi:
- Deployment β Pod:
selector.matchLabels: {app: vazifalar}Deployment'ga qaysi Pod'lar "meniki" ekanini aytdi. - Service β Pod (keyingi bo'limda): Service ham xuddi shu
app: vazifalarselector bilan o'sha Pod'larni topadi va ularga trafik yuboradi.
Label'larni buyruqdan ham ko'rish/filtrlash mumkin:
kubectl get pods --show-labels # har Pod'ning label'larini ko'rsatadi
kubectl get pods -l app=vazifalar # faqat shu label'li Pod'lar (-l = selector)
kubectl get pods -l 'app in (vazifalar,web)' # bir nechta qiymat bo'yicha
kubectl label pod <nom> tier=backend # mavjud Pod'ga label qo'shish
π Label/selector β K8s'da hamma bog'lanish shu orqali bo'ladi: Service β Pod, Deployment β Pod, NetworkPolicy β Pod, hatto Pod β Node (
nodeSelector). "X obyekti Y obyektni qanday topadi?" degan savolga K8s'da javob deyarli har doim "label/selector orqali" bo'ladi. IP yoki nom emas.
Service: o'tkinchi Pod'lar ustidan barqaror manzil¶
Endi muammoning oxirgi qismi: 3 ta Pod ishlayapti, har birining IP'si bor, lekin:
- Pod o'lib qayta yaratilsa, IP o'zgaradi β brauzer qaysi IP'ga ulanadi?
- 3 ta Pod bor β yukni ular orasida kim taqsimlaydi (load balancing)?
Yechim β Service. Service Pod'lar guruhi ustida bitta barqaror tarmoq nuqtasi (o'zgarmas IP va DNS nom) yaratadi va kirgan trafikni mos Pod'lar orasida avtomatik taqsimlaydi. Service Pod'larni β albatta β label selector orqali topadi.
# service.yaml
apiVersion: v1 # DIQQAT: Service v1 (Deployment'dan farqli)
kind: Service
metadata:
name: vazifalar
spec:
type: ClusterIP # default - klaster ichida ko'rinadigan
selector:
app: vazifalar # SHU label'li Pod'larga trafik yuboradi
ports:
- port: 80 # Service tinglaydigan port
targetPort: 3000 # Pod ichidagi konteyner porti
E'tibor bering: Service selector to'g'ridan app: vazifalar (oddiy kalit: qiymat), Deployment'dagi kabi matchLabels ostida EMAS β bu ikki obyektning kichik, lekin tez-tez xato qilinadigan farqi. port β Service'ga kelinadigan port, targetPort β u Pod ichida qaysi portga uzatishi (bizning ilova 3000-portni tinglaydi).
π‘ Service yaratilgach, klaster ichida unga DNS nom beriladi: oddiygina
vazifalar(yoki to'liqvazifalar.default.svc.cluster.local). Boshqa Pod'lar IP o'rniga shu nom bilan ulanadi βhttp://vazifalar:80. Pod'lar qancha o'lib-yaralsa ham, bu nom va Service IP o'zgarmaydi. Aynan shu β "barqaror nuqta" ning ma'nosi.
Service uch turi: ClusterIP, NodePort, LoadBalancer¶
type maydoni Service'ga kim murojaat qila olishini belgilaydi β faqat klaster ichidagilarmi yoki tashqaridagilar ham.
- ClusterIP (default) β Service faqat klaster ichida ko'rinadi. Tashqaridan kirib bo'lmaydi. Ichki servislararo aloqa uchun (masalan frontend β backend, ilova β ma'lumotlar bazasi). Eng ko'p ishlatiladigan tur.
- NodePort β Service har bir node'ning yuqori portida (30000β32767 oralig'ida) ochiladi, shunda
http://<node-IP>:<NodePort>orqali tashqaridan kirish mumkin. Lokal sinov (minikube) yoki oddiy holatlar uchun qulay, lekin port chiroyli emas (30080 kabi) va to'g'ridan production uchun kam ishlatiladi. - LoadBalancer β cloud provayderdan (AWS, GCP, Azure...) tashqi yuk balanslagich va tashqi IP so'raydi. Eng "production" tur, lekin haqiqiy cloud klaster kerak β lokal
minikube/kindda to'liq ishlamaydi (illustrativ qoladi).
ClusterIP'ni vaqtinchalik tashqaridan sinash uchun port-forward ishlatiladi (tur o'zgartirmasdan):
kubectl apply -f service.yaml
kubectl get svc # Service'lar ro'yxati, CLUSTER-IP va PORT
# Lokalda sinash: 8080-portni Service'ning 80-portiga ulash
kubectl port-forward svc/vazifalar 8080:80
# Endi brauzerda http://localhost:8080 ishlaydi (terminal ochiq turishi kerak)
kubectl get svc chiqishi:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
vazifalar ClusterIP 10.96.142.51 <none> 80/TCP 12s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d
EXTERNAL-IP <none> β ClusterIP tashqi IP olmaydi (bu normal). LoadBalancer turida bu ustun cloud bergan IP'ni ko'rsatardi.
π Real production'da tashqi kirish odatda Service emas, Ingress orqali bo'ladi. Har domen/yo'l uchun alohida LoadBalancer ochish qimmat β buning o'rniga bitta Ingress (16β17-bobdagi Nginx reverse proxy'ning K8s ekvivalenti) ko'plab Service'larni domen/yo'l bo'yicha boshqaradi. Ingress'ni 24-bobda ko'ramiz. Hozircha: ichki aloqa = ClusterIP, lokal sinov = NodePort yoki
port-forward.β οΈ
kubectl exposebilan Service'ni buyruqdan ham yaratish mumkin (kubectl expose deploy/vazifalar --port=80 --target-port=3000), lekin manifestni YAML faylda saqlash afzal β chunki u deklarativ, git'ga tushadi va takrorlanadi. Buyruqli usul tezkor sinov uchun yaxshi, production uchun emas.
ConfigMap va Secret: konfiguratsiyani koddan ajratish¶
Ilovaga konfiguratsiya (port, ma'lumotlar bazasi manzili, xususiyat bayroqlari) va sirlar (parol, API kalit) kerak. Ularni image ichiga "qotirib qo'yish" β yomon amaliyot: har o'zgarganda yangi image qurish kerak, sirlar image'da ochiq qoladi. K8s'da buni ajratish uchun ikki obyekt bor:
- ConfigMap β maxfiy bo'lmagan konfiguratsiya (
kalit: qiymat). Ochiq matn. - Secret β maxfiy ma'lumot (parol, token). Qiymat base64 bilan kodlanadi (bu shifrlash EMAS β quyida ogohlantirish bor).
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: vazifalar-config
data:
NODE_ENV: production
APP_TITLE: Vazifalar API
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: vazifalar-secret
type: Opaque
stringData: # stringData - oddiy matn yozasiz, K8s o'zi base64 qiladi
DATABASE_PASSWORD: parol123
π‘ Secret'da
stringDataishlating (oddiy matn yozasiz) β K8s o'zi base64 ga o'giradi.datamaydoni esa allaqachon base64 qilingan qiymat kutadi (echo -n parol123 | base64->cGFyb2wxMjM=).stringDataqulayroq va xatosizroq.
ConfigMap/Secret'dagi qiymatlarni Pod'ga muhit o'zgaruvchisi (env) sifatida ulash β eng keng tarqalgan usul:
# deployment.yaml ichida, containers: > env: o'rniga to'liqroq variant
containers:
- name: api
image: ghcr.io/foydalanuvchi/vazifalar-api:latest
ports:
- containerPort: 3000
env:
- name: NODE_ENV
valueFrom:
configMapKeyRef: # ConfigMap'dan bitta kalit
name: vazifalar-config
key: NODE_ENV
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef: # Secret'dan bitta kalit
name: vazifalar-secret
key: DATABASE_PASSWORD
Yoki butun ConfigMap'ni bir yo'la envFrom bilan ulash mumkin (har kalit alohida env bo'ladi):
β οΈ Secret base64 β bu shifrlash EMAS, faqat kodlash.
echo cGFyb2wxMjM= | base64 -distalgan kishiga parolni qaytarib beradi. Secret'ning haqiqiy maqsadi β sirlarni ConfigMap'dan/manifestdan ajratish va ularga kirishni RBAC bilan cheklash. Haqiqiy himoya uchun: Secret manifestini git'ga ochiq qo'ymang (Sealed Secrets / External Secrets / SOPS ishlating), klasterda encryption-at-rest yoqing. Bu mavzuni 24/26-boblarda ko'ramiz.
Hammasini birlashtirish: to'liq manifest¶
Endi namuna vazifalar ilovasini to'liq deploy qilamiz: ConfigMap + Secret + Deployment + Service bitta faylda (--- bilan ajratilgan). K8s'da bir nechta obyektni bitta faylga yozish odatiy:
# vazifalar.yaml - to'liq stack
apiVersion: v1
kind: ConfigMap
metadata:
name: vazifalar-config
data:
NODE_ENV: production
APP_TITLE: Vazifalar API
---
apiVersion: v1
kind: Secret
metadata:
name: vazifalar-secret
type: Opaque
stringData:
DATABASE_PASSWORD: parol123
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: vazifalar
labels:
app: vazifalar
spec:
replicas: 3
selector:
matchLabels:
app: vazifalar
template:
metadata:
labels:
app: vazifalar
spec:
containers:
- name: api
image: ghcr.io/foydalanuvchi/vazifalar-api:latest
ports:
- containerPort: 3000
envFrom:
- configMapRef:
name: vazifalar-config
- secretRef:
name: vazifalar-secret
---
apiVersion: v1
kind: Service
metadata:
name: vazifalar
spec:
type: ClusterIP
selector:
app: vazifalar
ports:
- port: 80
targetPort: 3000
Bitta buyruq bilan hammasini qo'llaymiz:
kubectl apply -f vazifalar.yaml
# configmap/vazifalar-config created
# secret/vazifalar-secret created
# deployment.apps/vazifalar created
# service/vazifalar created
kubectl get all # Pod, Deployment, ReplicaSet, Service - hammasi
kubectl port-forward svc/vazifalar 8080:80 # lokalda http://localhost:8080
Mana bog'lanish zanjiri qanday yopildi: Service (selector: app: vazifalar) β label'i mos Podlar (3 ta, Deployment yaratgan) β har Pod ichidagi konteyner (port 3000) β konfiguratsiya ConfigMap/Secret dan env orqali. Pod'lardan biri o'lsa, ReplicaSet yangisini ko'taradi (label o'sha), Service esa yangi Pod'ni avtomatik topib trafikni unga ham yuboradi. Hech narsani qo'lda yangilash kerak emas.
π
kubectl apply -fβ deklarativ: faylda "kerakli holat"ni e'lon qilasiz, K8s mavjud holat bilan solishtirib farqni amalga oshiradi. Faylni o'zgartirib qaytaapplyqilsangiz β K8s faqat o'zgargan qismni yangilaydi (masalanreplicas: 3ni5qilsangiz β 2 ta yangi Pod qo'shiladi). Bu β 21-bobdagi deklarativ tamoyilning amaliy ko'rinishi.
Yakun¶
Kubernetes'ning to'rt asosiy obyektini qurdik. Pod β eng kichik birlik, o'tkinchi (ephemeral), shuning uchun IP va nomiga tayanmaymiz. Deployment (apps/v1) ReplicaSet orqali belgilangan sondagi Pod'ni ushlab turadi β self-healing va replicas bilan masshtablash beradi. K8s'ning bog'lash mexanizmi β label va selector: obyektlar bir-birini IP emas, label orqali topadi (selector.matchLabels == template.metadata.labels qoidasi shu yerdan). Service (v1) o'tkinchi Pod'lar ustida barqaror tarmoq nuqtasi va load balancing yaratadi; uch turi β ClusterIP (ichki, default), NodePort (tashqi port), LoadBalancer (cloud) β tashqi kirish darajasi bilan farq qiladi. ConfigMap/Secret (v1) konfiguratsiya va sirlarni koddan ajratadi. Oxirida hammasini bitta manifestda birlashtirib kubectl apply -f bilan deploy qildik.
Endi ilovamiz klasterda ishlaydi β lekin "production-tayyor" emas: tashqi kirish (Ingress), resurs limitlari, sog'liq tekshiruvlari (probe), avtomatik masshtablash (HPA) hali yo'q. Aynan shularni 23-bobda β Production Kubernetes β qo'shamiz.
22-bob mashqlari¶
Oson¶
- Pod nima va u Docker konteyneridan nimasi bilan farq qiladi? "Bir Pod ichida bir necha konteyner" deganda ular nimani baham ko'radi?
- "Pod ephemeral" degani nima? Bundan kelib chiqadigan ikki amaliy xulosani ayting (IP va disk haqida).
- Har K8s manifestidagi to'rt asosiy maydonni (
apiVersion,kind,metadata,spec) sanang va har biri nimani bildirishini ayting. - Deployment, ReplicaSet va Pod orasidagi ierarxiyani ayting: kim kimni yaratadi?
- ClusterIP, NodePort va LoadBalancer turlarining qaysi biri tashqaridan kirishga ruxsat bermaydi, qaysi biri cloud tashqi IP oladi?
O'rta¶
- Deployment manifestidagi
spec.selector.matchLabelsvaspec.template.metadata.labelso'rtasida qanday qoida bor? Buzilsa nima bo'ladi? - Nega Pod'ga IP orqali emas, Service orqali murojaat qilamiz? Service Pod'larni qanday topadi?
- Service manifestidagi
portvatargetPortfarqini namuna ilova (Service 80, ilova 3000) misolida tushuntiring. - ConfigMap va Secret o'rtasidagi farq nima? Secret'ning base64 kodlashi sirni "himoyalaydi"mi β nega ha yoki yo'q?
kubectl runbilan yakka Pod yaratish nega production uchun yomon? Buning o'rniga nima ishlatiladi va u qanday afzallik beradi?
Qiyin¶
webnomli,nginx:1.27-alpineimage bilan, 2 nusxali (replicas: 2) Deployment manifestini yozing. Labelapp: webbo'lsin, konteyner 80-portni ochsin.selectorvatemplate.labelsto'g'ri mosligiga ishonch hosil qiling. So'ng uni qo'llash va 4 nusxaga masshtablash buyruqlarini yozing.- 11-mashqdagi
webDeployment uchun ClusterIP Service yozing: Service 8080-portda tinglasin, trafikni Pod'ning 80-portiga yuborsin, faqatapp: weblabel'li Pod'larga. So'ng lokalda brauzerdan sinash uchunport-forwardbuyrug'ini yozing. - Namuna vazifalar ilovasi uchun bitta faylga (
---bilan) ConfigMap + Deployment + Service yozing: ConfigMap'daNODE_ENV=productionvaAPP_PORT=3000bo'lsin; Deployment 3 nusxali bo'lib ConfigMap'nienvFrombilan butunlay ulasin; Service ClusterIP bo'lib 80β3000 uzatsin. Barcha label/selector mosligini saqlang.
Yechim β 11
# web-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels:
app: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web # selector.matchLabels bilan AYNAN bir xil
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
ports:
- containerPort: 80
kubectl apply -f web-deployment.yaml # qo'llash
kubectl get pods -l app=web # 2 ta Pod ko'rinishi kerak
kubectl scale deploy/web --replicas=4 # 2 -> 4 ga masshtablash
selector.matchLabels: {app: web} va template.metadata.labels: {app: web} aynan bir xil β Deployment o'zi yaratgan Pod'larni shu orqali tanidi. kubectl scale replicas ni 4 ga oshiradi va ReplicaSet darhol 2 ta yangi Pod qo'shadi.
Yechim β 12
# web-service.yaml
apiVersion: v1
kind: Service
metadata:
name: web
spec:
type: ClusterIP
selector:
app: web # Deployment Pod'lari label'iga mos (matchLabels EMAS, oddiy map)
ports:
- port: 8080 # Service tinglaydigan port
targetPort: 80 # Pod (nginx) konteyner porti
kubectl apply -f web-service.yaml
kubectl get svc web # ClusterIP va PORT(S) 8080/TCP
kubectl port-forward svc/web 8888:8080 # localhost:8888 -> Service:8080 -> Pod:80
# Endi brauzerda http://localhost:8888 nginx sahifasini ko'rsatadi
Service selector: app: web orqali 11-mashqdagi Pod'larni topadi. port: 8080 Service'ga kelinadigan, targetPort: 80 Pod ichidagi nginx porti. port-forward ClusterIP turini o'zgartirmasdan vaqtincha lokaldan kirish beradi.
Yechim β 13
# vazifalar-stack.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: vazifalar-config
data:
NODE_ENV: production
APP_PORT: "3000" # raqamni ham tirnoq ichida (string) yozing
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: vazifalar
labels:
app: vazifalar
spec:
replicas: 3
selector:
matchLabels:
app: vazifalar
template:
metadata:
labels:
app: vazifalar
spec:
containers:
- name: api
image: ghcr.io/foydalanuvchi/vazifalar-api:latest
ports:
- containerPort: 3000
envFrom:
- configMapRef:
name: vazifalar-config
---
apiVersion: v1
kind: Service
metadata:
name: vazifalar
spec:
type: ClusterIP
selector:
app: vazifalar
ports:
- port: 80
targetPort: 3000
kubectl apply -f vazifalar-stack.yaml
kubectl get all # ConfigMap'dan tashqari hammasi ko'rinadi
kubectl get configmap vazifalar-config # ConfigMap'ni alohida tekshirish
Uchala obyektda ham bog'lanish app: vazifalar label/selector orqali: Deployment selector.matchLabels == template.labels (Pod yaratish uchun), Service selector (trafik yuborish uchun). envFrom + configMapRef ConfigMap'dagi NODE_ENV va APP_PORT ni har Pod'ga muhit o'zgaruvchisi qilib ulaydi. APP_PORT raqamini tirnoq ichida yozdik, chunki ConfigMap data qiymatlari string bo'lishi shart.
β¬ οΈ Oldingi: 21 β Nega Kubernetes: arxitektura va lokal klaster Β· π README Β· Keyingi: 23 β Production Kubernetes β‘οΈ