Tetragon eBPF 可观测与执行策略
一个平台团队把 Tetragon 装进新节点池后,DaemonSet 很快全部 Ready,进程执行事件却只在旧节点出现。业务容器照常运行,安全面板也没有明显报错。逐节点检查才发现,新节点镜像没有可读的 /sys/kernel/btf/vmlinux,外部 BTF 又与实际内核 build 不匹配;CO-RE 程序没有得到可用的类型信息。绿色 Pod 只证明 agent 进程存活,没有证明目标 hook 已挂载,更没有证明事件进入 ring buffer。
另一个团队为了阻止容器写入敏感路径,把观测策略中的动作改成 Sigkill。测试进程确实被终止,文件内容却已经发生变化。值班人员把“进程死了”误当成“操作没发生”,直到审计复核才看到副作用。内核 hook 位置、动作时机、返回值覆盖能力和目标对象状态没有一起验证,使一条看似强硬的规则产生了错误安全感。
Tetragon 把内核事件关联到工作负载身份
Tetragon 是 Cilium 家族中的 eBPF 安全可观测与运行时执行组件。它在 Linux 内核 hook 上观察进程执行、系统调用、文件和网络 I/O,再关联 namespace、Pod、workload、二进制、父进程和 capability 等上下文。TracingPolicy 负责声明 hook、参数、selector 和 action,agent 把匹配结果写入 ring buffer,再通过 gRPC、JSON 文件或指标交给消费端。Tetragon 概览给出了这条基本链路。
它不是 Kubernetes 准入控制器:对象进入 kube-apiserver 时是否允许创建,不由 Tetragon 判断。它也不是长期保存和跨事件关联的 SIEM。网络访问控制继续由 Kubernetes NetworkPolicy、CiliumNetworkPolicy 或服务网格承担;Tetragon 可以观察 socket 和内核行为,却不应替代完整的网络策略控制面。
Tetragon 可以独立于 Cilium CNI 部署。使用 Cilium 的集群能获得统一生态和部分集成便利,但 agent 并不要求 Cilium Agent 先存在;官方还提供容器部署和 systemd 包入口。选型时因此要区分“属于 Cilium 项目”与“运行依赖 Cilium 数据面”,不要为了采用 Tetragon 被迫更换 CNI,也不要因为已有 Cilium 就跳过内核能力检查。
先把内核、BTF 和权限变成节点准入条件
Tetragon v1.7.0 的最低 Linux kernel 基线是 4.19,但最低版本不是完整能力承诺。BTF 为 CO-RE 程序提供目标内核类型信息;kprobe、tracepoint、fentry、返回值覆盖等能力还受内核配置、符号、架构和安全策略影响。arm64 的旧内核发行线还可能缺少完整 exec 参数读取能力,生产节点应按真实机型逐类探测,而不是只比较版本号。
在安装前选择每类节点的代表机执行:
uname -r
test -r /sys/kernel/btf/vmlinux && echo BTF_OK || echo BTF_MISSING
grep -E 'CONFIG_(BPF|BPF_SYSCALL|BPF_JIT|BPF_EVENTS|DEBUG_INFO_BTF|BPF_KPROBE_OVERRIDE|CGROUP_BPF)=' \
/boot/config-"$(uname -r)" 2>/dev/null || true
sudo tetra probe
tetra probe configBTF_OK 只说明文件可读,外部 BTF 仍必须与精确内核 build 匹配。tetra probe 中的 kprobe、fentry、ring buffer、override return 等结果才决定策略可采用哪些 hook 和动作。若日志出现 BTF search failed、verifier reject、symbol not found、attach failed 或 permission denied,应把该节点标为能力不满足;复制相邻版本 BTF 可能造成错误类型偏移,不能作为修复。
安装者通常需要创建 DaemonSet、CRD、ClusterRole 和 ClusterRoleBinding 的集群级权限。运行时 agent 默认使用 privileged: true、host network 和宿主机挂载,因为它要加载 BPF 并观察宿主进程;Operator 则应保持独立 ServiceAccount。安装权限与运行权限必须分开评审,不能因为安装由管理员完成,就让日志采集器或策略发布者继承同等节点权限。
固定 Chart 和 values 后逐步安装
下面以 Tetragon release 与 Chart 1.7.0 为可复核组合。先确认当前 context 和授权,再保存默认 values,最后执行安装。官方的Kubernetes 安装与升级文档以及对应的 Helm values 参考应与团队锁定文件一起评审。
kubectl config current-context
kubectl auth can-i create daemonsets.apps -n kube-system
kubectl auth can-i create clusterroles.rbac.authorization.k8s.io
helm repo add cilium https://helm.cilium.io
helm repo update cilium
helm show chart cilium/tetragon --version 1.7.0
helm show values cilium/tetragon --version 1.7.0 > tetragon-values-reference.yaml
helm upgrade --install tetragon cilium/tetragon \
--namespace kube-system \
--version 1.7.0 \
--values tetragon-values.yaml \
--wait生产 tetragon-values.yaml 至少要显式评审 tetragon.securityContext、host network、host mounts、nodeSelector、tolerations、resources、export 配置、gRPC endpoint、Operator 和 CRD 管理方式。默认 gRPC 使用 unix:///var/run/tetragon/tetragon.sock,暴露面小于节点 TCP 端口;需要跨 Pod 订阅时,应使用 TLS 或 mTLS、NetworkPolicy、独立客户端证书和短保留凭证,不能把 socket 或无认证端口开放给所有 namespace。
Operator 默认一个副本。仅把 replica 调大不构成 HA,扩展时还要启用 failover lease,并验证 leader 切换期间 CRD 调谐是否继续。CRD 默认由 Operator 管理,升级前应导出 schema 与策略实例;Helm 的 --atomic 可以回滚 release 资源,但不会自动证明 CRD schema 可安全降级。
安装完成要检查覆盖、探针、策略和出口
验证分四层。第一层是目标 Linux 节点是否都有 agent,污点节点、不同架构和专用节点池不能漏掉。第二层是 agent 日志是否显示 BPF 程序加载和 attach 成功。第三层是策略是否进入正确 domain 并处于预期 mode。第四层才是事件是否到达文件或 gRPC 消费端。
kubectl get nodes -o wide
kubectl get daemonset,pods -n kube-system \
-l app.kubernetes.io/name=tetragon -o wide
kubectl rollout status -n kube-system ds/tetragon --timeout=5m
kubectl logs -n kube-system ds/tetragon -c tetragon --tail=200 \
| grep -Ei 'BTF|verifier|attach|policy|error|warning'
kubectl exec -n kube-system ds/tetragon -c tetragon -- \
tetra tracingpolicy list健康判据应写成“目标节点有已加载探针的 agent,目标策略处于预期 mode,受控事件能从预期出口读取”。只看 DESIRED=CURRENT=READY 会遗漏 BTF、hook 和出口故障。若本地事件存在而 SIEM 没有,先区分文件 sink 与 gRPC:tetragon.exportDenyList 只过滤文件导出,不会自动过滤 gRPC 订阅,两个出口的字段和速率策略必须分别验证。
TracingPolicy 从 hook 走到 selector 和 action
TracingPolicy 是集群级 CRD,TracingPolicyNamespaced 把工作负载选择限制在 namespace。策略首先选择 kprobe、tracepoint、uprobe 或 fentry,再描述参数类型;Tetragon 依据 BTF 和符号解析参数,在内核中执行 selector,最后执行 action。一个 selector 内的多个匹配条件通常共同成立,多个 selector 采用首个匹配的短路选择,错误地理解 AND/OR 会扩大事件面或误伤对象。TracingPolicy API和 selector/action 文档应作为评审依据。
下面的教学策略只观察实验 namespace 中的进程执行。字段名和 hook 应以目标 release 的 CRD 与官方示例复核:
apiVersion: cilium.io/v1alpha1
kind: TracingPolicyNamespaced
metadata:
name: observe-process-exec
namespace: tetragon-lab
spec:
kprobes:
- call: "security_bprm_check"
syscall: false
args:
- index: 0
type: "linux_binprm"
selectors:
- matchActions:
- action: Postcall 决定挂载函数,函数是否存在要由目标内核符号确认;args.index 与 type 决定如何解码参数,错误类型可能让策略加载失败或产生错误字段;matchActions: Post 只上报,不改变业务行为。低层 hook 对内核版本很敏感,平台团队应提供经过版本矩阵验证的策略模板,业务团队通过 namespace、workload 或二进制条件收窄,不应自由猜测内核函数签名。
策略来源还分为 k8s、grpc 和 static domain。删除 Kubernetes CRD 不会清理 gRPC 动态加载或静态目录中的同类策略。遇到“资源已删但事件或阻断仍在”时,先查看 tetra tracingpolicy domains 和 tetra tracingpolicy list,按 domain 找到真正 owner,再执行删除。
用观察实验确认事件链而不改变业务
先创建隔离 namespace,应用只含 Post 的策略,再触发一次确定的 exec。下面命令给出可执行合同;输出内容是预期判据,不代表当前仓库环境已经运行过该实验。
kubectl create namespace tetragon-lab
kubectl apply -f observe-process-exec.yaml
kubectl run shell-lab -n tetragon-lab \
--image=busybox:1.36 --restart=Never -- sleep 3600
kubectl wait -n tetragon-lab --for=condition=Ready pod/shell-lab --timeout=120s
kubectl exec -n tetragon-lab shell-lab -- sh -c 'echo tetragon-observe'
kubectl exec -n kube-system ds/tetragon -c tetragon -- \
tetra getevents -o compact --namespace tetragon-lab预期证据包括 namespace、Pod、binary、父进程或 exec 类型,并且 echo 成功返回。若业务命令成功而事件为空,依次确认 Pod 所在节点的 agent、策略 load state、namespace 条件、事件出口和 ring buffer 丢失指标;不要通过删除所有 selector 来制造命中,那会把诊断变成全节点事件洪峰。
实验后执行 kubectl delete -f observe-process-exec.yaml、删除 tetragon-lab,并重新列出三个 domain。清理成功的证据是教学策略不再存在、实验 Pod 已删除、原有生产策略仍处于原 mode,而不是只看到 namespace 进入 Terminating。
执行动作必须验证副作用而不只看进程
策略 mode 包括 monitoring、enforcement 和 monitor_only。monitoring 忽略策略中的执行动作,适合灰度;enforcement 真正执行动作;没有执行动作的 monitor_only 不能临时切成 enforcement。mode 优先级从策略 YAML、加载参数到运行时 gRPC 逐级提高,因此 YAML 写着 monitoring 也可能被运行时设置覆盖。Enforcement mode解释了这套优先级。
Sigkill 会终止触发进程,却不保证被 hook 的操作没有先发生。对 write() 这类操作,收到 SIGKILL 后仍要检查文件内容、socket 发送结果或目标内核对象。需要阻止返回时,可评估 Override,但它依赖内核错误注入框架和 CONFIG_BPF_KPROBE_OVERRIDE,且只适用于允许覆盖返回值的函数。策略创建成功不等于返回值覆盖生效。
安全灰度应在一次性节点池完成:先以 monitoring 加载官方执行示例,确认事件和对象基线;再切 enforcement,检查调用返回码、进程状态和对象状态;最后回切 monitoring,确认业务恢复。反向证据包括 verifier/attach 错误、动作触发但对象已经改变,以及 tetra probe 不支持 override。任一情况都应停止推广,不能用更强信号代替正确的 hook 语义。
persistent enforcement 会把 BPF 程序 pin 在 /sys/fs/bpf/tetragon,agent 退出后动作仍可能持续,期间却没有正常事件流。只有明确需要 fail-closed、验证过内核升级与恢复路径、并有节点级清理权限的环境才应采用;普通检测场景优先让 agent 故障表现为可见的观测缺口。
反向实验用 BTF 缺口证明 Ready 不可信
不要在生产节点删除 BTF。可在不受支持的临时 VM、没有挂载 BTF 的一次性容器或专门节点池复现能力缺口,部署相同 Chart 与策略后观察 agent 日志:
kubectl get pods -n kube-system \
-l app.kubernetes.io/name=tetragon -o wide
kubectl logs -n kube-system ds/tetragon -c tetragon --tail=200 \
| grep -Ei 'BTF search failed|verifier|attach failed|symbol|permission'预期失败是 BTF search failed、类型重定位、verifier 或 attach 的明确错误;Pod 可能仍短暂 Running 或 Ready。恢复精确匹配的 BTF 或合格节点镜像后,应重新运行 tetra probe、确认策略 load state,并重做 exec 正例。这个闭环证明健康门禁需要外部受控事件或探针指标,单纯 readiness 不足。
项目接入要把策略、事件和变更身份绑定
团队接入不应让应用仓库直接拥有集群级执行权限。更稳妥的链路是:应用仓库提交 namespaced 策略意图,安全策略仓库保存审核后的 CRD,CI 做 schema、允许 hook、selector 范围和 action 检查,GitOps 以独立 ServiceAccount 发布;平台记录策略 digest、domain、mode、owner 和回滚版本。
事件输出至少携带 cluster、node、namespace、Pod UID、container ID、binary、策略名、策略版本和事件类型,才能与发布和资产系统关联。命令参数、文件路径、进程凭据和网络地址可能包含 token、客户标识或内部拓扑。聊天通知只发送事件 ID 和脱敏摘要,完整事件进入受控证据库;gRPC 客户端证书、日志后端 token 与 Operator 身份分别轮换和吊销。
镜像应固定 tag 或 digest,并按官方镜像与 SBOM 验证入口验证签名。策略中的 GetUrl、DNS 等可能产生主动出站行为的 action 应单独审批,因为它们不仅改变检测成本,也可能形成隐蔽数据出口。
容量成本看丢事件而不是只看 CPU
Tetragon 的成本由 hook 数量、事件率、selector 复杂度、参数大小、进程上下文、ring buffer、文件写入和 gRPC 消费共同决定。编译节点、批量容器启动、宽泛 exec/file 策略会形成高峰。只看 agent 平均 CPU 会漏掉短时 ring buffer 溢出,而丢失的事件会同时削弱检测与取证可信度。
至少监控 tetragon_observer_ringbuf_events_lost_total、tetragon_observer_ringbuf_queue_events_lost_total、tetragon_notify_overflowed_events_total、tetragon_export_ratelimit_events_dropped_total、tetragon_events_missing_process_info_total 以及 BPF map 更新错误。指标参考可用于确认目标版本名称。没有告警可能表示 selector 不匹配、导出过滤、消费端中断或事件已经丢失,不能直接解释为没有风险。
容量测试要覆盖业务峰值和下游 429/500。先收窄 hook 与 selector,再控制参数和字段,最后调整 buffer、资源与消费管道。文件 sink 和 gRPC 的过滤口径不同,消费端必须有背压、持久化、去重和重连设计;Tetragon agent 本身不替代耐久事件总线。
高可用分为节点传感器和策略控制面
agent 的高可用含义是每个目标节点都有一个实际加载 BPF 的 DaemonSet 实例。某个节点 agent 不可用,该节点就出现新事件缺口;同节点并排两个 agent 往往增加重复和资源竞争,并不能补回历史。Operator 负责 CRD 调谐,多副本需要 lease;gRPC 聚合、跨节点排序和持久化则属于外部事件管道。
升级应先进入与生产内核、架构和安全策略一致的 canary 节点池,比较 tetra probe、CRD schema、策略 load state、受控正例、执行反例、事件字段、丢失指标和资源峰值。DaemonSet 滚动期间每个被替换节点都有观测空窗,更新策略应限制并发不可用数量并记录实际空窗。
回滚必须同时恢复 agent、Operator、Chart values、TracingPolicy、mode、gRPC/文件解析器和 SIEM 字段映射。只回滚镜像可能留下新 CRD 或新策略动作。helm rollback 也不会替团队取消运行时 gRPC mode 覆盖,需要按 domain 和策略逐项核对。
卸载先撤执行语义再删除组件
退出前先把执行策略切回 monitoring,禁用 persistent enforcement,导出需要保留的策略和证据,再删除各 domain 中的策略。确认目标动作已经恢复后,才卸载 release:
kubectl get tracingpolicies,tracingpoliciesnamespaced -A -o yaml \
> tracing-policies-before-uninstall.yaml
kubectl delete tracingpolicy <policy-name>
kubectl delete tracingpolicynamespaced -n <namespace> <policy-name>
helm uninstall tetragon -n kube-system
kubectl get pods -A -o wide | grep -i tetragon || true
kubectl get clusterrole,clusterrolebinding | grep -i tetragon || true若使用过 --keep-sensors-on-exit,还要在每类节点检查 /sys/fs/bpf/tetragon 的 pin 是否清理。外部 gRPC 客户端、证书、NetworkPolicy、日志索引、解析器、dashboard 和告警规则也要核销;历史事件按审计保留策略处理,不能为了卸载干净提前销毁,也不能让无人负责的索引持续计费。
选择 Tetragon 的决定最终取决于团队是否需要低层、可编程的内核事件与可选执行,并且能维护 BTF、hook、selector、动作时机和节点矩阵。若团队更需要成熟高层规则生态,可比较 Falco;需要声明式工作负载约束,可比较 KubeArmor;需要通用准入或网络授权,应回到相应控制面。Tetragon 的优势来自精确能力,治理成本也恰好来自这种精确能力。
