Tetragon replaces Falco + auditd: consolidating runtime security into a single eBPF agent

Running both Falco and auditd on the same node is redundant and costly. Evaluating the direct move to Tetragon 1.4: inline enforcement in the kernel, practical TracingPolicy, and the event data overhead that few people talk about.

Reading progress 0%
Tetragon replaces Falco + auditd: consolidating runtime security into a single eBPF agent

A typical 2024 production node looks like this: auditd logs syscalls for compliance, Falco runs as a DaemonSet sending alerts to Slack, and a commercial EDR agent is plugged in by the security team. Three agents hooking syscalls, three event formats, three log pipelines. When node CPU spikes unexpectedly, the first thing you have to do is... kill some agents to see which one is causing it.

If your team is in that situation, the unified question about a single eBPF agent is no longer "should we try it" but "how do we migrate with minimal pain." This article directly evaluates the Tetragon approach — including the data costs that introductory articles usually ignore.

2026: eBPF is no longer an experimental toy

Two notable milestones. First, AWS EKS chooses Cilium as the default CNI starting in 2025 — when the largest cloud provider puts eBPF on the default path for managed Kubernetes, the debate over "is eBPF production-ready" is effectively closed. Second, Tetragon 1.4 (February 2026) completes the policy authoring aspect — its biggest weakness compared to Falco's mature rule set.

This means the problem is no longer about technology, but about operations: can a single Tetragon agent replace both Falco (detection) and auditd (audit trail), and what is the trade-off?

Falco observes, Tetragon enforces

The core difference is not about "eBPF or not" — Falco has had an eBPF driver for a long time. The difference lies in their position within the execution flow:

Falco Tetragon
Mechanism Observes syscall stream, evaluates rules in userspace Hooks directly in the kernel (kprobe/tracepoint), filters and enforces in-kernel
When a violation is detected Fire an alert; processing is handled by another system Possible SIGKILL process before syscall execution
Risk of omission Events may be dropped under high load, alerts arriving after the fact Enforce inline, no detect-then-react latency
Natural role Detection + alerting Detection + enforcement + audit trail

In short: Falco is a security camera, Tetragon is a camera plus a door lock. With auditd, Tetragon covers the audit trail — process exec, file access, network connection — with Kubernetes context (pod, namespace, label) that auditd never has. That is why one agent can replace two.

The cost of enforce inline: a wrong policy will kill production processes directly in the kernel, leaving no room to "review alert then decide." The correct workflow is to run the policy in observe mode for a few weeks, monitor events, and then enable enforcement. Sigkill.

Write a practical TracingPolicy

Three most common scenarios. First, intercept (and block) shell exec in a production container — a classic reverse shell scenario:

apiVersion: cilium.io/v1alpha1
kind: TracingPolicyNamespaced
metadata:
  name: block-shell-exec
  namespace: production
spec:
  kprobes:
    - call: "sys_execve"
      syscall: true
      args:
        - index: 0
          type: "string"
      selectors:
        - matchArgs:
            - index: 0
              operator: "Postfix"
              values: ["/bin/sh", "/bin/bash", "/bin/dash"]
          matchActions:
            - action: Sigkill

Call process execve with /bin/bash in namespace production killed before the shell could run. Not an alert after 2 seconds — it never runs.

Second, block file writing to /etc (protect /etc/passwd, /etc/shadow, sudo configuration): hook security_file_permission with selector Prefix: /etc and write permission conditions. Third, detect abnormal outbound connections: hook tcp_connect, use selector NotDAddr exclude internal IP ranges and valid endpoints — any egress connection to an unknown IP from an unauthorized workload will be exposed, along with the pod name and the initiating binary.

Strength of the selector model: filtering occurs in the kernel. Non-matching events are dropped on the spot, avoiding the overhead of serializing to userspace. This is the key to the next part.

Real cost: 180GB of events per day

This is what "getting started" guides don't mention. A real-world system of ~4,200 nodes generates about ~180GB of events per day — after dedup. Multiplied by a 90-day retention for compliance, you are looking at ~16TB of hot data for runtime security alone. Storage and pipeline costs, rather than eBPF CPU overhead, are the primary risks of consolidation.

Three principles derived:

  • Filter in the kernel, not at the collector. By default, Tetragon can export all process exec events — on nodes running many cron jobs or CI runners, that's a flood. Use selectors in TracingPolicy and configure --enable-process-credUse /export filters to only push what you will actually read.
  • Separate the two types of data from the start. Security alerts (low volume, high value, long retention) follow one path; audit trails (high volume, low cost, rare queries) follow another — object storage, compression, lifecycle policy. Dumping everything into a single Elasticsearch index is the fastest way to blow your budget.
  • Design retention before enabling agents, not after. "Log everything and decide later" regarding runtime events is a decision worth thousands of dollars per month. Sit with the compliance team to finalize: what needs 90 days, and what only needs 7 days.

Reference architecture: one eBPF stack, one egress path.

Once Cilium is used as the CNI, the logical piece is to consolidate all three observability layers into the same eBPF family, funneling them into a single point:

flowchart LR
    subgraph Node["Each node"]
        C[Cilium / Hubble<br/>network flows] --> OC
        T[Tetragon<br/>runtime security] --> OC
        B[Beyla / OBI<br/>app tracing] --> OC[OTel Collector<br/>DaemonSet]
    end
    OC -->|alert| S[SIEM / Alerting]
    OC -->|audit trail| O[Object storage<br/>rẻ, nén, retention dài]
    OC -->|trace + flow| BE[Observability backend]

OpenTelemetry Collector acts as a middle layer for filtering, routing, and fan-out — where you implement the three principles above without having to modify each agent. One node, one technology stack, one pipeline. Compared to a scenario where three agents conflict at the source, the reduction in debug surface area alone is worth it.

So, should Falco be dropped?

If you are already running Cilium and maintaining both Falco and auditd: yes, a migration roadmap toward Tetragon is logical, provided you stay in observe-mode long enough and solve the data problem first. If you are not using Cilium and the team's investment in Falco rules is deep, the migration value is much thinner — Falco remains a good detection tool.

But don't delude yourself about the nature of the decision. Choosing Tetragon is not about choosing a faster Falco — it is about shifting from a "detect then react" philosophy to "blocking in-place within the kernel." Any tool can be learned; what needs to change is the habit of treating runtime security as just an alert stream to read on Monday mornings.

Done — check your inbox.
Something went wrong. Please try again.