A Kubernetes tool leveraging eBPF for advanced Kubernetes security, auto-generating Network Policies, Seccomp Profiles, and more.
See the codeLeast-privilege Kubernetes security policies, generated from what your pods actually do
Overview · In action · Features · Architecture · Quick Start · Usage · AI Assistant · Compatibility · Performance · Telemetry · Contributing · License
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.
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).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.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).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.--output-dir and never applies anything to the cluster; you review and kubectl apply the files yourself.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.
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
| Component | Language | Runs as | Purpose |
|---|---|---|---|
| Controller | Rust + eBPF (C) | DaemonSet | Captures every TCP/UDP connection and syscall on each node |
| Broker | Rust (Actix) | Deployment + PostgreSQL | Stores per-pod behavioral baselines and serves the API |
| Evaluator | Go | Deployment | Evaluates live flows against AuditNetworkPolicy CRDs and reports would-deny verdicts — without dropping a packet |
CLI (kubectl kguardian) | Go | kubectl plugin | Generates NetworkPolicies and seccomp profiles from the observed baseline |
| Web UI | React + TypeScript | Deployment | Visualizes traffic, policies, and pod behavior |
| LLM Bridge | TypeScript | Optional Deployment | Natural-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) |
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.
The plugin follows the standard kubectl command structure:
kubectl kguardian gen <networkpolicy|seccomp> [pod-name] [flags]
| Flag | Applies to | Description |
|---|---|---|
-n, --namespace | both | Namespace scope (defaults to current context namespace) |
--all | both | All pods in the selected namespace (-a shorthand: networkpolicy only) |
-A, --all-namespaces | both | All pods in all namespaces |
--output-dir | both | Directory for generated files (network-policies / seccomp-profiles) |
-t, --type | networkpolicy | kubernetes (default) or cilium |
--dry-run | networkpolicy | true (default). Applying directly is not implemented yet — the CLI always writes files only |
--default-action | seccomp | Action 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.
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.
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.
The eBPF Controller requires Linux kernel 6.2 or newer on every node in the DaemonSet. Verify with uname -r before installing.
| Distro | Default kernel | Compatible? |
|---|---|---|
| Ubuntu 24.04 | 6.8 | ✅ |
| Ubuntu 22.04 | 5.15 | ❌ (needs HWE 6.2+) |
| RHEL 9 | 5.14 | ❌ |
| Amazon Linux 2023 | 6.1 | ❌ (needs kernel-6.12+ AMI) |
| Debian 12 | 6.1 | ❌ (needs backports) |
| Talos / Bottlerocket | usually 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.
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:
.status.podIP / .spec.clusterIP. A peer is therefore resolved to a podSelector regardless of which family the traffic used.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.LISTEN_ADDR env still binds verbatim when set.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.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.
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:
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.
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.
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.
Licensed under the Business Source License 1.1:
Rust
40.5%
TypeScript
25.3%
Go
16.8%
C
15.5%
A Kubernetes tool leveraging eBPF for advanced Kubernetes security, auto-generating Network Policies, Seccomp Profiles, and more.
See the codeLeast-privilege Kubernetes security policies, generated from what your pods actually do
Overview · In action · Features · Architecture · Quick Start · Usage · AI Assistant · Compatibility · Performance · Telemetry · Contributing · License
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.
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).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.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).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.--output-dir and never applies anything to the cluster; you review and kubectl apply the files yourself.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.
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
| Component | Language | Runs as | Purpose |
|---|---|---|---|
| Controller | Rust + eBPF (C) | DaemonSet | Captures every TCP/UDP connection and syscall on each node |
| Broker | Rust (Actix) | Deployment + PostgreSQL | Stores per-pod behavioral baselines and serves the API |
| Evaluator | Go | Deployment | Evaluates live flows against AuditNetworkPolicy CRDs and reports would-deny verdicts — without dropping a packet |
CLI (kubectl kguardian) | Go | kubectl plugin | Generates NetworkPolicies and seccomp profiles from the observed baseline |
| Web UI | React + TypeScript | Deployment | Visualizes traffic, policies, and pod behavior |
| LLM Bridge | TypeScript | Optional Deployment | Natural-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) |
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.
The plugin follows the standard kubectl command structure:
kubectl kguardian gen <networkpolicy|seccomp> [pod-name] [flags]
| Flag | Applies to | Description |
|---|---|---|
-n, --namespace | both | Namespace scope (defaults to current context namespace) |
--all | both | All pods in the selected namespace (-a shorthand: networkpolicy only) |
-A, --all-namespaces | both | All pods in all namespaces |
--output-dir | both | Directory for generated files (network-policies / seccomp-profiles) |
-t, --type | networkpolicy | kubernetes (default) or cilium |
--dry-run | networkpolicy | true (default). Applying directly is not implemented yet — the CLI always writes files only |
--default-action | seccomp | Action 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.
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.
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.
The eBPF Controller requires Linux kernel 6.2 or newer on every node in the DaemonSet. Verify with uname -r before installing.
| Distro | Default kernel | Compatible? |
|---|---|---|
| Ubuntu 24.04 | 6.8 | ✅ |
| Ubuntu 22.04 | 5.15 | ❌ (needs HWE 6.2+) |
| RHEL 9 | 5.14 | ❌ |
| Amazon Linux 2023 | 6.1 | ❌ (needs kernel-6.12+ AMI) |
| Debian 12 | 6.1 | ❌ (needs backports) |
| Talos / Bottlerocket | usually 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.
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:
.status.podIP / .spec.clusterIP. A peer is therefore resolved to a podSelector regardless of which family the traffic used.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.LISTEN_ADDR env still binds verbatim when set.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.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.
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:
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.
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.
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.
Licensed under the Business Source License 1.1:
Rust
40.5%
TypeScript
25.3%
Go
16.8%
C
15.5%