G-SERVICE Docs
Архитектура ISP (OSS/BSS)

Технологический стек

NestJS на Bun 1.3+, Drizzle ORM, zod v4, BullMQ, ConnectRPC, RabbitMQ, PostgreSQL, Kubernetes + Kustomize, ArgoCD. Go — только для high-load.

Технологический стек и Инфраструктура

Этот раздел описывает конкретные технологии, используемые в платформе, их роли и причины выбора.

Ключевой принцип: Основной бэкенд — NestJS (TypeScript). Go используется только для сверхнагруженных компонентов: Mediation (Netflow/IPFIX), Provisioning (Netconf/SNMP), AAA (FreeRADIUS CoA).

Почему двуязычная архитектура? В отличие от монолитных ISP-систем на одном стеке (Hydra Billing — Ruby, Splynx — PHP, WHMCS — PHP), мы используем NestJS для бизнес-логики (BSS: типобезопасность, DI, декораторы, экосистема npm) и Go для сетевого взаимодействия (OSS: zero-alloc parsing Netflow, concurrent SNMP polling, нативные RADIUS-библиотеки). Это позволяет каждой команде использовать оптимальный инструмент, сохраняя единый контракт через Protobuf.

Обзор стека

Loading diagram...

Языки и фреймворки

Основной стек: NestJS (TypeScript)

Ядро:

КомпонентБиблиотекаОбоснование
FrameworkNestJS 11+DI, модульность, enterprise-готовность, огромная экосистема @nestjs/*
RuntimeBun 1.3+Всё-в-одном: runtime + package manager + test runner + bundler. Быстрее Node.js, встроенный S3/PostgreSQL/Redis клиент, ESM + CJS без конфликтов
LanguageTypeScript 5.7+ (strict)satisfies, const type params, decorators stage 3, Bun нативно компилирует TS
Package ManagerBun (встроенный)Workspaces, isolated installs, security scanner, ~25× быстрее npm, не нужен отдельный pnpm/yarn
MonorepoTurborepo + Bun workspacesRemote caching, task pipelines. Bun workspaces для резолва зависимостей

Данные и валидация:

КомпонентБиблиотекаОбоснование
ORMDrizzle ORM (drizzle-orm + drizzle-kit)SQL-like API, zero overhead, type-safe joins/subqueries, ближе всего к SQL — нет magic, полный контроль
DB Driverdrizzle-orm/bun-sql (Bun.sql)Встроенный PostgreSQL-клиент Bun, prepared statements, zero dependencies
Migrationsdrizzle-kitdrizzle-kit generate + drizzle-kit migrate, declarative schema-first
Validationzod 4 (zod@^4.0)14× быстрее парсинг, 2× меньше bundle, JSON Schema из коробки, recursive objects, i18n, .meta()
NestJS + Zodnestjs-zodPipes, DTOs, OpenAPI schema generation из zod
Error HandlingneverthrowResult<T, E> тип (Rust-style), нет throw — явный error path

API и интеграции:

КомпонентБиблиотекаОбоснование
RPCConnectRPC (@connectrpc/connect + @connectrpc/connect-node)Protobuf-first, HTTP/1.1+2, JSON fallback, браузеры без прокси
ContractsProtobuf + buf.buildSchema-first, codegen (TS + Go), breaking change detection, BSR
Messaging@golevelup/nestjs-rabbitmqDecorator-based pub/sub, auto-reconnect, exchanges, DLX
Background JobsBullMQ 5 (@nestjs/bullmq)Redis-backed, priorities, cron, retry, rate limit, concurrency control
Job DashboardBull Board (@bull-board/nestjs)Web UI для мониторинга и ретрая джоб

Observability и надёжность:

КомпонентБиблиотекаОбоснование
Loggingnestjs-pino (pino)Самый быстрый JSON logger, structured, async, request context
Tracing@opentelemetry/sdk-node + auto-instrumentationOTel traces + metrics, pg/redis/amqp auto-instrumented
Health@nestjs/terminusReadiness/liveness probes, DB/Redis/RabbitMQ health indicators
Circuit BreakeropossumClosed→Open→Half-Open, проверен в production (Red Hat)
Retryp-retryExponential backoff, jitter, abort signal
Rate Limiting@nestjs/throttlerDecorator-based, Redis-backed, per-route/per-user
Graceful Shutdown@nestjs/common (built-in)enableShutdownHooks(), drain connections

Auth и безопасность:

КомпонентБиблиотекаОбоснование
Auth@nestjs/passport + passport-jwtKeycloak JWT, RBAC guards, @Roles() декораторы
RBACCustom guards + KeycloakPer-RPC/per-route права, realm roles
Config@nestjs/config + zod schemaEnv-based (12-factor), type-safe валидация при bootstrap
Caching@nestjs/cache-manager + cache-manager-ioredis-yetRedis-backed, TTL, @CacheKey() декораторы
HelmethelmetSecurity headers (CSP, HSTS, X-Frame), Express-compatible
CORS@nestjs/common (built-in CORS)Fine-grained CORS политики, настройка в main.ts

Тестирование:

КомпонентБиблиотекаОбоснование
Unit / E2Ebun:test (встроенный)Встроенный test runner Bun, concurrent tests, snapshots, mocks, VS Code integration
HTTP testingsupertestHTTP assertions для NestJS e2e
Integrationtestcontainers (@testcontainers/postgresql, redis, rabbitmq)Docker-based PostgreSQL/Redis/RabbitMQ для интеграционных тестов
Type testingbun:test expectTypeOf()Compile-time type assertions в тестах
Mockingbun:test mocks + @golevelup/ts-jestAuto-mock NestJS providers, mock.module()
API Contractbuf breakingПроверка обратной совместимости Protobuf в CI

High-Load компоненты: Go

Go используется только там, где нужна максимальная производительность или работа с низкоуровневыми сетевыми протоколами:

КомпонентЯзыкОбоснование
Mediation (Netflow/IPFIX)Go 1.23+Обработка миллионов flow-записей/сек, UDP listener, zero-alloc parsing
Provisioning (Vendor Adapter)Go 1.23+Netconf/SNMP/SSH к оборудованию, вендорные Go-библиотеки (gosnmp, junos-ez, netconf)
AAA (RADIUS CoA)Go 1.23+Низкоуровневый RADIUS-протокол, CoA UDP, минимальная latency

Frontend

КомпонентЯзык / ФреймворкОбоснование
Customer PortalNext.js 16 (React 19.2)Turbopack (stable), Cache Components + PPR, proxy.ts, React Compiler, View Transitions
CRM / Operator UIReact 19.2 + Vite 6SPA, TanStack Query, ConnectRPC-ES, shadcn/ui
Mobile AppsReact Native + ExpoЕдиная кодовая база iOS/Android, OTA updates

Базы данных и хранилища

PostgreSQL (основная СУБД)

  • Версия: 16+
  • Использование: Каждый сервис имеет свою БД (database-per-service). Общая БД запрещена.
  • Расширения:
    • uuid-ossp — генерация UUID
    • pg_trgm — полнотекстовый поиск (клиенты, адреса)
    • pgcrypto — шифрование чувствительных данных
    • timescaledb — для метрик и time-series данных (Mediation)
  • HA: Patroni + etcd для автоматического failover.
  • Бэкапы: WAL-G → S3, point-in-time recovery.
  • Миграции: drizzle-kit для NestJS-сервисов (schema-first, generate + migrate), goose для Go-сервисов.

Redis

  • Версия: 7+
  • Использование:
    • BullMQ: Фоновые задачи, cron-джобы, retry, приоритеты, rate limiting
    • Кэширование (@nestjs/cache-manager — каталог продуктов, профили)
    • Распределённые блокировки (Redlock)
    • Rate limiting (sliding window)
    • Session store для Customer Portal
    • Idempotency keys (TTL 24h)
  • HA: Redis Sentinel или Redis Cluster.

RabbitMQ

  • Версия: 4.x (с поддержкой Quorum Queues и Streams)
  • Использование:
    • Асинхронный обмен событиями и командами между сервисами
    • Dead Letter Queues (DLX/DLQ) для обработки ошибок
    • Transactional Outbox relay
  • Конфигурация:
    • Кластер из 3 нод (Quorum Queues = Raft-репликация)
    • Publisher Confirms для гарантии записи
    • Manual Ack на стороне консьюмеров
    • x-delivery-limit: 5 перед перемещением в DLQ
  • Мониторинг: rabbitmq_prometheus плагин → Prometheus → Grafana.
  • Подробнее: Топология exchanges/queues — в API-контрактах.

S3 / MinIO

  • Использование:
    • Архив CDR/UDR (долгосрочное хранение, СОРМ)
    • Бэкапы баз данных (WAL-G)
    • Статические файлы (инвойсы PDF, шаблоны)

Kubernetes + Kustomize

Почему Kustomize, а не Helm

КритерийKustomizeHelm
ПодходДекларативный overlay (patching)Шаблонизация (Go templates)
СложностьПростые YAML-файлы, нативный kubectlШаблоны, values, hooks, charts
Дебагkubectl diff — видно что применитсяhelm template + ручная проверка
GitOpsНативная поддержка ArgoCDПоддержка ArgoCD
КастомизацияStrategic merge patches, overlaysValues файлы
ЗависимостиНет (всё in-tree)Chart dependencies, repositories

Структура Kustomize-манифестов

k8s/
├── base/                           # Базовые манифесты (общие для всех env)
│   ├── kustomization.yaml
│   ├── namespace.yaml
│   ├── customer-core/
│   │   ├── deployment.yaml
│   │   ├── service.yaml
│   │   ├── hpa.yaml
│   │   └── pdb.yaml
│   ├── billing/
│   │   ├── deployment.yaml
│   │   ├── service.yaml
│   │   ├── hpa.yaml
│   │   └── pdb.yaml
│   ├── provisioning/
│   │   └── ...
│   ├── rabbitmq/
│   │   ├── statefulset.yaml
│   │   ├── service.yaml
│   │   └── configmap.yaml
│   └── common/
│       ├── network-policies.yaml
│       ├── resource-quotas.yaml
│       └── limit-ranges.yaml
├── components/                     # Переиспользуемые компоненты
│   ├── monitoring/
│   │   ├── kustomization.yaml
│   │   ├── service-monitor.yaml
│   │   └── prometheus-rules.yaml
│   ├── tracing/
│   │   ├── kustomization.yaml
│   │   └── otel-collector.yaml
│   └── security/
│       ├── kustomization.yaml
│       ├── network-policy-strict.yaml
│       └── pod-security-standards.yaml
└── overlays/                       # Окружения (патчи поверх base)
    ├── dev/
    │   ├── kustomization.yaml
    │   ├── patches/
    │   │   ├── replicas.yaml       # replicas: 1
    │   │   └── resources.yaml      # cpu: 100m, memory: 128Mi
    │   └── configmap-env.yaml
    ├── staging/
    │   ├── kustomization.yaml
    │   ├── patches/
    │   │   ├── replicas.yaml       # replicas: 2
    │   │   └── resources.yaml      # cpu: 250m, memory: 256Mi
    │   └── configmap-env.yaml
    └── production/
        ├── kustomization.yaml
        ├── patches/
        │   ├── replicas.yaml       # replicas: 3
        │   ├── resources.yaml      # cpu: 500m, memory: 512Mi
        │   └── tolerations.yaml
        ├── configmap-env.yaml
        └── sealed-secrets/

Пример: base/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: isp-platform

commonLabels:
  app.kubernetes.io/part-of: isp-platform
  app.kubernetes.io/managed-by: kustomize

resources:
  - namespace.yaml
  - customer-core/
  - billing/
  - provisioning/
  - rabbitmq/
  - common/

Пример: overlays/production/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - ../../base

components:
  - ../../components/monitoring
  - ../../components/tracing
  - ../../components/security

patches:
  - path: patches/replicas.yaml
  - path: patches/resources.yaml
  - path: patches/tolerations.yaml

configMapGenerator:
  - name: app-config
    behavior: merge
    literals:
      - LOG_LEVEL=info
      - ENVIRONMENT=production

images:
  - name: customer-core
    newName: registry.example.com/isp/customer-core
    newTag: v1.2.3
  - name: billing
    newName: registry.example.com/isp/billing
    newTag: v1.1.0

Пример: base/customer-core/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: customer-core
  labels:
    app.kubernetes.io/name: customer-core
    app.kubernetes.io/component: bss
spec:
  replicas: 2
  selector:
    matchLabels:
      app.kubernetes.io/name: customer-core
  template:
    metadata:
      labels:
        app.kubernetes.io/name: customer-core
    spec:
      serviceAccountName: customer-core
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 1000
        seccompProfile:
          type: RuntimeDefault
      containers:
        - name: customer-core
          image: customer-core:latest # Overridden by Kustomize images
          ports:
            - name: grpc
              containerPort: 8080
              protocol: TCP
            - name: metrics
              containerPort: 9090
              protocol: TCP
          envFrom:
            - configMapRef:
                name: app-config
            - secretRef:
                name: customer-core-secrets
          resources:
            requests:
              cpu: 250m
              memory: 256Mi
            limits:
              memory: 512Mi # Без CPU limit (best practice)
          livenessProbe:
            grpc:
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
          readinessProbe:
            grpc:
              port: 8080
            initialDelaySeconds: 3
            periodSeconds: 5
          startupProbe:
            grpc:
              port: 8080
            failureThreshold: 30
            periodSeconds: 2
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              app.kubernetes.io/name: customer-core

Kubernetes Best Practices

Pod Security:

  • runAsNonRoot: true — контейнеры не запускаются от root.
  • seccompProfile: RuntimeDefault — ограничение syscalls.
  • readOnlyRootFilesystem: true — где возможно.
  • Pod Security Standards: restricted namespace label.

Resource Management:

  • Requests установлены для всех контейнеров (CPU + Memory).
  • Limits только для Memory (без CPU limit — избегаем throttling).
  • LimitRange и ResourceQuota на уровне namespace.

High Availability:

  • PodDisruptionBudget (PDB): minAvailable: 1 для каждого сервиса.
  • topologySpreadConstraints: Распределение pod'ов по нодам/зонам.
  • HorizontalPodAutoscaler (HPA): По CPU utilization (target 70%).
  • KEDA: Autoscaling RabbitMQ consumers по длине очереди.

Probes:

  • startupProbe — для медленного старта (миграции БД, прогрев кэша).
  • livenessProbe — gRPC health check (ConnectRPC поддерживает из коробки).
  • readinessProbe — gRPC health check (не принимаем трафик пока не готовы).

Network Policies:

# Пример: Billing может подключаться только к своей PostgreSQL и RabbitMQ
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: billing-egress
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: billing
  policyTypes:
    - Egress
  egress:
    - to:
        - podSelector:
            matchLabels:
              app.kubernetes.io/name: postgresql-billing
      ports:
        - port: 5432
    - to:
        - podSelector:
            matchLabels:
              app.kubernetes.io/name: rabbitmq
      ports:
        - port: 5672
    - to: # DNS
        - namespaceSelector: {}
      ports:
        - port: 53
          protocol: UDP

CI/CD Pipeline

Обзор

Loading diagram...
ЭтапИнструментОписание
КодGit (GitLab)Monorepo (Turborepo), trunk-based development
LintESLint + Prettier, buf lintTS + Protobuf стиль, golangci-lint для Go-сервисов
Testbun:test, supertest, testcontainersUnit + e2e + integration с PostgreSQL/RabbitMQ/Redis
Scantrivy, bun auditУязвимости в образах и зависимостях
BuildDocker (multi-stage)NestJS: oven/bun:1.3-alpine, Go: distroless
Imagesk3s containerddocker save | k3s ctr import, без registry
Protobuf build, buf pushLint + breaking check + публикация в BSR
CDArgoCD + Helm + K3sGitOps, rollout restart + refresh-argo
IaCTerraformИнфраструктура (PostgreSQL, RabbitMQ, Redis)
SecretsHashiCorp Vault + ESOExternal Secrets Operator для K8s

ArgoCD + Helm

# ArgoCD Application (deploy/applications/isp-platform.yaml)
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: isp-platform
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://gitlab.local/isp-platform/g-service-monorepo.git
    targetRevision: HEAD
    path: infra/chart
    helm:
      valueFiles:
        - values.yaml
        - values.production.yaml
  destination:
    server: https://kubernetes.default.svc
    namespace: isp-platform
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

Среды (Environments)

СредаНазначениеArgoCD SyncДанные
devРазработка, экспериментыAuto (на каждый push)Synthetic/seed data
stagingPre-production тестированиеAuto (на merge в main)Анонимизированная копия prod
productionБоевая средаManual (approval)Реальные данные абонентов
drDisaster RecoverySync с prodРеплика prod (другой ДЦ)

Docker: Multi-stage Build

NestJS-сервисы (Customer Core, Billing, OMS, ...)

# --- Build stage ---
FROM oven/bun:1.3-alpine AS builder
WORKDIR /app
COPY bun.lock package.json ./
RUN bun install --frozen-lockfile
COPY . .
RUN bun run build

# --- Runtime stage ---
FROM oven/bun:1.3-alpine
RUN addgroup -g 1001 -S bunjs && adduser -S nestjs -u 1001
WORKDIR /app
COPY --from=builder --chown=nestjs:bunjs /app/dist ./dist
COPY --from=builder --chown=nestjs:bunjs /app/node_modules ./node_modules
COPY --from=builder --chown=nestjs:bunjs /app/package.json ./
USER nestjs
EXPOSE 8080
CMD ["bun", "run", "dist/main.js"]

Go-сервисы (Mediation, Provisioning, AAA)

FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app/server ./cmd/mediation/

FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /app/server /server
USER nonroot:nonroot
EXPOSE 8080 9090
ENTRYPOINT ["/server"]

Best practices:

  • Multi-stage build: Build-зависимости не попадают в финальный образ.
  • NestJS: oven/bun:1.3-alpine — минимальный образ (~120MB), Bun runtime быстрее Node.js.
  • Go: distroless/static — минимальная поверхность атаки (~20MB).
  • nonroot: Запуск от непривилегированного пользователя.

Сетевая инфраструктура (ISP-специфика)

BRAS / BNG

  • Модели: Mikrotik CCR, Juniper MX, Huawei ME60, Eltex.
  • Протоколы: PPPoE, IPoE (DHCP + Option 82).
  • Интеграция: RADIUS (auth/acct), CoA, SNMP, Netconf.

OLT (GPON/xPON)

  • Модели: Huawei MA56xx, ZTE C3xx, Eltex LTP.
  • Управление: SNMP, Netconf, CLI (через Provisioning).
  • Данные: В Network Inventory (порты, ONT, привязки).

FreeRADIUS

  • Версия: 3.2+ (или 4.x при доступности)
  • Backend: SQL (PostgreSQL) для radcheck/radreply/radacct.
  • HA: Два инстанса (primary/secondary), NAS настроен на оба.
  • Мониторинг: freeradius-exporter для Prometheus.
  • Подробнее: Интеграция с RADIUS.

Дополнительное оборудование

  • DPI (Deep Packet Inspection): Для СОРМ-1, QoS, фильтрации РКН.
  • DHCP Relay: Для IPoE-абонентов (Option 82 → RADIUS).
  • DNS: Рекурсивные серверы для абонентов + авторитативные для ISP.
  • ACS (TR-069): Удалённое управление CPE. Подробнее — OSS Layer.

Go-библиотеки (Mediation / Provisioning / AAA)

Эти библиотеки используются только в Go-сервисах (high-load компоненты).

КатегорияБиблиотекаНазначение
RPCconnectrpc.com/connectConnectRPC сервер/клиент
Protobufgoogle.golang.org/protobufProtobuf runtime
AMQPgithub.com/rabbitmq/amqp091-goRabbitMQ клиент (без абстракций, максимальный контроль)
Databasegithub.com/jackc/pgx/v5PostgreSQL driver (pool, batch, COPY, LISTEN/NOTIFY)
Migrationsgithub.com/pressly/goose/v3SQL-миграции
Logginglog/slog (stdlib)Structured JSON logging
Tracinggo.opentelemetry.io/otelOTel SDK (traces + metrics)
Circuit Breakergithub.com/sony/gobreaker/v2Circuit breaker (generics v2)
Configgithub.com/caarlos0/env/v11Env-based config (12-factor)
Networkgithub.com/gosnmp/gosnmpSNMP v2c/v3 для OLT/BRAS
Networkgithub.com/Juniper/go-netconfNetconf к оборудованию
RADIUSlayeh.com/radiusRADIUS CoA/Disconnect packets
Testinggithub.com/stretchr/testifyAssertions + mocks

Подробнее об API-контрактах и примерах кода — в API-контракты.


Выбор технологий: Decision Log

РешениеАльтернативыПричина выбора
Bun 1.3+ runtimeNode.js 22, DenoВсё-в-одном: runtime + pkg manager + test runner + bundler. Встроенный S3/PG/Redis клиент, ~25× быстрее npm install, native TS-компиляция
NestJS для backendHono, Elysia, ExpressEnterprise DI, модульность, огромная экосистема @nestjs/*, battle-tested. Работает на Bun runtime
Drizzle ORMPrisma, TypeORM, MikroORMSQL-like API, zero overhead, type-safe joins, полный контроль над SQL. Bun.sql как driver
zod 4class-validator, io-ts, joi14× быстрее v3, 2× меньше bundle, JSON Schema из коробки, i18n, .meta(), recursive objects
BullMQAgenda, Bee-Queue, TemporalRedis-native, приоритеты, rate limit, cron, NestJS-модуль, Bull Board UI
Go для high-loadBun для всегоGo только для Netflow/SNMP/RADIUS — миллионы pps, UDP, zero-alloc. Остальное — NestJS
neverthrowthrow/catch, Effect-TSRust-style Result<T,E>, лёгкий, явные error paths, нет hidden control flow
bun:testJest, VitestВстроенный в Bun, concurrent tests, snapshots, VS Code, expectTypeOf(), не нужен отдельный runner
TurborepoNx, LernaRemote caching, task pipelines + Bun workspaces для решения
Next.js 16Remix, AstroTurbopack (stable), Cache Components + PPR, React Compiler, View Transitions, proxy.ts
Protobuf + bufOpenAPI, JSON SchemaSchema-first, codegen TS+Go, breaking detection, BSR
ConnectRPCgRPC, tRPC, RESTgRPC-compatible + HTTP/1.1 + JSON fallback, единый протокол TS↔Go
RabbitMQKafka, NATSFlexible routing (exchanges), DLX/DLQ, Quorum Queues, проще для масштаба ISP
PostgreSQLMySQL, CockroachDBЗрелость, TimescaleDB, pg_trgm, advisory locks, LISTEN/NOTIFY
KustomizeHelm, plain YAMLДекларативный, нативный kubectl, проще дебаг
ArgoCDFlux, JenkinsGitOps, UI, нативная поддержка Kustomize
FreeRADIUSСобственное решениеСтандарт ISP, поддержка всех NAS-вендоров

Ссылки по теме

On this page