Skip to main content

Architecture Overview

KubeVision follows a clean layered architecture with real-time data flow.

System Diagram

                    Browser (React + shadcn/ui)
┌────────┴────────┐
REST WebSocket
│ │
┌───────────▼─────────────────▼──────────────┐
│ KubeVision Backend (Go + Gin) │
│ │
│ Middleware: RequestID → Logger → Auth │
│ → RBAC → Audit │
│ │
│ Handler ──→ Service ──→ K8sRepo │
│ (params) (logic) (cache+fallback) │
│ │ │
│ ┌──────────┴──────────┐ │
│ │ │ │
│ Informer Cache API Server │
│ │ │
│ Informer Watch ──→ EventListener │
│ │ │
│ WS Hub ──→ Browser │
│ │
│ Plugins: Prometheus │ Grafana │ ArgoCD │
│ DB: SQLite (dev) / PostgreSQL (prod) │
└─────────────────────────────────────────────┘

Design Principles

#PrincipleDescription
1Simple FirstUse stdlib when possible, minimize third-party deps
2Progressive EnhancementMVP core first, advanced features plug in
3Generic ResourcesOne Handler + registry covers all K8s resources
4Real-time FeedbackInformer cache + WebSocket, sub-second updates
5Interface DrivenAll dependencies injected via interfaces
6Secure by DefaultSecrets masked, audit on, least privilege

Layers

Handler Layer

HTTP request entry point. Parses parameters, validates input, delegates to Service layer. A single generic ResourceHandler handles CRUD for all Kubernetes resource types.

Service Layer

Business logic: input validation, error mapping, caching strategy. ResourceService provides unified CRUD with cache-first reads and API Server fallback.

Repository Layer

Data access abstraction. K8sRepo wraps Informer cache and dynamic client. UserRepo, ClusterRepo, etc. wrap GORM for database operations.

Middleware Stack

Requests flow through: RequestID → Logger → Auth (JWT) → RBAC → Audit

Each middleware is composable and can be applied per-route.

Key Interfaces

type K8sResourceRepo interface {
List(ctx, cluster, ns, resource) (items, stale, error)
Get(ctx, cluster, ns, resource, name) (*Unstructured, error)
Create(ctx, cluster, ns, resource, obj) (*Unstructured, error)
Update(ctx, cluster, ns, resource, name, obj) (*Unstructured, error)
Delete(ctx, cluster, ns, resource, name) error
DryRun(ctx, cluster, ns, resource, name, obj) (*Unstructured, error)
}

type ClusterManager interface {
DynamicClient(cluster string) (dynamic.Interface, error)
RESTConfig(cluster string) (*rest.Config, error)
}

type ResourceRegistry interface {
Get(name string) (*ResourceInfo, error)
All() []ResourceInfo
}