土法炼钢 · 系统与基础设施

【Tetragon / eBPF】Agent 生命周期:BTF、安装形态与三条策略加载路径

文章导航

分类入口
kubernetessecurity
标签入口
#tetragon#ebpf#agent#btf#tracingpolicy#grpc#daemonset#v1.7.0

目录

前一篇把 事件导出 钉到 JSON sink 与 gRPC 分流。本篇换到策略加载轴与 Sensor/Hook 轴的交界:程序没挂上、策略「已 apply 却无事件」、第三方客户端连不上 agent,常见并不在选择器 YAML,而在 BTF 发现失败、socket 地址变更、或三条加载路径撞名

本篇在系列中的位置

篇目 核心内容
第 4 篇 · 事件导出路径 JSON / gRPC / 过滤边界
第 5 篇 · Agent 生命周期 BTF/CO-RE、安装形态、Unix socket、三条加载路径
第 6 篇 · TracingPolicy CRD、collectionKey、enable/disable
系列目录 全部篇目

版本锚定:Tetragon v1.7.0(源码 tag v1.7.0,2026-04-29)。机制结论对齐该 tag 下 pkg/btf/pkg/sensors/pkg/option/、Upgrade notes 与 Helm values。无真实 Tetragon 节点则不粘贴伪造 tetra / agent 日志输出。


一、BTF / CO-RE:程序挂不上时先查这里

Tetragon 的 TracingPolicy hook(kprobe / fentry / LSM 等)依赖内核 BTF 做类型校验与 CO-RE 重定位。agent 启动时通过 pkg/btf.InitCachedBTFobserverFindBTF 解析 BTF 文件;解析失败会直接中止内核自动发现,后续 sensor 无法按预期加载。

发现顺序(v1.7.0)

observerFindBTFpkg/btf/btf.go)在未指定 --btf 时按以下顺序查找:

  1. 环境变量 TETRAGON_BTF(若设置且文件存在)。
  2. 内核暴露的默认路径:/sys/kernel/btf/vmlinuxdefaults.DefaultBTFFile)。
  3. Tetragon lib 目录下的 metadata/vmlinux-<kernelVersion>
  4. lib 目录下的 btf 文件。
  5. 全部失败则返回错误,提示用 --btf 指定路径、或用 --kernel 指定内核版本。

用户显式传入 --btf 时,只检查该路径是否存在;不存在则报 user specified BTF does not exist

失败表象与校验分级

表象 优先核对 源码锚点
agent 启动即中止 / 日志含 BTF search failed /sys/kernel/btf/vmlinux 是否存在;发行版是否裁掉 BTF;--btf 是否指错 observerFindBTF
策略 YAML 已 apply,特定 kprobe 加载失败 hook 名 / syscall 是否写错;参数类型与 BTF 原型是否一致 pkg/btf/validation.go
仅警告、策略仍加载 ValidationWarnError:类型不完全匹配但仍继续 同文件 ValidationWarnError
硬失败、策略拒绝 ValidationFailedError:例如 syscall 原型找不到 同文件 ValidationFailedError

validation.go 在校验 kprobe 规格时默认读取同一套 BTF(可经 TETRAGON_BTF 覆盖)。syscall 场景下,找不到原型会包装成 ValidationFailedError;参数类型与 BTF 不完全一致时多为 ValidationWarnError——警告不等于已挂上正确语义,事件字段可能缺参或类型漂移。

CO-RE 本身的 verifier / 重定位算法不在本篇展开,见站内 ebpf/。本篇只钉 Tetragon 如何找 BTF、找不到时 agent 停在哪一步

排障口诀:策略轴上的「无事件」若伴随 agent 启动失败或 BTF 相关错误,先落本篇,再去改 TracingPolicy 选择器

与 base sensor 的先后关系

cmd/tetragon/main.goInitCachedBTF 成功之后才继续 BPF 特性日志与后续观察者初始化;静态 TracingPolicy 目录与 --tracing-policy 文件的加载发生在更后阶段(loadTpFromDir / addTracingPolicy)。因此:

  1. BTF 失败 → 往往到不了「策略已加载」状态。
  2. BTF 成功、base process sensor 正常,但某条 TracingPolicy 的单个 hook 校验失败 → 更像「策略轴局部失败」,应用 Validation* 错误区分,而不是重装整个 DaemonSet。

内置 process sensor 与动态 hook 的职责切分见 第 3 篇;本篇只要求读者记住:agent 生命周期上,BTF 是硬前置


二、DaemonSet 与主机安装:同一进程模型,不同运维面

两种常见部署形态共用同一 agent 二进制与同一套 sensor 加载逻辑,差别在如何把进程放到「能看见全部主机 PID / cgroup」的位置,以及配置如何注入。

维度 Kubernetes DaemonSet(Helm chart @ v1.7.0) 主机直接安装
进程可见性 chart 默认 hostNetwork: true;容器需 privileged / 等效能力以挂 BPF 本机 root(或具备 BPF 能力)进程
配置入口 Helm values → agent flags / config systemd unit、--config-dir、命令行
策略 CR 默认开启 TracingPolicy CRD(--enable-tracing-policy-crd 默认 true) 通常走文件 / gRPC;无 API server 则无 CR 路径
gRPC 默认(chart) unix:///var/run/tetragon/tetragon.sock 取决于启动参数(见下一节)
policyfilter chart enablePolicyFilter: True 二进制 flag 默认 false(见第 8 篇)

Helm values 写明:Tetragon 必须在 host network 上,进程可见性才完整。把 DaemonSet 改成非 hostNetwork、或丢掉挂 BPF 所需能力,会出现「Pod Running 但几乎无主机进程事件」——这是安装形态问题,不是选择器写错。

主机安装适合无 K8s、或把策略当静态文件管理的场景;一旦需要 TracingPolicyNamespaced / pod 标签过滤,仍要打开 K8s API 与 policyfilter(第 8 篇)。

安装形态还影响排障入口:DaemonSet 上你先看 Pod 日志与挂载的 hostPath(socket、lib、BTF);主机安装上你先看 unit 的 ExecStart 是否带了与文档不一致的 --server-address / --btf / --tracing-policy-dir。两种形态下 collectionKey 语义相同——不要按「K8s 装的」和「裸进程」假设存在两套策略命名空间。


三、v1.7.0 默认 gRPC:Unix socket

v1.7.0 Upgrade notes 写明:Helm 默认 server-addresslocalhost:54321 改为 /var/run/tetragon/tetragon.sock(文档与 chart 写作 unix:///var/run/tetragon/tetragon.sock)。该 socket 在节点上对 root 用户同路径可用;第三方连接 agent 的程序必须更新地址。

同时要对齐三处口径,避免混用 live 文档与二进制默认值:

入口 v1.7.0 行为
Upgrade notes / Helm tetragon.grpc.address 默认 Unix socket
docs/.../concepts/events.md 「default helm install」暴露 unix:///var/run/tetragon/tetragon.sock;可用 --server-address
pkg/option/flags.go KeyServerAddress 默认值 仍为 localhost:54321(裸跑二进制且未改 flag 时)

结论:以 Helm / Upgrade notes 为准写「v1.7.0 默认安装」;裸二进制默认仍是 TCP localhost。 升版后 tetra getevents 连不上,优先查客户端是否还在打 54321,而不是先怀疑策略未加载。

server-address 可关闭 gRPC。JSON 文件导出与 gRPC 所见集合的差异见 第 4 篇

升版检查清单(机制向,非菜谱):

  1. 所有 tetra / 自研 gRPC 客户端是否改为 Unix socket(或显式保留 TCP 并改 Helm values)。
  2. 节点上 /var/run/tetragon/tetragon.sock 是否对排障用户可见(权限与挂载)。
  3. 是否仍有旁路进程监听旧的 54321——Upgrade notes 要求更新第三方程序,不是只升级 chart 版本号。

四、三条加载路径,同一 collectionKey map

官方 Tracing Policy 文档(v1.7.0)列出三种运行时加载方式:

  1. Kubernetes CRkubectl apply TracingPolicy / TracingPolicyNamespaced;informer 调用 sensors.Manager.AddTracingPolicypkg/watcher/crdwatcher/tracingpolicy.go)。
  2. gRPC / tetraAddTracingPolicy RPC,YAML 经 tracingpolicy.FromYAML 后进入同一 Manager。
  3. 启动静态文件--tracing-policy 指定单文件,或 --tracing-policy-dir(默认目录见 daemon configuration:/etc/tetragon/tetragon.tp.d/)扫描后 AddTracingPolicycmd/tetragon/main.goaddTracingPolicy / loadTpFromDir)。

三条路径分成三张独立策略表。pkg/sensors 用:

type collectionKey struct {
    name, namespace string
}

Manager.AddTracingPolicy 构造 collectionKey{tp.TpName(), tp.TpNamespace()},写入同一 collectionMap。集群级 TracingPolicy 的 namespace 为空字符串;TracingPolicyNamespaced 带真实 namespace。键已存在且状态不是加载错误时,再次 add 会失败(handler.addTracingPolicy)。

因此「改了 CR 不生效」的高频原因:同名集合其实由 gRPC 或静态文件先占用;或 cluster-scoped 与 namespaced 的 (name, namespace) 不同,你以为在改同一份策略。v1.7.0 没有 domain sharding(k8s/grpc/static 分域);也不存在 tetra tracingpolicy domains 这类本版本 CLI。分域是后续版本话题,本系列不把它写成 v1.7.0 能力。

sequenceDiagram
  participant Boot as AgentBoot
  participant BTF as BTFDiscovery
  participant Base as BaseSensor
  participant Load as PolicyLoadPaths
  participant Map as CollectionMap
  participant Hook as HookAttach

  Boot->>BTF: InitCachedBTF
  alt BTF missing
    BTF-->>Boot: abort autodiscovery
  else BTF ok
    Boot->>Base: load process base sensor
    Load->>Map: kubectl CR or gRPC or file
    Note over Load,Map: collectionKey name plus namespace
    Map->>Hook: sensor load and attach
  end

上图只回答「从启动到 hook 挂上」的顺序;选择器如何在 hook 内过滤见 第 7 篇,CRD 字段与 enable/disable 见 第 6 篇

失败表象速查(落本篇时)

表象 先查
agent 起不来 / 反复 CrashLoop BTF 路径;--btf / TETRAGON_BTF;特权与 bpffs
Pod Running 但几乎无主机进程事件 hostNetwork / 能力是否被改掉
tetra 连不上 客户端是否仍打 localhost:54321;socket 文件是否存在
kubectl apply 成功但 list 不见或行为像旧策略 collectionKey 是否被文件/gRPC 占用
只在部分节点无效 该节点 BTF/内核是否与策略 hook 前提一致(不是「半个集群策略语法不同」)

五、学术谱系、争论与开放问题

谱系:把「在内核可挂钩点上做强制与观测」写成可扩展框架的经典工作是 Wright, Cowan, Smalley, Morris, Kroah-Hartman, Linux Security Modules: General Security Support for the Linux Kernel(USENIX Security 2002)。LSM 定义的是通用 hook 框架;Tetragon 的 LSM sensor / TracingPolicy 是后来在 eBPF 上消费部分 hook 能力的工程路径。本篇讨论的 BTF 发现与 sensor 生命周期,是「hook 框架能否在本机落地」的前置条件,不是「Tetragon 实现了 LSM 框架」。

系统调用拦截工具的经典失败模式见 Garfinkel, Traps and Pitfalls(NDSS 2003):用户态拦截存在 TOCTOU 与可见性窗口。Tetragon 把过滤与部分动作推到 BPF,正是为缩小这类窗口;但若 BTF/加载失败导致 hook 根本未挂上,学术上的「in-kernel」优势不会自动兑现。

争论:CR 便利 vs 低层 hook 误配

主张 代价
以 CR / Helm 为中心 声明式、可审计、与 GitOps 同构 易忽略同节点上文件/gRPC 同名集合;升级 socket 破坏外部客户端
以静态文件 / 显式 gRPC 为中心 加载路径短、无 API server 依赖 多节点一致性与变更审计要另做;易与 CR 撞名

没有文献能宣布某一侧在所有平台上更优。可检验命题是:你的变更流水线是否唯一写入一条加载路径,以及升版检查清单是否包含 gRPC 地址。

开放问题

  1. 无 OCI runtime hook 时,身份感知策略的 best-effort 窗口有多大——第 8 篇第 15 篇
  2. 标签风暴下 policyfilter 更新延迟如何被 metrics 暴露——后续运维与排障篇回收。

六、小结

  1. BTF 按「内核 vmlinux → metadata → lib/btf → 失败」发现;校验分 Warn 与 Failed。
  2. DaemonSet 与主机安装共用 agent;可见性依赖 host 网络与 BPF 能力,不依赖「多写几条 YAML」。
  3. v1.7.0 默认 Helm 安装使用 Unix socket;裸二进制 flag 默认仍是 localhost:54321
  4. kubectl / gRPC / 静态文件三条路径进入同一 collectionKey{name, namespace} map;撞名优先查路径,不查 domain CLI。
  5. 下一篇展开 TracingPolicy CRD 字段与 enable/disable 在 v1.7.0 的真实错误语义。

不写边界(本篇)


七、参考资料

规范 / 官方文档(A)

源码(A)

核心论文

站内对照

实验台账


上一篇:事件导出路径 · 系列目录 · 下一篇:TracingPolicy

读完这篇,下一步读什么

优先读同系列或同问题的下一篇,把单篇消费变成主题集群。


By .