Report event source failures and node coverage in policy status - #247
Merged
Merged
Conversation
Signed-off-by: Jim Bugwadia <jim@nirmata.com>
Signed-off-by: Jim Bugwadia <jim@nirmata.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved source-dependency and monitor-policy classification issues can produce inaccurate coverage and Applied status.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
This PR adds event-source lifecycle observability, per-node coverage aggregation, and monitor-policy status gating.
Changes:
- Adds readiness, failure, retry, and recovery metrics.
- Tracks expected DaemonSet nodes and aggregates source status.
- Updates APIs, CRDs, Helm resources, documentation, and tests.
Review findings:
- Critical (1 vote): Include
open,network, andprotocolpoll sources in dependency coverage. - Moderate (1 vote): Treat omitted modes and empty behaviors correctly when deriving dependencies.
- Nit (1 vote): Clarify the
openexecmgr.Newfailure message regarding filename coverage. - Nit (1 vote): Use
compiler.IsObserveModefor mode classification.
File summaries
| File | Summary |
|---|---|
pkg/runtimeevent/iface.go |
Defines source lifecycle states and callbacks. |
pkg/runtimeevent/iface_test.go |
Tests readiness callback behavior. |
pkg/metrics/metrics.go |
Adds source availability and failure metrics. |
pkg/metrics/metrics_test.go |
Tests source metrics. |
pkg/controller/statuswriter.go |
Aggregates source status and policy coverage conditions. |
pkg/controller/statuswriter_test.go |
Tests aggregation, recovery, and membership changes. |
pkg/controller/daemonplacement.go |
Discovers expected DaemonSet nodes. |
pkg/controller/daemonplacement_test.go |
Tests placement detection. |
pkg/collector/pollsource.go |
Announces poll-source readiness. |
pkg/collector/collector.go |
Tracks lifecycle transitions and retries. |
pkg/collector/collector_test.go |
Tests lifecycle and retry behavior. |
pkg/bpf/exectrace/source.go |
Reopens readers and reports readiness. |
pkg/bpf/exectrace/source_test.go |
Tests reader recovery. |
pkg/bpf/dnsquery/source.go |
Reports DNS reader readiness. |
docs/users/reference/runtimepolicy.md |
Documents source coverage and conditions. |
docs/users/reference/metrics.md |
Documents source metrics. |
docs/dev/DEVELOPMENT.md |
Adds validation guidance. |
docs/dev/DESIGN.md |
Documents lifecycle and aggregation architecture. |
cmd/kyverno-runtime/daemon.go |
Wires lifecycle reporting and placement tracking. |
charts/kyverno-runtime/templates/daemonset.yaml |
Supplies placement identity. |
charts/kyverno-runtime/templates/clusterrole.yaml |
Grants DaemonSet read access. |
charts/kyverno-runtime/crds/runtime.nirmata.io_runtimepolicies.yaml |
Updates the source-status schema. |
api/v1alpha1/zz_generated.deepcopy.go |
Updates generated deepcopy support. |
api/v1alpha1/runtimepolicy_types.go |
Adds source status fields and conditions. |
Agents.md |
Updates package and filtering guidance. |
Review details
Files not reviewed (1)
- api/v1alpha1/zz_generated.deepcopy.go: Generated file
Suppressed comments (4)
pkg/controller/statuswriter.go:690
- When
openexecmgr.Newfails, the daemon recordsexec-tracewithDependencyUnavailableand does not register the open/exec manager or either related source, so filename observations cannot remain available in that failure path. This generic message is therefore misleading; generate a dependency-specific message (or otherwise include the reason) that reports filename coverage as unavailable too.
if state == runtimeevent.SourceStateUnavailable {
return "exec trace source is unavailable; argv observations are unavailable, but exec filename observations may remain available"
}
pkg/controller/statuswriter.go:662
- The dependency is inferred from a non-nil behavior pointer, but an empty
Behavior{}(or a rule with no values or expression) compiles to an emptyAllowDenyPairand creates no observation attachment. A no-op monitor policy will therefore be markedEventSourcesAvailable=Unknown/Falseand itsAppliedcondition will be gated even though it cannot produce events; derive this from the evaluated pair'sHasEntries()(or otherwise distinguish behaviors that can produce targets).
if behavior.Exec != nil && !slices.Contains(dependencies, execTraceSource) {
dependencies = append(dependencies, execTraceSource)
}
if behavior.DNS != nil && !slices.Contains(dependencies, dnsQuerySource) {
dependencies = append(dependencies, dnsQuerySource)
pkg/controller/statuswriter.go:653
- When
spec.modeis omitted, the status path deliberately treats the policy asNoMode(baseAppliedCondition), but this default makes the same policy look like monitor mode here. A policy with anexecordnsbehavior can therefore publishEventSourcesAvailable=Unknown/Falseand source entries even though it is not attached or observed; treat a nil mode as non-observe before deriving dependencies.
mode := compiler.ModeMonitor
if spec.Mode != nil {
mode = string(*spec.Mode)
}
if !compiler.IsObserveMode(mode) {
pkg/controller/statuswriter.go:293
- This new monitor-only gate should use the repository's
compiler.IsObserveModehelper rather than comparing the mode string directly. Otherwise this path can diverge from the mode classification used bysourceDependenciesif another observe mode is introduced.
if mode == compiler.ModeMonitor {
- Files reviewed: 24/25 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Signed-off-by: Jim Bugwadia <jim@nirmata.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes and why
An event source that fails to load or stops reading now appears in per-source availability/failure metrics and in affected monitor policies'
EventSourcesAvailablecondition. Previously, these failures only produced logs, making missing observations indistinguishable from quiet workloads.Each daemon writes policy-relevant source status into its node shard. Cluster aggregation preserves failures across healthy-node updates and reports
Unknownwhen an expected daemon has not reported. Expected nodes come from DaemonSet pod placement and desired count, including pending pods; node deletion and placement changes trigger recomputation. MonitorAppliedreflects incomplete observation coverage without changing enforcement semantics.Dependencies cover every producer: open/exec use
openexec-observe, network/protocol useegress-observe, DNS usesdnsquery, and exec additionally usesexec-trace. Empty behaviors and rules add no dependency. Nonempty expressions conservatively retain dependencies across empty evaluations because later reevaluation can produce targets.Reader readiness and retry transitions share one lifecycle callback; poll sources announce readiness only after a successful poll, and exec tracing reopens its reader on retry and synchronizes reader startup with concurrent closure. Initialization failures require a daemon restart. Status is last-reported availability, without a stale-daemon heartbeat detector; membership changes converge through Kubernetes controller/cache updates and the status flush interval.
Fixes #92.
How it was validated
make buildandmake testpass, including race detection.make kind-installandmake smoke-quickstartpass.make test-e2e-lsmpassed both enforcement and syscall-storm suites on kind with BPF-LSM active (capability,bpf,landlock); daemon restart count remained zero.make lint-docspasses.Unknown; deleting it restoresTrueafter controller convergence. Removing BPF privileges produces source gauges of0, initialization-failure counters, andEventSourcesAvailable=False/Applied=False. Restoring privileges returns source gauges to1and source availability toTrue. Temporary resources were removed and original privileges restored.Generated artifacts
make verify-crdsand regeneration of deepcopy artifacts produce no drift.Documentation
docs/dev/DESIGN.mdand development guidance updated.Commits
git commit -s.