Vanilla Kubernetes

Treći deo: Produkcione operacije, otpornost i enterprise integracije
Monitoring i logovi – osnovno praćenje rada aplikacija u klasteru
IX. Dostupnost, skaliranje i observability
41. Logovi, događaji i korelacija – aplikacija, čvor, kontrolna ravan i audit trag

Kada korisnik prijavi da je aplikacija „pala”, stanje Running, jedan crveni alarm ili poslednjih deset redova jednog loga nisu dovoljni za pouzdan zaključak. Incident se u Kubernetes-u prostire kroz više slojeva: zahtev ulazi kroz mrežni put, dolazi do Service endpoint-a i poda, aplikacioni proces poziva zavisnosti, kubelet i container runtime održavaju kontejner, kontroleri usklađuju željeno i stvarno stanje, a kube-apiserver obrađuje administrativne i automatizovane promene. Svaki sloj proizvodi drugačiji dokaz i odgovara na drugačije pitanje.

Ova lekcija se nadovezuje na monitoring, metrike i alarme iz prethodne lekcije. Metrika i alarm najčešće pokazuju da postoji odstupanje i koliko ono traje; log objašnjava šta je komponenta zabeležila; Kubernetes Event pokazuje šta je kontroler, scheduler ili kubelet pokušao da uradi nad objektom; audit zapis pokazuje ko je, kada i kojim API zahtevom čitao ili menjao stanje. Korelacija tih izvora pretvara skup poruka u proverljivu vremensku osu incidenta.

Cilj nije da administrator „traži grešku” nasumičnim pretraživanjem, već da sačuva dokaze, ograniči vremenski prozor i obim, postavi hipotezu, pronađe zajedničke identifikatore, potvrdi neposredni i osnovni uzrok, primeni najmanje rizičnu korekciju i dokaže oporavak. Posebno je važno razlikovati dijagnostičke logove od bezbednosnog audit traga: oni se dopunjuju, ali jedan ne može pouzdano da zameni drugi.

Četiri ravni dokaza i pitanja na koja odgovaraju

Izvor Šta beleži Tipično pitanje Važno ograničenje
Aplikacioni i kontejnerski log Poruke procesa sa stdout/stderr, uključujući status zahteva, grešku, zavisnost i identifikator korelacije. Šta je aplikacija uradila sa konkretnim zahtevom i zašto nije uspela? Ne dokazuje ko je promenio Kubernetes objekat; lokalna kopija nestaje sa životnim ciklusom čvora ili poda.
Kubernetes Event Zapažanje komponente o objektu: scheduling, image pull, mount, probe, eviction ili druga promena stanja. Zašto pod nije raspoređen, pokrenut ili spreman? Retencija je ograničena, ponavljanja se agregiraju, Event nije garantovano trajan ni potpun audit zapis.
Log čvora i kontrolne ravni Rad kubelet-a, runtime-a, kernela, CNI/CSI komponente, API servera, scheduler-a, controller manager-a i etcd-a. Da li je kvar lokalizovan na pod, čvor, runtime, mrežu, storage ili samu kontrolnu ravan? Lokacija i pristup zavise od distribucije; upravljani servis često ne izlaže host ni kontrolnu ravan korisniku.
Kubernetes audit zapis Hronološki zapis API zahteva kroz faze obrade, sa identitetom, glagolom, resursom, URI-jem, odgovorom i drugim metapodacima prema audit policy-ju. Ko je poslao zahtev, šta je pokušao ili promenio, kada, odakle i sa kojim rezultatom? Postoji samo ako je audit konfigurisan; sadržaj zavisi od nivoa politike, a backend i retencija su odgovornost operatora.

Događaj BackOff može objasniti da kubelet odlaže novo pokretanje kontejnera, aplikacioni log prethodne instance može pokazati nevažeću konfiguraciju, audit zapis može povezati problem sa promenom ConfigMap-a, a metrika može odrediti trenutak kada je stopa grešaka porasla. Tek zajedno ti dokazi grade uzročni lanac. Korelacija ne znači da zapisi imaju isti format ili isti sat; znači da administrator normalizuje vreme, identitete i kontekst dovoljno precizno da podrže isti zaključak.

Vreme, identiteti i kontekst – osnova pouzdane korelacije

Prvi tehnički preduslov jeste sinhronizovano vreme. Čvorovi, kontrolna ravan, aplikacije i centralni sistemi treba da koriste pouzdan NTP izvor. Pretraga se vodi u jednom dogovorenom vremenskom standardu, po mogućstvu UTC, dok se lokalna vremenska zona prikazuje samo korisniku. Razlika od nekoliko minuta može pogrešno povezati rollout i grešku ili sakriti činjenicu da je zahtev otkazao pre nego što je konfiguracija promenjena.

Drugi preduslov su stabilni identifikatori. Naziv poda nije dovoljan jer rollout stvara nove podove. Za korelaciju se čuvaju najmanje namespace, naziv workload-a, Pod UID, naziv i ID kontejnera, čvor, image digest, revizija Deployment-a, identitet API korisnika ili ServiceAccount-a i, kada aplikacija podržava, request_id, trace_id ili poslovni identifikator koji nije osetljiv podatak. Pod UID razlikuje dve instance koje mogu imati slična imena, dok image digest dokazuje stvarno izvršeni artefakt bolje od promenljive oznake image-a.

INCIDENT_START='2026-07-18T09:12:00Z'
INCIDENT_END='2026-07-18T09:27:00Z'
NAMESPACE='prod-app'
POD='web-api-7c9f6c8d7b-x4k2m'

kubectl get pod "$POD" -n "$NAMESPACE" \
  -o jsonpath='{.metadata.uid}{"\n"}{.spec.nodeName}{"\n"}{range .status.containerStatuses[*]}{.name}{" imageID="}{.imageID}{" containerID="}{.containerID}{"\n"}{end}'

Komande u ovom prvom koraku samo čitaju stanje. Vremenski prozor treba proširiti nekoliko minuta pre alarma i nakon oporavka, jer uzrok obično prethodi simptomu. Administrator beleži aktivni kontekst i sopstveni identitet kako prikupljanje dokaza ne bi bilo izvedeno nad pogrešnim klasterom ili nalogom:

kubectl config current-context
kubectl auth whoami
kubectl version
date --utc --iso-8601=seconds

Kubernetes objekti i Events: operativno zapažanje, ne audit istorija

kubectl get i kubectl describe daju sadašnje stanje objekta, uslove, razloge čekanja ili prekida i povezane događaje. Kod poda se proveravaju PodScheduled, Initialized, ContainersReady i Ready, broj restartovanja, state i lastState svakog kontejnera, čvor i vreme kreiranja. Kod Deployment-a se porede željene, ažurirane, spremne i dostupne replike, uslovi i aktivna revizija.

kubectl get deployment,replicaset,pod,service,endpointslice \
  -n prod-app -o wide
kubectl describe deployment web-api -n prod-app
kubectl describe pod web-api-7c9f6c8d7b-x4k2m -n prod-app

Kubernetes Event je namespaced API objekat, osim događaja vezanih za cluster-scoped objekte. Produkuju ga komponente koje posmatraju resurs. Polja type, reason, note ili poruka, regarding/involvedObject, reportingController, vreme i broj ponavljanja treba tumačiti zajedno. Warning ne mora automatski značiti prekid usluge, a Normal može biti važan za vremensku osu, na primer Scheduled, Pulled, Created i Started.

kubectl events -n prod-app --for pod/web-api-7c9f6c8d7b-x4k2m
kubectl events -n prod-app --types=Warning
kubectl get events -n prod-app \
  --sort-by=.metadata.creationTimestamp
kubectl get events -A \
  --field-selector=reason=FailedScheduling \
  --sort-by=.metadata.creationTimestamp

kubectl events je noviji, čitljiv interfejs koji podržava filtriranje po objektu i tipu; kubectl get events ostaje važan kada je potreban strukturisan izlaz, JSONPath ili kompatibilnost sa starijim klijentom. Dostupne opcije uvek se proveravaju komandom kubectl events --help za konkretnu verziju klijenta. Sortiranje po .metadata.creationTimestamp nije savršena hronologija ponovljenih događaja: agregirani Event može imati starije vreme nastanka i novije poslednje pojavljivanje. Za precizniju analizu čuva se YAML ili JSON objekta, a ne samo tabelarni prikaz.

kubectl get events -n prod-app -o yaml \
  > incident-events-prod-app.yaml
kubectl get pod web-api-7c9f6c8d7b-x4k2m -n prod-app -o yaml \
  > incident-pod.yaml

Preusmeravanje u fajl ne menja klaster, ali lokalni fajl može sadržati IP adrese, identitete, nazive interne infrastrukture i poruke aplikacije. Čuva se u kontrolisanom incidentnom direktorijumu sa ograničenim pravima, poznatim rokom retencije i hash vrednošću ako se zahteva dokaz integriteta. Events se ne koriste kao zamena za audit: oni obično opisuju posledicu nad objektom, a ne pouzdano identitet i kompletan API zahtev koji je izazvao promenu.

Aplikacioni i kontejnerski logovi

Preporučeni obrazac za kontejnersku aplikaciju jeste da operativne logove piše na standardni izlaz i standardni izlaz za greške. Container runtime ih čuva u CRI formatu na čvoru, kubelet upravlja rotacijom, a API server i kubelet omogućavaju pristup komandom kubectl logs. Kubernetes ne obezbeđuje ugrađenu trajnu centralnu arhivu; za pretragu posle rescheduling-a, brisanja poda ili gubitka čvora potreban je cluster-level logging pipeline.

Dobar aplikacioni zapis sadrži vremensku oznaku sa vremenskom zonom, nivo, servis i verziju, okruženje, request ili trace ID, vrstu operacije, rezultat, trajanje i klasifikovanu grešku. Strukturisani JSON olakšava indeksiranje, ali samo ako su tipovi i nazivi polja dosledni. Višelinijski stack trace mora biti obrađen pravilima agenta kako ne bi postao stotine nepovezanih zapisa. Lozinke, bearer tokeni, privatni ključevi, session kolačići, kompletna tela zahteva i osetljivi lični podaci ne smeju postati dijagnostički materijal.

{
  "timestamp": "2026-07-18T09:16:42.381Z",
  "level": "ERROR",
  "service": "web-api",
  "version": "2.4.1",
  "request_id": "req-7f3a9c",
  "operation": "GET /orders/{id}",
  "duration_ms": 2031,
  "error_type": "dependency_timeout",
  "dependency": "orders-db",
  "message": "upstream request exceeded deadline"
}

Primer namerno ne sadrži korisnički token, puni URL sa parametrima niti sadržaj narudžbine. Redakcija i maskiranje treba da se izvrše što bliže izvoru, pre slanja u centralni backend; naknadno brisanje iz indeksiranih kopija, replika i backup-a može biti teško ili nemoguće.

Precizna upotreba komande kubectl logs

kubectl logs je read-only prema workload-u, ali rezultat može sadržati poverljive podatke i poziv se može pojaviti u audit tragu. Kod više kontejnera naziv se navodi eksplicitno. Vremenski i količinski filter smanjuju opterećenje API servera i količinu izloženih podataka. Opcija --timestamps je važna za korelaciju, a --prefix razlikuje pod i kontejner kada se čita više izvora.

kubectl logs -n prod-app pod/web-api-7c9f6c8d7b-x4k2m \
  -c web --since-time='2026-07-18T09:12:00Z' \
  --timestamps --tail=500

kubectl logs -n prod-app deployment/web-api \
  --all-pods=true --all-containers=true \
  --since=15m --timestamps --prefix \
  --max-log-requests=5

Podrška za selektor resursa i pojedine opcije zavisi od verzije kubectl; referenca klijenta mora odgovarati klasteru i instaliranom alatu. Kod velikog broja replika paralelni zahtev može opteretiti API i kubelet-e, pa se broj istovremenih zahteva ograničava. -f prati novi izlaz, ali nije arhiva i ne treba ga ostavljati bez vremenskog ograničenja tokom incidenta.

Kod CrashLoopBackOff najvredniji je često log završene instance:

kubectl get pod web-api-7c9f6c8d7b-x4k2m -n prod-app \
  -o jsonpath='{range .status.containerStatuses[*]}{.name}{" current="}{.state}{" previous="}{.lastState}{" restarts="}{.restartCount}{"\n"}{end}'

kubectl logs -n prod-app web-api-7c9f6c8d7b-x4k2m \
  -c web --previous --timestamps --tail=500

Kubelet uobičajeno čuva log samo jedne prethodne, završene instance kontejnera. --previous ne može vratiti log starog poda koji je Deployment zamenio niti proizvoljnu stariju instancu iz niza restartovanja. Ako je pod obrisan, čvor izgubljen ili lokalni log rotiran, pouzdano preostaje samo centralni backend koji je zapis ranije preuzeo. Zato incidentna procedura nalaže prikupljanje loga pre brisanja ili ponovnog kreiranja poda, osim kada hitno ograničavanje bezbednosnog ili dostupnosnog rizika ima prednost.

Aplikacija koja piše u fajl unutar kontejnera zaobilazi standardni tok ako agent taj fajl izričito ne prikuplja. Sidecar za transformaciju ili prosleđivanje može biti opravdan, ali povećava potrošnju resursa i broj tačaka otkaza. Direktno slanje iz svake aplikacije u udaljeni backend vezuje aplikaciju za mrežu i dobavljača log sistema; node-level agent je uobičajeniji produkcioni obrazac jer odvaja aplikaciju od transporta i dodaje Kubernetes metapodatke.

Čvor: kubelet, container runtime, kernel, CNI i CSI

Na Linux čvoru kubelet i runtime pod systemd-om tipično pišu u journald. Kontejnerski logovi se prema CRI konvenciji nalaze ispod /var/log/pods, a /var/log/containers obično sadrži simboličke veze. Tačna lokacija i servisna jedinica zavise od operativnog sistema, runtime-a i distribucije. Direktan host pristup koristi se tek kada namespace-level dokazi ukažu na problem čvora ili kada API nije dostupan.

sudo journalctl -u kubelet \
  --since '2026-07-18 09:12:00 UTC' \
  --until '2026-07-18 09:27:00 UTC' \
  --output=short-iso-precise

sudo journalctl -u containerd \
  --since '2026-07-18 09:12:00 UTC' \
  --until '2026-07-18 09:27:00 UTC' \
  --output=short-iso-precise

sudo journalctl -k \
  --since '2026-07-18 09:12:00 UTC' \
  --until '2026-07-18 09:27:00 UTC'

Ove komande samo čitaju dnevnik, ali zahtevaju host privilegije. U kubelet logu se traže Pod UID, container ID, probe greške, volume mount, image i runtime RPC problemi; u runtime logu sandbox, image unpack i shim greške; u kernel logu OOM, filesystem, mrežni interfejs i hardverski događaji. Ista poruka ponovljena na više podova istog čvora sugeriše node-level obim; ista aplikaciona greška na više čvorova pre upućuje na zajedničku konfiguraciju ili zavisnost.

crictl je administratorski CLI za CRI runtime i koristi se na čvoru kada kubelet/API pogled nije dovoljan. Endpoint treba unapred bezbedno konfigurisati u /etc/crictl.yaml; automatsko isprobavanje poznatih endpoint-a je sporije i može dati nejasne rezultate.

sudo crictl ps -a --name web-api
sudo crictl pods --name web-api
sudo crictl inspect <CONTAINER_ID>
sudo crictl logs --timestamps <CONTAINER_ID>

Komande su read-only, ali inspect može prikazati konfiguracione vrednosti i mount informacije. Komande crictl stop, rm, stopp i rmp menjaju runtime stanje, zaobilaze uobičajeni Kubernetes tok i nisu dijagnostički korak za produkciju bez izričite procedure. Kubelet može odmah ponovo kreirati uklonjeno stanje, čime se dokaz gubi bez trajne korekcije uzroka.

Ako SSH nije dostupan, ovlašćeni cluster administrator može koristiti kubectl debug node/<NODE>. Debug pod dobija pristup host filesystem-u pod /host, što je veoma privilegovan pristup i mora biti ograničen RBAC-om, auditovan i uklonjen posle rada.

kubectl debug node/worker-02 -it \
  --image=ubuntu:24.04 \
  --profile=sysadmin

# U debug kontejneru, host fajlovi su tipično ispod /host.
ls -la /host/var/log
exit

kubectl get pods -A \
  --field-selector=spec.nodeName=worker-02

Profil, dostupnost i bezbednosne posledice kubectl debug zavise od verzije i admission politike. Image mora poticati iz odobrenog registra. Ne instaliraju se paketi niti menjaju host fajlovi samo radi pogodnosti; pre rada se proverava da li platforma nudi podržani support bundle ili node diagnostics postupak.

Kubernetes Node Log Query omogućava upit sistemskih logova preko kubelet API-ja. Funkcija je u Kubernetes-u 1.36 stabilna, ali enableSystemLogHandler je podrazumevano false i zvanična preporuka je da ostane isključen osim tokom aktivne dijagnostike. Omogućavanje širi osetljivu površinu kubelet API-ja i zahteva eksplicitnu procenu RBAC-a, mrežnog pristupa, auditovanja i povratka na početno stanje. U starijim verzijama status feature gate-a i mogućnosti upita se razlikuju; zato se ova funkcija ne pretpostavlja kao univerzalno dostupna.

Kontrolna ravan i razlike modela implementacije

U kubeadm klasteru komponente kontrolne ravni najčešće rade kao static podovi čiji su manifesti na control-plane čvoru, a mirror Pod objekti vidljivi u namespace-u kube-system. Ako API server i kubelet rade dovoljno dobro i RBAC dozvoljava, njihovi kontejnerski logovi mogu se čitati preko kubectl logs. Ako je API nedostupan, pregled se izvodi lokalno preko crictl i sistemskih logova na control-plane čvoru.

kubectl get pods -n kube-system -o wide \
  | grep -E 'kube-apiserver|kube-scheduler|kube-controller-manager|etcd'

kubectl logs -n kube-system kube-apiserver-cp-01 \
  --since=15m --timestamps --tail=500
kubectl logs -n kube-system kube-scheduler-cp-01 \
  --since=15m --timestamps --tail=300

kube-apiserver log pomaže kod autentikacije, autorizacije, admission-a, timeout-a i komunikacije sa etcd-om; scheduler log kod odluka o raspoređivanju; controller manager kod reconcile petlji; etcd log kod latencije, quorum-a, disk I/O-a i alarma. Osetljive vrednosti iz ovih izvora ne kopiraju se nekontrolisano u tiket ili čet. Povećanje verbosity nivoa komponenti menja stanje, može proizvesti veliki volumen i izložiti dodatne detalje, pa zahteva odobrenu, vremenski ograničenu promenu i rollback.

Kod systemd ili drugačije instaliranih komponenti koriste se odgovarajući servisni logovi. U upravljanom Kubernetes servisu korisnik često nema host pristup niti direktne logove kontrolne ravni; koriste se provider audit/diagnostic logovi, servis za podršku i dokumentovan postupak eskalacije. Ne treba primenjivati kubeadm putanje i komande na upravljani servis niti pretpostaviti da provider čuva svaki izvor podrazumevano. Retencija, cena, region, enkripcija i uključivanje control-plane log kategorija proveravaju se u dokumentaciji konkretnog servisa.

Kubernetes audit: ko je pozvao API i sa kojim ishodom

Kubernetes auditing daje bezbednosno relevantan hronološki skup zapisa o zahtevima korisnika, ServiceAccount-a, kontrolne ravni i drugih klijenata prema API serveru. Audit može zabeležiti faze RequestReceived, ResponseStarted, ResponseComplete i Panic. Jedan događaj može sadržati audit ID, stage, request URI, verb, user i grupe, source IP, user agent, referencu objekta, status odgovora i anotacije admission ili authorization sloja.

Audit nije automatski centralni SIEM niti istorija svih promena. Operator mora proslediti kube-apiserver-u audit policy i konfigurisati log ili webhook backend. Bez politike nema smislenog audit zapisa. Politika bira nivo po pravilima odozgo nadole:

Nivo Sadržaj Primena i rizik
None Događaj se ne beleži. Za veoma bučne, niskovredne zahteve samo kada je izostavljanje opravdano; može stvoriti slepu tačku.
Metadata Metapodaci zahteva bez tela zahteva i odgovora. Dobar podrazumevani balans za veliki broj operacija; često dovoljan za identitet, verb, resurs i rezultat.
Request Metapodaci i telo zahteva, bez tela odgovora. Korisno za promene konfiguracije, ali može zabeležiti osetljive podatke i povećati volumen.
RequestResponse Metapodaci, telo zahteva i telo odgovora. Najskuplji i najosetljiviji nivo; koristi se selektivno, nikada kao nepromišljeni globalni podrazumevani nivo.

Sledeći laboratorijski primer ilustruje princip najmanjeg potrebnog sadržaja. Ne predstavlja univerzalnu produkcionu politiku: zahtevi usklađenosti, verzija, agregirani API-ji, admission webhooks, očekivani volumen i model pretnji moraju se analizirati pre primene.

apiVersion: audit.k8s.io/v1
kind: Policy
omitStages:
  - RequestReceived
rules:
  - level: None
    resources:
      - group: ""
        resources:
          - events

  - level: Metadata
    resources:
      - group: ""
        resources:
          - secrets

  - level: Request
    verbs:
      - create
      - update
      - patch
      - delete
    resources:
      - group: apps
        resources:
          - deployments

  - level: Metadata

Redosled je presudan: primenjuje se prvo pravilo koje odgovara zahtevu. Za Secrets je u primeru izabran Metadata da telo objekta ne bi ušlo u audit log. Izostavljanje RequestReceived smanjuje duplikaciju i volumen, ali zapis tada ne dokazuje prijem zahteva koji nikada nije stigao do kasnije faze. Odluka mora biti dokumentovana. Izostavljanje Events resursa smanjuje buku, ali organizacija treba da proceni da li je ta slepa tačka prihvatljiva.

Za log backend API serveru se, između ostalog, zadaju putanja, maksimalna starost, broj backup fajlova, veličina rotacije i format. Za webhook backend zadaje se kubeconfig i način baferovanja. Promena flag-ova API servera restartuje ili ponovo kreira komponentu i može ugroziti dostupnost kontrolne ravni ako su putanja, mount, dozvole ili konfiguracija pogrešni. U HA klasteru politika mora biti dosledna na svim API serverima, backend mora podneti zbirni volumen, a rollout se izvodi po odobrenom postupku, jedan član u trenutku, uz proveru zdravlja između koraka.

--audit-policy-file=/etc/kubernetes/audit-policy.yaml
--audit-log-path=/var/log/kubernetes/audit/audit.log
--audit-log-format=json
--audit-log-maxage=30
--audit-log-maxbackup=10
--audit-log-maxsize=100

Prikaz flag-ova je referenca, ne komanda za neposredno izvršavanje. Kod kubeadm static Pod-a policy fajl i direktorijum loga moraju biti dostupni kontejneru kroz odgovarajuće hostPath mount-ove, sa bezbednim vlasništvom i dozvolama. Pogrešan YAML, nepostojeći mount ili nemogućnost pisanja mogu sprečiti pokretanje API servera. Pre promene čuvaju se manifest i konfiguracija, validira politika u izolovanom okruženju i priprema tačan rollback. Kod managed servisa koristi se provider mehanizam; korisnik obično ne menja ove flag-ove.

Čitanje i tumačenje audit zapisa

Audit log je JSON Lines: svaki red je zaseban JSON objekat, a ceo fajl nije jedan JSON niz. Za lokalnu, odobrenu analizu može se koristiti jq. Pretraga se ograničava vremenom, glagolom, namespace-om, resursom, korisnikom ili auditID-jem. Sledeći primer čita fajl; ne menja klaster.

sudo jq -c '
  select(.stage == "ResponseComplete")
  | select(.objectRef.namespace == "prod-app")
  | select(.objectRef.resource == "deployments")
  | select(.verb == "patch" or .verb == "update")
  | {
      time: .stageTimestamp,
      auditID: .auditID,
      user: .user.username,
      groups: .user.groups,
      sourceIPs: .sourceIPs,
      userAgent: .userAgent,
      verb: .verb,
      object: .objectRef,
      code: .responseStatus.code
    }
' /var/log/kubernetes/audit/audit.log

Korisnik može biti čovek, system:serviceaccount:<namespace>:<name>, kontroler ili impersonirani identitet. userAgent i source IP pomažu, ali sami nisu kriptografski dokaz osobe. Kod impersonacije audit događaj može sadržati originalnog i impersoniranog korisnika; kod reverse proxy-ja source IP zavisi od mrežne arhitekture i trusted proxy konfiguracije. HTTP status 200 ili 201 potvrđuje uspešan API odgovor, ali ne potvrđuje da je aplikacija kasnije postala zdrava. Za to se rezultat povezuje sa generation/observedGeneration, rollout stanjem, Events, logovima i funkcionalnim testom.

Audit ID povezuje faze istog API zahteva i često se vraća klijentu u response header-u. On nije isto što i aplikacioni request ili trace ID. Ako API zahtev pokreće novi rollout, vremenska osa može povezati audit zapis promene Deployment-a sa novom ReplicaSet revizijom, kreiranjem podova, kubelet događajima i aplikacionim logovima novih instanci.

Projektovanje centralnog log pipeline-a

Produkcioni pipeline najčešće ima node-level agent kao DaemonSet, transportni ili bafer sloj, centralni storage/index backend, pretragu i vizuelizaciju, alarme i po potrebi SIEM integraciju. Agent čita CRI logove i sistemske izvore, dodaje Kubernetes metapodatke i prosleđuje zapise. Kontrolna ravan i audit mogu imati odvojene izvore i strožu kontrolu pristupa. Izbor Fluent Bit-a, Fluentd-a, Vector-a, OpenTelemetry Collector-a ili platformske komponente zavisi od podržane arhitekture; Kubernetes projekat ne propisuje jedan backend.

Projektna odluka Posledica Dokaz ispravnosti
Node-level agent Ne zahteva izmenu svake aplikacije, ali mora tolerisati restart, log rotaciju, taint-ove i pritisak na čvoru. Zapisi sa svakog čvora stižu sa očekivanim kašnjenjem; agent restart ne proizvodi nekontrolisane duplikate ili gubitak.
Bafer i backpressure Štiti od kratkog prekida backenda, ali zauzima disk/memoriju čvora; pun bafer može ugroziti workload. Kontrolisan test prekida backenda potvrđuje oporavak i definisanu politiku odbacivanja.
Label/metadata indeksiranje Olakšava pretragu, ali nekontrolisana cardinality povećava indeks, cenu i latenciju. Dozvoljena polja su dokumentovana; dinamični request ID nije skupocena indeksna labela ako backend to ne podnosi.
Retencija i tiering Duža retencija podržava istrage i usklađenost, ali povećava trošak i period izlaganja podataka. Automatsko istecanje, legal hold i restore pretrage testirani su prema politici.
Razdvajanje audit i aplikacionih logova Omogućava stroži RBAC, neizmenjivost i drugačiju retenciju za bezbednosni trag. Aplikacioni operater ne može menjati audit zapise; bezbednosni tim može korelisati oba izvora po odobrenju.

Visoka dostupnost log sistema nije samo broj replika. Potrebni su redundantni agenti po čvorovima, dovoljno lokalnog bafera, HA ingest i query sloj, zaštićen storage, monitoring samog pipeline-a, kontrola kvota i dokumentovan oporavak. Prate se ingest latency, dropped records, parser errors, retry/backpressure, veličina bafera, zauzeće storage-a, query latency i neuspeh autentikacije. Log sistem koji tiho odbacuje zapise proizvodi lažan osećaj sigurnosti.

Transport treba da bude autentifikovan i šifrovan, pristup zasnovan na ulogama i tenant-u, a administrativne radnje nad log platformom auditovane. Za bezbednosno značajan trag razmatraju se write-once ili immutable storage kontrole, odvojeni administrativni domen i hash/integritet mehanizmi. Enkripcija sama ne sprečava ovlašćenog administratora da izbriše zapis; neizmenjivost i razdvajanje dužnosti rešavaju drugačiji rizik.

Sistematičan tok korelacije incidenta

  1. Definiši simptom, obim i posledicu. Zapiši ko je pogođen, koji endpoint ili funkcija, od kada, da li je problem stalan i da li obuhvata jedan pod, čvor, namespace, region ili ceo klaster.
  2. Sačuvaj početno stanje. Zabeleži kontekst, identitet, UTC vreme, verziju, objekte, uslove, Events, log trenutne i prethodne instance, Pod UID, čvor, image digest i aktivnu reviziju. Ne restartuj prvi.
  3. Ograniči vremenski prozor. Počni nekoliko minuta pre prvog alarma i uključi period posle poslednjeg simptoma. Proveri sinhronizaciju satova i kašnjenje ingest-a.
  4. Postavi jednu proverljivu hipotezu. Na primer: „rollout revizije 12 uveo je pogrešan DB endpoint, pa nove replike vraćaju 503”. Odredi koji bi dokaz hipotezu potvrdio, a koji oborio.
  5. Poveži slojeve. Alarm određuje vreme; audit pokazuje promenu; ReplicaSet i Pod UID identifikuju novu instancu; Event pokazuje lifecycle; aplikacioni log i trace pokazuju grešku zavisnosti; node log potvrđuje ili isključuje infrastrukturni kvar.
  6. Razdvoji neposredni i osnovni uzrok. Neposredni uzrok može biti connection refused; osnovni uzrok pogrešna GitOps vrednost, nedostatak validacije i neadekvatan rollout gate.
  7. Primeni najmanje rizičnu korekciju. Rollback poznate revizije je često sigurniji od improvizovanog patch-a. Pre promene zabeleži odobrenje, očekivani efekat, rollback i kriterijum prekida.
  8. Dokaži oporavak. Proveri rollout, ready endpoint-e, funkcionalni zahtev, greške i latenciju, odsustvo novih Warning događaja, stabilnost tokom dogovorenog perioda i audit zapis korekcije.
  9. Dokumentuj i spreči ponavljanje. Sačuvaj vremensku osu, dokaze, uzrok, workaround, trajnu meru, vlasnika i rok; ažuriraj alert, runbook, policy ili pipeline test.

Integrisani praktikum: od lošeg rollout-a do auditovane vremenske ose

Kontekst i cilj. Tim održava interni portal u namespace-u log-lab. Aplikacija ima dve replike i zapisuje strukturisane poruke. Administrator najpre uspostavlja baznu liniju, zatim laboratorijski uvodi pogrešan readiness path, prikuplja Events i logove, pronalazi API promenu u audit zapisu kada je audit dostupan, vraća prethodnu reviziju i dokazuje oporavak. Vežba namerno izaziva samo nedostupnost novih endpoint-a; ne zaustavlja čvor niti kontrolnu ravan.

Topologija. Radna stanica sa kubectl pristupa vanilla Kubernetes klasteru; Deployment portal pokreće dva nginx poda na jednom ili više worker čvorova; Service bira spremne podove. Audit deo se izvodi samo u laboratoriji u kojoj je audit već bezbedno konfigurisan ili uz nadzor administratora kontrolne ravni.

Preduslovi i prava. Potreban je schedulable worker, DNS i pristup odobrenom registru. Korisnik mora moći da upravlja objektima u laboratorijskom namespace-u i čita pods, pods/log i events. Čitanje node/control-plane/audit logova zahteva odvojena, viša prava i nije uslov da bi osnovni scenario bio završen. Aktivni audit se ne konfiguriše ad hoc tokom ove vežbe.

Rizik i rollback. Svi workload objekti su izolovani u novom namespace-u. Negativni test menja samo readiness path i vraća se komandom kubectl rollout undo. Brisanje namespace-a je dozvoljeno samo po završetku i nakon izvoza potrebnih dokaza.

  1. Provera konteksta, identiteta i ovlašćenja.
    kubectl config current-context
    kubectl auth whoami
    kubectl auth can-i create deployments.apps -n log-lab
    kubectl auth can-i get pods/log -n log-lab
    kubectl auth can-i list events -n log-lab
    date --utc --iso-8601=seconds

    Očekivani rezultat i odluka. Kontekst mora biti laboratorijski. Provere za namespace koji još ne postoji i dalje ispituju autorizaciju; ako su prava odbijena, vežba se ne nastavlja proširenjem sopstvenih privilegija, već se traži namenski nalog ili unapred pripremljen namespace.

  2. Kreiranje referentne aplikacije. Manifest je deklarativni dokaz početnog stanja. Image tag je radi prenosivosti primera eksplicitan; u kontrolisanom produkcionom okruženju koristi se odobren digest.
    apiVersion: v1
    kind: Namespace
    metadata:
      name: log-lab
      labels:
        purpose: logging-correlation-practice
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: portal-content
      namespace: log-lab
    data:
      index.html: |
        <!doctype html>
        <html lang="sr">
        <head><meta charset="utf-8"><title>Log lab</title></head>
        <body><h1>Portal je dostupan</h1></body>
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: portal
      namespace: log-lab
      labels:
        app: portal
    spec:
      replicas: 2
      revisionHistoryLimit: 5
      selector:
        matchLabels:
          app: portal
      template:
        metadata:
          labels:
            app: portal
        spec:
          containers:
            - name: web
              image: nginx:1.27-alpine
              imagePullPolicy: IfNotPresent
              ports:
                - name: http
                  containerPort: 80
              readinessProbe:
                httpGet:
                  path: /
                  port: http
                periodSeconds: 5
                timeoutSeconds: 2
                failureThreshold: 3
              resources:
                requests:
                  cpu: 25m
                  memory: 32Mi
                limits:
                  cpu: 200m
                  memory: 128Mi
              volumeMounts:
                - name: content
                  mountPath: /usr/share/nginx/html/index.html
                  subPath: index.html
                  readOnly: true
            - name: activity-log
              image: busybox:1.36.1
              command:
                - /bin/sh
                - -c
              args:
                - |
                  while true; do
                    printf '{"timestamp":"%s","level":"INFO","service":"portal","pod":"%s","message":"heartbeat"}\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$HOSTNAME"
                    sleep 10
                  done
              resources:
                requests:
                  cpu: 5m
                  memory: 8Mi
                limits:
                  cpu: 50m
                  memory: 32Mi
          volumes:
            - name: content
              configMap:
                name: portal-content
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: portal
      namespace: log-lab
    spec:
      selector:
        app: portal
      ports:
        - name: http
          port: 80
          targetPort: http
    kubectl apply -f 01-log-lab.yaml
    kubectl rollout status deployment/portal -n log-lab --timeout=120s
    kubectl get deployment,pod,service,endpointslice -n log-lab -o wide

    Validacija. Deployment ima dve dostupne replike, svaki pod 2/2 spremna kontejnera, a EndpointSlice spremne adrese. Ako image nije dostupan, proveravaju se Events i koristi organizaciono odobren mirror; ne isključuje se bezbednost registra.

  3. Bazna linija i funkcionalni dokaz.
    PORTAL_POD="$(kubectl get pod -n log-lab -l app=portal \
      -o jsonpath='{.items[0].metadata.name}')"
    
    kubectl get pod "$PORTAL_POD" -n log-lab \
      -o jsonpath='{.metadata.uid}{"\n"}{.spec.nodeName}{"\n"}{range .status.containerStatuses[*]}{.name}{" imageID="}{.imageID}{" restarts="}{.restartCount}{"\n"}{end}'
    
    kubectl run portal-client -n log-lab --rm -i --restart=Never \
      --image=curlimages/curl:8.10.1 -- \
      curl -fsS http://portal.log-lab.svc.cluster.local/
    
    kubectl logs -n log-lab "$PORTAL_POD" -c web \
      --since=5m --timestamps --tail=50
    kubectl logs -n log-lab "$PORTAL_POD" -c activity-log \
      --since=2m --timestamps --tail=20

    Validacija. Klijent vraća Portal je dostupan; nginx access log beleži uspešan zahtev, a pomoćni kontejner JSON heartbeat. Beleže se UTC vreme, Pod UID, čvor i imageID.

  4. Kontrolisana promena i negativni test. Pre patch-a beleži se vreme. Promena je state-changing i dozvoljena samo u ovoj laboratoriji.
    CHANGE_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
    printf 'change_time=%s\n' "$CHANGE_TIME"
    
    kubectl annotate deployment portal -n log-lab \
      kubernetes.io/change-cause='lab: invalid readiness path for correlation practice' \
      --overwrite
    
    kubectl patch deployment portal -n log-lab --type='json' -p='[
      {
        "op": "replace",
        "path": "/spec/template/spec/containers/0/readinessProbe/httpGet/path",
        "value": "/not-ready"
      }
    ]'
    
    kubectl rollout status deployment/portal -n log-lab --timeout=45s

    Očekivani rezultat. Status rollout-a treba da istekne jer novi podovi dobijaju HTTP 404 na readiness proveri. Timeout je očekivani dokaz testa, ne razlog za ponavljanje patch-a.

  5. Trijaža od najmanje invazivnog dokaza.
    kubectl get deployment,replicaset,pod,endpointslice \
      -n log-lab -l app=portal -o wide
    
    NOT_READY_POD="$(kubectl get pod -n log-lab -l app=portal \
      -o jsonpath='{range .items[*]}{.metadata.name}{" "}{range .status.conditions[?(@.type=="Ready")]}{.status}{"\n"}{end}{end}' \
      | awk '$2=="False"{print $1; exit}')"
    
    kubectl describe pod "$NOT_READY_POD" -n log-lab
    kubectl events -n log-lab --for pod/"$NOT_READY_POD"
    kubectl get pod "$NOT_READY_POD" -n log-lab \
      -o jsonpath='{.metadata.uid}{"\n"}{.spec.nodeName}{"\n"}{.spec.containers[?(@.name=="web")].readinessProbe}{"\n"}'
    
    kubectl logs -n log-lab "$NOT_READY_POD" -c web \
      --since-time="$CHANGE_TIME" --timestamps --tail=100

    Tumačenje. Simptom je nedovršen rollout; obim su nove replike; posledica je da one ne ulaze u Service endpoint-e. Event Unhealthy i HTTP 404 potvrđuju neposredni uzrok. Nginx access log pokazuje probe zahteve prema /not-ready. Osnovni uzrok je namerna pogrešna promena pod template-a, a ne pad procesa ili čvora.

  6. Korelacija sa audit tragom, ako ga laboratorija izlaže. Operator audit sistema filtrira isti vremenski period, namespace, Deployment i glagole patch/update. Namespace korisnik ne treba da dobije host pristup samo radi vežbe.
    sudo jq -c \
      --arg ns 'log-lab' \
      --arg name 'portal' '
        select(.stage == "ResponseComplete")
        | select(.objectRef.namespace == $ns)
        | select(.objectRef.resource == "deployments")
        | select(.objectRef.name == $name)
        | select(.verb == "patch" or .verb == "update")
        | {
            time: .stageTimestamp,
            auditID: .auditID,
            user: .user.username,
            sourceIPs: .sourceIPs,
            userAgent: .userAgent,
            verb: .verb,
            code: .responseStatus.code
          }
      ' /var/log/kubernetes/audit/audit.log

    Validacija. Očekuju se uspešni zahtevi za anotaciju i patch sa odgovarajućim identitetom i vremenom. Ako audit nije konfigurisan ili policy izostavlja ove zahteve, nalaz se beleži kao observability gap; ne tvrdi se da promene nije bilo.

  7. Rollback i potvrda oporavka. Pre rollback-a čuvaju se dokazi; zatim se vraća prethodna revizija.
    mkdir -p evidence
    kubectl get deployment,replicaset,pod,endpointslice -n log-lab -o yaml \
      > evidence/pre-rollback-objects.yaml
    kubectl get events -n log-lab -o yaml \
      > evidence/pre-rollback-events.yaml
    kubectl logs -n log-lab "$NOT_READY_POD" -c web \
      --timestamps --tail=500 \
      > evidence/not-ready-web.log
    
    kubectl rollout history deployment/portal -n log-lab
    kubectl rollout undo deployment/portal -n log-lab
    kubectl rollout status deployment/portal -n log-lab --timeout=120s
    
    kubectl get deployment,pod,endpointslice -n log-lab -o wide
    kubectl run portal-client-final -n log-lab --rm -i --restart=Never \
      --image=curlimages/curl:8.10.1 -- \
      curl -fsS http://portal.log-lab.svc.cluster.local/

    Kriterijum završetka. Deployment ponovo ima dve dostupne replike; svi aktuelni podovi su spremni; EndpointSlice označava očekivane adrese kao ready; funkcionalni zahtev uspeva; nema novih ponavljajućih Unhealthy događaja nakon stabilizacije. Audit, ako je dostupan, beleži rollback promenu.

  8. Integritet dokaza i cleanup.
    find evidence -type f -maxdepth 1 -print0 \
      | sort -z \
      | xargs -0 sha256sum \
      > evidence/SHA256SUMS
    
    kubectl get all,configmap,endpointslice -n log-lab
    kubectl delete namespace log-lab
    kubectl get namespace log-lab

    Upozorenje. Brisanje namespace-a je destruktivna laboratorijska cleanup radnja i uklanja objekte i API-dostupne lokalne logove. Izvršava se tek nakon provere da je cilj tačno log-lab i da su dokazi sačuvani. U produkciji se namespace ne briše kao troubleshooting postupak.

Merljivi kriterijumi prihvatanja praktikuma. Polaznik može da izdvoji Pod UID, čvor i image digest; prikaže log konkretnog kontejnera u ograničenom UTC periodu; objasni zašto Event nije audit; koreliše patch sa novom revizijom i Unhealthy događajem; razlikuje neposredni od osnovnog uzroka; sačuva dokaze pre rollback-a; vrati dve dostupne replike; izvrši funkcionalni test i dokumentuje audit gap kada audit nije omogućen.

Tipični simptomi i troubleshooting grane

Simptom Prva read-only provera Karakterističan nalaz Bezbedna korektivna smernica
kubectl logs je prazan Proveri pravi pod, kontejner, trenutnu/prethodnu instancu, vreme i da li aplikacija piše na stdout/stderr. Proces piše u interni fajl, pod je nov ili filter isključuje period. Ispravi logging obrazac ili agent konfiguraciju; ne uključuj trajni debug bez procene volumena i podataka.
--previous nema zapis Pregledaj restartCount, lastState, UID i vreme kreiranja poda. Pod je zamenjen ili nema prethodne instance koju kubelet čuva. Pretraži centralni backend po starom Pod UID-u; uvedi pouzdanu centralnu retenciju.
Event postoji, audit ne postoji Proveri da li je audit omogućen, policy pravilo, backend zdravlje i retencija. Zahtev nije obuhvaćen politikom, zapis je istekao ili backend nije radio. Evidentiraj slepu tačku; testiraj i koriguj policy/pipeline kroz kontrolisanu promenu.
Svi podovi na jednom čvoru imaju problem kubectl get pods -A -o wide, Node conditions/Events, kubelet, runtime i kernel log. DiskPressure, OOM, CNI/CSI ili runtime greške u istom periodu. Cordon/drain samo po proceduri i uz PDB/kapacitet proveru; prvo sačuvaj node dokaze.
Logovi kasne ili nedostaju samo centralno Uporedi kubectl logs sa agentom, ingest latency, retries, dropped records i baferom. Aplikacija radi, ali pipeline ima backpressure, parser grešku ili kvotu. Oslobodi kapacitet ili vrati poznatu agent konfiguraciju; potvrdi nadoknadu bafera bez duplikata.
Audit volumen naglo raste Grupiši po verb-u, resursu, korisniku, stage-u i user agent-u. Watch/list buka, controller petlja ili preširok RequestResponse. Preciziraj policy tek nakon procene bezbednosne vrednosti; ne utišavaj sumnjiv izvor pre istrage.
Vremena se ne podudaraju Proveri UTC offset, NTP stanje, format aplikacije i ingest timestamp naspram event timestamp-a. Lokalna zona, drift ili backend koristi vreme prijema. Ispravi sinhronizaciju i normalizaciju; dokumentuj nesigurnost stare vremenske ose.

Administratorske prakse

Završna kontrolna tačka

Zaključak

Logovi nisu jedna datoteka niti jedan proizvod. U Kubernetes-u oni čine skup dokaza raspoređenih između aplikacije, runtime-a, kubelet-a, čvora, kontrolne ravni, audit backenda i centralnog sistema. Events prikazuju operativna zapažanja o objektima, audit prikazuje API aktivnosti, a aplikacioni i sistemski logovi objašnjavaju ponašanje procesa i infrastrukture. Pouzdana dijagnoza nastaje tek kada se njihova vremena, identiteti i kontekst ukrste sa stanjem objekata, metrikama, alarmima i funkcionalnim rezultatom.

Najveći operativni rizici nisu samo odsustvo loga, već i pogrešno poverenje u nepotpun zapis, gubitak dokaza usled brisanja poda, nesinhronizovani satovi, tiho odbacivanje u pipeline-u, preširok audit koji izlaže tajne, nedovoljna retencija i privilegije koje omogućavaju istoj osobi da proizvede i ukloni trag. Zbog toga se logging projektuje kao usluga sa SLO-om, kapacitetom, bezbednošću, kontrolom integriteta, testiranim oporavkom i jasnim vlasništvom.

Odgovoran administrator ne menja stanje da bi „video da li će proraditi”. On najpre očuva početni snimak, postavlja proverljivu hipotezu, bira najmanje invazivnu proveru, potvrđuje uzrok iz više nezavisnih izvora i tek tada izvodi kontrolisanu korekciju. Incident je završen kada je usluga stabilna, dokaz oporavka dokumentovan, auditovana promena razumljiva i trajna mera smanjuje verovatnoću ponavljanja.

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