kguardian-dev/kguardian

A Kubernetes tool leveraging eBPF for advanced Kubernetes security, auto-generating Network Policies, Seccomp Profiles, and more.

Rust

67

2,832 commits

updated Sep 30, 2026

See the code

See what people are saying

README

kguardian

Least-privilege Kubernetes security policies, generated from what your pods actually do

Docs   Kubernetes   License  

Chart   Security Scan   Stars   Last Commit  

🔭 Overview

kguardian watches pod traffic and syscalls with eBPF, then writes Kubernetes NetworkPolicy, CiliumNetworkPolicy, and seccomp profiles from what it sees — no hand-authored rules.

It's built for platform and security teams who want policy-as-code without writing rules by hand: the Controller (an eBPF DaemonSet) captures every TCP/UDP connection and syscall on each node, the Broker stores the per-pod baseline in PostgreSQL, and the kubectl kguardian plugin turns that baseline into least-privilege policy YAML for any pod, namespace, or the whole cluster.

📸 In action

Network Map: every observed flow in a namespace, with trusted, egress, and denied edges
Network Map — every flow eBPF saw, in one graph: trusted, egress, and would-deny edges for a live namespace (here, Flux).
Policy Builder: a least-privilege NetworkPolicy generated from observed traffic
Policy Builder — a least-privilege NetworkPolicy or CiliumNetworkPolicy written from what the workload actually did.
Workloads, seccomp columns: an enforcing SeccompProfile CR with node readiness and drift
Workloads · Seccomp — per-workload syscall allow-lists with node readiness and drift against the deployed SeccompProfile, audit mode by default.
Export a SeccompProfile CR: diff against the deployed CR and the manifest to commit
Policy as code — export the SeccompProfile CR, see the diff against what is deployed, commit it. kguardian never applies anything itself.

✨ Features

  • Network Policy generation — least-privilege Kubernetes NetworkPolicy and Cilium CiliumNetworkPolicy resources from observed pod-to-pod traffic. Each flow's peer is identified when it is captured, not when a policy is generated, so a recycled pod IP never allow-lists the wrong workload (how peers are attributed).
  • Seccomp profile generation — per-workload syscall allowlists derived from runtime traces, exported as a SeccompProfile CR you commit; the controller places the file on every node only once you apply it. Capture is tiered (full by default, cheap thanks to in-BPF dedup; high/medium/low/custom for monitoring-only clusters), and only a full capture yields a profile safe to enforce.
  • Live compute gauges and noisy-neighbour detection — every pod on the map carries a live CPU/memory gauge from cgroup v2, and the broker raises a finding when a pod is starved (noisy-neighbor, cpu-contended, memory-pressure) or under-provisioned by its own limits (cpu-throttled, memory-limit-thrash). With the optional eBPF scheduler probe it names the pod, system unit or kernel thread that was on the CPU while the victim waited — and it never blames a neighbour for a pod's own CFS throttling (how it works).
  • Policy auditing before enforcement — the AuditNetworkPolicy CRD is byte-identical to an upstream NetworkPolicy, but instead of dropping packets the evaluator reports every flow the policy would deny. Ship policies with confidence instead of blackholing production.
  • Flexible targeting — generate per-pod, per-namespace, or cluster-wide.
  • Review-first by design — the CLI writes YAML to --output-dir and never applies anything to the cluster; you review and kubectl apply the files yourself.
  • GitOps-friendly output — plain YAML/JSON files ready for review or a GitOps pipeline.
  • Optional AI assistant — query traffic and syscall data in natural language via the LLM Bridge, in the web UI or from your own MCP client.

Example policies for common workloads (nginx, Postgres, kube-dns, Prometheus, Istio sidecar, a Go microservice) live in the Policy Gallery. For a comparison with Inspektor Gadget and Security Profiles Operator, see the docs site.

🏗️ Architecture

graph LR
    subgraph "Each Node"
        C[Controller<br/>Rust + eBPF]
    end
    B[Broker<br/>Rust + Actix]
    DB[(PostgreSQL)]
    E[Evaluator<br/>Go]
    UI[Web UI<br/>React]
    CLI[kubectl kguardian<br/>Go]

    C -->|traffic + syscalls| B
    B --> DB
    B -->|flows| E
    E -->|would-deny verdicts| B
    UI --> B
    CLI -->|generate policies| B

    style C fill:#4E3AD9,color:#fff
    style B fill:#6D5CE6,color:#fff
    style E fill:#6D5CE6,color:#fff
    style UI fill:#6D5CE6,color:#fff
    style CLI fill:#3B2BA8,color:#fff
ComponentLanguageRuns asPurpose
ControllerRust + eBPF (C)DaemonSetCaptures every TCP/UDP connection and syscall on each node
BrokerRust (Actix)Deployment + PostgreSQLStores per-pod behavioral baselines and serves the API
EvaluatorGoDeploymentEvaluates live flows against AuditNetworkPolicy CRDs and reports would-deny verdicts — without dropping a packet
CLI (kubectl kguardian)Gokubectl pluginGenerates NetworkPolicies and seccomp profiles from the observed baseline
Web UIReact + TypeScriptDeploymentVisualizes traffic, policies, and pod behavior
LLM BridgeTypeScriptOptional DeploymentNatural-language assistant over cluster traffic — runs all tools and policy/seccomp generation in-process, and optionally serves them to external MCP clients (llm-bridge/README.md)

🚀 Quick Start

Prerequisites: Kubernetes v1.19+, kubectl v1.19+, and Linux kernel 6.2+ on every node that runs the Controller DaemonSet (see Compatibility).

Install the in-cluster components with Helm, then the kubectl plugin:

helm install kguardian oci://ghcr.io/kguardian-dev/charts/kguardian \
  --namespace kguardian --create-namespace
sh -c "$(curl -fsSL https://raw.githubusercontent.com/kguardian-dev/kguardian/main/scripts/quick-install.sh)"

Give the Controller some time to observe real traffic, then generate policies:

# Least-privilege NetworkPolicy for one pod (dry-run, saved to ./policies)
kubectl kguardian gen networkpolicy my-pod -n default --output-dir ./policies

# Cilium policies for every pod in a namespace
kubectl kguardian gen netpol --all -n staging --type cilium --output-dir ./policies

# Seccomp profiles for all pods in all namespaces
kubectl kguardian gen seccomp -A --output-dir ./seccomp

Review the generated YAML, then apply it yourself (kubectl apply -f ./policies). Manual download, custom Helm values, Kind setup, verification, upgrades, and uninstall are covered in the Installation Guide.

🛠️ Usage

The plugin follows the standard kubectl command structure:

kubectl kguardian gen <networkpolicy|seccomp> [pod-name] [flags]
FlagApplies toDescription
-n, --namespacebothNamespace scope (defaults to current context namespace)
--allbothAll pods in the selected namespace (-a shorthand: networkpolicy only)
-A, --all-namespacesbothAll pods in all namespaces
--output-dirbothDirectory for generated files (network-policies / seccomp-profiles)
-t, --typenetworkpolicykubernetes (default) or cilium
--dry-runnetworkpolicytrue (default). Applying directly is not implemented yet — the CLI always writes files only
--default-actionseccompAction for unlisted syscalls: SCMP_ACT_ERRNO (default), SCMP_ACT_LOG, SCMP_ACT_KILL

Full command reference, including audit workflows and advanced flags, is in the CLI docs.

🤖 AI Assistant

kguardian ships an optional natural-language assistant: ask questions like "what has this pod talked to in the last hour?" or "generate a seccomp profile for the payments namespace" from the Web UI. It's a single service, the LLM Bridge (SSE streaming), that reads the broker's data directly and generates policies and seccomp profiles in-process — bring your own API key for OpenAI, Anthropic, Gemini, or GitHub Copilot.

ai:
  enabled: true
  provider: anthropic          # openai | anthropic | gemini | copilot
  secret: kguardian-anthropic  # Secret holding the key under `api-key`

Running an OpenAI-compatible gateway (LiteLLM, vLLM, a proxy)? Add ai.baseUrl and ai.model. Two things to know: the API key is still required — provider availability is gated on the key alone, so point ai.secret at your gateway's virtual key (or a dummy value if it's unauthenticated) — and kguardian appends the request path to your base URL verbatim, never adding or stripping /v1. See the AI assistant setup.

🔌 Connect your own MCP client

The same 23 tools can be served over MCP at POST /mcp on the LLM Bridge, so Claude Code — or any MCP client — can read your cluster's observed telemetry and write policies from it. Off by default; enable with ai.mcp.*, port-forward, and add one server entry:

kubectl -n kguardian port-forward svc/kguardian-llm-bridge 8080:8080
claude mcp add --transport http kguardian http://localhost:8080/mcp \
  --header "Authorization: Bearer $KGUARDIAN_MCP_TOKEN"

Full walkthrough: Connect an MCP Client. Env vars, routes, and local development: llm-bridge/README.md.

🧩 Compatibility

The eBPF Controller requires Linux kernel 6.2 or newer on every node in the DaemonSet. Verify with uname -r before installing.

DistroDefault kernelCompatible?
Ubuntu 24.046.8✅
Ubuntu 22.045.15❌ (needs HWE 6.2+)
RHEL 95.14❌
Amazon Linux 20236.1❌ (needs kernel-6.12+ AMI)
Debian 126.1❌ (needs backports)
Talos / Bottlerocketusually 6.1+check distro version

Kernel versions reflect the GA/server defaults shipped by each distro as of May 2026; newer kernels are typically available via each distro's opt-in channels.

IP families

IPv4, IPv6, and dual-stack clusters are all supported. The Controller reads both AF_INET and AF_INET6 sockets, and policy generation emits /32 or /128 ipBlocks per peer — a dual-stack pod gets both families in one policy.

Things to know:

  • Dual-stack pods and Services are tracked on every address, not just the primary one in .status.podIP / .spec.clusterIP. A peer is therefore resolved to a podSelector regardless of which family the traffic used.
  • Nodes built with CONFIG_IPV6=n are handled: the IPv6 socket fields are read behind a CO-RE existence guard, so the Controller loads and runs normally on such kernels — it simply never sees v6 flows there.
  • Every service listener is dual-stack. The broker, frontend, llm-bridge and evaluator bind the IPv6 unspecified address (accepting IPv4 as v4-mapped) and fall back to IPv4-only on kernels without IPv6 — so the stack serves IPv4-only, dual-stack, and IPv6-only clusters alike. The broker's LISTEN_ADDR env still binds verbatim when set.
  • Kernels with IPv6 as a module but no module BTF (kernels older than 5.11, or built with CONFIG_DEBUG_INFO_BTF_MODULES=n — Debian 11's 5.10 is the common case) can't attach the IPv6 UDP probes. The Controller detects this at startup, logs a warning, and runs with those probes disabled rather than failing; IPv6 TCP capture is unaffected.
  • UDP flows are captured from connected sockets (glibc's DNS resolver connects, so pod DNS is covered on both families). Unconnected sendto() datagrams carry no destination on the socket at the probe point and are not captured — the same behaviour IPv4 has always had, notable mainly for musl-based (Alpine) resolvers.

A generated policy is only as complete as what was observed. If a workload speaks both families but was only exercised over one during the observation window, the policy will reflect that — review before enforcing, as always.

📊 Performance

Reference figures from a real-world deployment — a 3-node cluster (18 vCPU / 47 GiB RAM per node, Cilium CNI) observing 234 pods across 26 namespaces of mixed traffic:

  • Controller (eBPF DaemonSet): ~60 MiB memory and ~0.1–0.6 vCPU per node, tracking the node's connection/syscall rate.
  • Broker + evaluator: evaluator ~26 MiB / <0.01 vCPU idle; broker sized at 512 MiB request / 2 GiB limit with plenty of headroom at this scale.
  • PostgreSQL is the dominant consumer (~0.4–2 GiB RAM here, CPU spiking under ingest + autovacuum) — size it generously.
  • Storage growth is dedup-bounded: once a workload's flow set is learned, new rows drop to ~0/min in steady state. The database grows with new behavior, not with time or traffic volume; broker.audit.retention.days caps the audit-verdict history.

This is one measured data point, not a synthetic sweep — treat it as an order-of-magnitude envelope. Expect numbers to scale with flow cardinality, not raw pod count.

📡 Telemetry

The broker performs a daily anonymous version check-in that powers the UI's update notice and is the project's only usage signal. Exactly six fields are sent — a random install UUID, broker/chart/Kubernetes versions, node count, and CPU architecture; no cluster names, IPs, or workload data, ever. It's on by default, announced at install time, documented field-by-field in the telemetry docs, and disabled with --set telemetry.enabled=false.

🤝 Contributing

Contributions are welcome — read the contributing guide to get started. The release process and versioning strategy are documented in RELEASES.md, and security reports go through SECURITY.md.

📄 License

Licensed under the Business Source License 1.1:

  • Free for development, testing, evaluation, and non-production/non-commercial use
  • Commercial use requires a commercial license (contact the licensors)
  • Converts to Apache License 2.0 on January 1, 2029
ebpf
kubernetes
security

kguardian-dev/kguardian

A Kubernetes tool leveraging eBPF for advanced Kubernetes security, auto-generating Network Policies, Seccomp Profiles, and more.

Rust

67

2,832 commits

updated Sep 30, 2026

See the code

See what people are saying

README

kguardian

Least-privilege Kubernetes security policies, generated from what your pods actually do

Docs   Kubernetes   License  

Chart   Security Scan   Stars   Last Commit  

🔭 Overview

kguardian watches pod traffic and syscalls with eBPF, then writes Kubernetes NetworkPolicy, CiliumNetworkPolicy, and seccomp profiles from what it sees — no hand-authored rules.

It's built for platform and security teams who want policy-as-code without writing rules by hand: the Controller (an eBPF DaemonSet) captures every TCP/UDP connection and syscall on each node, the Broker stores the per-pod baseline in PostgreSQL, and the kubectl kguardian plugin turns that baseline into least-privilege policy YAML for any pod, namespace, or the whole cluster.

📸 In action

Network Map: every observed flow in a namespace, with trusted, egress, and denied edges
Network Map — every flow eBPF saw, in one graph: trusted, egress, and would-deny edges for a live namespace (here, Flux).
Policy Builder: a least-privilege NetworkPolicy generated from observed traffic
Policy Builder — a least-privilege NetworkPolicy or CiliumNetworkPolicy written from what the workload actually did.
Workloads, seccomp columns: an enforcing SeccompProfile CR with node readiness and drift
Workloads · Seccomp — per-workload syscall allow-lists with node readiness and drift against the deployed SeccompProfile, audit mode by default.
Export a SeccompProfile CR: diff against the deployed CR and the manifest to commit
Policy as code — export the SeccompProfile CR, see the diff against what is deployed, commit it. kguardian never applies anything itself.

✨ Features

  • Network Policy generation — least-privilege Kubernetes NetworkPolicy and Cilium CiliumNetworkPolicy resources from observed pod-to-pod traffic. Each flow's peer is identified when it is captured, not when a policy is generated, so a recycled pod IP never allow-lists the wrong workload (how peers are attributed).
  • Seccomp profile generation — per-workload syscall allowlists derived from runtime traces, exported as a SeccompProfile CR you commit; the controller places the file on every node only once you apply it. Capture is tiered (full by default, cheap thanks to in-BPF dedup; high/medium/low/custom for monitoring-only clusters), and only a full capture yields a profile safe to enforce.
  • Live compute gauges and noisy-neighbour detection — every pod on the map carries a live CPU/memory gauge from cgroup v2, and the broker raises a finding when a pod is starved (noisy-neighbor, cpu-contended, memory-pressure) or under-provisioned by its own limits (cpu-throttled, memory-limit-thrash). With the optional eBPF scheduler probe it names the pod, system unit or kernel thread that was on the CPU while the victim waited — and it never blames a neighbour for a pod's own CFS throttling (how it works).
  • Policy auditing before enforcement — the AuditNetworkPolicy CRD is byte-identical to an upstream NetworkPolicy, but instead of dropping packets the evaluator reports every flow the policy would deny. Ship policies with confidence instead of blackholing production.
  • Flexible targeting — generate per-pod, per-namespace, or cluster-wide.
  • Review-first by design — the CLI writes YAML to --output-dir and never applies anything to the cluster; you review and kubectl apply the files yourself.
  • GitOps-friendly output — plain YAML/JSON files ready for review or a GitOps pipeline.
  • Optional AI assistant — query traffic and syscall data in natural language via the LLM Bridge, in the web UI or from your own MCP client.

Example policies for common workloads (nginx, Postgres, kube-dns, Prometheus, Istio sidecar, a Go microservice) live in the Policy Gallery. For a comparison with Inspektor Gadget and Security Profiles Operator, see the docs site.

🏗️ Architecture

graph LR
    subgraph "Each Node"
        C[Controller<br/>Rust + eBPF]
    end
    B[Broker<br/>Rust + Actix]
    DB[(PostgreSQL)]
    E[Evaluator<br/>Go]
    UI[Web UI<br/>React]
    CLI[kubectl kguardian<br/>Go]

    C -->|traffic + syscalls| B
    B --> DB
    B -->|flows| E
    E -->|would-deny verdicts| B
    UI --> B
    CLI -->|generate policies| B

    style C fill:#4E3AD9,color:#fff
    style B fill:#6D5CE6,color:#fff
    style E fill:#6D5CE6,color:#fff
    style UI fill:#6D5CE6,color:#fff
    style CLI fill:#3B2BA8,color:#fff
ComponentLanguageRuns asPurpose
ControllerRust + eBPF (C)DaemonSetCaptures every TCP/UDP connection and syscall on each node
BrokerRust (Actix)Deployment + PostgreSQLStores per-pod behavioral baselines and serves the API
EvaluatorGoDeploymentEvaluates live flows against AuditNetworkPolicy CRDs and reports would-deny verdicts — without dropping a packet
CLI (kubectl kguardian)Gokubectl pluginGenerates NetworkPolicies and seccomp profiles from the observed baseline
Web UIReact + TypeScriptDeploymentVisualizes traffic, policies, and pod behavior
LLM BridgeTypeScriptOptional DeploymentNatural-language assistant over cluster traffic — runs all tools and policy/seccomp generation in-process, and optionally serves them to external MCP clients (llm-bridge/README.md)

🚀 Quick Start

Prerequisites: Kubernetes v1.19+, kubectl v1.19+, and Linux kernel 6.2+ on every node that runs the Controller DaemonSet (see Compatibility).

Install the in-cluster components with Helm, then the kubectl plugin:

helm install kguardian oci://ghcr.io/kguardian-dev/charts/kguardian \
  --namespace kguardian --create-namespace
sh -c "$(curl -fsSL https://raw.githubusercontent.com/kguardian-dev/kguardian/main/scripts/quick-install.sh)"

Give the Controller some time to observe real traffic, then generate policies:

# Least-privilege NetworkPolicy for one pod (dry-run, saved to ./policies)
kubectl kguardian gen networkpolicy my-pod -n default --output-dir ./policies

# Cilium policies for every pod in a namespace
kubectl kguardian gen netpol --all -n staging --type cilium --output-dir ./policies

# Seccomp profiles for all pods in all namespaces
kubectl kguardian gen seccomp -A --output-dir ./seccomp

Review the generated YAML, then apply it yourself (kubectl apply -f ./policies). Manual download, custom Helm values, Kind setup, verification, upgrades, and uninstall are covered in the Installation Guide.

🛠️ Usage

The plugin follows the standard kubectl command structure:

kubectl kguardian gen <networkpolicy|seccomp> [pod-name] [flags]
FlagApplies toDescription
-n, --namespacebothNamespace scope (defaults to current context namespace)
--allbothAll pods in the selected namespace (-a shorthand: networkpolicy only)
-A, --all-namespacesbothAll pods in all namespaces
--output-dirbothDirectory for generated files (network-policies / seccomp-profiles)
-t, --typenetworkpolicykubernetes (default) or cilium
--dry-runnetworkpolicytrue (default). Applying directly is not implemented yet — the CLI always writes files only
--default-actionseccompAction for unlisted syscalls: SCMP_ACT_ERRNO (default), SCMP_ACT_LOG, SCMP_ACT_KILL

Full command reference, including audit workflows and advanced flags, is in the CLI docs.

🤖 AI Assistant

kguardian ships an optional natural-language assistant: ask questions like "what has this pod talked to in the last hour?" or "generate a seccomp profile for the payments namespace" from the Web UI. It's a single service, the LLM Bridge (SSE streaming), that reads the broker's data directly and generates policies and seccomp profiles in-process — bring your own API key for OpenAI, Anthropic, Gemini, or GitHub Copilot.

ai:
  enabled: true
  provider: anthropic          # openai | anthropic | gemini | copilot
  secret: kguardian-anthropic  # Secret holding the key under `api-key`

Running an OpenAI-compatible gateway (LiteLLM, vLLM, a proxy)? Add ai.baseUrl and ai.model. Two things to know: the API key is still required — provider availability is gated on the key alone, so point ai.secret at your gateway's virtual key (or a dummy value if it's unauthenticated) — and kguardian appends the request path to your base URL verbatim, never adding or stripping /v1. See the AI assistant setup.

🔌 Connect your own MCP client

The same 23 tools can be served over MCP at POST /mcp on the LLM Bridge, so Claude Code — or any MCP client — can read your cluster's observed telemetry and write policies from it. Off by default; enable with ai.mcp.*, port-forward, and add one server entry:

kubectl -n kguardian port-forward svc/kguardian-llm-bridge 8080:8080
claude mcp add --transport http kguardian http://localhost:8080/mcp \
  --header "Authorization: Bearer $KGUARDIAN_MCP_TOKEN"

Full walkthrough: Connect an MCP Client. Env vars, routes, and local development: llm-bridge/README.md.

🧩 Compatibility

The eBPF Controller requires Linux kernel 6.2 or newer on every node in the DaemonSet. Verify with uname -r before installing.

DistroDefault kernelCompatible?
Ubuntu 24.046.8✅
Ubuntu 22.045.15❌ (needs HWE 6.2+)
RHEL 95.14❌
Amazon Linux 20236.1❌ (needs kernel-6.12+ AMI)
Debian 126.1❌ (needs backports)
Talos / Bottlerocketusually 6.1+check distro version

Kernel versions reflect the GA/server defaults shipped by each distro as of May 2026; newer kernels are typically available via each distro's opt-in channels.

IP families

IPv4, IPv6, and dual-stack clusters are all supported. The Controller reads both AF_INET and AF_INET6 sockets, and policy generation emits /32 or /128 ipBlocks per peer — a dual-stack pod gets both families in one policy.

Things to know:

  • Dual-stack pods and Services are tracked on every address, not just the primary one in .status.podIP / .spec.clusterIP. A peer is therefore resolved to a podSelector regardless of which family the traffic used.
  • Nodes built with CONFIG_IPV6=n are handled: the IPv6 socket fields are read behind a CO-RE existence guard, so the Controller loads and runs normally on such kernels — it simply never sees v6 flows there.
  • Every service listener is dual-stack. The broker, frontend, llm-bridge and evaluator bind the IPv6 unspecified address (accepting IPv4 as v4-mapped) and fall back to IPv4-only on kernels without IPv6 — so the stack serves IPv4-only, dual-stack, and IPv6-only clusters alike. The broker's LISTEN_ADDR env still binds verbatim when set.
  • Kernels with IPv6 as a module but no module BTF (kernels older than 5.11, or built with CONFIG_DEBUG_INFO_BTF_MODULES=n — Debian 11's 5.10 is the common case) can't attach the IPv6 UDP probes. The Controller detects this at startup, logs a warning, and runs with those probes disabled rather than failing; IPv6 TCP capture is unaffected.
  • UDP flows are captured from connected sockets (glibc's DNS resolver connects, so pod DNS is covered on both families). Unconnected sendto() datagrams carry no destination on the socket at the probe point and are not captured — the same behaviour IPv4 has always had, notable mainly for musl-based (Alpine) resolvers.

A generated policy is only as complete as what was observed. If a workload speaks both families but was only exercised over one during the observation window, the policy will reflect that — review before enforcing, as always.

📊 Performance

Reference figures from a real-world deployment — a 3-node cluster (18 vCPU / 47 GiB RAM per node, Cilium CNI) observing 234 pods across 26 namespaces of mixed traffic:

  • Controller (eBPF DaemonSet): ~60 MiB memory and ~0.1–0.6 vCPU per node, tracking the node's connection/syscall rate.
  • Broker + evaluator: evaluator ~26 MiB / <0.01 vCPU idle; broker sized at 512 MiB request / 2 GiB limit with plenty of headroom at this scale.
  • PostgreSQL is the dominant consumer (~0.4–2 GiB RAM here, CPU spiking under ingest + autovacuum) — size it generously.
  • Storage growth is dedup-bounded: once a workload's flow set is learned, new rows drop to ~0/min in steady state. The database grows with new behavior, not with time or traffic volume; broker.audit.retention.days caps the audit-verdict history.

This is one measured data point, not a synthetic sweep — treat it as an order-of-magnitude envelope. Expect numbers to scale with flow cardinality, not raw pod count.

📡 Telemetry

The broker performs a daily anonymous version check-in that powers the UI's update notice and is the project's only usage signal. Exactly six fields are sent — a random install UUID, broker/chart/Kubernetes versions, node count, and CPU architecture; no cluster names, IPs, or workload data, ever. It's on by default, announced at install time, documented field-by-field in the telemetry docs, and disabled with --set telemetry.enabled=false.

🤝 Contributing

Contributions are welcome — read the contributing guide to get started. The release process and versioning strategy are documented in RELEASES.md, and security reports go through SECURITY.md.

📄 License

Licensed under the Business Source License 1.1:

  • Free for development, testing, evaluation, and non-production/non-commercial use
  • Commercial use requires a commercial license (contact the licensors)
  • Converts to Apache License 2.0 on January 1, 2029
ebpf
kubernetes
security

Languages

Rust

40.5%

TypeScript

25.3%

Go

16.8%

C

15.5%