AI 博客

Falco、Tetragon、Tracee 与 KubeArmor 对比

规则库大小什么也决定不了,「检测 vs 阻止」也一样。Kubernetes 运行时安全假定一个工作负载有一条行为基线,而一个编码智能体的基线是「一个开发者可能做的任何事」——所以那根轴是:传感器能不能把一次系统调用归因到某一次工具调用。然后是第二个决定:杀掉一个工具子进程并不能停下一个智能体,它只是给那个循环递去一次无从解释的崩溃与一个重试的理由。

作者 智能体 AI 维基 28 分钟读完

在这件事上,规则库大小什么也决定不了,「检测 vs 阻止」也一样。真正决定一个运行时传感器摆在智能体前面有没有用的那根轴,是它能不能把一次系统调用归因到某一次工具调用——因为整套 Kubernetes 运行时安全模型都假定「一个工作负载有一条行为基线」,而一个编码智能体的基线是「一个开发者可能做的任何事」。这件事弄错,你买到的是一个对智能体本该跑的每一次 curl 都报警的传感器。弄对了,第二个决定才是那个从没被人正确表述过的:杀掉一个工具子进程并不能停下一个智能体,它只是给那个循环递去一次无从解释的崩溃,以及一个「换个方式再试」的理由。

一眼概览

四个项目,对「然后呢」给出四个不同的答案。

项目出身与状态机制最擅长
Falco Sysdig,2016 年;2018 年捐给 CNCF;2024 年毕业 eBPF 驱动(或内核模块)把 tracepoint 与 kprobe 事件喂给一个 YAML 规则引擎 广度。最大的社区规则库、映射到 ATT&CK,也是别家都拿来对标的那套检测
Tetragon Isovalent / Cilium,CNCF eBPF 原生传感器加 TracingPolicy;一个 override 动作能在系统调用主体运行之前把它拦下 进程谱系与内核内强制,而且是四者中实测开销最低的
Tracee Aqua Security,开源 eBPF 原生传感器,自带特征库加 Rego 策略,并能抓取制品 取证。容器逃逸、注入与权限提升的特征,而且证据一并带上
KubeArmor AccuKnox,2021 年;CNCF Sandbox,正在申请 Incubation 用 AppArmor、SELinux 或 BPF-LSM 策略让内核直接拒绝该操作;eBPF 只用于可见性 声明式最小权限。一张关于二进制、路径与目的地的允许清单,就地强制
Sensor CPU cost, millicores on a 2-vCPU node Horizontal bar chart of steady-state agent CPU consumption measured in one 2025 comparison on two-vCPU Kubernetes nodes. Falco used roughly 430 millicores, Tracee about 92, and Tetragon about 6.5. KubeArmor was not in that measurement. The spread is roughly sixty-fold between the highest and lowest. Steady-state sensor CPU, millicores per node 100 200 300 400 Falco 430 Tracee 92 Tetragon 6.5 KubeArmor not included in this measurement One 2025 comparison, one workload shape, 2-vCPU nodes. Read the ordering, not the digits. Cost is per event, and an agent harness execs a new process for every tool call.
一份 2025 年的对比、一种工作负载形状。发现在于次序;那些数字本身搬不走。

这个差距对智能体比对普通服务更要紧,而原因是机械的:这些传感器按事件计费,而一个智能体外壳会为每一次工具调用 exec 出一个新进程。一个启动一次、然后处理请求的服务几乎不产生 exec 事件。一个带 shell 工具、跑二十步任务的智能体会产生几百个,再加上它跑的每条命令的每个子进程。不管在你的内核上绝对数字是多少,你的智能体节点就是那些「按事件计费的传感器会变贵」的节点。

为什么那套标准模型在智能体工作负载上会坏掉

Kubernetes 运行时安全建立在一条几乎总成立、而在这里不成立的假设上。这条假设是:一个工作负载有一条可被描述的基线——这个镜像会跑这些二进制、打开这些路径、连这些服务,别的任何事都值得一条告警。正是这条假设让共享规则库成为可能——「容器里起了一个 shell」是一条好检测,因为在一个正常容器里它确实是条好检测。

智能体把它翻了过来。一个编码智能体的工作就是起 shell、装包、克隆仓库、跑测试套件、拉起编译器,并向各种源开网络连接。把 Falco 的默认规则集指向一个编码智能体节点,你会在第一个成功任务上就触发 Terminal shell in container、Launch package management process、Write below etc 以及十几条别的。而通常的应对——对那个命名空间把这些规则压掉——留给你的是一个「盯着智能体、而大部分检测已被关掉」的传感器,那比不部署更糟,因为现在多出了一块暗示自己有覆盖的仪表盘。

所以该问候选传感器的不是「它能检测什么」,而是「它能分辨什么」。有三项能力承担着分量:

  • 进程谱系。一条规则能不能表达「这个 curl 是智能体那个 shell 工具在第三层的后代」,而不是「这个 pod 里发生了一次 curl」?智能体自己的工具调用与一段载荷的子进程,在 pod 这一级看起来一模一样,在 exec 树上则完全不同。
  • 按进程的策略,而不是按镜像的策略。一个智能体 pod 通常跑着一个长寿的外壳进程,加上一串短命的子进程。一条按镜像划范围的策略用一条规则把两者都盖住;一条按进程子树划范围的策略能允许外壳做事、同时约束那些子进程。
  • 一个能活着进到事件里的运行标识。四者都不原生提供它,而这正是值得围着它做工程的那道缝:你的外壳知道当下是哪次运行、哪次工具调用,而传感器知道是哪个 PID 干了什么。把两者 join 起来,意味着要盖一个内核看得见的印——按运行划一个 cgroup、按会话给一个专用 uid 或 gid,或者一个传感器会导出的进程组标签——而它能把一串匿名系统调用变成可归因的动作。这与各自隔离的运行,互相找到了对方里的那套 join 论点是同一个,只是往下挪了一层。

对候选名单的实际后果:Tetragon 的长处恰恰是前两项,因为进程谱系是它的原生模型、而不是一项富化。把它选来跑智能体工作负载,这是个比它那个人人都在引用的开销数字更好的理由。

每一个究竟挂在哪里

Where each sensor attaches, relative to the kernel's permission decision The agent process issues a syscall. Sensors attached to tracepoints and kprobes observe the call and can report it, which is where Falco and Tracee sit. Sensors attached to LSM hooks run before the kernel grants permission, which is where KubeArmor sits and where Tetragon's override action takes effect. Everything to the left of the permission decision can deny; everything to the right can only report, or kill the process after the fact. One syscall, and the line that decides whether a sensor can say no Agent tool call execve, openat, connect one exec per tool call LSM hooks fire BEFORE permission a hook here can return EPERM Kernel grants or denies the decision point after this, the effect happened CAN PREVENT CAN ONLY REPORT, OR KILL AFTER KubeArmor AppArmor / SELinux / BPF-LSM declarative allow-list, inline deny eBPF used for visibility only Tetragon — override TracingPolicy with an override stops the call before its body runs also does process lineage Falco tracepoints / kprobes, eBPF driver largest community rule library alerting; response is a separate tool Tracee signatures plus Rego policy artefact capture for forensics strong on escape and injection OpenShell, for contrast same primitives (Landlock, seccomp) but installed by the harness, per agent process, before the agent starts. These four are node-wide sensors owned by the platform team. Different owner, different lifecycle, both useful. For an agent, the side of the dashed line matters less than what the response does to the loop: a denial returns an error the model can read and adapt to; a kill returns an unexplained crash it will retry.
那条虚线是内核的许可判定。在它左边你能说不;在它右边你只能说「发生过一件事」。

Falco

Falco 是那个参照点,而它对得起这个位置。2016 年生于 Sysdig、2018 年捐给 CNCF、2024 年毕业,它通过一个 eBPF 驱动读取内核事件流,并拿一套可读的 YAML 语法规则去求值,配着可得的最广社区规则库与持续维护的 ATT&CK 映射。它的模型是告警:一次命中产出一个事件,而「拿它做点什么」是生态里另一个组件的事、不是引擎的一部分。对智能体而言,请把它当成你的勘探工具——在一批智能体节点上以纯告警模式跑两周,它的输出就是一份「你的智能体实际都在干什么」的行为清单,而那正是你在能为本清单上任何别的东西写策略之前所需要的东西。

Tetragon

Tetragon 是 eBPF 原生的,而且是围着进程树建起来的,而这正是在这里要紧的那条性质。一条 TracingPolicy 能匹配内核函数与参数,而它的 override 动作会在系统调用主体执行之前把这次调用拦下——是真正的预防、而不是事后反应。它自己的文档对那个多数报道会抹平的区别很谨慎:override 是阻止,而一个 Sigkill 动作会终止该进程、但不保证那次正在飞的操作被停住了。请记住这句话;它就是下一节的全部内容。它在上面那份对比里也以很大差距成为三个传感器里开销最低的,而对 exec 频繁的智能体节点来说,这不是一个可以四舍五入掉的细节。

Tracee

Tracee 是那个取证答案。它带一套映射到 ATT&CK 的特征库、支持用 Rego 写自定义检测,而它的差异化在于制品抓取——某条规则命中时,你拿到的是证据、而不是日志里的一行。它在容器逃逸与进程注入模式上尤其强,而对一个按设计就在运行不可信代码的智能体来说,那正是对的那份候选名单。如果你的失败模式是「出了一次事故,而我们几乎什么都重建不出来」——也就是只有一边看得见那次入侵里描述的处境——那这个项目正是直接冲着它去的。

KubeArmor

KubeArmor 是这里的异类,也是某件具体活儿的最佳人选。它压根不用 eBPF 来做强制——它把策略编译到 AppArmor、SELinux 或 BPF-LSM,让内核自己去拒绝那个操作,eBPF 只用来做可见性。它由 AccuKnox 在 2021 年创建,自 2021 年 11 月起处于 CNCF Sandbox,目前正在申请 Incubation。它想要的形状是一张声明式允许清单:这些二进制可以执行、这些路径可以写、这些目的地可以到。对一个「合法工具面你数得出来」的智能体——一个客服智能体、一个数据分析智能体、一个只有六个脚本的运维智能体——这非常接近对的那道控制;而它与 OpenShell 用 Landlock 和 seccomp 摆出的姿态相同,主要区别在于策略归谁所有。

响应动作才是那个决定,而「杀掉它」通常是错的

Three response actions and what each does to a running agent loop Three columns. An alert leaves the action completed and the loop unaware, so the agent keeps going and a human arrives later. A SIGKILL removes the tool subprocess with no explanation, so the model sees a crash and retries a different way, and the in-flight operation may already have landed. A denial returns EPERM to the tool, which the harness surfaces as a tool error the model can read, so the agent adapts or stops and the refusal is attributable. The response action is the product decision, not the detection ALERT ONLY Falco, Tracee default the action completed the loop never noticed a human arrives minutes later good: no blast radius on false positives Use for: unknown behaviour SIGKILL THE PROCESS Tetragon, KubeArmor tool subprocess disappears model sees an unexplained crash it retries, differently in-flight operation may already have landed Use for: the agent itself, once DENY BEFORE EXECUTE LSM hook returns EPERM nothing happened tool returns a readable error model adapts or asks the refusal is attributable to a named rule Use for: everything you can name Killing a tool subprocess does not stop an agent — it hides the reason and hands the loop a retry.
同一条检测,三种未来。只有一种会告诉智能体发生了什么。

对一个常规工作负载来说,检测与阻止坐在一根直白的轴上:告警更便宜更安全,拦截更强更有风险,而杀掉一个进程是拦截的钝版本。对智能体而言,这根轴会弯,因为你要响应的那个东西不是那个进程——而是一个会观察结果、然后再次行动的循环。

杀掉那个子进程,智能体看到的是一个「退出了、没有输出」的工具。它完全不知道为什么,它没有理由相信这个动作是被禁止的、而不是不稳定的,而它对一个不稳定工具受训得来的反应就是再试一次,常常换条路。你压掉了一次尝试、什么也没教给那个循环,代价是仪表盘上多了一个看起来像强制的信号。更糟的是,按 Tetragon 自己的提醒,那个在信号落地时已经在飞的操作很可能已经完成了。

换成拒绝那次系统调用,形状就整个变了。工具拿到 EPERM,你的外壳把它呈现成一次工具错误,而模型读到的是一句描述「被拒绝了」的话。现在它可以调整、可以提问、可以停下,而你的追踪里装着一次可归因、挂在一条具名规则上的拒绝,而不是一个无从解释的退出码。这就是「一道智能体能推理的控制」与「一道它只能撞上去的控制」之间的区别,也正是结构化拒绝与「为什么」轨迹那套论点,只是搬到内核边界、而不是工具边界上讲。

  • 对任何你叫得出名字的东西,优先选「执行前拒绝」。挂在 LSM 钩子上的强制(KubeArmor,或 Tetragon 的 override)返回的是一个错误、而不是一具尸体。
  • 把「杀」留给智能体进程,而不是工具。如果结论是「这次运行必须停」,那就停这次运行——外壳、循环、整个东西——并把原因记下来。杀掉一个子进程是一个被读成完整措施的半措施。
  • 确保那次拒绝以文字形式抵达模型。一次以空 stderr 形式呈现的策略拒绝,功能上与一次杀掉无异。这是外壳侧的工作,也是团队会跳过的那部分。
  • 对智能体节点来说,纯告警是一个正当的稳态。考虑到一个合法智能体的行为面有多宽,一个高召回检测器加一条人工队列,胜过一个调得过头、会弄坏任务的拦截器。请接受这一点,并把它好好埋点,而不是假装你能靠拦截拦到安全。

什么时候选哪个

处境先上因为
生产里已经有智能体,而运行时可见性完全为零Falco,纯告警检测面最广,也是拿到行为清单最快的路;之后再基于数据去调
工具调用频繁的智能体节点,而你在意归因Tetragon进程谱系是原生的,而按事件的开销是这组里实测最低的
你本来就在跑 CiliumTetragon同一个项目家族、同一套运维模型,节点上少一个 agent
智能体的合法工具面数得出来KubeArmor对一个有界的面来说,挂在 LSM 钩子上强制的声明式允许清单是最便宜的正确控制
你需要重建事故,而不只是察觉它们Tracee制品抓取加逃逸与注入特征,给你的是证据而不是一行日志
你想要一层智能体放宽不了的强制OpenShell 或 KubeArmor两者都编译到内核原语;按「策略该归谁所有」来挑——外壳还是平台团队

常见的生产形状是其中两个、而不是一个:一个高召回检测器以告警模式盯着你数不出来的那部分行为,加一张就地强制的允许清单管住你数得出来的那部分。这不是拿不定主意——这两者回答的是不同的问题,而只跑后一个意味着你永远学不到自己哪里弄错了。

常见问题

如果我已经在跑 OpenShell 或一个 seccomp 档位,还需要这里的某一个吗?

它们回答不同的问题。一条按进程的内核策略框住的是「一个智能体可以做什么」,并且由启动它的那一方装上。这四个是由平台团队拥有的节点级传感器,它们跨工作负载地看——包括智能体的子进程、旁挂容器,以及任何逃出来的东西。强制那一层确有重叠,可见性并不重复。

Falco 的默认规则在智能体节点上管用吗?

按原样不管用。像「容器里起了一个 shell」或「跑了一个包管理器」这样的检测,对正常工作负载是对的,而它们描述的是一个智能体平平无奇的周二。请预期要重写、而不是压制,并且要写引用进程谱系、而不是引用镜像身份的规则。

eBPF 强制在生产里安全吗?

挂在 LSM 钩子上的强制是一条受支持的内核机制,而 KubeArmor 走的 AppArmor 与 SELinux 那条路已有数十年历史。风险不在机制,而在你的策略:一次就地拒绝上的误报会弄坏一个任务。任何新策略都请先以审计模式跑,再按规则逐条提升。

怎么把一个运行或会话标识送进传感器的事件里?

盖一个内核看得见的印。按运行划一个 cgroup、按会话给一个专用 uid 或 gid、或者一个独立的进程组,这些对这些传感器都是可见的,并且能与你外壳自己的追踪干净地 join 上。在写策略之前先把这件事做掉,才让基于谱系的规则成为可能。

哪一个会抓住一个通过短链服务外泄的智能体?

按默认配置,一个都不会——一次发往热门主机的 HTTPS 连接在系统调用层面并不异常。那个失败类别是出站策略问题,不是运行时传感器问题;机制在「只允许 GET」本身就是一条写信道里。这些工具看得见发起那次连接的进程,那在事后有用,但不是一道控制。

延伸阅读

本站:

项目来源:

  • Falco——CNCF 已毕业的运行时安全项目。
  • Tetragon——基于 eBPF 的安全可观测性与运行时强制。
  • Tracee——用 eBPF 做运行时安全与取证。
  • KubeArmor——用 LSM 做运行时安全强制。