Skip to content

Per-pod program-load failure is reported as NoMatchingPods, not EnforcementUnavailable #188

Description

@dtoledo67

Summary

When a per-pod BPF program fails to load or attach, the pod never enters the matched-pod
index, and the policy that selects it reports Applied=False / PodsMatched=False with reason
NoMatchingPods — even though the selector matched the pod. The one status surface an operator
checks says "your selector is wrong", while the truth is "this node cannot program the pod". For an
enforce policy this is a truth gap: enforcement is absent and the status points away from the cause.

This is the same class CLAUDE.md's observability rule names — a monitoring gap that looks identical
to "nothing happened" is worse than an error
— except here it is worse than silent: the condition is
actively misleading.

Reproduction

Observed on a kernel that ships /sys/kernel/btf/vmlinux but does not implement BTF map load
(BPF_BTF_LOADENOSYS) — Docker Desktop's LinuxKit VM is one. Any per-pod program-load/attach
failure reproduces the same status; the BTF-map case is just an easy trigger.

  1. Daemon starts; per-pod attach fails:
podwatcher  giving up on event after max requeues
  {"pod": "ai-agents/discover", "type": "create", "requeues": 5,
   "error": "field CgroupDnsIngress: program cgroup_dns_ingress: map domain_ids:
             load BTF: detect support for Map BTF (Var/Datasec):
             detect support for BTF: function not implemented"}
  1. A monitor dns (or any network/open/exec) policy selecting app=discover — a label the
    pod carries — reports:
PodsMatched=False / NoMatchingPods : no pod on any of 1 reporting node(s) matches the
                                     policy's podSelector/namespaceSelector
Applied=False     / NoMatchingPods
  1. For the enforce case, the workload reaches a denied destination while the policy shows
    Applied=False/NoMatchingPods — nothing in status, and no EnforcementUnavailable /
    ObservationUnavailable condition, records that the pod was selected and could not be programmed.

Why this is NoMatchingPods

The attach failure requeues 5× (podWatcher) and is dropped, so the pod is never admitted to the
matched-pod index the status derives PodsMatched from. Absence-because-load-failed is then
indistinguishable from absence-because-selector-missed, and the reason string picks the latter.

Ask

A pod that a policy's selector matches, but which the node could not program, should surface as
EnforcementUnavailable / ObservationUnavailable (per the policy's mode) with the load/attach
error in the message — not as NoMatchingPods. The distinction already exists for other
programming failures in pkg/lsmmgr (ObservationAvailable/ObservationUnavailable); the gap is
that a per-pod attach failure routed through the podwatcher requeue path never reaches it and falls
through to the selector-missed reason instead.

Concretely, either:

  • carry the "selected but unprogrammable" fact out of the podwatcher so the status shard can report
    it as a per-node EnforcementUnavailable/ObservationUnavailable with cause, or
  • at minimum, distinguish "no pod selected" from "selected pods failed to program" in the
    PodsMatched/Applied reason so NoMatchingPods is never shown for a selector that did match.

Related

Environment

Product 6bf0494 (v0.0.5-8-g6bf0494). Surfaced during eBay PoV test execution; full evidence in
the PoV run log (nirmata-platform-engineering, projects/runtime/runs/2026-08-17-run01.md).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority/P1High: correctness, security or truth gap

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions