Case study
Deployovanje klijentskog Node.js sajta uz GitLab CI/CD i Kubernetes za dva sata

Primer upotrebe
Web-design studio je isporucio novu klijentsku aplikaciju i bilo je potrebno brzo zavrsiti infrastrukturni deo: uzeti postojeci GitLab repozitorijum sa Node.js aplikacijom, izgraditi je komandom npm run build i uciniti je dostupnom kao zivi sajt na klijentskom domenu, uz CI/CD putanju spremnu za naredna izdanja.
Ulazni podaci
- izvorni kod u GitLab repozitorijumu
- Node.js aplikacija
- komanda za produkcioni build:
npm run build
Isporuceno
- funkcionalan sajt na klijentskom domenu
- GitLab pipeline koji gradi i objavljuje kontejnersku sliku aplikacije pri svakom relevantnom push-u
- deploy u Kubernetes pripremljen kroz ponovo upotrebljiv pristup zasnovan na Helm-u
- SSL izdat automatski tokom deploy-a
Kompletno resenje je isporuceno za oko dva sata.
Korak 1. Priprema aplikacije za isporuku u kontejneru
Prvi zadatak je bio da se aplikacija upakuje na predvidiv i ponovljiv nacin, tako da isti artefakt moze da se gradi u CI i deploy-uje u Kubernetes.
Pocetni radni Dockerfile je pripremljen direktno u istom repozitorijumu:
| |
Ovo vec koristi multi-stage build, sto je ispravan smer za produkcionu isporuku.
Zasto je multi-stage build vazan
Kod Node.js projekata, naivna single-stage slika cesto sadrzi:
- kompletan izvorni kod
- zavisnosti potrebne za build
- development zavisnosti
- cache package manager-a
- privremene fajlove nastale tokom build procesa
To funkcionise, ali unosi nepotrebnu tezinu u produkciju.
Sa multi-stage build pristupom, sav tezi posao se obavlja u builder fazi, dok runtime faza dobija samo potreban izlaz aplikacije. U ovom slucaju, u runtime-u je potreban samo izgradjeni direktorijum .output. To znaci:
- manje slike
- brzi push u registry
- brzi pull u Kubernetes
- manje zauzece prostora u container registry-ju
- manja povrsina napada u produkciji

Korak 2. Dorada Dockerfile-a za CI/CD upotrebu
Nakon prve radne verzije, Dockerfile je optimizovan radi predvidivijeg CI build procesa i boljeg koriscenja cache-a.
Finalni optimizovani Dockerfile
| |
Sta je unapredjeno
npm ciumestonpm install
Time build u CI postaje deterministickiji, jer se zavisnosti instaliraju striktno iz lock fajla.Sloj sa zavisnostima je odvojen pre kopiranja celog source tree-ja
Time se poboljsava ponovno koriscenje Docker slojeva. Kada developeri menjaju kod aplikacije, ali ne i zavisnosti, sloj sa instalacijom zavisnosti moze ostati u cache-u.Runtime faza ostaje minimalna
Finalni kontejner sadrzi samo produkcioni runtime i izgradjeni izlaz, bez kompletnog source tree-ja i bez build okruzenja.Cistija runtime komanda
Malo unapredjenje, ali korisno za citljivost i odrzavanje.
Praktican uticaj na velicinu
Glavna dobit nije dosla od male sintaksne dorade, vec od upotrebe multi-stage runtime slike umesto tipicne single-stage slike sa “svim ukljucenim”.
Za projekat ovog tipa, realno poredjenje izgleda ovako:
- naivna single-stage slika: ~420 MB
- finalna multi-stage runtime slika: ~130 MB
To je smanjenje od oko 290 MB po slici, odnosno otprilike 69% manje.
Zasto je to vazno na nedeljnom nivou
Ovaj tim tipicno push-uje nove verzije nekoliko puta po satu. Kada se uzme konzervativan primer:
- 3 push-a po satu
- 8 radnih sati dnevno
- 5 radnih dana nedeljno
To daje:
- 120 push-eva slika nedeljno
Uz 290 MB ustede po slici, nedeljna razlika iznosi:
- 120 × 290 MB = 34,800 MB
- priblizno 34.8 GB manje podataka o slikama
To je samo akumulacija na strani registry-ja pre ciscenja. Ako se garbage collection u registry-ju pokrece jednom nedeljno, ta razlika moze ostati zauzeta tokom celog perioda. Drugim recima, optimizacija koja na nivou jednog build-a izgleda mala, veoma brzo prerasta u desetine gigabajta ustede nedeljno.
Isto smanjenje pomaze i brzini deploy-a, jer svaki push u registry i svaki pull koji Kubernetes nodovi rade prenosi znatno manje podataka. Cak i na umerenoj mrezi, smanjenje od nekoliko stotina MB po izdanju postaje odmah primetno pri cestim isporukama.

Korak 3. Priprema GitLab pipeline-a
Kada je aplikacija spakovana u kontejner, sledeci korak je bio automatizacija provere build-a i objavljivanja slike u GitLab CI/CD.
Trazeni raspored stage-ova bio je:
U ovoj fazi projekta, pipeline je implementiran do build-a slike i push-a u registry.
Stage-ovi deploy i rollback su namerno ostavljeni za sledecu fazu, jer se sam deploy radio kroz Kubernetes + Helmwave.
Primer .gitlab-ci.yml
| |
Sta ovaj pipeline radi
- pokrece lint provere
- pokrece testove ako postoje
- gradi Docker sliku
- taguje je commit SHA vrednoscu
- push-uje je u GitLab container registry
- dodatno azurira
latesttag na glavnoj isporucnoj putanji
Time se dobija cist build artefakt spreman za deploy u Kubernetes.

Korak 4. Primer izlaza pipeline-a pri izvrsavanju
Ispod je reprezentativan primer izlaza pipeline-a za uspesno izvrsavanje kroz fazu build-and-push:
| |
Korak 5. Deploy u Kubernetes uz ponovo upotrebljiv Helm chart
Kada je slika vec objavljena u registry, deploy u Kubernetes bio je pravolinijski.
Umesto pisanja posebnog chart-a samo za ovaj projekat, za deploy je upotrebljen univerzalni Helm chart koji moze da se koristi za veliki broj web aplikacija. To je vazno u realnom radu sa klijentima, jer smanjuje rutinski posao i ubrzava pokretanje narednih projekata.
Zasto ovaj pristup dobro funkcionise
Za tipicnu Node.js web aplikaciju obicno je potrebno prilagoditi samo nekoliko vrednosti:
- image repository
- image tag
- service port
- ingress hostname
- broj replika
- environment variables po potrebi
Sve ostalo je vec standardizovano u chart-u.
Primer values fajla
| |
Sta je Kubernetes odradio automatski
Posto je klaster vec imao standardne komponente na mestu, vecina rutinskog posla nije zahtevala rucnu intervenciju:
- Kubernetes je povukao sliku iz registry-ja
- Ingress je izlozio aplikaciju na ciljanom hostname-u
- CertManager je zatrazio i izdao SSL sertifikat
- service je rutirao saobracaj do poda aplikacije
Vazan operativni detalj: DNS za domen je bio podesen pre pocetka deploy-a. To znaci da nije bilo cekanja na DNS propagaciju tokom implementacije, pa je zivi sajt bio online za svega nekoliko minuta nakon sto je Kubernetes release primenjen.

Rezultat
Studio je trazio jednostavan ishod: uzeti GitLab repozitorijum sa Node.js aplikacijom i dovesti ga do produkciono spremnog stanja sa zivim domenom i osnovom za CI/CD.
To je isporuceno kroz kratak i praktican niz koraka:
- pripremljen je produkcioni Dockerfile u istom repozitorijumu
- optimizovana je strategija izgradnje slike kroz multi-stage build
- postavljen je GitLab pipeline za lint, test, build i push u registry
- slika aplikacije je objavljena u container registry
- aplikacija je deploy-ovana u Kubernetes uz ponovo upotrebljiv Helm chart i Helmwave
- aplikacija je izlozena kroz Ingress uz automatski SSL preko CertManager-a
Krajnje isporuke
- zivi sajt na ciljnom domenu
- kontejnerizovan build aplikacije
- automatizovan build i push slike pri promenama u kodu
- ponovo upotrebljiva Kubernetes deploy konfiguracija
- automatski omogucen SSL
- skalabilna osnova za buducu automatizaciju deploy-a i rollback-a
Vreme isporuke
Ukupno vreme implementacije: oko dva sata.

Tu se vidi stvarna vrednost standardizovanog delivery stack-a: kada se Docker, GitLab CI/CD, Kubernetes, Helm, Ingress i CertManager koriste na ponovljiv nacin, cak i novi klijentski projekat moze vrlo brzo da predje put od repozitorijuma do zivog domena.