Home SOFTWAREPomoć i savetiArhitektura modernih web aplikacija – Deo 9: DevOps, CI/CD i observability

Arhitektura modernih web aplikacija – Deo 9: DevOps, CI/CD i observability

od itn
CI/CD i observability

Dobrodošli u deveti deo serijala na ITNetwork.rs! Do sada smo prošli kroz monolit i mikroservise, frontend, API-je, baze, serverless, performanse, i bezbednost. Danas ulazimo u srž modernog inženjeringaDevOps prakse, CI/CD pipeline-ove i observability. Naučićemo kako automatizovati sve od koda do produkcije, kako pratiti sistem u realnom vremenu, i kako reagovati pre nego što korisnik primeti problem.

Šta je DevOps?

„DevOps nije alat – to je kultura.“

Cilj: Ukloniti silos između razvoja i operacija.

Tradicionalno DevOps
„Baci preko zida“ „You build it, you run it“
Ručni deploy Automatski, ponovljivi
Downtime od 2h Zero-downtime
„Radi na mom računaru“ Radi svuda

1. Infrastructure as Code (IaC)

Alati:

Alat Tip Kada koristiti
Terraform Deklarativni Multi-cloud, kompleksni sistemi
Pulumi Imperativni (JS/TS) Programeri koji vole kod
AWS CDK Programski (TS) AWS-only
Dockerfile Za aplikaciju Svuda
Primer: Terraform + AWS (S3 + CloudFront)
# main.tf
provider "aws" {
  region = "eu-central-1"
}

resource "aws_s3_bucket" "static" {
  bucket = "itnetwork-static-${random_id.id.hex}"
}

resource "random_id" "id" {
  byte_length = 4
}

resource "aws_cloudfront_distribution" "cdn" {
  origin {
    domain_name = aws_s3_bucket.static.bucket_regional_domain_name
    origin_id   = "S3-static"
  }

  enabled             = true
  is_ipv6_enabled     = true
  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = "S3-static"

    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }

    viewer_protocol_policy = "redirect-to-https"
    min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }
}

output "cdn_url" {
  value = aws_cloudfront_distribution.cdn.domain_name
}

Pokretanje: terraform init → plan → apply

2. CI/CD Pipeline – od commit-a do produkcije

Faze:

CI CD Pipeline fazePrimer: GitHub Actions za Next.js + Node.js mikroservis

# .github/workflows/ci-cd.yml
name: CI/CD

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build-test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: testdb
        ports: [5432:5432]
        options: >-
          --health-cmd "pg_isready -U postgres"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run lint
        run: npm run lint

      - name: Run tests
        run: npm test
        env:
          DATABASE_URL: postgres://postgres:postgres@localhost:5432/testdb

      - name: Build
        run: npm run build

  security-scan:
    runs-on: ubuntu-latest
    needs: build-test
    steps:
      - uses: actions/checkout@v4
      - name: Run Snyk
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

  deploy-staging:
    runs-on: ubuntu-latest
    needs: security-scan
    environment: staging
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v25
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
          vercel-args: '--prod --env=staging'

  deploy-production:
    runs-on: ubuntu-latest
    needs: deploy-staging
    environment: production
    steps:
      - name: Manual Approval
        uses: trstringer/manual-approval@v1
        with:
          approvers: admin1,admin2
      - name: Deploy to Production
        uses: amondnet/vercel-action@v25
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-args: '--prod'
3. Observability – tri stuba
Stub Šta meri Alat
Metrics Brojevi (CPU, latency) Prometheus
Logs Tekstualni događaji Loki / ELK
Traces Put zahteva kroz servise Jaeger / OpenTelemetry
3.1 Metrics – Prometheus + Grafana

prometheus.yml

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'node-app'
    static_configs:
      - targets: ['app:3000']
  - job_name: 'postgres'
    static_configs:
      - targets: ['postgres-exporter:9187']
Grafana dashboard (JSON model)
{
  "title": "API Health",
  "panels": [
    {
      "type": "stat",
      "title": "P95 Latency",
      "targets": [
        {
          "expr": "histogram_quantile(0.95, sum(rate(http_request_duration_ms_bucket[5m])) by (le))"
        }
      ]
    }
  ]
}
3.2 Logs – Loki + Grafana

docker-compose.yml (loki + promtail)

services:
  loki:
    image: grafana/loki:2.9
    ports: ["3100:3100"]
    command: -config.file=/etc/loki/local-config.yaml

  promtail:
    image: grafana/promtail:2.9
    volumes:
      - ./promtail.yaml:/etc/promtail/config.yml
      - /var/log:/var/log
    command: -config.file=/etc/promtail/config.yml
promtail.yaml
scrape_configs:
  - job_name: app
    static_configs:
      - targets: [localhost]
        labels:
          job: app
          __path__: /var/log/app/*.log
3.3 Traces – OpenTelemetry

Node.js instrumentacija

// tracing.ts
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
import { PrismaInstrumentation } from '@opentelemetry/instrumentation-prisma';

const provider = new NodeTracerProvider();
const exporter = new OTLPTraceExporter({
  url: 'http://jaeger:4318/v1/traces'
});

provider.addSpanProcessor(new BatchSpanProcessor(exporter));
provider.register();

registerInstrumentations({
  instrumentations: [
    new HttpInstrumentation(),
    new ExpressInstrumentation(),
    new PrismaInstrumentation()
  ]
});

Rezultat: Vidimo gde zahtev „gubi“ vreme – DB? Redis? External API?

4. GitOps – deklarativni deployment

Alat: ArgoCD

# argocd-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: web-app
spec:
  project: default
  source:
    repoURL: https://github.com/itnetwork-rs/web-app.git
    targetRevision: HEAD
    path: k8s/prod
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Promeniš YAML u Git-u → ArgoCD automatski deploy-uje

5. Praktičan primer: Kompletan CI/CD + Observability

Kompletan CI/CD + ObservabilityPoređenje: Ručni vs Automatski deploy

Aspekt Ručni CI/CD + GitOps
Vreme deploy-a 30 min 3 min
Greške Česte Retke
Rollback Ručno Jedan klik
Audit trail Ne postoji Git log
Timska saradnja Blokirana Paralelna
Zaključak: DevOps stack 2025
Sloj Alat
IaC Terraform / Pulumi
CI/CD GitHub Actions / GitLab CI
Deploy ArgoCD / Flux
Metrics Prometheus + Grafana
Logs Loki
Traces OpenTelemetry + Jaeger
Alerting Alertmanager → Slack/Email

Zlatno pravilo: „Ako ne možeš da deploy-uješ sa jednim klikom – još nisi završio.“

Šta dalje?

U desetom i poslednjem delu ulazimo u arhitekturu budućnosti:

  • WebAssembly
  • AI-driven aplikacije
  • Progressive Web Apps
  • Zero-Trust, Quantum-ready

Tvoj izazov

  1. Napravi GitHub Actions pipeline za svoj projekat
  2. Postavi Prometheus + Grafana lokalno (docker-compose up)
  3. Dodaj OpenTelemetry u svoj Node.js servis
  4. Komentariši ispod: „Koliko često deploy-uješ na produkciju?“

Autor: Dušan Antonijević – saradnik ITNetwork.rs
Hvala na čitanju! Podeli tekst sa kolegama.

Banner

Banner

Možda će vam se svideti i