Skip to content

Observability

The agent serves three endpoints on monitoring.metricsPort.

Path Purpose
/metrics Prometheus exposition
/healthz Liveness. Succeeds whenever the process is running
/ready Readiness. Fails when policy requires BPF-LSM but it is not loaded

Liveness deliberately does not depend on readiness, so a degraded agent is not restarted in a loop.

Metrics

Metric Meaning
kernelseal_exec_events_total Process executions observed
kernelseal_secrets_issued_total Secrets released to processes
kernelseal_secrets_denied_total Secret requests refused
kernelseal_access_blocked_total Accesses blocked by the LSM
kernelseal_access_audit_total Accesses audited but allowed
kernelseal_protected_pids Currently protected processes
kernelseal_pods_watched Size of the pod cache
kernelseal_lsm_loaded 1 when the LSM programs are attached

Two of these deserve alerts:

kernelseal_protected_pids dropping below the expected count is the only indication that an agent restart ended protection for running workloads. The BPF maps do not survive the agent process, so an upgrade, OOM kill or eviction leaves already-running protected processes unprotected, with nothing in their own logs to say so.

kernelseal_pods_watched at zero on a node-wide agent means every request is being refused, which is otherwise hard to distinguish from an agent with nothing to do.

Logging

monitoring.logLevel accepts debug, info, warn or error and defaults to info. Per-exec tracing sits at debug, because a host that runs a configured binary in a loop otherwise produces a continuous stream of [EXEC] lines that buries everything else. Secret delivery and LSM decisions are logged at info and above, so the default level shows what matters.

[START] Starting KernelSeal - Secret Protection System
   Version: v1.2.0
[CONFIG] Loaded KernelSeal configuration from /etc/kernelseal/config.yaml
[REGISTER] 2 secrets registered for binary: myapp
[OK] Exec monitor BPF programs loaded and attached
[FILTER] Kernel-side filtering enabled for 1 binaries: [myapp]
[OK] LSM BPF programs loaded and attached
[CONFIG] Policy configured: mode=enforce, environ=true, mem=true, ptrace=true
[SOCKET] Listening on /run/kernelseal/kernelseal.sock (mode 0660)
[METRICS] Serving /metrics, /healthz and /ready on [::]:9090

[PROTECT] pid=5678 marked protected before release (pid=5678 uid=1000 ...)
[ISSUE] Released 2 secrets to "myapp" [API_KEY DB_PASSWORD] (pid=5678 ...)
[LSM BLOCKED] PID=9999 (cat) uid=0 attempted environ access to PID=5678

The most useful line in the log

[REGISTER] N secrets registered for binary: ... with N of zero means the sources did not resolve. The shim will be told the binary has nothing bound to it and the process runs unprotected, which looks identical to enforcement being broken. Check this first.

Denials name the calling pod's namespace, name and UID rather than only a PID, which is usually gone by the time anyone reads the log.

Verifying protection is actually on

# Blocked access attempts
curl -s localhost:9090/metrics | grep kernelseal_access_blocked_total

# Currently protected processes
curl -s localhost:9090/metrics | grep kernelseal_protected_pids

# Enforcement is available
curl -s localhost:9090/metrics | grep kernelseal_lsm_loaded

Note that kubectl exec into a pod starts a new process, which is not the protected one, so its own environment will not contain the secrets. That is expected and is not evidence that delivery failed.