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

【Tetragon / eBPF】TracingPolicy:CRD、三条加载路径与 collectionKey

文章导航

分类入口
kubernetessecurity
标签入口
#tetragon#ebpf#tracingpolicy#crd#collectionkey#fentry#grpc#v1.7.0

目录

第 5 篇 说明三条加载路径进入同一 map。本篇把 TracingPolicy 本身钉死:集群级与命名空间级 CR 差在哪、spec 上有哪些 hook 字段(含 v1.7.0 的 fentries)、list/enable/disable 在本版本的真实语义,以及为何「同名策略」会静默对不上你以为的那份 YAML。

本篇在系列中的位置

篇目 核心内容
第 5 篇 · Agent 生命周期 BTF、socket、三条路径入口
第 6 篇 · TracingPolicy CRD、collectionKey、加载/卸载与 enable/disable
第 7 篇 · 选择器与内核过滤 selector 语义与动作
系列目录 全部篇目

版本锚定:Tetragon v1.7.0(源码 tag v1.7.0)。CRD 与加载逻辑以 pkg/k8s/apis/cilium.io/v1alpha1/tracing_policy_types.gopkg/sensors/handler.gopkg/server/server.go 为准。不把 live 站点的 domain sharding 写成 v1.7.0 事实。无环境则不伪造 tetra tracingpolicy list 输出。


一、TracingPolicyTracingPolicyNamespaced

两者共用同一份 TracingPolicySpec,差别在作用域与 host 过滤资格

TracingPolicy TracingPolicyNamespaced
API kind TracingPolicy TracingPolicyNamespaced
作用域 Cluster(+genclient:nonNamespaced Namespaced
shortName tgtp tgtpn
TpNamespace() 空字符串 对象 metadata.namespace
策略生效范围 可由 podSelector / containerSelector / hostSelector 再收窄 该 namespace 内 Pod;见第 8 篇
hostSelector 允许 null / {}(v1.7.0) kubebuilder XValidation:禁止非空 spec.hostSelector

源码侧 TracingPolicyNamespaced 的校验消息写明:TracingPolicyNamespaced should have a null spec.hostSelector.pkg/sensors/k8s.goupdatePolicyFilter 对「有 namespace 且 hostSelector != nil」再挡一层。

官方概念文档提醒:TracingPolicy 是低层、强能力配置,需要内核与容器知识,否则容易踩 TOCTOU 一类问题。本系列把强制执行语义放到 第 10 篇,本篇只钉加载与字段面。

接口层面两者都实现 tracingpolicy.TracingPolicyTpName / TpNamespace / TpSpec / TpInfo)。Manager 不区分「这份 YAML 当初是 kubectl 还是文件」——只认接口与 collectionKey。这是撞名问题的根源:运维视角的「来源」在 map 里被抹平。


二、CRD 字段总表(v1.7.0)

下表对应 TracingPolicySpectracing_policy_types.go)。hook 细节见 第 3 篇;选择器见第 7 篇;K8s 身份字段见第 8 篇。

字段 类型(文档口径) 作用
kprobes []KProbeSpec kprobe / kretprobe 挂载点
tracepoints []TracepointSpec tracepoint / rawtp
uprobes []UProbeSpec 用户态 uprobe
lsmhooks []LsmHookSpec LSM hook
usdts []UsdtSpec USDT
fentries []KProbeSpec v1.7.0 fentry sensor(与 kprobe 共用 KProbeSpec 形状)
loader bool 启用 loader 事件
podSelector LabelSelector Pod 标签过滤
containerSelector LabelSelector 容器字段过滤(运行时以 policyfilter 为准,见第 8 篇)
hostSelector LabelSelector 主机工作负载:v1.7.0 仅 null / {}
lists []ListSpec 列表规格
enforcers []EnforcerSpec enforcer
options []OptionSpec 覆盖选项
selectorsMacros map[string]KProbeSelector 选择器宏,供 hook 按名引用

本版本没有 spec.nodeSelector 该字段合入晚于 v1.7.0(2026-06-27),系列第 16 篇才作版本后开放项。

fentrieskprobes 共用 KProbeSpec 形状,但走 fentry sensor(Release notes · PR #4039;BPF 侧见 bpf/process/bpf_generic_fentry.c 线索,机制展开在第 3 篇)。写策略时不要假设「把 kprobes: 改成 fentries: 一定行为相同」——挂载原语与内核版本前提不同。

身份相关字段(podSelector / containerSelector / hostSelector)只决定哪些工作负载进入策略;hook 内参数过滤仍由 selectors 完成。两层同时存在时,排障顺序是:先确认工作负载是否进入集合(第 8 篇),再确认 selector first-match(第 7 篇)。

官方文档示例(说明「默认可匹配全部工作负载」时的骨架;非本机实测输出):

apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
  name: "workload-filtering"
spec:
  kprobes:

(摘自 v1.7.0 docs/.../k8s-filtering.md;完整组合语义见第 8 篇。)


三、三条加载路径与 collectionKey

回顾第 5 篇:无论入口是 CR、gRPC 还是文件,最终都调用 Manager.AddTracingPolicy,键为:

\[ \texttt{collectionKey} = (\texttt{name}, \texttt{namespace}) \]

其中 cluster-scoped 策略的 namespace 为空。handler.addTracingPolicypkg/sensors/handler.go)在键已存在且状态不是 LoadErrorState 时拒绝覆盖。

flowchart LR
  kubectl["kubectl_apply_CR"] --> add["Manager.AddTracingPolicy"]
  grpc["tetra_or_gRPC_Add"] --> add
  file["tracing_policy_file_or_dir"] --> add
  add --> key["collectionKey_name_namespace"]
  key --> map["collectionMap"]
  map --> sensors["Sensors_load_attach"]
路径 入口 解析 删除 / 更新要点
CR informer add/update/delete 对象即 TracingPolicy 实现 update:先 DeleteTracingPolicyAddTracingPolicy
gRPC Server.AddTracingPolicy tracingpolicy.FromYAML DeleteTracingPolicy RPC
文件 --tracing-policy / --tracing-policy-dir FromFileFromYAML 进程生命周期内由启动加载;热更新通常改走 gRPC/CR

文件路径在启动阶段由 cmd/tetragon/main.goloadTpFromDir / addTracingPolicy 调用同一 AddTracingPolicy。daemon configuration 文档写明默认目录 /etc/tetragon/tetragon.tp.d/,可用 --tracing-policy-dir 更改。

撞名排查顺序tetra tracingpolicy list(或等价 list RPC)看 (name, namespace) → 确认该键来自 CR、文件还是 gRPC → 再决定改哪一侧。不要假设「只有 kubectl apply 的那份有效」。

静态目录与单文件可以同时使用:loadTpFromDir 先扫目录,再加载 --tracing-policy 指向的文件;二者仍进同一 map。目录内组织方式(按子目录分类)只影响运维检索,不创造额外的键空间。


四、list / enable / disable(含 v1.7.0 gRPC 陷阱)

list

Manager.ListTracingPolicies 遍历 collectionMap,返回策略名、namespace、状态等(具体字段以 protobuf API 为准)。这是核对「谁占用了 collectionKey」的首选接口。

enable / disable(Manager 层仍存在)

Manager.EnableTracingPolicy / DisableTracingPolicy 通过 configureTracingPolicy 在已加载集合上切换启用状态(unload / load),键仍是 collectionKey{name, namespace}

废弃 gRPC:默认直接报错

v1.7.0 Upgrade notes 与 pkg/server/server.go 一致:

因此:文档或旧脚本若仍调用 Enable/Disable TracingPolicy gRPC,在 默认 v1.7.0 配置下会失败——这是版本行为,不是策略 YAML 写错。CLI 子命令若封装了 ConfigureTracingPolicy,以该版本 tetra 帮助为准;本篇不臆造子命令输出。

加载失败可覆盖

addTracingPolicy 允许在已有集合处于 LoadErrorState 时用同键重试加载。其它状态的同键 add 返回「collection with the key already exists」类错误。这解释了「修完 YAML 再 apply 仍失败」:若旧集合已是 Enabled/Disabled,需要先 delete,而不是指望 add 覆盖。

集合状态机(排障用)

collection 在 handler 路径上会出现 Enabled / Disabled / Loading / Unloading / LoadError / Error 等状态(见 pkg/sensors/collection.godoEnableTracingPolicy / doDisableTracingPolicy)。对排障够用的压缩表:

状态方向 含义 常见下一步
进入 Enabled sensors 已 load/attach 查 selector / policyfilter / 导出过滤
停在 LoadError 本次 load 失败,错误留在集合上 读 list 中的错误;修 YAML/BTF 后同键重试或先 delete
Disabled 已 unload,集合仍占键 ConfigureTracingPolicy 再 enable,或 delete 释放键
同键 add 被拒 键被非 LoadError 集合占用 先 list 出来源,再 delete 对侧路径

CR informer 的 update 路径是「先删后加」(updateTracingPolicy),与「就地 patch 期望热更新同一 BPF 对象」不是同一模型:中间会有短暂未加载窗口。对强制执行策略,变更应纳入发布窗口预期(细节见第 10、13 篇)。


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

谱系:Wright et al.(USENIX Security 2002)给出内核可挂钩安全模块的框架视角;TracingPolicy 把「挂哪个点、滤什么、做什么动作」收成一份用户可版本化的声明。Garfinkel(NDSS 2003)提醒:声明再漂亮,若拦截点或加载路径错位,安全属性仍可能落空——本篇的 collectionKey 撞名与废弃 gRPC 报错,正是工程上的「路径错位」变体。

争论:声明式 CR vs 显式 gRPC/文件

主张 在 v1.7.0 的代价
只走 CR GitOps 友好;与 K8s RBAC 对齐 与文件/gRPC 同键冲突时,表象像「CR 没生效」
文件 + gRPC 无 CRD / 无 API server 也能用 多节点一致性与审计要自建;Enable/Disable 旧 RPC 已默认失效

开放问题:后续版本引入的 domain sharding 是否从根上消除撞名——本系列锚定 v1.7.0,只记录「当前必须用唯一 (name, namespace) 纪律」,不把未合入本 tag 的设计写成现状。


六、小结

  1. TracingPolicy 集群级;TracingPolicyNamespaced 仅命名空间内 Pod,且禁止 hostSelector
  2. v1.7.0 speckprobes / tracepoints / uprobes / lsmhooks / usdts / fentriesnodeSelector
  3. 三条加载路径共享 collectionKey{name, namespace};撞名先 list 再删对侧。
  4. Enable/Disable TracingPolicy gRPC 默认报错;用 ConfigureTracingPolicy 或临时 --enable-deprecated-tracingpolicy-grpc
  5. 下一篇进入选择器:AND、最多 5 个、first-match,以及内核动作与用户态动作的分界。

不写边界(本篇)


七、参考资料

规范 / 官方文档(A)

源码(A)

核心论文

站内对照

实验台账


上一篇:Agent 生命周期 · 系列目录 · 下一篇:选择器与内核过滤

读完这篇,下一步读什么

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


By .