lookout triage delta
Every abnormal object in one scan — the first call for “anything wrong in this cluster?”: broken/pending pods, stalled rollouts, workloads blocked from creating pods at all, node pressure/NPD/preemption, gridlocked PDBs, degraded kube-system add-ons, quotas at their limits.
MCP tool: k8s_triage_delta (MCP profile: triage)
lookout triage delta [flags]| Flag | Type | Default | Meaning |
|---|---|---|---|
--only | string | pods,nodes,pdb,system,quota | comma-separated finding classes to scan: any subset of pods,nodes,pdb,system,quota |
--restarts | int | 5 | flag containers restarted at least this many times |
--pending-age | duration | 5m | flag Pending pods older than this; also the grace before a not-ready container in a Running pod is flagged |
--quota-warn | int | 90 | warn when a ResourceQuota resource reaches this percent of its hard limit (the hard limit itself is always critical) |
--cron-grace | duration | 5m | how late a CronJob activation may be before it counts as missed; absorbs normal controller scheduling latency |
Common flags (every lookout command)
Section titled “Common flags (every lookout command)”| Flag | Type | Default | Meaning |
|---|---|---|---|
--namespace | string | — | limit the scan to one namespace |
-A | bool | — | scan all namespaces |
--workload | string | — | target one workload as <Kind>/<namespace>/<name>, e.g. Deployment/prod/api |
--since | duration | — | how far back to look (0 = command default) |
--format | string | logfmt | output format: logfmt|json (one record per line either way) |
--timeout | duration | 10s | abort the invocation after this long (exit 1) |
--kubeconfig | string | — | path to a kubeconfig file, instead of $KUBECONFIG / ~/.kube/config |
--context | string | — | kubeconfig context to read, instead of its current-context. Selects a cluster for THIS invocation only — nothing is written back — so concurrent invocations can target different clusters. Reported as context=<name> in the summary line |
--exemptions | string | — | path to a git-reviewed exemption file (YAML); covered findings are ANNOTATED with their reason and expiry and counted as exempt=<n> in the summary, never dropped |
Finding kinds
Section titled “Finding kinds”Every kind= this command can emit, and the severities it carries them at. Nothing else appears in its output; a kind absent from a run means the check looked and found nothing. See the finding-kind glossary for the whole vocabulary.
| Kind | Severity | Claim |
|---|---|---|
pod.crashloop | critical | a container is crash looping |
pod.imagepull | critical | a container cannot pull its image |
pod.waiting | warning | a container is stuck in an error waiting state (CreateContainerConfigError, InvalidImageName, …) |
pod.oomkilled | warning | a container’s last termination was an OOM kill |
pod.restarts | warning | a container has restarted at least —restarts times |
pod.notready | warning | a container in a Running pod has been not-ready past the —pending-age grace |
pod.failed | warning | the pod reached phase Failed |
pod.pending | critical, warning | the pod has been Pending longer than —pending-age with no container-level diagnosis; critical when the scheduler has declared it Unschedulable, which is a capacity or constraint problem rather than latency |
workload.replicafailure | critical | the controller cannot create pods at all (quota, PodSecurity, admission) — no pod exists to diagnose |
workload.stalled | critical | a Deployment’s Progressing condition is False: the rollout has given up |
workload.rollout | critical, warning | replicas are short of desired; critical when nothing is serving at all |
job.failed | warning | a Job’s Failed condition is set |
cron.missed | critical, warning | an unsuspended CronJob’s schedule said to run more than —cron-grace ago and status says it did not; critical once several activations in a row are gone |
cron.unparseable | warning | a CronJob’s spec.schedule could not be parsed, so its activations cannot be judged at all |
node.notready | critical | the node’s Ready condition is not True |
node.pressure | critical | the node reports Memory/Disk/PID pressure |
node.condition | critical, warning | a non-standard node condition is True — NPD and its cousins publish problems that way |
node.cordoned | warning | the node is unschedulable but still holds pods: a stuck drain or a forgotten maintenance step |
node.preempt | critical, warning, info | a reclaim taint marks the node for termination; severity tracks how imminent |
pdb.gridlocked | critical, warning | the budget permits no disruptions; critical when healthy pods are already below the required minimum |
addon.degraded | critical, warning | a kube-system add-on (dns, proxy, cni, csi, metrics, connectivity) is short of replicas; critical when none are available |
quota.near | warning | a ResourceQuota resource is at or past —quota-warn percent of its hard limit |
quota.exhausted | critical | a ResourceQuota resource is at its hard limit: the next create is rejected |
Output fields
Section titled “Output fields”Beyond the shared envelope fields (kind, severity, namespace, kind_of_object, name, reason, message, fingerprint, exempt_reason, exempt_expires):
| Field | Meaning |
|---|---|
container | container the finding is about (init containers prefixed init:) |
image | image reference that failed to pull |
restarts | container restart count |
exit_code | exit code of the container’s last termination |
last_state | reason of the container’s last termination (e.g. OOMKilled) |
age | how long the abnormal state has persisted |
desired | desired replica/scheduled count from spec |
ready | ready count from status |
updated | updated-to-current-revision count from status |
available | available count from status |
failed | failed pod count of a Job |
schedule | a CronJob’s spec.schedule |
expected | the activation a CronJob should have run and did not |
missed_runs | activations missed since the anchor; ≥N when the walk was capped |
anchor | what the missed count was measured from: last_schedule or creation |
time_zone | a CronJob’s spec.timeZone, when set |
last_schedule | a CronJob’s status.lastScheduleTime, or never |
active_jobs | Jobs a CronJob still has running |
condition | node condition type that is abnormal |
taint | taint key indicating reclaim/drain |
pods | pods affected (behind a cordoned node or a PDB) |
healthy | currently healthy pods behind a PDB |
required | pods the PDB requires healthy |
addon | system add-on role: dns, proxy, cni, csi, metrics, connectivity |
resource | ResourceQuota resource name at or near its limit |
used | quota usage from status |
hard | quota hard limit from status |
pct | quota usage as percent of the hard limit |
Output contract
Section titled “Output contract”Output: one finding per line (logfmt; —format=json for one JSON object
per line), keys in fixed order; healthy resources emit nothing. The final
line is always the summary: scanned=
Examples
Section titled “Examples”lookout triage deltalookout triage delta --namespace=prod --only=pods,quotalookout triage delta --only=nodes --format=json