tetragon 的 podselector 不生效因 label 匹配逻辑与 kubernetes 不一致:仅在 pod 创建时读取 metadata.labels,不支持 matchexpressions、动态更新或大写/下划线 key;需用 matchlabels、全小写中划线 key,并结合 namespaceselector 双层过滤,显式设置 priority 避免冲突,且须显式声明 containerruntime。

为什么 tetragon 的 podSelector 不生效?label 匹配逻辑和 Kubernetes 不一致
因为 tetragon 的 label 过滤不是直接复用 kube-apiserver 的 selector 解析器,而是通过 eBPF 程序在内核态做匹配——它只认 Pod 启动时注入的 labels(即 metadata.labels),不感知 label selector 的动态计算、不支持 matchExpressions,也不处理 label 被 runtime 修改后的更新。
-
tetragon只在 Pod 创建时读取一次labels,后续 patch 或 annotate 不触发策略重载 - 必须用
matchLabels,写成matchExpressions: [{key: "env", operator: "In", values: ["prod"]}]会静默忽略 - label key 必须全小写、中划线分隔(如
tenant-id),带下划线或大写字母的 key(如tenant_id)在 eBPF map 中会被截断或哈希错位 - 多租户场景下,建议用固定前缀隔离,比如统一加
tenant.k8s.io/前缀,避免不同租户误用同名 label
如何让 TetragonPolicy 精确作用于某租户的所有 Pod?用 namespace + label 双层过滤
单靠 label 容易跨 namespace 漏匹配(比如 dev 和 prod namespace 都有 app: api),tetragon 支持在 podSelector 外叠加 namespaceSelector,但注意:两者是 AND 关系,且 namespace selector 只支持 matchNames,不支持 label 匹配。
- 正确写法:
podSelector: matchLabels: tenant.k8s.io/id: "acme" namespaceSelector: matchNames: ["acme-prod", "acme-staging"] - 错误写法:
namespaceSelector里写matchLabels: {name: acme-prod}——tetragon会直接跳过整个策略 - 如果租户 namespace 命名无规律,只能靠 label 标识 namespace 层级,此时需在所有 Pod 注入冗余 label,例如
tenant.k8s.io/ns: acme-prod,再统一用podSelector匹配 - 验证是否生效:用
kubectl get tetracapsule -o wide查看策略绑定的 Pod 数量;若为 0,大概率是 label 键名拼写或 namespace 名不匹配
tetragon 多租户策略冲突时谁优先?策略顺序不决定优先级,靠 priority 字段
tetragon 不按 YAML 文件创建顺序或名字字母序执行策略,所有策略默认 priority=0。当两个策略对同一 Pod 的同一事件(如 exec)定义了不同动作(allow vs deny),结果取决于 priority 值:数值越小,优先级越高;相同 priority 时,行为未定义(实际常为 deny 优先,但不可依赖)。
- 必须显式设置
priority,例如租户白名单策略设为priority: 10,平台级禁止策略设为priority: 5 -
priority是 int32,范围 -2147483648 到 2147483647,但建议控制在 1–100 内,避免维护混乱 - 不要用
priority: 0做业务策略——它常被 Tetragon 自身的 default-deny 策略占用 - 调试时用
tetra get events --output json | jq '.policy_name'看事件最终匹配的策略名,再比对其priority
为什么租户 Pod 的 syscall 事件没上报?检查 processArgs 和 containerRuntime 兼容性
多租户场景下常启用 processArgs: true 来审计命令行参数,但这会显著增加 eBPF map 占用和 event 体积;更关键的是,tetragon 对 containerd 和 CRI-O 的进程上下文提取逻辑不同,某些 runtime 下 podSelector 匹配成功,但因无法关联到容器 ID,导致事件丢失。
- 确认 runtime 类型:
kubectl get node -o wide看CONTAINER-RUNTIME列,containerd v1.7+ 推荐用containerRuntime: "containerd",旧版或 CRI-O 需显式指定"crio" -
processArgs: true在高并发 exec 场景可能触发 eBPF map full(错误日志含map insert failed: -12),此时要调大--bpf-map-size-process-args启动参数 - 租户 Pod 若用了 distroless 或 scratch 镜像,
/proc/[pid]/cmdline可能为空,processArgs报告空字符串——这不是 bug,是 kernel 行为 - 最简验证法:先关掉
processArgs,用eventType: "exec"+processName: "sh"测试基础事件是否上报,再逐步开功能










