System Architecture
kguardian is designed as a distributed system with four main components that work together to observe, analyze, and secure your Kubernetes workloads.Components
Controller
Language: Rust + eBPF (C)Deployment: DaemonSet (one per node)Purpose: Observes kernel-level events
Broker
Language: Rust + Actix-webDeployment: Deployment with PostgreSQLPurpose: Stores and serves telemetry data
CLI
Language: GoDeployment: kubectl pluginPurpose: Generates security policies
UI
Language: React + TypeScriptDeployment: Web applicationPurpose: Visualizes network topology
Data Flow
1. eBPF Monitoring
The Controller attaches eBPF programs to kernel hooks (
tcp_connect, syscall enter/exit, etc.) on each node. When pods make network connections or execute syscalls, eBPF programs capture:- Source/destination IPs and ports
- Protocol (TCP/UDP)
- Syscall names and arguments
- Container network namespace inode
- Timestamp
eBPF runs in the kernel with minimal overhead (~1-2% CPU), avoiding the need for sidecar proxies or agent injection.
2. Event Enrichment
The Controller’s userspace component:
- Receives events from eBPF via perf buffers
- Queries containerd to map network namespace inodes to container IDs
- Matches containers to Kubernetes pods via the API server
- Enriches events with pod name, namespace, labels, and owner references
3. Data Transmission
Enriched events are sent to the Broker via HTTP POST:
- Network traffic →
/podsand/pod/spec - Syscall data →
/pods/syscalls - Service mappings →
/svc/spec
4. Storage & Indexing
The Broker stores all telemetry in PostgreSQL with indexes on:
- Pod IP address
- Pod name + namespace
- Timestamp (for time-range queries)
- Traffic type (INGRESS/EGRESS)
5. Policy Generation
The CLI queries the Broker API:
- Fetches all traffic for a specific pod
- Identifies unique source/destination IPs
- Resolves IPs to pods/services via the Broker
- Groups traffic by protocol and port
- Deduplicates rules
- Generates K8s/Cilium NetworkPolicy YAML
6. Visualization
The UI fetches data from the Broker and renders:
- An interactive graph of pod-to-pod communication (React Flow)
- Tables of traffic details with filtering
- Real-time updates as new data arrives
Technology Stack
Controller (Rust + eBPF)
Why Rust?
Why Rust?
- Memory safety without garbage collection (critical for low-level system programming)
- Performance on par with C/C++ for userspace eBPF handling
- libbpf-rs bindings provide excellent eBPF ergonomics
- Tokio async runtime for efficient event processing
eBPF Programs
eBPF Programs
- Written in C, compiled with
clang -target bpf - Use
libbpf-cargoto generate Rust skeleton bindings (.skel.rs) - Attach to kprobes:
tcp_connect,tcp_sendmsg, etc. - Use BPF maps for kernel ↔ userspace communication
Kubernetes Integration
Kubernetes Integration
- kube-rs: Rust Kubernetes client for pod watching
- Watches pods on the current node via field selector
- Filters by excluded namespaces (kube-system, kguardian, etc.)
- Handles pod lifecycle events (create, update, delete)
Broker (Rust + Actix-web + PostgreSQL)
API Framework
API Framework
- Actix-web: High-performance HTTP server (thousands of req/sec)
- RESTful API with JSON payloads
- Async request handling with Tokio
- Diesel ORM for type-safe SQL queries
Data Schema
Data Schema
Tables:
pods: Pod metadata (name, namespace, IP, labels, spec)services: Service metadata (name, namespace, cluster IP, selectors)pod_traffic: Network connections (src/dst IP, port, protocol, type)pod_syscalls: Syscall observations (pod, syscall names, count, architecture)
Data Retention
Data Retention
Currently, data is retained indefinitely. Future versions will support:
- Configurable retention periods
- Automatic data aggregation/rollup
- Export to external systems (S3, etc.)
CLI (Go)
Why Go?
Why Go?
- kubectl plugin ecosystem: Natural fit for K8s tooling
- client-go: Official Kubernetes Go client
- cobra: Industry-standard CLI framework
- Cross-platform binaries without dependencies
Policy Generation Logic
Policy Generation Logic
Network policies:
- Query
/pod/traffic/name/:namespace/:podfrom Broker - For each unique peer IP, query
/pod/ip/:ipor/svc/ip/:ip - Build
NetworkPolicyPeerwithpodSelector+namespaceSelector - Group by direction (ingress/egress) and port/protocol
- Deduplicate rules via JSON marshaling comparison
- Generate YAML with
sigs.k8s.io/yaml
Seccomp Generation Logic
Seccomp Generation Logic
- Query
/pod/syscalls/name/:namespace/:podfrom Broker - Extract unique syscall names from aggregated data
- Group by architecture (x86_64, arm64, etc.)
- Generate JSON with
defaultAction: SCMP_ACT_ERRNO - Add
syscallsarray withaction: SCMP_ACT_ALLOW
UI (React + TypeScript)
Frontend Stack
Frontend Stack
- React 19: Modern UI framework
- TypeScript: Type safety for complex state
- Vite: Fast build tooling
- TailwindCSS 4: Utility-first styling
- React Flow: Interactive network graph rendering
Visualization
Visualization
- Pods rendered as collapsible nodes (expand to show containers)
- Edges show traffic direction with arrows
- Namespace-based grouping with color coding
- Interactive filtering by namespace, pod, traffic type
Data Display
Data Display
- Traffic table with sorting and pagination
- Pod details panel with labels and metadata
- Real-time updates via polling the Broker API
- Dark mode support (matches Cilium Hubble aesthetic)
Deployment Architecture
Standard Deployment (Helm)
High Availability
For production, configure:- Broker replicas: 2-3 for load balancing
- PostgreSQL: Use managed service (RDS, Cloud SQL) or PostgreSQL operator with replication
- Controller: Automatically HA via DaemonSet (one per node)
- UI: 2+ replicas behind ingress/load balancer
The Controller must run on every node you want to monitor. Use node selectors or tolerations if you have specialized node pools.
Security Considerations
Controller Privileges
Controller Privileges
The Controller requires:
- Privileged container (to load eBPF programs)
- hostNetwork (to access node network namespace)
- CAP_BPF, CAP_PERFMON, CAP_SYS_RESOURCE capabilities
Data Access
Data Access
- Broker API currently has no authentication (assumes network isolation)
- For production, consider:
- Network policies to restrict Broker access
- Ingress with authentication (OAuth2 proxy, etc.)
- mTLS between components
Data Sensitivity
Data Sensitivity
The PostgreSQL database contains:
- Pod names, namespaces, labels
- IP addresses and ports of communication
- Syscall activity
Performance Characteristics
| Component | CPU (idle) | CPU (busy) | Memory | Notes |
|---|---|---|---|---|
| Controller | 10-20m | 50-100m | 50-100Mi | Per node, depends on pod count |
| Broker | 5-10m | 50-200m | 100-200Mi | Scales with request rate |
| PostgreSQL | 10-20m | 50-100m | 256Mi-1Gi | Depends on data volume |
| UI | 1-5m | 10-20m | 50-100Mi | Static content serving |
In testing with 100 pods generating moderate traffic, total cluster overhead is ~200-400m CPU and ~500Mi-1Gi memory.
Scalability
- Controllers: Scale linearly with node count (DaemonSet)
- Broker: Stateless, can add replicas behind a load balancer
- PostgreSQL: Vertical scaling or read replicas for high query loads
- CLI: No scaling concerns (client-side)
- UI: Horizontal scaling behind ingress
- Sharding data by namespace
- Time-windowed queries
- Data aggregation/rollup