Vanilla Kubernetes

Treći deo: Produkcione operacije, otpornost i enterprise integracije
Dodatak 5. Vanilla Kubernetes game day – kvar čvora, degradacija servisa i oporavak
XII. Laboratorijsko okruženje i integrisani projekti
Dodatak 5. Game day – kvar čvora, degradacija servisa, oporavak, dokazi i retrospektiva

Game day je vremenski ograničena, unapred odobrena i posmatrana vežba u kojoj tim namerno uvodi kontrolisan poremećaj da bi proverio pretpostavke o otpornosti sistema, spremnost ljudi, kvalitet procedura i pouzdanost dokaza. Cilj nije demonstracija dramatičnog kvara niti takmičenje u brzini, već bezbedno učenje: da li monitoring prepoznaje problem, da li se uticaj pravilno procenjuje, da li se uzrok lokalizuje bez nasumičnih intervencija, da li oporavak vraća stvarnu funkcionalnost i da li tim može da objasni šta se dogodilo.

Laboratorija nadograđuje klaster iz prethodnih dodataka: jedan control plane čvor k8s-cp01, dva worker čvora k8s-w01 i k8s-w02, administratorsku stanicu admin01, containerd i funkcionalan CNI. Izvode se dva glavna eksperimenta. Prvi simulira neočekivanu nedostupnost jednog worker čvora. Drugi degradira aplikacioni servis tako što jedna replika postaje nespremna, ali ostaje pokrenuta. Time se jasno razdvajaju infrastrukturni kvar, Node kontrola, raspoređivanje, readiness signal, EndpointSlice stanje i korisnički rezultat.

Referentni baseline prati Kubernetes 1.35 iz Dodatka 4, ali se vežba ne vezuje za proizvoljnu oznaku latest. Pre izvođenja proveravaju se tačna patch verzija klastera, verzija klijenta, CNI i runtime-a, kao i dokumentacija koja pripada instaliranoj minor grani. Komande u ovoj lekciji koriste stabilne Kubernetes objekte i standardne kubectl postupke, ali stvarne podrazumevane pragove Node kontrolera i eviction ponašanje treba očitati iz konkretne konfiguracije control plane-a, a ne pretpostaviti.

1. Ishodi učenja i granice eksperimenta

Po završetku game day-a polaznik treba da ume da izmeri početno stanje, definiše hipotezu i blast radius, razlikuje dobrovoljnu od nedobrovoljne disrupcije, prepozna posledice gubitka čvora, pronađe promenu u Node Lease-u i uslovima čvora, prati ponovno raspoređivanje podova, protumači readiness i EndpointSlice stanje, vrati sistem u poznato dobro stanje i izradi retrospektivu bez okrivljavanja pojedinca.

GranicaDozvoljeno u vežbiNije dozvoljeno
OkruženjeIzolovan laboratorijski klaster bez produkcionih korisnika i podatakaIzvođenje na produkciji bez zasebnog dizajna, odobrenja i change procesa
ČvorZaustavljanje samo k8s-w02 ili njegove VM nakon potvrđenog baseline-aGašenje k8s-cp01, oba worker-a ili ESXi hosta u ovoj vežbi
AplikacijaPromena ConfigMap-a kontrolisane aplikacije game-day/webIzmena CNI-ja, kube-proxy pravila, sertifikata ili stvarnih tajni
PodaciStateless demo workload i privremeni dijagnostički podoviTest gubitka persistent volume-a bez zasebnog backup/restore scenarija
IntervencijaJedna promena u jednom trenutku, sa vremenom i vlasnikomNasumičan restart više komponenti, brisanje podova bez dokaza ili korišćenje --force radi ubrzanja

Stop kriterijumi: facilitator odmah prekida eksperiment ako Kubernetes API postane nedostupan, ako drugi worker pređe u NotReady, ako se pojavi gubitak trajnih podataka, ako se više ne može pristupiti VM konzoli, ako opterećenje napusti laboratorijski opseg ili ako tim ne može pouzdano da utvrdi poslednju izvršenu promenu. Prekid nije neuspeh vežbe; to je dokaz da je bezbednosna granica funkcionisala.

2. Referentna topologija i promenljive

UlogaHostnameNode IPResursiOperativna uloga u vežbi
Control planek8s-cp01192.168.50.114 vCPU, 8 GB RAM, 80 GBAPI, scheduler, controller manager i lokalni etcd; ne uvodi se kvar
Worker 1k8s-w01192.168.50.214 vCPU, 8 GB RAM, 100 GBPreživeli čvor i cilj ponovnog raspoređivanja
Worker 2k8s-w02192.168.50.224 vCPU, 8 GB RAM, 100 GBČvor na kome se izaziva kontrolisani prekid
Administratorska stanicaadmin01192.168.50.10Linux, kubectl, curl, SSHKomandni, dokazni i vremenski zapis
Node mrežaVMware port group192.168.50.0/24MTU prema baseline-uSSH, API i Node saobraćaj
Pod / Service mrežaCNI / Kubernetes10.244.0.0/16 / 10.96.0.0/12Bez preklapanjaPod komunikacija i ClusterIP
PromenljivaReferentna vrednostPravilo
TARGET_NODEk8s-w02Jedini čvor na kome se uvodi kvar
SURVIVING_NODEk8s-w01Mora ostati zdrav i imati dovoljan allocatable kapacitet
LAB_NAMESPACEgame-daySvi aplikacioni resursi vežbe nalaze se ovde
APP_NAMEwebDeployment, Service i PDB koriste iste labels
EVIDENCE_DIRgame-day-evidence-YYYYMMDD-HHMMSSNe sadrži kubeconfig, tokene, Secrets ni privatne ključeve
OBSERVATION_WINDOW15 minuta po scenarijuNije timeout produkcionog incidenta; facilitator ga prilagođava laboratoriji

Ako se shell promenljive koriste radi pogodnosti, važe samo u tekućoj sesiji. Na admin01, običnim korisnikom sa ispravnim kubeconfig-om, sledeće komande samo postavljaju lokalne vrednosti i odmah ih proveravaju. Ne koriste se za destruktivne petlje.

export TARGET_NODE='k8s-w02'
export LAB_NAMESPACE='game-day'
printf 'TARGET_NODE=%s\nLAB_NAMESPACE=%s\n' "$TARGET_NODE" "$LAB_NAMESPACE"
test -n "$TARGET_NODE" && test -n "$LAB_NAMESPACE"

3. Mapa game day laboratorije

FazaMestoPromenaDokaz uspeha
1. Odobrenje i ulogeTimDefinišu se obim, vreme, stop kriterijumi i komunikacijaPopunjen game day brief
2. Baselineadmin01 i sva tri čvoraNema promene; prikuplja se početno stanjeAPI, čvorovi, sistemski podovi, DNS i runtime zdravi
3. Workloadadmin01Kreiraju se namespace, Deployment, Service i PDBTri spremne replike, endpoint-i i HTTP odgovor
4. Kvar čvorak8s-w02 ili vCenterZaustavlja se kubelet ili VMNode heartbeat zastaje; uticaj je ograničen
5. Dijagnostikaadmin01, k8s-w02, vCenterRead-only korelacija slojevaPotvrđena hipoteza i vremenska linija
6. Oporavak čvorak8s-w02 i admin01Vraća se VM/kubelet i schedulingReady, sve replike spremne, nema kritičnih događaja
7. Degradacija servisaadmin01Jedna replika postaje NotReadyEndpointSlice uklanja nespreman backend; Service ostaje funkcionalan
8. Oporavak aplikacijeadmin01Vraća se ispravna konfiguracijaTri endpoint-a i stabilan funkcionalni test
9. RetrospektivaTimNema promene klasteraČinjenice, nalazi, vlasnici i rokovi akcija

4. Uloge, komunikacija i game day brief

Polje brief-aPrimer
Hipoteza 1Gubitak jednog worker-a ne prekida dostupnost troreplikatnog stateless servisa duže od dogovorenog laboratorijskog prozora
Hipoteza 2Readiness kvar uklanja neispravnu repliku iz Service endpoint-a bez nepotrebnog restartovanja kontejnera
Blast radiusSamo namespace game-day i worker k8s-w02
Početak/krajUTC timestamp i maksimalno trajanje
RollbackStart kubelet/VM, uncordon po potrebi, povratak ConfigMap-a i rollout status
Komunikacioni kanalJedan dogovoreni kanal i jedna vremenska linija
Stop autoritetFacilitator i bilo koji član koji uoči izlazak iz blast radius-a

5. Faza baseline-a – dokaz poznatog dobrog stanja

Mesto: admin01; običan korisnik sa odobrenim kubeconfig-om. Vrsta: read-only. Cilj je da se pre fault injection-a dokaže zdravlje upravljačke ravni, čvorova i mreže. Ako baseline nije uspešan, game day se ne pokreće: postojeći kvar ne sme postati deo eksperimenta bez jasne oznake.

kubectl version
kubectl cluster-info
kubectl get nodes -o wide
kubectl get --raw='/readyz?verbose'
kubectl get pods -n kube-system -o wide
kubectl get events -A --sort-by='.metadata.creationTimestamp'

Očekuje se odziv API-ja, uspešan readyz, sva tri Node objekta u stanju Ready i sistemski podovi bez nerešenih CrashLoopBackOff, ImagePullBackOff ili dugotrajnog Pending stanja. Upozorenje u Events nije automatski aktivna greška: proveravaju se vreme, broj ponavljanja, pogođeni objekat i da li se događaj i dalje ponavlja.

Mesto: svaki Kubernetes čvor pojedinačno; korisnik labadmin sa sudo. Sledeće provere su read-only i potvrđuju servise, vreme, disk i mrežni identitet.

sudo systemctl is-active kubelet containerd
timedatectl show -p NTPSynchronized
df -h /
ip -br address
ip route
sudo journalctl -u kubelet --since '-15 min' --no-pager | tail -n 80

Preživeli worker mora imati dovoljno CPU-a, memorije i dozvoljenih scheduling uslova za zamenske podove. Sa admin01 proveriti allocatable resurse, zahteve i postojeće taint vrednosti:

kubectl describe node k8s-w01
kubectl describe node k8s-w02
kubectl get pods -A -o custom-columns='NS:.metadata.namespace,POD:.metadata.name,NODE:.spec.nodeName,CPU:.spec.containers[*].resources.requests.cpu,MEM:.spec.containers[*].resources.requests.memory'

Kontrolna tačka: API je spreman, CoreDNS i CNI su zdravi, oba worker-a su Ready, nema pressure uslova, runtime i kubelet rade, vreme je sinhronizovano, disk nije pri kritičnom pragu i k8s-w01 ima kapacitet za tri demo replike. U suprotnom zabeležiti nalaz i odložiti vežbu.

6. Priprema dokaznog paketa

Mesto: admin01; običan korisnik. Kreiranje lokalnog direktorijuma menja samo administratorsku stanicu. U dokazni paket ne smeju ući ~/.kube/config, Secret sadržaj, bootstrap tokeni, privatni ključevi ni nefiltrirani environment podaci.

EVIDENCE_DIR="game-day-evidence-$(date -u +%Y%m%d-%H%M%S)"
test -n "$EVIDENCE_DIR" || exit 1
mkdir -m 0700 -- "$EVIDENCE_DIR"
printf '%s\n' "$EVIDENCE_DIR"

date -u +%FT%TZ | tee "$EVIDENCE_DIR/00-start-utc.txt"
kubectl get nodes -o wide > "$EVIDENCE_DIR/01-nodes-before.txt"
kubectl get pods -A -o wide > "$EVIDENCE_DIR/02-pods-before.txt"
kubectl get events -A --sort-by='.metadata.creationTimestamp' > "$EVIDENCE_DIR/03-events-before.txt"
kubectl version -o yaml > "$EVIDENCE_DIR/04-kubectl-version.yaml"

Datoteke predstavljaju snimak, ne kompletnu observability platformu. Za realnu organizaciju koriste se centralni monitoring, logovi, audit i vremenski usklađeni dashboard-i sa pravilima retention-a. Game day zapis mora navesti vremensku zonu; UTC olakšava korelaciju između Kubernetes, systemd, vCenter i aplikacionih zapisa.

7. Postavljanje otpornog probnog workload-a

Mesto: admin01; korisnik sa pravom kreiranja resursa u laboratorijskom namespace-u. Vrsta: state-changing, ali ograničena na game-day. Manifest kreira tri replike, anti-affinity preferencu, requests, readiness/liveness probe, Service i PDB. Preferirana anti-affinity nije garancija raspodele; zato se stvarni položaj podova proverava pre kvara.

apiVersion: v1
kind: Namespace
metadata:
  name: game-day
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: game-day
spec:
  replicas: 3
  strategy:
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                topologyKey: kubernetes.io/hostname
                labelSelector:
                  matchLabels:
                    app: web
      containers:
        - name: web
          image: registry.k8s.io/e2e-test-images/agnhost:2.53
          args: ["netexec", "--http-port=8080"]
          ports:
            - name: http
              containerPort: 8080
          resources:
            requests:
              cpu: 25m
              memory: 32Mi
            limits:
              cpu: 200m
              memory: 128Mi
          readinessProbe:
            httpGet:
              path: /healthz
              port: http
            periodSeconds: 3
            failureThreshold: 2
          livenessProbe:
            httpGet:
              path: /healthz
              port: http
            periodSeconds: 10
            failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: game-day
spec:
  selector:
    app: web
  ports:
    - name: http
      port: 80
      targetPort: http
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web
  namespace: game-day
spec:
  minAvailable: 2
  unhealthyPodEvictionPolicy: AlwaysAllow
  selector:
    matchLabels:
      app: web

Pre primene manifest sačuvati kao game-day.yaml, pregledati, verzionisati i izvršiti server-side proveru. Referencu slike i digest, kada organizacija zahteva reproducibilnost, potvrditi u odobrenom registru; ako instalirana Kubernetes grana koristi drugačiju verziju test slike, promena mora biti dokumentovana.

kubectl apply --server-side --dry-run=server -f game-day.yaml
kubectl apply -f game-day.yaml
kubectl rollout status deployment/web -n game-day --timeout=180s
kubectl get pods -n game-day -o wide
kubectl get pdb -n game-day
kubectl get endpointslice -n game-day -l kubernetes.io/service-name=web -o wide

PDB štiti od dobrovoljnih evikcija pokrenutih Eviction API-jem, kao što je standardni kubectl drain. Ne može sprečiti nestanak VM, kvar diska, mrežnu particiju ili drugu nedobrovoljnu disrupciju; takav kvar se uračunava u dostupni budžet. PDB takođe nije mehanizam koji ograničava Deployment rolling update. Polje unhealthyPodEvictionPolicy: AlwaysAllow sprečava da trajno nespreman pod nepotrebno blokira administrativni drain, ali ne zamenjuje analizu uzroka nespremnosti.

Funkcionalni test iz privremenog Pod-a dokazuje DNS, Service i aplikacioni odgovor. Komanda menja stanje samo kreiranjem kratkotrajnog Pod-a koji se posle završetka uklanja.

kubectl run service-check -n game-day --rm -i --restart=Never \
      --image=busybox:1.36.1 \
  -- /bin/sh -c 'for i in 1 2 3 4 5; do wget -qO- http://web/hostname; echo; done'

Kontrolna tačka: Deployment ima 3/3 dostupne replike; bar jedna replika je na k8s-w02; EndpointSlice sadrži tri spremne adrese; PDB prikazuje dozvoljenu disrupciju u skladu sa trenutnim zdravljem; pet zahteva uspeva. Ako scheduler smesti sve replike na jedan worker zbog kapaciteta ili ograničenja, ne nastavljati dok se topologija i resursi ne isprave.

8. Kontrolni eksperiment – cordon, drain i uncordon

Pre neočekivanog kvara korisno je dokazati kako izgleda planirana disrupcija. cordon sprečava novo raspoređivanje, ali ne uklanja postojeće podove. drain koristi bezbedne evikcije, poštuje PDB i grace period; DaemonSet podovi ostaju i zato je potreban --ignore-daemonsets. Mesto: admin01. Vrsta: state-changing. Ne koristi se --disable-eviction, jer bi zaobišao PDB, niti --force bez prethodne analize unmanaged podova.

kubectl cordon k8s-w02
kubectl get node k8s-w02
kubectl drain k8s-w02 --ignore-daemonsets --timeout=180s
kubectl get pods -n game-day -o wide
kubectl get pdb -n game-day
kubectl uncordon k8s-w02
kubectl get node k8s-w02

Ako drain blokira PDB, ne povećavati silom dozvoljeni prekid. Proveriti broj zdravih replika, kapacitet drugog čvora, readiness probe, tačan selector PDB-a i unmanaged/emptyDir podove. Opcija --delete-emptydir-data prihvata gubitak lokalnih ephemeral podataka i koristi se samo kada je taj rizik eksplicitno odobren. Uspešan drain znači da su odgovarajući workload podovi bezbedno eviktovani; ne znači da je aplikacija funkcionalno proverena.

9. Scenario A – neočekivani kvar worker čvora

Scenario ima dve varijante. Varijanta A1, za početnu vežbu, zaustavlja samo kubelet i ostavlja SSH dostupan; lakša je za oporavak i omogućava lokalne dokaze. Varijanta A2 gasi VM i realističnije prikazuje potpuni gubitak čvora, ali zahteva potvrđen pristup vCenter-u ili hipervizorskoj konzoli. Izvodi se samo jedna varijanta po prolazu.

9.1. Poslednja provera pre fault injection-a

Mesto: admin01; read-only. Scribe beleži vreme i položaj podova. Facilitator potvrđuje da je k8s-w02 schedulable posle kontrolnog drain-a i da je najmanje jedna replika na njemu.

date -u +%FT%TZ
kubectl get node k8s-w02
kubectl get pods -n game-day -o wide
kubectl get lease -n kube-node-lease k8s-w02 -o yaml
kubectl get endpointslice -n game-day -l kubernetes.io/service-name=web -o yaml

9.2. Varijanta A1 – zaustavljanje kubelet-a

Mesto: samo k8s-w02; labadmin sa sudo. Vrsta: state-changing i reverzibilna. Containerd može nastaviti da drži postojeće kontejnere aktivnim, ali čvor prestaje da šalje kubelet heartbeat i ne izvršava nove PodSpec odluke.

date -u +%FT%TZ
sudo systemctl stop kubelet
sudo systemctl is-active kubelet

Očekivani izlaz poslednje komande je inactive. Ako se zaustavi containerd ili izgubi SSH, scenario više nije A1; primenjuje se stop kriterijum i prelazi na konzolu, bez dodatnog improvizovanog kvara.

9.3. Varijanta A2 – gašenje VM

Mesto: vCenter ili drugi odobreni VMware alat; ovlašćeni operator. Najpre se potvrđuje tačan VM identitet k8s-w02. Guest shutdown je uredno gašenje, dok power-off više liči na nagli kvar, ali nosi veći rizik po lokalni filesystem. Za ovu vežbu prednost ima uredan shutdown, osim kada je zasebno odobreno testiranje naglog prekida. Ne vraća se stari VM snapshot kao način oporavka Node-a.

10. Posmatranje, trijaža i potvrda uzroka

Mesto: admin01; read-only. Ne očekuje se da Node odmah postane NotReady. Kubelet heartbeat i Lease prestaju, zatim Node kontroler nakon svojih pragova menja uslov i dodaje odgovarajuće taint vrednosti. Pod evikcije takođe nisu trenutne. Podrazumevane vrednosti postoje u upstream dokumentaciji, ali rezultat se meri u ovom klasteru i povezuje sa stvarnom konfiguracijom controller manager-a.

kubectl get nodes -w

U drugom terminalu pratiti podove i endpoint-e:

kubectl get pods -n game-day -o wide -w

U trećem terminalu, bez beskonačnog čuvanja izlaza, periodično prikupiti sledeće dokaze:

date -u +%FT%TZ
kubectl get node k8s-w02 -o yaml
kubectl get lease -n kube-node-lease k8s-w02 -o yaml
kubectl describe node k8s-w02
kubectl get pods -n game-day -o wide
kubectl get endpointslice -n game-day -l kubernetes.io/service-name=web -o yaml
kubectl get events -n game-day --sort-by='.metadata.creationTimestamp'

Dokazi se tumače po slojevima. Zastareo renewTime Lease-a potvrđuje prestanak heartbeat-a. Ready: Unknown ili False i taint node.kubernetes.io/unreachable ili node.kubernetes.io/not-ready pokazuju reakciju control plane-a. Pod koji je još prikazan kao Running na nedostupnom Node-u nije dokaz da stvarno uslužuje zahteve: API stanje može biti zastarelo. Service dostupnost se dokazuje zahtevom, EndpointSlice stanjem i, kada postoji, metrikama uspešnosti i latencije.

10.1. Funkcionalni test tokom kvara

kubectl run outage-check -n game-day --rm -i --restart=Never \
  --image=busybox:1.36.1 \
  -- /bin/sh -c 'n=0; while [ "$n" -lt 20 ]; do date -u +%FT%TZ; wget -T 2 -qO- http://web/hostname || echo REQUEST_FAILED; n=$((n+1)); sleep 1; done'

Rezultat se beleži kao broj uspešnih i neuspešnih zahteva i najveća primećena pauza, ne samo kao „radi/ne radi”. Troreplikatni stateless workload na dva worker-a može ostati dostupan, ali to nije garantovano ako su sve replike bile na pogođenom Node-u, ako preživeli čvor nema kapacitet, ako topology/affinity pravila onemogućavaju raspoređivanje ili ako sama aplikacija zavisi od node-local stanja.

10.2. Lokalni dokazi za A1

Mesto: k8s-w02; labadmin sa sudo; read-only. Birati vremenski prozor koji počinje nekoliko minuta pre fault injection-a.

sudo systemctl status kubelet --no-pager
sudo journalctl -u kubelet --since '-20 min' --no-pager
sudo systemctl status containerd --no-pager
sudo crictl ps -a
ip -br address
ip route
df -h / /var/lib/containerd /var/lib/kubelet

Za A2 se lokalni podaci možda ne mogu prikupiti dok se VM ne vrati. Tada vCenter stanje, VM događaji, konzola, datastore i mrežni podaci postaju primarni infrastrukturni dokazi. Nedostupan SSH sam po sebi ne dokazuje kvar kubelet-a; uzrok može biti VM power state, guest mreža, firewall, DNS ili host infrastruktura.

11. Oporavak worker čvora

Oporavak počinje tek kada su zabeleženi simptom, obim, poslednja promena, hipoteza i dokazi koji potvrđuju uzrok. Za A1, na k8s-w02 se vraća samo kubelet. Za A2 se VM uključuje i čeka se operativni sistem; ne izvodi se kubeadm reset niti ponovni kubeadm join nad postojećim članom bez dokaza da je identitet čvora nepovratno izgubljen.

A1 – mesto: k8s-w02; sudo; state-changing.

sudo systemctl start kubelet
sudo systemctl is-active kubelet
sudo journalctl -u kubelet --since '-5 min' --no-pager

Ako je čvor ostao cordon-ovan iz ranije faze, tek nakon stabilnog Ready stanja i provere lokalnih servisa vratiti scheduling sa admin01:

kubectl get node k8s-w02
kubectl uncordon k8s-w02
kubectl get nodes
kubectl get pods -n game-day -o wide
kubectl rollout status deployment/web -n game-day --timeout=180s
kubectl get endpointslice -n game-day -l kubernetes.io/service-name=web -o wide

Vraćanje Node-a u Ready ne vraća automatski prethodni raspored podova i ne treba ručno „balansirati” klaster brisanjem zdravih podova bez potrebe. Scheduler reaguje na nove zahteve; postojeći zdravi podovi ostaju gde jesu. Ako je cilj ponovna raspodela, koristi se kontrolisan rollout ili alat/politika predviđena za to, uz proveru dostupnosti.

Kriterijum oporavka: Node je stabilno Ready; Lease se obnavlja; kubelet i containerd su aktivni; Deployment ima 3/3 dostupne replike; EndpointSlice ima očekivane spremne adrese; CoreDNS i CNI pod na vraćenom čvoru su zdravi; funkcionalni test nema greške; nema novih nerešenih warning događaja. Tek tada se scenario zatvara.

12. Scenario B – kontrolisana degradacija servisa

Cilj drugog scenarija je da se pokaže razlika između procesa koji radi i instance koja je spremna da prima saobraćaj. Readiness neuspeh uklanja Pod iz Service backend-a, ali kubelet zbog toga ne restartuje kontejner. Liveness neuspeh može izazvati restart i zato se ne zloupotrebljava za zavisnosti ili prolazno opterećenje: pogrešna liveness provera može proizvesti kaskadni kvar.

Pošto referentna slika daje isti /healthz odgovor za sve replike, najbezbednija vežba degradacije koristi privremenu promenu readiness putanje u novom Deployment rollout-u. To utiče na sve nove Podove i zato se rollout strategija i PDB posmatraju. Blast radius ostaje namespace game-day. Pre promene izvesti aktivni Deployment kao dokaz, ali ga ne koristiti kao jedini izvor istine umesto verzionisanog manifesta.

kubectl get deployment web -n game-day -o yaml > "$EVIDENCE_DIR/20-web-before-degradation.yaml"
kubectl patch deployment web -n game-day --type='json' \
  -p='[{"op":"replace","path":"/spec/template/spec/containers/0/readinessProbe/httpGet/path","value":"/not-ready"}]'
kubectl rollout status deployment/web -n game-day --timeout=60s || true
kubectl get pods -n game-day -o wide
kubectl get endpointslice -n game-day -l kubernetes.io/service-name=web -o yaml
kubectl describe deployment web -n game-day
kubectl get events -n game-day --sort-by='.metadata.creationTimestamp'

|| true se ovde koristi samo da očekivani timeout ne prekine laboratorijski niz provera; ne znači da se greška ignoriše. Očekuje se da novi Pod ostane Running, ali 0/1 Ready, dok stari spremni podovi ostaju zbog rolling update pravila. Deployment ne završava rollout, a Service treba da zadrži samo spremne endpoint-e. Ako nema nijednog endpoint-a ili korisnički test potpuno otkaže, aktivira se stop kriterijum i odmah se prelazi na rollback.

kubectl run degraded-check -n game-day --rm -i --restart=Never \
  --image=busybox:1.36.1 \
  -- /bin/sh -c 'for i in 1 2 3 4 5 6 7 8 9 10; do wget -T 2 -qO- http://web/hostname || echo REQUEST_FAILED; done'

12.1. Dijagnostički tok

  1. Simptom: rollout ne završava, novi Pod je Running ali nije spreman.
  2. Obim: samo novi ReplicaSet u namespace-u game-day; Node i sistemski podovi ostaju zdravi.
  3. Dokaz: kubectl describe pod prikazuje readiness probe failure; EndpointSlice ne označava taj Pod kao spreman backend.
  4. Neposredni uzrok: readiness HTTP putanja /not-ready vraća neuspeh.
  5. Osnovni uzrok: kontrolisana promena Pod template-a bez odgovarajućeg health endpoint-a.
  6. Posledica: smanjen broj kapaciteta i zaglavljen rollout, ali Service nastavlja da koristi spremne replike.
  7. Korekcija: povratak verzionisanog manifesta ili rollout undo na prethodnu reviziju.

Za konkretan nespreman Pod, sa admin01 izvršiti read-only proveru:

kubectl get pods -n game-day
kubectl describe pod -n game-day <NAZIV_NESPREMNOG_PODA>
kubectl logs -n game-day <NAZIV_NESPREMNOG_PODA> --since=10m
kubectl get rs -n game-day
kubectl rollout history deployment/web -n game-day

Zamenska vrednost se najpre kopira iz kubectl get pods; ne izvršava se doslovno. U HTML prikazu je znak < escapovan. Nije opravdano restartovati kubelet, CNI ili ceo čvor, jer su dokazi lokalizovali problem u Pod template-u.

13. Rollback degradacije i puna validacija

Mesto: admin01; state-changing. Preferirani rollback je ponovna primena ispravnog, pregledanog i verzionisanog game-day.yaml. rollout undo je dozvoljena laboratorijska alternativa kada je prethodna revizija jasno identifikovana.

kubectl apply -f game-day.yaml
kubectl rollout status deployment/web -n game-day --timeout=180s
kubectl get deployment,replicaset,pods,service,pdb -n game-day -o wide
kubectl get endpointslice -n game-day -l kubernetes.io/service-name=web -o yaml
kubectl get events -n game-day --sort-by='.metadata.creationTimestamp'

Zatim ponoviti funkcionalni test i sačuvati završne dokaze:

kubectl run recovery-check -n game-day --rm -i --restart=Never \
  --image=busybox:1.36.1 \
  -- /bin/sh -c 'for i in 1 2 3 4 5 6 7 8 9 10; do wget -T 2 -qO- http://web/hostname || exit 1; done'

date -u +%FT%TZ | tee "$EVIDENCE_DIR/90-end-utc.txt"
kubectl get nodes -o wide > "$EVIDENCE_DIR/91-nodes-after.txt"
kubectl get pods -A -o wide > "$EVIDENCE_DIR/92-pods-after.txt"
kubectl get events -A --sort-by='.metadata.creationTimestamp' > "$EVIDENCE_DIR/93-events-after.txt"
kubectl get all,pdb,endpointslice -n game-day -o yaml > "$EVIDENCE_DIR/94-game-day-after.yaml"

Komanda kubectl get all ne obuhvata sve vrste resursa; zato su PDB i EndpointSlice izričito navedeni. Dokazni YAML može sadržati interne IP adrese i metapodatke, pa se pre deljenja klasifikuje i sanitizuje. Hash paketa dokaza omogućava proveru naknadne izmene, ali ne dokazuje istinitost prvobitno prikupljenih podataka.

tar -czf "${EVIDENCE_DIR}.tar.gz" -- "$EVIDENCE_DIR"
sha256sum "${EVIDENCE_DIR}.tar.gz" > "${EVIDENCE_DIR}.tar.gz.sha256"

14. Matrica simptoma i dijagnostičkih grana

SimptomPrvi dokazVerovatna granaNe raditi automatski
Node je NotReady ili UnknownNode conditions, Lease, kubelet journal, VM power stateKubelet, OS, mreža, runtime ili hipervizorkubeadm reset i ponovni join
Pod je PendingPod Events i scheduler porukeNedovoljan kapacitet, affinity, taint, PVCRestart containerd-a pre odluke schedulera
Pod je Running, 0/1 ReadyProbe Events, opis Pod-a, endpoint conditionReadiness konfiguracija ili aplikaciona zavisnostBrisanje svih podova ili Node restart
Service nema endpoint-eSelector, labels, EndpointSlice, readinessPogrešna oznaka ili sve replike nespremneNasumična izmena CNI/firewall pravila
Endpoint-i postoje, HTTP ne radiDirektan Pod test, port/targetPort, NetworkPolicy, proxy slojAplikacija, Service mapiranje ili transportZaključak da je DNS uzrok bez DNS testa
API je nedostupancluster-info, readyz, control plane VM i static Pod logoviControl plane/etcd/mreža; stop kriterijumNastavak fault injection-a

15. RTO, RPO, SLI i dokaz oporavka

Game day ne treba proglasiti uspešnim samo zato što su podovi ponovo zeleni. Unapred se definiše šta se meri. Za stateless demo servis RPO je praktično nula jer nema poslovnih podataka, ali to ne govori ništa o stvarnom StatefulSet-u ili bazi. RTO se meri od dogovorenog početka korisničkog uticaja do potvrđenog povratka funkcionalnog SLI-ja, ne do trenutka kada je operator izvršio poslednju komandu.

MeraPočetakKrajDokaz
Vreme detekcijeFault injectionPrvi tačan signal/alertUTC vremenska linija i monitoring događaj
Vreme trijažePrvi signalPotvrđena komponenta i blast radiusHipoteza potkrepljena Lease/Node/probe dokazom
Vreme oporavkaPočetak uticajaStabilan funkcionalni testNiz uspešnih zahteva i zdravi backend-i
Greške zahtevaTokom scenarijaKraj observation prozoraBroj REQUEST_FAILED i ukupnih zahteva
KapacitetPre kvaraTokom degradacijeBroj Ready replika i EndpointSlice adresa
RPOPoslednji pouzdan podatakPotvrđeno vraćeno stanjeZa stateful sistem: aplikaciona konzistentnost i probni restore

16. Retrospektiva bez okrivljavanja

Retrospektiva se održava dok su činjenice sveže, ali tek nakon stabilizacije. Usmerena je na sistem, interfejse, procedure i pretpostavke, a ne na pronalaženje krivca. Ljudska odluka se analizira u kontekstu informacija, ovlašćenja, pritiska i alata koji su bili dostupni u tom trenutku. Svaki zaključak mora razlikovati činjenicu, pretpostavku i naknadnu interpretaciju.

CelinaPitanjaObavezni izlaz
OčekivanjeŠta smo mislili da će se dogoditi i zašto?Početna hipoteza i izvor pretpostavke
ČinjeniceŠta se zaista dogodilo, kojim redosledom?UTC timeline sa dokazima
DetekcijaKoji signal je prvi bio koristan, a koji bučan ili odsutan?Promena alerta/dashboard-a ili potvrda da nije potrebna
OdgovorKoja odluka je pomogla, šta je usporilo trijažu?Izmena runbook-a, pristupa ili uloga
OtpornostDa li su PDB, replike, requests i probes radili kako je zamišljeno?Tehnička akcija sa vlasnikom i kriterijumom prihvatanja
DokaziŠta nismo mogli da rekonstruišemo?Logging/audit/retention poboljšanje
RizikDa li se blast radius zadržao i da li su stop kriterijumi bili dovoljni?Ažurirana sigurnosna granica naredne vežbe

Akcija bez vlasnika, roka, prioriteta i proverljivog kriterijuma nije zatvorena akcija. Primer dobre formulacije je: „Platform tim do 15. avgusta dodaje alert za zastareo Node Lease; prihvatanje: u ponovljenoj A1 vežbi alert nastaje u odobrenom pragu i sadrži naziv čvora i link ka runbook-u.” Formulacija „poboljšati monitoring” nije merljiva.

17. Očuvanje ili uklanjanje laboratorijskih resursa

Mogućnost A – očuvanje klastera i workload-a

Klaster se može sačuvati kao poznato dobro okruženje za ponavljanje game day-a. Zadržavaju se verzionisani manifest, brief, sanitizovani dokazni paket, retrospektiva i otvorene akcije. Proverava se da nijedan Node nije ostao cordon-ovan, da nema privremenih taint vrednosti, zaglavljenog rollout-a ili dijagnostičkog Pod-a i da svi resursi imaju vlasnika.

kubectl get nodes
kubectl get deployment,pods,service,pdb -n game-day -o wide
kubectl rollout status deployment/web -n game-day --timeout=180s
kubectl get events -n game-day --sort-by='.metadata.creationTimestamp'

Mogućnost B – uklanjanje samo resursa vežbe

State-changing postupak. Sa admin01 se briše samo namespace game-day. Ovo uklanja namespaced workload, Service, PDB i povezane Podove; ne resetuje klaster i ne uklanja dokazni paket sa administratorske stanice.

kubectl delete namespace game-day
kubectl get namespace game-day

Ako namespace ostane u stanju Terminating, finalizer se ne uklanja naslepo. Identifikuje se resurs ili API servis koji sprečava završetak. Potpuni kubeadm reset nije deo ovog game day-a: kvar čvora i aplikaciona degradacija moraju se oporaviti bez rušenja poznato dobrog klastera.

Administratorske prakse

Završna kontrolna tačka

Zaključak

Otpornost Kubernetes sistema ne nastaje samim brojem replika. Ona zavisi od raspodele podova, realnog kapaciteta preživelih čvorova, kvalitetnih health signala, odgovarajućih disruption budžeta, mreže i skladišta, ali i od sposobnosti tima da brzo razlikuje simptom od uzroka. Game day pretvara te pretpostavke u proverljive tvrdnje. Ako čvor nestane, administrator mora znati šta Node kontroler zaista vidi, kada API stanje može biti zastarelo i kako se korisnički uticaj meri. Ako pod radi ali nije spreman, mora razumeti zašto Service menja skup backend-a bez restartovanja kontejnera.

Najvažnija veština nije izvršenje fault injection komande, već disciplina oko nje: odobren blast radius, poznato dobro početno stanje, jedna promena u jednom trenutku, jasni stop kriterijumi, očuvanje dokaza, hipoteza pre korekcije i puna validacija posle oporavka. Nasumični restart može privremeno ukloniti simptom, ali istovremeno uništiti podatke potrebne da se spreči ponavljanje. Odgovoran operator bira najmanju korekciju koja odgovara potvrđenom uzroku.

Ova laboratorija namerno ostaje u granicama stateless workload-a i jednog worker kvara. Produkcioni game day zahteva dodatne scenarije za HA control plane, etcd, CSI i podatke, DNS, ingress/load balancer, identitet, registrije, spoljne zavisnosti, zone otkaza, backup i probni restore. Svaki takav scenario mora imati sopstveni RPO/RTO, bezbednosnu procenu, vlasnike i povratni plan. Zrelost se ne meri veličinom izazvanog kvara, već količinom pouzdanog znanja i trajnih poboljšanja koja tim iz vežbe dobije.

← Dodatak 4 Povratak na sadržaj Zaključak →