In twenty years of building and securing cloud infrastructure, the attack pattern that has burned me most consistently is not the exotic zero-day. It is the attacker who lands inside a container, realizes they have more headroom than expected, and starts poking around: running curl to exfiltrate, writing a cron job to /etc/cron.d, or spawning a reverse shell. The attack takes five minutes. Traditional tooling detects it in the logs about four minutes after the damage is done.
This is the central problem with most runtime security approaches: they are fundamentally retrospective. They observe, they alert, they write to a SIEM. By the time a human acts on a Falco alert, the process has already completed, the file is already written, and the attacker has already moved laterally. Detection is necessary but not sufficient. What changes the economics of a runtime attack is enforcement that operates at the speed of the kernel itself.
That is what Tetragon does. It is a CNCF project, originally developed by Isovalent (now part of Cisco as the Cilium team), and it applies eBPF programs directly to kernel hook points. When a TracingPolicy matches, Tetragon can send a SIGKILL to the offending process synchronously, before the syscall completes, before any data leaves the host. This is architecturally different from every userspace-based runtime security tool.
Why Userspace Detection Has a Structural Problem
Before getting into Tetragon’s internals, it is worth being precise about the limitation it addresses. Most runtime security tools, including Falco in its traditional form, work something like this: a kernel module or eBPF probe captures events and streams them to a userspace daemon, which applies rules and fires alerts. The detection happens after the event has been processed by the kernel.
This creates a class of vulnerabilities known as TOCTOU: time-of-check to time-of-use. The tool checks security state after the fact. For many threats this is acceptable, especially low-and-slow reconnaissance. But for high-speed attacks, a shell command that spawns, exfiltrates, and exits in under a second will complete before any userspace engine has processed the event stream. I have seen post-mortems where Falco correctly detected the intrusion, but the attacker had already exfiltrated a database dump by the time the PagerDuty page landed.
The other issue is that userspace rule engines sit outside the kernel’s execution path. They observe what happened, but they are not in a position to prevent it. seccomp and AppArmor can enforce at the kernel boundary, but they require predefined profile files managed per-node, and their rule languages are not Kubernetes-native. You cannot say “deny this syscall only for pods with label tier: prod and only if the process binary is not in the allowed set.” That kind of context-aware enforcement requires eBPF.
Tetragon addresses both problems: it runs the policy evaluation inside the kernel, and it can take enforcement actions (SIGKILL, return value override) before the problematic syscall completes. The check and the action are atomic from the kernel’s perspective.
Tetragon’s Architecture: Three Layers of Observability
Tetragon ships as a DaemonSet and runs one agent per node. Each agent loads eBPF programs into the kernel at the hook points defined by your TracingPolicy resources. When an event matches a policy selector, the eBPF program can emit the event to a ringbuffer (for observability) and optionally execute an enforcement action (for blocking).

The three primary visibility layers are:
Process execution. Tetragon tracks every execve and execveat call. You get the full ancestry tree: which container, which pod, which namespace, which user, which binary, which arguments. This is richer than what you get from Kubernetes audit logs, which only cover API server calls. A process that spawns inside a container without touching the Kubernetes API is invisible to audit logging but fully visible to Tetragon.
File access. Tetragon hooks open, openat, read, write, and related calls. You can write policies that alert or kill on any attempt to read /etc/shadow, write to /etc/cron.d, or open any file under /proc by a process that should not need it.
Network connections. Tetragon observes connect, accept, bind, and sendmsg at the socket level. You can enforce that a specific container image never makes outbound connections to anything outside an allowlist of CIDRs, and Tetragon will terminate the connection at the kernel level.
All three layers are surfaced as Kubernetes-native events with full pod context: namespace, pod name, labels, container name, and the process tree that led to the event. This context-awareness is one of Tetragon’s biggest architectural advantages over generic eBPF tools, which require additional correlation to map kernel events back to Kubernetes workloads.
TracingPolicy: The Kubernetes-Native Policy API
The core configuration primitive in Tetragon is the TracingPolicy custom resource. This is where you define what to observe, how to filter, and what actions to take on a match. The mental model is: hook point plus selectors plus actions.
A minimal policy that kills any process that spawns curl or wget inside a container looks like this:
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: block-network-tools
spec:
kprobes:
- call: "sys_execve"
syscall: true
args:
- index: 0
type: "string"
selectors:
- matchArgs:
- index: 0
operator: "Postfix"
values:
- "/curl"
- "/wget"
- "/nc"
- "/ncat"
matchActions:
- action: Sigkill
The Sigkill action sends SIGKILL to the process synchronously at the kprobe entry point, before execve hands control to the new binary. The spawned process never runs. This is the enforcement semantic that distinguishes Tetragon from detection-only tools.
You can layer selectors to add Kubernetes context. A matchNamespaces selector limits the policy to specific namespaces. A matchCapabilities selector targets only processes with specific Linux capabilities. A matchBinaries selector limits enforcement to specific binary paths. The combination allows you to write policies like “kill any process that opens /etc/shadow if that process is not sshd or passwd, in any pod in the prod namespace.” That level of surgical enforcement is not achievable with seccomp profiles or AppArmor without significant operational overhead.
For understanding the broader policy-as-code landscape in Kubernetes, see the OPA and Kyverno policy enforcement guide for admission-time controls, and note that Tetragon operates at runtime rather than admission time: it is the enforcement layer for events that happen after a pod is already running.
In-Kernel Enforcement: How SIGKILL Actually Works
The enforcement mechanism is worth understanding at a mechanistic level, because it is what separates Tetragon from its peers architecturally.
When Tetragon loads an eBPF program on kprobe/sys_execve, that program runs in the kernel context at the entry point of the syscall, before the kernel has done anything with the request. The eBPF program evaluates the selectors: is this binary on the blocklist? Does this call come from a pod in a monitored namespace? If all conditions match, the program calls bpf_send_signal(SIGKILL), which is an eBPF helper that injects a signal into the current task. The SIGKILL is delivered to the process thread group before the kernel returns from the syscall entry. The process is dead before execve runs.
This is fundamentally different from a userspace agent receiving an event and then trying to send SIGKILL. By the time a userspace agent processes an event, schedules a kill, and that kill is delivered, the process has likely already run. Even on a fast machine with a low-latency event pipeline, there is a gap of at least a few milliseconds, which is enough for many attacks to complete. The in-kernel path has essentially zero gap.
The other enforcement action is return value override: instead of killing the process, Tetragon can override the return value of the kernel function to return an error code, making the syscall appear to fail without terminating the process. This is useful for scenarios where you want to deny a specific capability but keep the process running, for example, making connect() return ECONNREFUSED for any connection outside an allowlist while leaving the application running.
File and Network Enforcement in Practice
I have deployed Tetragon in regulated environments where we needed demonstrable evidence that specific files could not be read by workloads that did not need them. This is the kind of requirement that comes up in PCI-DSS and FedRAMP environments, where auditors want to see technical controls, not just policies on paper.

For file enforcement, a typical policy blocks reads of secret material from application containers:
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: block-sensitive-file-reads
spec:
kprobes:
- call: "fd_install"
syscall: false
args:
- index: 1
type: "file"
selectors:
- matchArgs:
- index: 1
operator: "Prefix"
values:
- "/etc/shadow"
- "/etc/kubernetes/pki"
- "/run/secrets/kubernetes.io/serviceaccount/token"
matchActions:
- action: Sigkill
For network enforcement, Tetragon can deny outbound connections that would bypass service mesh mTLS. This matters in a zero-trust networking architecture where you want to guarantee that every connection is authenticated, not just observed. A policy that kills any process making an outbound connection to a non-loopback address without going through the mesh sidecar is enforceable with Tetragon in a way that is not practically achievable with network policies alone.
One nuance to understand: Tetragon network enforcement operates at the socket system call level, so it is below the service mesh sidecar. A Tetragon policy can block connections that even an Envoy sidecar would see as legitimate, because the policy evaluation happens before the packet hits the sidecar. This is useful for defense-in-depth but requires careful policy design to avoid blocking traffic you actually want.
Tetragon vs Falco vs Tracee: Choosing the Right Tool
This comparison comes up in almost every security architecture review I run, and the answer is almost never “just one.” The tools have genuinely different design centers.
Falco, now a CNCF graduated project, is a detection and alerting engine. Its rule language is mature, there is a large community rule library, and its integration with Kubernetes audit logs adds visibility that Tetragon does not have out of the box. Falco 0.40 made the modern eBPF driver the default, bringing overhead near Tetragon’s in-kernel filtering. Where Falco excels is in behavioral anomaly detection: rules that describe normal behavior and alert on deviations. But Falco cannot enforce in-kernel. A Falco alert is a notification; the action is always in your hands. The container runtime security guide using Falco covers its deployment model and rule authoring in detail.
Tracee, from Aqua Security, occupies a forensics-first position. It captures extraordinarily rich event streams, including events that Tetragon does not hook by default, and its output is optimized for forensic analysis and threat hunting. The tradeoff is resource consumption: Tracee is the most CPU and memory intensive of the three. For environments where the primary use case is incident investigation and threat hunting rather than real-time blocking, Tracee’s depth of capture is valuable.
Tetragon’s design center is enforcement with observability as a secondary output. If your threat model requires that a specific class of attack literally cannot complete, even if detection systems are delayed or compromised, Tetragon is the right choice.

In practice, the pattern I have seen work best in production is Falco for broad behavioral detection and SIEM integration, combined with Tetragon for targeted enforcement on your highest-risk scenarios. You define a small number of TracingPolicies that address your worst-case attack paths (reverse shell spawning, sensitive file reads, exfiltration via unexpected outbound), and you use Falco to cast a wide net for anything unusual. This is defense-in-depth without the operational overhead of running two full-stack solutions: Tetragon’s agent footprint is small, and its policies are narrow by design.
Production Deployment
Deploying Tetragon via Helm is straightforward if you are already running Cilium for Kubernetes networking, but Tetragon also runs independently of Cilium. The two products share an eBPF heritage but have separate Helm charts and can be deployed independently.
helm repo add cilium https://helm.cilium.io
helm install tetragon cilium/tetragon \
--namespace kube-system \
--set tetragon.grpc.address="localhost:54321" \
--set tetragon.enableProcessCred=true \
--set tetragon.enableProcessNs=true
The tetra CLI is the primary operational tool for querying events in real time:
kubectl exec -it -n kube-system ds/tetragon -c tetragon -- \
tetra getevents -o compact --pods my-suspicious-pod
For production, you want to ship Tetragon events to your SIEM. The agent emits events in JSON format over gRPC, and there is native integration with Elastic, Splunk, and any OpenTelemetry-compatible backend. If you are running a cloud-native observability stack with Prometheus, Loki, and Grafana, Tetragon exports Prometheus metrics for event counts and enforcement actions that slot directly into existing dashboards.
One operational concern I have seen bite teams: the Sigkill action on a broad process selector can take down legitimate workloads if your policy selectors are not carefully scoped. I recommend starting every TracingPolicy in “observe-only” mode by omitting the matchActions block entirely, running it for a week, reviewing the event stream, and only then adding enforcement actions. Tetragon makes this workflow easy: observability and enforcement use the same policy syntax, so you iterate in place.
Node kernel version matters. Tetragon requires Linux 4.19 or later as a hard minimum, and the project recommends the most recent LTS kernel (5.10 or later) for full enforcement feature support, particularly on arm64 where earlier kernels have bugs affecting exec argument reads. Most managed Kubernetes offerings (EKS, GKE, AKS) run kernels well above these thresholds, but if you are operating on older node images, check the Tetragon compatibility notes before deploying.
Integrating with CNAPP and Your Security Data Lake
Tetragon does not replace a Cloud-Native Application Protection Platform. A CNAPP provides posture management, vulnerability scanning, and image analysis at build and admission time. Tetragon operates exclusively at runtime. They are complementary layers of the defense stack.
For security operations teams, Tetragon events are most valuable when they land in a security data lake or SIEM. The JSON events map naturally to the OCSF schema (Open Cybersecurity Schema Framework), and the Kubernetes context fields (namespace, pod, labels) are present natively, which saves the correlation work that makes most runtime security event streams difficult to operationalize. A Tetragon enforcement event, a SIGKILL delivery with full process ancestry and container identity, is a high-fidelity signal that maps directly to a case in your SOC workflow.
One integration pattern worth highlighting: Tetragon enforcement actions can drive automated incident response. If Tetragon kills a process in a production pod, that event can trigger an automated workflow: cordon the node, capture a memory snapshot, notify the on-call team, and open an incident ticket. This is not built into Tetragon itself, but the event stream is clean enough to build on top of with minimal enrichment work.
Kernel Secrets and What Tetragon Cannot Do
Tetragon is not a silver bullet, and after twenty years I am allergic to security tools positioned as one. There are meaningful limits.
eBPF program limitations. eBPF programs run in a verifier-constrained environment. They cannot make arbitrary memory allocations, cannot block indefinitely, and have limits on instruction count and complexity. Very complex policy logic must be split across multiple programs or partially implemented in userspace. For most production security policies this is not a practical constraint, but if you are trying to implement a sophisticated stateful policy (block the third connection from this IP in the last sixty seconds), you may hit the limits of what the eBPF verifier will allow.
Kernel version variability. The syscall interface Tetragon hooks is stable, but the internal kernel function signatures change across kernel versions. A TracingPolicy that hooks a kernel function by name (not a stable tracepoint) may need updates when you upgrade your kernel. Stick to tracepoints and syscall hooks where possible; they are guaranteed stable across kernel versions.
Not a substitute for Kubernetes RBAC. Tetragon enforces at the process level inside a running container. It does not prevent a misconfigured RBAC policy from allowing an unauthorized API server call. Admission-time controls, RBAC, and network policies are all still necessary. Tetragon is the last line of defense for what happens inside a running process, not a replacement for admission-time controls.
Container escape scenarios. If an attacker successfully escapes the container namespace to the host, the TracingPolicies scoped to Kubernetes namespaces may not catch the post-escape behavior. Tetragon does have NamespacePolicies that can be scoped to Linux namespaces rather than Kubernetes namespaces, but host-level protection requires careful policy design that most teams do not invest in initially. Pair Tetragon with gVisor or Kata Containers for strong isolation for the most sensitive workloads.
When to Adopt Tetragon
The right time to add Tetragon to your security stack is when you can articulate specific attack scenarios that your current tooling cannot block. “We want better runtime security” is not a sufficient use case; “we need to guarantee that no process inside our payment processing pods can write to the filesystem or make outbound connections, and we need that guarantee to be technical rather than policy-based” is.
Tetragon is also the right choice when you are operating in an environment where SOC response time is measured in minutes and attacker dwell time is measured in seconds. If your threat model includes sophisticated attackers who can move quickly inside a compromised container, a detection-only posture is structurally insufficient. You need enforcement that operates at machine speed, not human speed. eBPF in the kernel is as close to machine speed as you can get.
After more than two years of tracking its production maturity, my read is that Tetragon has crossed the threshold from interesting project to reliable production tool. The TracingPolicy API is stable, the Helm chart is well-maintained, and the CNCF backing provides long-term maintenance assurance. For teams that are serious about runtime security and willing to invest in policy authoring, it closes a real gap in the defense stack that no other tool addresses as directly.
Get Cloud Architecture Insights
Practical deep dives on infrastructure, security, and scaling. No spam, no fluff.
By subscribing, you agree to receive emails. Unsubscribe anytime.
