Vanilla Kubernetes

Prvi deo: Temelji, arhitektura i izgradnja klastera
DaemonSet, Job i CronJob – čvorski servisi, završivi poslovi i planirano izvršavanje
IV. Osnovni workload objekti i kontrolne petlje
18. DaemonSet, Job i CronJob – čvorski servisi, završivi poslovi i planirano izvršavanje

Prethodna lekcija uvela je ReplicaSet i Deployment kao kontrolere trajno aktivnih, zamenljivih Pod replika. Međutim, nisu svi workload-i dugovečni servisi. Neki proces mora postojati na svakom odgovarajućem čvoru, drugi mora izvršiti konačan zadatak i uspešno se završiti, a treći isti završivi zadatak mora pokretati prema rasporedu. Kubernetes za te tri namere pruža DaemonSet, Job i CronJob. Njihova zajednička osobina jeste deklarativna kontrolna petlja; kriterijum uspeha im je suštinski različit.

DaemonSet iz API grupe apps/v1 održava Pod na svim ili izabranim čvorovima. Job i CronJob pripadaju stabilnoj grupi batch/v1: Job održava izvršavanje dok ne dostigne uslov završetka, dok CronJob prema rasporedu kreira nove Job objekte. Administrator zato ne bira objekat prema tome koliko često želi da pokrene komandu, već prema životnom ciklusu rada, modelu paralelizma, toleranciji na ponavljanje, zahtevanom položaju i načinu dokazivanja uspeha.

Tri različite kontrolne namere

ObjekatŽeljeno stanjeUspehTipična namenaNije dobar izbor
DaemonSetPo jedan Pod na svakom odgovarajućem čvoruBroj dostupnih Pod-ova prati broj ciljnih čvorovaLog, monitoring, CNI, CSI i bezbednosni agentiPoslovna aplikacija sa fiksnim brojem replika
JobZadati broj uspešnih završetakaUslov Complete ili definisana success policyImport, izvoz, obrada skupa podataka, migracioni korakTrajno aktivan servis ili neograničena petlja
CronJobKreiranje Job-a za dospeli terminSvaka instanca se ocenjuje kao zaseban JobPeriodični izveštaj, cleanup, sinhronizacija, backup orkestracijaPrecizan real-time scheduler ili posao koji nije idempotentan

Nijedan od ova tri objekta sam po sebi ne obezbeđuje poslovnu transakciju „tačno jednom”. Kubernetes može ponovo pokrenuti kontejner, zameniti Pod, a CronJob u retkim okolnostima može kreirati dva Job-a za isti termin ili propustiti kreiranje. Proces mora biti idempotentan: ponovljeno izvršavanje sa istim ulazom ne sme da korumpira stanje, duplira naplatu ili proizvede nekontrolisane sporedne efekte. Za osetljive operacije koriste se jedinstveni ključevi, transakcije, zaključavanje ili evidencija obrađenog poslovnog događaja u pouzdanom spoljnom sistemu.

DaemonSet – servis vezan za skup čvorova

DaemonSet kontroler posmatra čvorove i obezbeđuje da svaki čvor koji odgovara Pod šablonu dobije odgovarajući Pod. Kada se novi čvor priključi klasteru, nastaje novi DaemonSet Pod; kada čvor prestane da bude odgovarajući ili se ukloni, kontroler i garbage collector usklađuju stanje. Broj Pod-ova zato nije eksplicitna vrednost replicas, već funkcija broja i osobina ciljnih čvorova.

Tipični DaemonSet workload-i moraju lokalno posmatrati ili opsluživati čvor: agent prikuplja logove iz dozvoljene host putanje, node exporter objavljuje metrike, CNI komponenta priprema mrežu, CSI node plugin priključuje volume, a bezbednosni senzor posmatra događaje jezgra. Ako proces samo treba više stateless replika dostupnih preko mreže, Deployment je prikladniji. „Jedan Pod po čvoru” nije isto što i visoka dostupnost aplikacije.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-observer
  namespace: it-tutorijali
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: node-observer
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  minReadySeconds: 5
  template:
    metadata:
      labels:
        app.kubernetes.io/name: node-observer
        app.kubernetes.io/component: node-agent
    spec:
      serviceAccountName: node-observer
      nodeSelector:
        kubernetes.io/os: linux
        training.tashizza.com/observer: "enabled"
      containers:
        - name: observer
          image: busybox:1.36.1
          command: ["sh", "-c"]
          args:
            - while true; do echo "node=${NODE_NAME} time=$(date -u +%FT%TZ)"; sleep 30; done
          env:
            - name: NODE_NAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
          resources:
            requests:
              cpu: 10m
              memory: 16Mi
            limits:
              cpu: 100m
              memory: 64Mi
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop: ["ALL"]
      securityContext:
        runAsNonRoot: true
        runAsUser: 65534
        seccompProfile:
          type: RuntimeDefault
      terminationGracePeriodSeconds: 20

Selektor mora odgovarati oznakama Pod šablona i nakon kreiranja je praktično nepromenljiv. Ograničenje na Linux i eksplicitno označene čvorove sprečava slučajno postavljanje laboratorijskog agenta na svaki čvor. Produkcioni sistemski DaemonSet-i često koriste tolerations, priority class, host mrežu, host PID ili hostPath, ali svaka od tih mogućnosti širi privilegije i domet incidenta. Ne treba ih prepisivati iz primera bez konkretne potrebe, Pod Security procene i odobrenja platformskog tima.

Raspoređivanje, taint-ovi i bezbednosna granica DaemonSet-a

DaemonSet kontroler dodaje node affinity koja vezuje svaki kreirani Pod za određeni čvor, a default scheduler obavlja raspoređivanje. Pod šablon može ograničiti skup čvorova pomoću nodeSelector ili node affinity pravila. Toleration samo dopušta raspoređivanje na čvor sa odgovarajućim taint-om; ona ne bira čvor i ne uklanja potrebu za selektorom ili affinity pravilom. Kubernetes automatski dodaje neke tolerations DaemonSet Pod-ovima da bi čvorski servisi opstali u posebnim stanjima čvora, ali aplikacioni manifest i dalje mora eksplicitno dokumentovati nameru za dedicated ili control-plane čvorove.

Pristup host filesystem-u preko hostPath zaobilazi deo izolacije kontejnera. Putanja može otkriti kredencijale, container runtime socket ili osetljive logove, a write mount može promeniti sam čvor. Kada je pristup neophodan, mount se ograničava na najmanju konkretnu putanju, po mogućnosti sa readOnly: true, uz ne-root UID, uklonjene capabilities, seccomp profil, read-only root filesystem i namenski ServiceAccount. Pristup runtime socket-u gotovo je ekvivalentan administratorskoj kontroli čvora i zahteva posebno bezbednosno odobrenje.

Ažuriranje i rollback DaemonSet-a

Strategija RollingUpdate podrazumevano zamenjuje stare Pod-ove kada se promeni spec.template. maxUnavailable ograničava broj nedostupnih ciljnih čvorova tokom promene; maxSurge, kada ga podržava verzija klastera, dopušta privremeni dodatni Pod na čvoru. Vrednosti se mogu zadati brojem ili procentom, ali maxUnavailable i maxSurge ne mogu oba biti nula. Za agente koji zaključavaju host resurs ili koriste host port često nije bezbedno imati dve verzije na istom čvoru, pa surge zahteva proveru kompatibilnosti.

Strategija OnDelete ne zamenjuje postojeće Pod-ove automatski nakon promene šablona; novi šablon važi tek kada se stari Pod ručno ukloni ili nestane. Ova strategija omogućava strogo kontrolisano održavanje po čvorovima, ali lako ostavlja mešovite verzije. Status se proverava kroz desiredNumberScheduled, currentNumberScheduled, numberReady, numberAvailable, numberUnavailable i updatedNumberScheduled, a ne samo brojanjem Pod-ova.

kubectl rollout status daemonset/node-observer -n it-tutorijali --timeout=180s
kubectl rollout history daemonset/node-observer -n it-tutorijali
kubectl rollout undo daemonset/node-observer -n it-tutorijali
kubectl get daemonset node-observer -n it-tutorijali -o wide

Prve dve i poslednja komanda čitaju stanje; rollout undo ga menja. Pre rollback-a pregledaju se revizije, razlog neuspeha, kompatibilnost konfiguracije i efekat na čvor. Rollback je završen tek kada je rollout status uspešan, svi ciljni čvorovi imaju spreman očekivani Pod, agent funkcionalno radi i nema zaostalih starih Pod-ova.

Job – posao sa konačnim ishodom

Job kreira jedan ili više Pod-ova i nastavlja pokušaje dok se ne ostvari definisani broj uspešnih završetaka ili dok posao ne postane trajno neuspešan. Izlazni kod glavnog procesa je presudan: kod nula predstavlja uspešan završetak kontejnera, a nenulti kod grešku. Proces koji obavi posao pa ostane u beskonačnoj petlji nikada neće kompletirati Job; pomoćni kontejner koji ne završava takođe može sprečiti terminalno stanje Pod-a.

apiVersion: batch/v1
kind: Job
metadata:
  name: inventory-export
  namespace: it-tutorijali
spec:
  backoffLimit: 3
  activeDeadlineSeconds: 300
  ttlSecondsAfterFinished: 3600
  template:
    metadata:
      labels:
        app.kubernetes.io/name: inventory-export
    spec:
      restartPolicy: Never
      containers:
        - name: exporter
          image: busybox:1.36.1
          command: ["sh", "-c"]
          args:
            - 'echo "export-start=$(date -u +%FT%TZ)"; sleep 5; echo "export-complete"'
          resources:
            requests:
              cpu: 10m
              memory: 16Mi
            limits:
              cpu: 100m
              memory: 64Mi
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop: ["ALL"]
      securityContext:
        runAsNonRoot: true
        runAsUser: 65534
        seccompProfile:
          type: RuntimeDefault

Job Pod dozvoljava restartPolicy: Never ili OnFailure, ne Always. Sa Never svaki neuspeh ostavlja zaseban Failed Pod, što olakšava dijagnostiku; sa OnFailure kubelet ponovo pokreće kontejner unutar istog Pod-a, pa aplikacija mora tolerisati lokalno ponavljanje. Čak i sa jednom completion vrednošću i Never proces ponekad može biti pokrenut više puta. Spoljni efekti zato moraju biti idempotentni.

Paralelizam, completions i Indexed Job

ObrazacKljučna poljaPonašanjeUslov aplikacije
Jedan završetakpodrazumevano parallelism: 1, completions: 1Jedan uspešan Pod kompletira JobPonovljiv završivi proces
Fiksni broj završetakacompletions: N, parallelism: MNajviše M Pod-ova paralelno dok N ne uspeBezbedna konkurentna obrada
Work queueparallelism bez completionsWorker-i uzimaju stavke iz spoljnog redaKoordinisan red i potvrda obrade
IndexedcompletionMode: IndexedSvaki Pod dobija stabilan indeks od 0 do N−1Deterministička podela rada po indeksu

Kod Indexed Job-a indeks je dostupan, između ostalog, kroz anotaciju i promenljivu JOB_COMPLETION_INDEX. Savremene stabilne verzije podržavaju backoffLimitPerIndex i maxFailedIndexes, čime se pokušaji i prag neuspeha kontrolišu po segmentu. successPolicy može završiti Indexed Job kada dovoljan skup indeksa uspe. Ove mogućnosti treba vezati za minimalnu podržanu verziju klastera i validirati serverskim dry-run postupkom; ne treba ih stavljati u manifest koji mora raditi na starijim klasterima bez provere API podrške.

Retry, rok izvršavanja i politika neuspeha

backoffLimit podrazumevano iznosi šest i ograničava ponovne pokušaje uz eksponencijalno odlaganje. activeDeadlineSeconds ograničava ukupno aktivno vreme Job-a i ima prvenstvo nad raspoloživim retry pokušajima. Kada se rok dostigne, aktivni Pod-ovi se prekidaju, a Job dobija razlog DeadlineExceeded. Ova polja ne zamenjuju aplikacioni timeout za pojedinačan mrežni poziv; oba nivoa moraju biti projektovana zajedno.

Stabilni podFailurePolicy omogućava da se na osnovu exit koda ili Pod uslova izabere FailJob, Ignore, Count, odnosno FailIndex u odgovarajućem Indexed obrascu. Zahteva restartPolicy: Never, a pravila se obrađuju redom do prvog podudaranja. Na primer, exit kod koji označava trajno neispravnu konfiguraciju treba odmah završiti bez beskorisnih pokušaja, dok potvrđeni infrastrukturni disruption može biti izuzet iz retry brojanja. Exit kodovi su deo ugovora aplikacije i moraju biti dokumentovani, testirani i povezani sa monitoring alarmima.

Završetak, čuvanje dokaza i automatsko čišćenje

Završeni Job i njegovi Pod-ovi ostaju radi pregleda statusa i logova dok ih korisnik, viši kontroler ili TTL controller ne ukloni. ttlSecondsAfterFinished određuje koliko sekundi posle terminalnog stanja Job postaje podoban za kaskadno brisanje. Kratak TTL rasterećuje API server, ali može ukloniti jedini lokalni dokaz pre nego što administrator istraži incident. Produkciona praksa zato prvo centralizuje stdout/stderr, status i poslovni rezultat, pa zatim primenjuje razumnu retenciju.

U Kubernetes verzijama 1.31 i novijim terminalni uslovi Complete i Failed standardno se postavljaju tek po završetku svih Job Pod-ova. Ranije verzije mogle su prikazati terminalni Job dok su neki Pod-ovi još završavali. Automatizacija koja pokreće sledeći posao mora uzeti u obzir verziju, terminalne conditions i rizik paralelnog korišćenja istog resursa.

CronJob – raspored koji stvara Job objekte

CronJob ne izvršava kontejner direktno. CronJob kontroler procenjuje raspored i za dospeli termin kreira Job iz jobTemplate; Job zatim upravlja Pod-ovima. Izmena CronJob-a utiče samo na buduće Job objekte, ne menja već kreirane Job-ove i aktivne Pod-ove. Ovaj lanac vlasništva, CronJob → Job → Pod, ključan je za dijagnostiku i čišćenje.

apiVersion: batch/v1
kind: CronJob
metadata:
  name: inventory-report
  namespace: it-tutorijali
spec:
  schedule: "*/5 * * * *"
  timeZone: "Etc/UTC"
  concurrencyPolicy: Forbid
  startingDeadlineSeconds: 120
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 3
  suspend: false
  jobTemplate:
    spec:
      backoffLimit: 2
      activeDeadlineSeconds: 180
      ttlSecondsAfterFinished: 3600
      template:
        metadata:
          labels:
            app.kubernetes.io/name: inventory-report
        spec:
          restartPolicy: Never
          containers:
            - name: report
              image: busybox:1.36.1
              command: ["sh", "-c"]
              args:
                - 'echo "report-time=$(date -u +%FT%TZ)"; sleep 10; echo "report-complete"'
              resources:
                requests:
                  cpu: 10m
                  memory: 16Mi
                limits:
                  cpu: 100m
                  memory: 64Mi
              securityContext:
                allowPrivilegeEscalation: false
                readOnlyRootFilesystem: true
                capabilities:
                  drop: ["ALL"]
          securityContext:
            runAsNonRoot: true
            runAsUser: 65534
            seccompProfile:
              type: RuntimeDefault

Raspored, vremenska zona, propušteni termini i konkurentnost

schedule koristi pet polja cron izraza: minut, sat, dan u mesecu, mesec i dan u nedelji. Polje timeZone koristi naziv iz IANA baze, na primer Etc/UTC ili Europe/Belgrade, i predstavlja stabilan API od Kubernetes 1.27. Umetanje TZ ili CRON_TZ u sam raspored nije podržano. UTC je najpredvidljiviji za infrastrukturne poslove; poslovni raspored u lokalnoj zoni mora eksplicitno uzeti u obzir letnje računanje vremena, kada se lokalni termin može preskočiti ili pojaviti dvaput.

concurrencyPolicyAko prethodni Job još radiPosledicaPrimer odluke
AllowNovi Job se kreiraPreklapanje, veća potrošnja i mogući sudar nad podacimaSamo kada su paralelne instance bezbedne
ForbidNovi termin se preskačeNema preklapanja, ali nastaje missed scheduleIzveštaj ili cleanup koji ne sme raditi paralelno
ReplaceAktivni Job se zamenjuje novimPrethodni rad se prekida; potreban checkpoint ili bezbedan restartRezultat najnovijeg termina je važniji od starog

startingDeadlineSeconds određuje koliko kasno kontroler još sme pokrenuti propušteni termin. Vrednost manja od deset sekundi može sprečiti zakazivanje jer kontroler raspored proverava približno na deset sekundi. Ako ima više od sto propuštenih termina u relevantnom prozoru, kontroler ne pokreće posao i beleži poruku too many missed start times. Neograničen catch-up nije bezbedan za česte poslove posle dužeg control-plane prekida.

Raspoređivanje je približno, ne strogo real-time i ne garantuje exactly-once. Od Kubernetes 1.32 Job koji kreira CronJob dobija anotaciju batch.kubernetes.io/cronjob-scheduled-timestamp sa originalnim RFC3339 terminom. Ta vrednost je korisna kao idempotency ključ i za merenje kašnjenja, ali manifest koji mora podržati starije verzije ne sme pretpostaviti da anotacija postoji.

Suspenzija, ručno pokretanje i retencija istorije

suspend: true sprečava buduća zakazana kreiranja, ali ne zaustavlja Job-ove koje je CronJob već pokrenuo. Propušteni termini tokom suspenzije računaju se kao missed schedules; posle nastavka mogu biti razmatrani prema startingDeadlineSeconds. Pre ukidanja suspenzije administrator zato procenjuje da li bi nastao neželjeni catch-up. Za testiranje se ne menja produkcioni raspored na svaku minutu, već se iz šablona kreira jednokratni Job sa jedinstvenim imenom.

kubectl create job --from=cronjob/inventory-report inventory-report-manual-001 -n it-tutorijali
kubectl wait --for=condition=complete job/inventory-report-manual-001 -n it-tutorijali --timeout=180s
kubectl logs -n it-tutorijali job/inventory-report-manual-001

Prva komanda menja stanje, dok druge dve čitaju ishod. Ručni Job nije zakazana instanca i mora imati jedinstveno ime. successfulJobsHistoryLimit i failedJobsHistoryLimit ograničavaju broj završenih Job objekata koje CronJob zadržava. To je kapacitivna politika, dok TTL meri vreme od završetka; istovremena primena može ukloniti Job čim bilo koji mehanizam ispuni uslov. Dokaz mora pre toga biti izvezen u centralni sistem.

Dostupnost, resursi, storage i bezbednost batch rada

Batch Pod-ovi se takmiče za isti CPU, memoriju, ephemeral storage i API kapacitet kao dugovečni servisi. Bez requests vrednosti veliki paralelni Job može biti nepredvidljivo raspoređen; bez limits ili quota može ugroziti druge workload-e. parallelism se određuje prema kapacitetu klastera, propusnosti baze, API rate limit-u i mogućnosti skladišta, a ne samo prema željenom vremenu završetka. PriorityClass, ResourceQuota i odvojeni node pool mogu zaštititi kritične servise.

Lokalni emptyDir ne preživljava zamenski Pod. Posao koji nastavlja obradu mora checkpoint čuvati u trajnom ili spoljnjem sistemu i koristiti atomsko objavljivanje rezultata. ReadWriteOnce volume može sprečiti paralelne Pod-ove na različitim čvorovima; ReadWriteMany ne garantuje aplikaciono zaključavanje. Backup Job nije backup strategija dok nisu potvrđeni konzistentnost izvora, enkripcija, retencija, restore test i odvajanje privilegija.

Job i CronJob treba da koriste namenski ServiceAccount sa minimalnim RBAC pravima, a automountServiceAccountToken: false kada Kubernetes API nije potreban. Tajne se ne stavljaju u argumente komande ili obične promenljive ako mogu završiti u Pod specifikaciji, logovima ili proces listi. Slike se vezuju za odobren digest, skeniraju, izvršavaju bez root privilegija i sa minimalnim capabilities. Cron raspored nije bezbednosna kontrola: kompromitovan nalog ostaje kompromitovan i između termina.

Dijagnostika od kontrolera ka procesu

Dijagnostika počinje read-only dokazima i prati vlasnički lanac. Za DaemonSet se porede željeni, aktuelni, spremni i ažurirani Pod-ovi, zatim ciljni čvorovi, label/taint podudaranje, scheduler događaji i kontejnerski logovi. Za CronJob se proveravaju raspored, zona, last schedule time, active Job-ovi i događaji; zatim se otvara konkretan Job, njegovi conditions i Pod-ovi. Tek na kraju se menja konfiguracija.

kubectl get daemonset -n it-tutorijali
kubectl describe daemonset node-observer -n it-tutorijali
kubectl get pods -n it-tutorijali -l app.kubernetes.io/name=node-observer -o wide

kubectl get cronjob inventory-report -n it-tutorijali
kubectl describe cronjob inventory-report -n it-tutorijali
kubectl get jobs -n it-tutorijali --sort-by=.metadata.creationTimestamp
kubectl describe job JOB_NAME -n it-tutorijali
kubectl get pods -n it-tutorijali -l job-name=JOB_NAME -o wide
kubectl logs -n it-tutorijali job/JOB_NAME --all-containers=true
kubectl get events -n it-tutorijali --sort-by=.metadata.creationTimestamp

Ako Job koristi restartPolicy: OnFailure, kubectl logs POD -c CONTAINER --previous čita prethodnu instancu restartovanog kontejnera. Ako je Pod zamenjen ili TTL već obrisao objekte, lokalni log više nije dostupan. U enterprise klasteru korelišu se centralni kontejnerski logovi, Kubernetes događaji, audit zapis kreiranja ili izmene, metrike stanja objekata i aplikacioni zapis rezultata. Događaji imaju ograničenu retenciju i nisu audit dnevnik.

SimptomNeposredni uzrokDokazBezbedna korekcija
DaemonSet nema Pod na jednom čvoruLabel, taint, resurs ili OS ne odgovaraNode labels/taints i Pod događajiIspraviti namerni kriterijum; ne uklanjati zaštitni taint naslepo
Job stalno ponavlja PodProces vraća nenulti kod ili biva ubijenExit code, reason, prethodni log i događajiObustaviti retry oluju, sačuvati dokaz, popraviti uzrok
Job je Complete, rezultat nedostajeAplikacija vraća 0 pre potvrde upisaAplikacioni log i ciljni sistemIspraviti ugovor procesa i atomsku validaciju rezultata
CronJob nije kreirao JobSuspenzija, deadline, pogrešan raspored ili mnogo propuštenih terminaCronJob spec, status i događajiIspraviti raspored/deadline i kontrolisano testirati ručni Job
Dva Job-a rade istovremenoAllow, retko duplo kreiranje ili ručni JobOwner reference, scheduled timestamp i vreme kreiranjaIdempotency/locking; zatim odgovarajuća concurrency policy

Integrisani praktikum: čvorski observer, završivi izvoz i planirani izveštaj

Kontekst i cilj. Platformski tim želi bezbedan laboratorijski dokaz tri modela: observer radi samo na označenim Linux čvorovima, izvoz se završava jednom uz kontrolisan retry i rok, a periodični izveštaj ne sme da se preklopi sa prethodnim izvršavanjem. Kriterijumi prihvatanja su jednak broj DaemonSet ready Pod-ova i ciljnih čvorova, Job sa uslovom Complete, ručno izveden Job iz CronJob šablona sa potvrđenim logom i uspešno dijagnostikovan kontrolisani kvar.

Topologija, prava i rizik. Potreban je funkcionalan laboratorijski klaster sa najmanje jednim schedulable Linux worker čvorom, kubectl i pravima nad Namespace, DaemonSet, Job, CronJob, Pod i ServiceAccount objektima u it-tutorijali, uz čitanje nodes i events. Label promena na čvoru utiče na raspoređivanje i u produkciji zahteva change odobrenje. Vežba ne koristi hostPath, privileged kontejner ni control-plane toleration.

  1. Potvrditi kontekst, verziju i ovlašćenja.
    kubectl config current-context
    kubectl auth whoami
    kubectl version
    kubectl auth can-i create daemonsets.apps -n it-tutorijali
    kubectl auth can-i create jobs.batch -n it-tutorijali
    kubectl auth can-i create cronjobs.batch -n it-tutorijali
    kubectl auth can-i patch nodes
    kubectl get nodes -L kubernetes.io/os
    Očekivanje i validacija: kontekst mora biti laboratorijski, tri namespace provere moraju vratiti yes, a najmanje jedan worker mora biti Ready i Linux. Ako patch nodes nije dozvoljen, label postavlja ovlašćeni administrator ili se koristi unapred označen laboratorijski čvor; prava se ne proširuju samo radi pogodnosti.
  2. Kreirati namespace i označiti tačno jedan ciljni worker. Zameniti WORKER_NAME stvarnim imenom nakon read-only pregleda.
    kubectl create namespace it-tutorijali --dry-run=client -o yaml | kubectl apply -f -
    kubectl get nodes
    kubectl label node WORKER_NAME training.tashizza.com/observer=enabled
    kubectl get nodes -L training.tashizza.com/observer
    Rizik: kubectl label menja čvor. Ne koristiti --overwrite dok se ne proveri postojeća vrednost i vlasnik oznake. Validacija: tačno planirani worker prikazuje vrednost enabled.
  3. Sačuvati manifeste. Kreirati direktorijum ~/vanilla-k8s/18-workloads i u fajlove daemonset.yaml, job.yaml i cronjob.yaml prekopirati tri manifesta iz teorijskog dela. Dodati ServiceAccount objekt pre DaemonSet-a:
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: node-observer
      namespace: it-tutorijali
    automountServiceAccountToken: false
    Validacija pre promene:
    kubectl apply --dry-run=server -f daemonset.yaml
    kubectl apply --dry-run=server -f job.yaml
    kubectl apply --dry-run=server -f cronjob.yaml
    kubectl diff -f daemonset.yaml
    kubectl diff -f job.yaml
    kubectl diff -f cronjob.yaml
    Serverski dry-run mora proći. Izlazni kod 1 za očekivanu razliku iz kubectl diff nije isto što i schema ili admission greška. Ako timeZone nije prepoznat, proveriti verziju klastera; ne uklanjati polje bez dokumentovane odluke o zoni.
  4. Primeniti i validirati DaemonSet.
    kubectl apply -f daemonset.yaml
    kubectl rollout status daemonset/node-observer -n it-tutorijali --timeout=180s
    kubectl get daemonset node-observer -n it-tutorijali
    kubectl get pods -n it-tutorijali -l app.kubernetes.io/name=node-observer -o wide
    kubectl logs -n it-tutorijali -l app.kubernetes.io/name=node-observer --tail=5
    Očekivanje: DESIRED, CURRENT, READY i AVAILABLE odgovaraju broju označenih odgovarajućih čvorova. Pod se nalazi na označenom worker-u, a log sadrži njegovo ime. Ako Pod ostane Pending, pregledati kubectl describe pod i čvorove; ne dodavati široku toleration pre potvrde uzroka.
  5. Dokazati reconciliation bez kvara čvora. Snimiti ime Pod-a, obrisati samo taj laboratorijski Pod i posmatrati zamenu.
    kubectl get pods -n it-tutorijali -l app.kubernetes.io/name=node-observer -o wide
    kubectl delete pod POD_NAME -n it-tutorijali
    kubectl rollout status daemonset/node-observer -n it-tutorijali --timeout=180s
    kubectl get pods -n it-tutorijali -l app.kubernetes.io/name=node-observer -o wide
    Očekivanje: nastaje Pod sa novim imenom na istom ciljnom čvoru. Ovo je state-changing laboratorijski test, ne dokaz da aplikacija preživljava stvarni gubitak čvora.
  6. Pokrenuti završivi Job i potvrditi poslovni ishod.
    kubectl apply -f job.yaml
    kubectl wait --for=condition=complete job/inventory-export -n it-tutorijali --timeout=320s
    kubectl get job inventory-export -n it-tutorijali
    kubectl logs -n it-tutorijali job/inventory-export
    kubectl get pods -n it-tutorijali -l job-name=inventory-export
    Validacija: Job ima Complete=True, Pod je Completed, log sadrži export-complete, a ciljni poslovni sistem bi u realnom scenariju morao potvrditi artefakt. Status bez provere rezultata nije dovoljan.
  7. Simulirati kontrolisani neuspeh kao novi Job. Ime i Pod šablon postojećeg Job-a nisu pogodni za proizvoljnu izmenu, pa se pravi zaseban manifest job-fail.yaml sa imenom inventory-export-fail, backoffLimit: 1 i argumentom echo "configuration error"; exit 42. Primeniti ga i prikupiti dokaz:
    kubectl apply --dry-run=server -f job-fail.yaml
    kubectl apply -f job-fail.yaml
    kubectl wait --for=condition=failed job/inventory-export-fail -n it-tutorijali --timeout=180s
    kubectl describe job inventory-export-fail -n it-tutorijali
    kubectl get pods -n it-tutorijali -l job-name=inventory-export-fail
    kubectl logs -n it-tutorijali job/inventory-export-fail --all-containers=true
    Dijagnostički nalaz: simptom je Failed Job; neposredni uzrok je exit 42; osnovni uzrok u scenariju je namerno neispravna konfiguracija. Privremena mera je obustavljanje daljih pokretanja, trajna korekcija je ispravan manifest i validacija ulaza. Ne povećavati backoffLimit za trajnu grešku.
  8. Primeniti CronJob, a test izvršiti ručnim Job-om.
    kubectl apply -f cronjob.yaml
    kubectl get cronjob inventory-report -n it-tutorijali
    kubectl create job --from=cronjob/inventory-report inventory-report-manual-001 -n it-tutorijali
    kubectl wait --for=condition=complete job/inventory-report-manual-001 -n it-tutorijali --timeout=240s
    kubectl logs -n it-tutorijali job/inventory-report-manual-001
    kubectl get job inventory-report-manual-001 -n it-tutorijali -o jsonpath='{.metadata.ownerReferences}'
    Očekivanje: ručni Job kompletira i log sadrži report-complete. Owner reference je prazan jer je Job izveden iz šablona, ali ga CronJob nije kreirao. Time se razlikuje funkcionalni test šablona od dokaza scheduler-a; zakazano izvršavanje se potvrđuje kasnije pojavom Job-a čiji je vlasnik CronJob.
  9. Testirati suspenziju bez prekidanja postojećih Job-ova.
    kubectl patch cronjob inventory-report -n it-tutorijali --type=merge -p '{"spec":{"suspend":true}}'
    kubectl get cronjob inventory-report -n it-tutorijali
    kubectl get jobs -n it-tutorijali --sort-by=.metadata.creationTimestamp
    Validacija: SUSPEND je True; postojeći Job-ovi nisu obrisani. Pre nastavka pregledati startingDeadlineSeconds i dužinu suspenzije. Za rollback primeniti izvorni cronjob.yaml sa suspend: false i potvrditi SUSPEND=False.
  10. Očistiti laboratoriju i vratiti čvor. Pre brisanja pregledati tačne ciljeve. TTL može već ukloniti neke završene Job-ove.
    kubectl get daemonset,job,cronjob,pods -n it-tutorijali
    kubectl delete -f cronjob.yaml
    kubectl delete -f job-fail.yaml --ignore-not-found
    kubectl delete -f job.yaml --ignore-not-found
    kubectl delete -f daemonset.yaml
    kubectl label node WORKER_NAME training.tashizza.com/observer-
    kubectl get all -n it-tutorijali
    kubectl get node WORKER_NAME --show-labels
    Kriterijum završetka: nema objekata iz vežbe, nema zaostalog observer Pod-a, a laboratorijska node label je uklonjena. Namespace se briše samo ako je namenski napravljen za ovu vežbu i potvrđeno je da ne sadrži tuđe objekte.

Incident response i recovery obrazac

  1. Simptom, obim i posledica: utvrditi koji DaemonSet čvorovi, koji Job ili koji termini CronJob-a su pogođeni i da li je poslovni rezultat nepotpun, dupliran ili zakašnjen.
  2. Dokazi pre promene: sačuvati spec/status, ownerReferences, Pod exit kodove, događaje, aktuelne i prethodne logove, audit zapis poslednje izmene, scheduled timestamp i stanje ciljnog sistema.
  3. Hipoteza i potvrda: odvojiti API/admission, kontroler, scheduler, image/runtime, resurse, mrežu/storage, autorizaciju i aplikacionu grešku. Jedna potvrđena činjenica vredi više od niza nasumičnih patch operacija.
  4. Containment: suspendovati CronJob ako proizvodi štetu, ograničiti paralelizam ili zaustaviti novi rollout. Suspenzija CronJob-a ne zaustavlja aktivne Job-ove; njihovo brisanje je posebna, potencijalno destruktivna odluka.
  5. Korekcija i recovery: popraviti verzionisani manifest, izvršiti serverski dry-run i kontrolisani ručni Job, zatim nastaviti raspored. Kod DaemonSet-a koristiti rollout i pratiti čvor po čvor.
  6. Validacija: potvrditi tehničko terminalno stanje, funkcionalni rezultat, odsustvo duplikata, očekivani broj čvorova i normalizovane metrike. Dokumentovati osnovni uzrok, workaround, trajnu meru i vlasnika akcije.

Administratorske prakse

Završna kontrolna tačka

Zaključak

DaemonSet, Job i CronJob pokazuju da Kubernetes workload nije sinonim za trajno aktivnu aplikaciju. DaemonSet vezuje desired state za skup čvorova, Job za konačan broj uspešnih izvršavanja, a CronJob za raspored stvaranja Job objekata. Razumevanje njihovih kontrolnih petlji sprečava pogrešne obrasce kao što su Deployment za čvorski agent, beskonačni proces unutar Job-a ili cron raspored koji se tretira kao garancija exactly-once izvršenja.

Odgovoran administrator povezuje scheduling, retries, rokove, konkurentnost i retenciju sa posledicama po dostupnost, performanse, bezbednost i oporavak. Posebno štiti čvor od preširokih privilegija DaemonSet-a, zavisne sisteme od nekontrolisanog batch paralelizma i poslovne podatke od ponovljenog ili preklopljenog izvršavanja.

Praktična sposobnost meri se dokazima: očekivani Pod postoji na svakom ciljnom čvoru, Job ima terminalni uslov i potvrđen rezultat, CronJob stvara pravilan Job u očekivanom vremenskom prozoru, a neuspeh se može objasniti kroz conditions, događaje, exit kodove i logove. Tek tada su rollout, retry, ručno pokretanje, suspenzija, recovery i cleanup kontrolisane administratorske radnje, a ne niz komandi bez razumevanja posledica.

← Prethodna lekcija Povratak na sadržaj Sledeća lekcija →