Tarkibga o'tish

24 β€” Ingress, storage, Helm va GitOps

⬅️ Oldingi: 23 β€” Production Kubernetes Β· 🏠 README Β· Keyingi: 25 β€” Monitoring: Prometheus va Grafana ➑️

Bu bobda: Har bir Service uchun alohida LoadBalancer (va alohida IP) olish qimmat va boshqarib bo'lmas muammosidan boshlab β€” Ingress (networking.k8s.io/v1) bilan ko'p Service'ni bitta tashqi kirish nuqtasiga ulashni, domen va path bo'yicha marshrutlashni (rules, host, http.paths, pathType, backend.service) va TLS'ni (tls bloki, cert-manager bilan avtomatik sertifikat) o'rganamiz, Ingress ishlashi uchun Ingress Controller (nginx-ingress) kerakligini ko'ramiz; Pod ephemeral (vaqtinchalik) ekanini va ma'lumotni saqlash uchun PersistentVolume (PV) / PersistentVolumeClaim (PVC) / StorageClass (dynamic provisioning) bilan haqiqiy diskni Pod'ga ulashni, DB kabi stateful ilovalar uchun StatefulSet (apps/v1, barqaror nom + headless Service + volumeClaimTemplates) ni ko'rib chiqamiz; takroriy YAML'ni shablonlash uchun Helm paket menejerini (Chart.yaml, values.yaml, templates/, helm install/upgrade/rollback/uninstall, --set/-f) o'rganamiz; va nihoyat GitOps (Argo CD / Flux β€” Git haqiqat manbai, push vs pull deploy) hamda managed Kubernetes (EKS/GKE/AKS) ga kirish darajasida qaraymiz.


Muammo: har bir ilovaga alohida IP olib bo'lmaydi

22 va 23-boblarda ilovamizni Kubernetes'da Deployment + Service bilan ishga tushirdik. Tashqi dunyoga ochish uchun type: LoadBalancer Service ishlatdik β€” cloud unga tashqi IP berdi. Bitta ilova uchun bu yaxshi ishladi.

Endi real loyihani tasavvur qiling: sizda api.example.uz (backend), example.uz (frontend), admin.example.uz (admin panel) bor. Har biriga alohida LoadBalancer Service qilsangiz β€” cloud sizdan har bir IP uchun alohida to'lov oladi (oyiga $15-20 atrofida), va sizda uchta turli IP bo'ladi. DNS'da uchta yozuv, uchta sertifikat, hammasini qo'lda boshqarish kerak. Ilova soni 10 taga yetganda β€” bu chidab bo'lmas holatga aylanadi.

πŸ“Œ Yana bir muammo: LoadBalancer Service faqat TCP/port darajasida ishlaydi. U "example.uz/api ga kelganni backend'ga, example.uz/ ga kelganni frontend'ga yubor" deya olmaydi β€” chunki u HTTP yo'lini (path) yoki domen nomini (host) ko'rmaydi. Bizga L7 (HTTP darajasida) marshrutlash kerak.

Yechim β€” Ingress. Bitta tashqi kirish nuqtasi, bitta IP, va domen/path bo'yicha aqlli marshrutlash. Bu β€” Kubernetes ichidagi reverse proxy (17-bobda nginx'da ko'rgan reverse proxy g'oyasini eslang). Bu bobda Ingress'dan boshlab, ma'lumotni saqlash (storage), ilovalarni paketlash (Helm) va Git orqali deploy qilish (GitOps) gacha boramiz.


Ingress: bitta eshik, ko'p ilova

Ingress (kirish) β€” klasterga tashqaridan keladigan HTTP/HTTPS trafikni domen va path bo'yicha turli Service'larga taqsimlovchi qoidalar to'plami. U β€” klaster oldidagi aqlli darvozabon: "api.example.uz so'rovini api-service'ga, example.uz/admin ni admin-service'ga yubor".

Internet -> Ingress Controller -> host va path bo'yicha turli Service'larga -> Pod'larga marshrutlash, TLS sertifikat Ingress darajasida tugatiladi degan diagramma

⚠️ Eng muhim nozik nuqta: Ingress obyektining o'zi hech narsa qilmaydi. U faqat qoidalar ro'yxati (YAML). Bu qoidalarni bajaradigan dastur kerak β€” bu Ingress Controller.

Ingress Controller nima va nega kerak

Ingress resursi β€” bu "men shunday marshrutlashni xohlayman" degan deklaratsiya. Lekin uni amalda bajaradigan kimdir bo'lishi kerak. Bu vazifani Ingress Controller bajaradi β€” klasterda ishlaydigan haqiqiy reverse proxy (odatda nginx). Eng mashhuri β€” nginx-ingress (ingress-nginx).

Ingress Controller:

  1. Klasterdagi barcha Ingress obyektlarini kuzatib turadi.
  2. Ulardagi qoidalarni o'qib, ichki nginx config'iga aylantiradi.
  3. O'zi bitta LoadBalancer Service orqali tashqi IP oladi β€” va butun klaster uchun shu bitta IP yetarli bo'ladi.

πŸ“Œ Demak mantiq: bitta Ingress Controller (bitta tashqi IP) + ko'p Ingress qoidalari (har ilova uchun). Pulli IP bitta, marshrutlash esa cheksiz. Mana shu LoadBalancer-har-ilova muammosini hal qiladi.

Ingress Controller'ni o'rnatish (illustrativ β€” real klaster kerak):

# nginx-ingress controller (rasmiy manifest)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml

# o'rnatilgach, uning tashqi IP'sini ko'rish
kubectl get service -n ingress-nginx

ℹ️ Illustrativ: yuqoridagi kubectl apply real klaster (minikube/kind/cloud) talab qiladi va internetdan manifest yuklaydi. Lokalda biz uni bajarmaymiz; quyidagi Ingress YAML'ning strukturasini esa offline tekshirdik.

Ingress manifesti: host va path bo'yicha marshrutlash

Mana to'liq Ingress namunasi. Bu uchta holatni ko'rsatadi: domen bo'yicha, path bo'yicha marshrutlash va TLS:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    # nginx-ingress'ga maxsus ko'rsatma (controller'ga qarab o'zgaradi)
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
    # 1) Domen (host) bo'yicha: api.example.uz -> api-service
    - host: api.example.uz
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 80
    # 2) Asosiy domen, path bo'yicha bo'linadi
    - host: example.uz
      http:
        paths:
          - path: /admin
            pathType: Prefix
            backend:
              service:
                name: admin-service
                port:
                  number: 80
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 80

Asosiy maydonlar:

  • apiVersion: networking.k8s.io/v1 β€” Ingress'ning barqaror (stable) versiyasi. ❌ Eski extensions/v1beta1 yoki networking.k8s.io/v1beta1 β€” olib tashlangan, ishlatmang.
  • ingressClassName: nginx β€” qaysi Ingress Controller bu qoidani bajarishini aytadi (klasterda bir nechta controller bo'lishi mumkin).
  • rules β€” marshrutlash qoidalari ro'yxati. Har biri host (domen) va http.paths (path'lar).
  • pathType β€” path qanday solishtiriladi:
  • Prefix β€” yo'l boshi mos kelsa (/admin -> /admin/users ham tushadi). Eng ko'p ishlatiladi.
  • Exact β€” aniq mos kelishi shart.
  • backend.service.name + backend.service.port.number β€” so'rov qaysi Service'ga va uning qaysi portiga yuborilishi.

πŸ’‘ Tartib muhim: nginx-ingress eng uzun mos keluvchi prefixni tanlaydi. Yuqorida /admin /dan oldin tekshiriladi, shuning uchun example.uz/admin/... admin'ga, qolgani frontend'ga ketadi.

Ingress vs Service (LoadBalancer)

Service LoadBalancer Ingress
Daraja L4 (TCP/port) L7 (HTTP: host + path)
Tashqi IP Har Service'ga alohida (pulli) Bitta controller'ga, hammaga umumiy
Marshrutlash Yo'q (faqat port) Domen va path bo'yicha
TLS Yo'q (ilova o'zi qiladi) Markazda, Ingress'da tugatiladi
Qachon Bitta TCP xizmat (DB, gRPC) Ko'p HTTP ilova, bitta klaster

πŸ“Œ Qoida: HTTP(S) ilovalar uchun β€” Ingress. LoadBalancer Service'ni faqat HTTP bo'lmagan (masalan tashqaridan ochiq DB yoki maxsus TCP protokol) holatlar uchun yoki Ingress Controller'ning o'zini ochish uchun saqlang.

TLS va cert-manager bilan avtomatik HTTPS

Ingress sertifikatni markazda boshqarishga imkon beradi β€” har ilova o'zi HTTPS qilmaydi, Ingress Controller TLS'ni tugatadi (terminate). spec.tls bloki domen va sertifikat saqlangan Secret'ni bog'laydi:

spec:
  tls:
    - hosts:
        - api.example.uz
        - example.uz
      secretName: example-tls   # TLS sertifikat shu Secret'da
  rules:
    - host: api.example.uz
      # ... (yuqoridagidek)

Sertifikatni qo'lda olish va Secret'ga solish zerikarli (18-bobdagi Certbot'ni eslang). Klasterda buni cert-manager avtomatlashtiradi: u Let's Encrypt'dan ACME orqali sertifikat oladi, Secret'ga yozadi va 90 kunda avtomatik yangilaydi β€” xuddi 18-bobdagi certbot.timer kabi, lekin Kubernetes ichida.

metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod

Shu annotatsiya bilan cert-manager Ingress'dagi tls.hosts domenlari uchun sertifikatni o'zi oladi va secretName'ga joylaydi. (18-bobda Let's Encrypt va ACME'ni batafsil ko'rganmiz β€” cert-manager o'sha jarayonni klaster ichida bajaradi.)

ℹ️ Illustrativ: cert-manager o'rnatish va Let's Encrypt'dan real sertifikat olish jonli klaster, real domen va ochiq port talab qiladi β€” o'z klasteringizda bajaring.


Storage: Pod o'chsa, ma'lumot yo'qoladi

Hozirgacha ilovalarimiz stateless edi β€” ma'lumotni o'zida saqlamasdi. Lekin DB (PostgreSQL), fayl yuklamalari, yoki Redis kabi narsalar ma'lumotni saqlashi kerak.

Muammo: Pod ephemeral (vaqtinchalik). Pod o'chsa, qayta yaratilsa yoki boshqa node'ga ko'chsa β€” uning ichidagi disk butunlay yo'qoladi. Pod ichiga yozilgan PostgreSQL ma'lumotlari Pod restart bo'lishi bilan yo'q bo'ladi. Bu β€” falokat.

Yechim: Pod'ning umridan uzoq yashaydigan, alohida disk. Kubernetes'da bu β€” PersistentVolume tizimi.

PV, PVC va StorageClass

Kubernetes storage'ni uch tushuncha bilan boshqaradi:

Pod -> PVC (talab) -> PV (haqiqiy hajm) -> bulutdagi disk; StorageClass PVC kelganda PV'ni avtomatik yaratadi degan diagramma

  • PersistentVolume (PV) β€” klasterdagi haqiqiy disk bo'lagi (cloud disk, NFS, lokal disk). Bu β€” "ombordagi mavjud hajm".
  • PersistentVolumeClaim (PVC) β€” disk uchun talabnoma: "menga 5 GB, ReadWriteOnce rejimida disk kerak". Pod PV'ni to'g'ridan-to'g'ri emas, PVC orqali so'raydi. Bu β€” "men shunday hajm istayman" degan ariza.
  • StorageClass β€” PVC kelganda PV'ni avtomatik yaratish (dynamic provisioning) qoidasi. Cloud'da odatda standart StorageClass bor: PVC yozsangiz, u o'zi cloud disk yaratib, PV qilib bog'laydi. Qo'lda PV yaratish shart emas.

πŸ“Œ Mantiqni o'xshatish bilan: PVC β€” restoranda buyurtma ("menga 5 GB"), StorageClass β€” oshpaz (buyurtmaga ko'ra taom tayyorlaydi, ya'ni PV yaratadi), PV β€” tayyor taom (haqiqiy disk). Pod faqat buyurtma beradi (PVC), qolganini tizim qiladi.

PVC manifesti:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-pvc
spec:
  accessModes:
    - ReadWriteOnce        # bitta node'dan o'qish/yozish
  resources:
    requests:
      storage: 5Gi         # 5 gigabayt so'raymiz
  storageClassName: standard   # qaysi StorageClass (cloud'da odatda standart bor)

accessModes β€” diskga kirish rejimi:

  • ReadWriteOnce (RWO) β€” bitta node disk'ni o'qiydi/yozadi. DB uchun eng ko'p ishlatiladi.
  • ReadOnlyMany (ROX) β€” ko'p node faqat o'qiydi.
  • ReadWriteMany (RWX) β€” ko'p node yozadi (NFS kabi maxsus storage kerak).

PVC'ni Pod'ga ulash

PVC'ni Pod (yoki Deployment) ichida volumes + volumeMounts bilan ulaymiz:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:17
          env:
            - name: POSTGRES_PASSWORD
              value: "maxfiy-parol"   # haqiqatda Secret'dan oling
          volumeMounts:
            - name: pgdata
              mountPath: /var/lib/postgresql/data
      volumes:
        - name: pgdata
          persistentVolumeClaim:
            claimName: postgres-pvc    # yuqoridagi PVC
  • volumes β€” Pod'ga qaysi hajmlar ulanishini e'lon qiladi; bu yerda persistentVolumeClaim.claimName orqali PVC'ga ishora.
  • volumeMounts.mountPath β€” disk konteyner ichida qayerga ulanishi (/var/lib/postgresql/data β€” PostgreSQL ma'lumotlari shu yerda).

Endi Pod o'chsa ham, disk PVC sifatida saqlanib qoladi; yangi Pod o'sha PVC'ni qayta ulaydi va ma'lumot joyida turadi.

⚠️ env'da parolni ochiq yozish β€” faqat namuna. Production'da 23-bobda ko'rgan Secret'dan valueFrom.secretKeyRef bilan oling.

StatefulSet: DB kabi stateful ilovalar uchun

Deployment + PVC oddiy holatda ishlaydi, lekin DB klasteri (bir nechta PostgreSQL/MongoDB replikasi) uchun yetarli emas: har replikaga o'z barqaror nomi va o'z alohida diski kerak. Buni StatefulSet beradi.

StatefulSet Deployment'dan farqi:

  • Barqaror, oldindan aytib bo'ladigan nom: Pod'lar db-0, db-1, db-2 deb tartib bilan nomlanadi (Deployment'da tasodifiy app-7d8f...). Pod o'chib qayta yaratilsa ham o'sha nom qaytadi.
  • Har Pod'ga alohida storage: volumeClaimTemplates orqali har replika uchun alohida PVC avtomatik yaratiladi (db-0 -> o'z diski, db-1 -> boshqa disk).
  • Headless Service bilan ishlaydi: har Pod'ga barqaror DNS nom beradi (db-0.db, db-1.db).
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres        # headless Service nomi (barqaror DNS uchun)
  replicas: 3
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:17
          ports:
            - containerPort: 5432
          volumeMounts:
            - name: pgdata
              mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:        # har replikaga alohida PVC
    - metadata:
        name: pgdata
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 5Gi
  • serviceName β€” headless Service nomi; StatefulSet shu orqali Pod'larga barqaror DNS beradi.
  • volumeClaimTemplates β€” PVC shabloni: StatefulSet har Pod uchun (pgdata-postgres-0, pgdata-postgres-1, ...) alohida PVC yaratadi.

πŸ“Œ Qoida: oddiy stateless ilova -> Deployment. Saqlanadigan ma'lumotli, identifikatsiyasi muhim ilova (DB, message queue) -> StatefulSet. Boshlovchi uchun ko'p hollarda boshqariladigan cloud DB ishlatish (klaster ichida DB ishlatishdan) osonroq β€” buni ham yodda tuting.


Helm: Kubernetes'ning paket menejeri

Hozirgacha har bir resurs uchun alohida YAML yozdik: Deployment, Service, Ingress, PVC, ConfigMap, Secret... Bitta ilova uchun bu 5-6 fayl. Endi shu ilovani uchta muhitga (dev, staging, prod) deploy qilish kerak β€” har birida replika soni, domen, resurs limitlari boshqacha.

Variant 1: YAML'larni uch marta nusxalab, qiymatlarni qo'lda o'zgartirish. Natija β€” nusxalar bir-biridan farq qila boshlaydi, xato kiradi, boshqarib bo'lmaydi.

Variant 2: Helm β€” Kubernetes'ning paket menejeri (Linux'da apt/npm kabi, lekin K8s manifestlari uchun). Helm YAML'ni shablonlash (template) va versiyalash imkonini beradi.

Helm chart (templates + values) -> render bosqichi -> tayyor K8s manifestlar -> klasterga release sifatida o'rnatiladi degan diagramma

Chart strukturasi

Helm paketi β€” chart deb ataladi. Bu β€” quyidagi tuzilishdagi papka:

myapp/
β”œβ”€β”€ Chart.yaml          # chart metadatasi (nom, versiya)
β”œβ”€β”€ values.yaml         # standart qiymatlar (sozlanadi)
└── templates/
    β”œβ”€β”€ deployment.yaml # {{ }} shabloni bilan
    └── service.yaml

Chart.yaml β€” chart haqida ma'lumot:

apiVersion: v2
name: myapp
description: Mening ilovam uchun Helm chart
type: application
version: 0.1.0          # chart versiyasi
appVersion: "1.0.0"     # ichidagi ilova versiyasi

values.yaml β€” standart, o'zgartiriladigan qiymatlar:

replicaCount: 2
image:
  repository: ghcr.io/myuser/myapp
  tag: "1.0.0"
service:
  port: 80

templates/deployment.yaml β€” {{ }} shablon ifodalari bilan (qiymatlar values.yaml'dan keladi):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-myapp
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Release.Name }}-myapp
  template:
    metadata:
      labels:
        app: {{ .Release.Name }}-myapp
    spec:
      containers:
        - name: myapp
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          ports:
            - containerPort: {{ .Values.service.port }}

⚠️ Illustrativ shablon: yuqoridagi templates/deployment.yamldagi {{ .Values... }} qatorlari β€” Helm-specific shablon sintaksisi, sof YAML emas. Helm uni helm install paytida render qilib, haqiqiy YAML'ga aylantiradi. .Release.Name β€” helm install da bergan release nomi, .Values.X β€” values.yamldagi qiymat. (Shu sababli bu faylni to'g'ridan-to'g'ri kubectl apply qilib bo'lmaydi β€” avval Helm render qilishi kerak.)

Helm buyruqlari

# 1) Tashqi chart repozitoriyni qo'shish
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

# 2) Chart'ni klasterga o'rnatish (release nomi = "web")
helm install web ./myapp

# 3) values'ni o'zgartirib o'rnatish
helm install web ./myapp --set replicaCount=5
helm install web ./myapp -f prod-values.yaml

# 4) Mavjud release'ni yangilash (yangi versiya / yangi qiymatlar)
helm upgrade web ./myapp --set image.tag=1.1.0

# 5) Xato bo'lsa β€” oldingi holatga qaytish
helm rollback web 1        # 1-revizyaga qaytar

# 6) O'chirish
helm uninstall web

# Render natijasini ko'rish (klasterga tegmasdan)
helm template web ./myapp

Asosiy g'oyalar:

  • release β€” chart'ning klasterga o'rnatilgan nusxasi. Bitta chart'ni turli nom bilan ko'p marta o'rnatish mumkin (web, web-staging).
  • --set key=value β€” bitta qiymatni buyruq qatorida o'zgartirish (tezkor).
  • -f values.yaml β€” butun qiymatlar faylini berish (muhit bo'yicha: dev-values.yaml, prod-values.yaml).
  • helm upgrade / helm rollback β€” Helm har o'rnatishni revizya (versiya) sifatida saqlaydi; xato bo'lsa bir buyruq bilan oldingi ishchi holatga qaytasiz.

πŸ“Œ Nega Helm: takroriy YAML'ni bir marta shablonlab, qiymatlar bilan ko'p muhitga sozlash; butun ilovani bir buyruq bilan o'rnatish/yangilash/qaytarish; va tayyor chart'lardan (PostgreSQL, Redis, nginx-ingress) foydalanib, g'ildirakni qaytadan ixtiro qilmaslik.

πŸ’‘ Tayyor chart'lar ko'p: helm install my-db bitnami/postgresql bilan butun PostgreSQL'ni (PVC, Service, Secret bilan) bir buyruqda o'rnatasiz. Ko'p mashhur dasturlarning rasmiy Helm chart'i bor.

ℹ️ Illustrativ: helm install/upgrade real klaster talab qiladi. Quyida (verify qismida) chart fayllari va render natijasi YAML strukturasini offline tekshirdik; {{ }} shablon qatorlari esa Helm tomonidan render qilinishini yodda tuting.


GitOps: Git β€” haqiqat manbai

Hozirgacha biz kubectl apply yoki helm upgrade ni qo'lda terminaldan ishga tushirdik. Bu β€” push model: odam (yoki CI) klasterga o'zgarishni "itaradi". Muammolari:

  • Klasterning haqiqiy holati Git'dagi YAML'dan farq qilishi mumkin (kimdir qo'lda kubectl edit qilgan β€” Git bilmaydi).
  • Kim, qachon, nimani o'zgartirgani β€” tarix kubectl history'da emas, hech qayerda aniq qayd etilmaydi.
  • Rollback β€” qo'lda, xatoga moyil.

GitOps boshqacha yondashuv: Git repozitoriysi = klasterning yagona haqiqat manbai. Klaster qanday bo'lishi kerakligi (barcha manifestlar/Helm chart) Git'da yotadi. Klaster ichidagi agent Git'ni doimiy kuzatadi va klasterni Git holatiga avtomatik moslashtiradi.

Push vs Pull deploy

  • Push (an'anaviy): CI quvuri tashqaridan klasterga kubectl apply qiladi. CI'da klaster kaliti (kubeconfig) saqlanadi β€” xavfsizlik xavfi.
  • Pull (GitOps): klaster ichidagi agent (Argo CD / Flux) Git'ni o'zi tortib oladi (pull) va o'zgarishni qo'llaydi. Klaster kaliti tashqariga chiqmaydi; agar kimdir qo'lda o'zgartirsa, agent uni Git holatiga qaytaradi (self-healing, drift correction).

πŸ“Œ GitOps qoidasi: klasterga to'g'ridan-to'g'ri kubectl apply qilmaysiz β€” o'zgarishni Git'ga commit/PR qilasiz, qolganini agent bajaradi. Deploy = git push. Rollback = git revert. Audit = Git tarixi.

Argo CD va Flux

Ikki asosiy GitOps vositasi:

  • Argo CD β€” Git'ni kuzatuvchi agent + qulay veb-UI (qaysi ilova Git bilan sinxron, qaysi biri "drift" qilgan β€” vizual ko'rinadi). Boshlash uchun qulayroq.
  • Flux β€” yengilroq, UI'siz, CLI/Kubernetes-native; GitOps tamoyillariga qattiq amal qiladi.

Ikkalasi ham bir g'oyani amalga oshiradi: Git holatini klasterga doimiy moslashtirish.

ℹ️ Illustrativ: Argo CD / Flux o'rnatish va ulardan foydalanish jonli klaster talab qiladi β€” bu bobda faqat g'oyani kirish darajasida beramiz; amaliy qism o'z klasteringizda.


Managed Kubernetes (qisqa)

Hozirgacha lokal minikube/kind haqida gapirdik. Production'da Kubernetes'ni o'zingiz boshqarish (control plane, etcd, yangilashlar, zaxira) β€” juda mehnat talab va xatarli. Shuning uchun ko'pchilik managed Kubernetes ishlatadi:

  • EKS (Amazon), GKE (Google), AKS (Azure) β€” cloud control plane'ni siz uchun boshqaradi.

Nega self-managed o'rniga managed:

  • Control plane sizning tashvishingiz emas: apiserver, etcd, scheduler'ni cloud boshqaradi, yangilaydi, zaxira oladi.
  • Tugmani bosib node qo'shish (autoscaling), cloud LoadBalancer/disk/IAM bilan integratsiya tayyor.
  • Siz faqat ilovangizga (manifestlar, Helm) e'tibor berasiz, infratuzilmani emas.

πŸ’‘ Boshlovchi uchun maslahat: production K8s kerak bo'lsa β€” boshidan managed (GKE/EKS/AKS) ni tanlang. Self-managed klaster (kubeadm bilan) β€” o'rganish uchun yaxshi, lekin kichik jamoa uchun kunlik boshqaruvga arzimaydi.


24-bob mashqlari

Quyidagi mashqlarning ko'pi YAML manifest yozish va tushunchalarni mustahkamlash haqida β€” bularni lokalda (kubectl apply --dry-run=client, yaml parse bilan) mashq qilasiz. Jonli klaster talab qiladiganlar (Ingress Controller, cert-manager, Argo CD, helm install) illustrativ β€” o'z klasteringizda bajaring.

Oson

  1. Ingress va LoadBalancer Service o'rtasidagi asosiy farqni (qaysi darajada ishlaydi, IP soni, marshrutlash imkoni) ayting.
  2. "Ingress obyektining o'zi hech narsa qilmaydi" β€” bu nima degani? Qoidalarni kim bajaradi?
  3. Pod "ephemeral" deganda nima nazarda tutiladi? Bu DB uchun nega muammo?
  4. PV, PVC va StorageClass β€” uchalasini bir jumladan ta'riflang (restoran o'xshatishidan foydalaning).
  5. Helm'da Chart.yaml, values.yaml va templates/ papkasi har biri nima uchun?
  6. GitOps'da deploy qilish, rollback qilish va audit (kim nima qildi) qanday bajariladi?

O'rta

  1. pathType: Prefix va pathType: Exact farqini misol bilan tushuntiring. example.uz/admin so'rovi /admin (Prefix) qoidasiga tushadimi?
  2. PVC manifestida accessModes nima? ReadWriteOnce va ReadWriteMany qachon ishlatiladi?
  3. Deployment + PVC bilan StatefulSet o'rtasidagi uchta asosiy farqni ayting. DB klasteri uchun qaysi biri to'g'ri va nega?
  4. helm upgrade va helm rollback qanday ishlaydi? Helm release versiyalarini qanday saqlaydi?
  5. GitOps'da push va pull deploy farqini ayting. Pull (Argo CD/Flux) nega xavfsizlik jihatdan afzal?

Qiyin

  1. shop.example.uz uchun Ingress yozing: /api (Prefix) -> api-svc:8080, qolgan barcha yo'l (/, Prefix) -> web-svc:80. ingressClassName: nginx ishlating.
Yechim
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: shop-ingress
spec:
  ingressClassName: nginx
  rules:
    - host: shop.example.uz
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-svc
                port:
                  number: 8080
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-svc
                port:
                  number: 80

/api /dan oldin yozilgan; nginx-ingress eng uzun mos prefix'ni tanlagani uchun /api/... so'rovlari api-svc'ga, qolgani web-svc'ga ketadi. apiVersion: networking.k8s.io/v1 β€” Ingress'ning barqaror versiyasi. Bu manifest kubectl apply --dry-run=client dan o'tadi.

  1. redis-pvc nomli PVC yozing: 2 GB, ReadWriteOnce, standard StorageClass. Keyin uni redis Deployment'ida /data ga ulang.
Yechim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: redis-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
  storageClassName: standard
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis
          image: redis:7-alpine
          volumeMounts:
            - name: data
              mountPath: /data
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: redis-pvc

PVC 2Gi disk so'raydi (StorageClass uni avtomatik yaratadi). Deployment volumes.persistentVolumeClaim.claimName orqali PVC'ni ulaydi va volumeMounts.mountPath bilan konteyner ichida /data'ga bog'laydi. Redis o'chsa ham disk saqlanadi.

  1. Chart.yaml va values.yaml (replicaCount, image.repository, image.tag) yozing, so'ng replicas va imageni values.yamldan oladigan minimal templates/deployment.yaml shablonini yozing.
Yechim

Chart.yaml:

apiVersion: v2
name: todo
description: Todo API uchun chart
type: application
version: 0.1.0
appVersion: "1.0.0"

values.yaml:

replicaCount: 3
image:
  repository: ghcr.io/myuser/todo
  tag: "1.0.0"

templates/deployment.yaml (shablon β€” Helm render qiladi):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-todo
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Release.Name }}-todo
  template:
    metadata:
      labels:
        app: {{ .Release.Name }}-todo
    spec:
      containers:
        - name: todo
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

{{ .Values.X }} qiymatlar values.yamldan, {{ .Release.Name }} esa helm install <nom> ... dan keladi. helm install todo ./todo --set replicaCount=5 bilan replika sonini bir muhitda o'zgartirish mumkin. (Shablon qatorlari sof YAML emas β€” Helm render qilgach kubectl apply qilinadi.)

  1. postgres uchun 2 replikali StatefulSet yozing: headless serviceName: postgres, har replikaga 10 GB ReadWriteOnce PVC (volumeClaimTemplates), /var/lib/postgresql/data ga ulangan.
Yechim
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres
  replicas: 2
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:17
          ports:
            - containerPort: 5432
          volumeMounts:
            - name: pgdata
              mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
    - metadata:
        name: pgdata
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 10Gi

serviceName headless Service'ga bog'laydi (har Pod barqaror DNS oladi: postgres-0.postgres, postgres-1.postgres). volumeClaimTemplates har replika uchun alohida PVC yaratadi (pgdata-postgres-0, pgdata-postgres-1) β€” har biriga 10 GB. Pod o'chsa, o'sha nom va disk qaytadi. Bu manifest apps/v1 apiVersion bilan, kubectl apply --dry-run=client dan o'tadi.

  1. Bir hamkasbingiz "GitOps shunchaki CI'da kubectl apply yozish" deydi. Bu xato β€” GitOps (pull) bilan an'anaviy CI push deploy orasidagi farqni va GitOps afzalligini tushuntiring.
Yechim

An'anaviy push: CI quvuri tashqaridan klasterga kubectl apply/helm upgrade qiladi. CI'da klaster kaliti (kubeconfig) saqlanadi (xavf), va klasterning haqiqiy holati Git'dan ajralib ketishi mumkin (kimdir qo'lda o'zgartirsa β€” hech kim bilmaydi).

GitOps (pull): Git = yagona haqiqat manbai. Klaster ichidagi agent (Argo CD/Flux) Git'ni o'zi kuzatadi va klasterni Git holatiga doimiy moslashtiradi. Afzalliklari: (1) klaster kaliti tashqariga chiqmaydi β€” agent ichkarida; (2) drift tuzatish/self-healing β€” qo'lda o'zgarish Git holatiga qaytariladi; (3) deploy = git push, rollback = git revert, audit = Git tarixi (kim/qachon/nima β€” hammasi commit'larda). Demak GitOps faqat "apply'ni boshqa joyga ko'chirish" emas β€” boshqaruv modelini Git-markazli qiladi.

  1. Qachon LoadBalancer Service, qachon Ingress ishlatiladi? Ikkita aniq stsenariy bilan tushuntiring.
Yechim

Ingress β€” ko'p HTTP(S) ilovani bitta tashqi IP orqali ochganda. Masalan example.uz (frontend), api.example.uz (backend), example.uz/admin (admin) β€” uchalasi bitta Ingress Controller IP'sida, host/path bo'yicha marshrutlanadi, TLS markazda. Bu β€” odatiy veb-ilova holati.

LoadBalancer Service β€” HTTP bo'lmagan yoki maxsus TCP xizmat tashqariga ochilganda. Masalan tashqaridan ulanish kerak bo'lgan PostgreSQL (5432-port, sof TCP) yoki gRPC/maxsus protokol β€” Ingress (L7 HTTP) bularni marshrutlay olmaydi, shuning uchun LoadBalancer (L4) kerak. Shuningdek Ingress Controller'ning o'zi tashqi IP'ni LoadBalancer Service orqali oladi.

Qoida: HTTP(S) -> Ingress; sof TCP/maxsus protokol yoki bitta xizmatga to'g'ridan-to'g'ri IP -> LoadBalancer.


⬅️ Oldingi: 23 β€” Production Kubernetes Β· 🏠 README Β· Keyingi: 25 β€” Monitoring: Prometheus va Grafana ➑️