lookout triage top
Point-in-time CPU/memory saturation vs limits: kubectl top, but judged — usage-vs-limit percent per container with the OOM asymmetry built in (memory ≥95% of limit is critical, CPU caps at warning: it throttles, it does not kill); -A adds node usage vs allocatable. Trends/ETAs live in the sentinel’s saturation source; —history adds window stats via the cloud provider.
MCP tool: k8s_resource_top
lookout triage top [flags]| Flag | Type | Default | Meaning |
|---|---|---|---|
--top-warn | int | 80 | report a container/node only at or above this percent of its limit/allocatable (zero nominal state; memory additionally turns critical at 95%) |
--all | bool | — | exploratory dump: emit every sampled row regardless of —top-warn (info severity below it), sorted by pct descending; containers capped at —limit |
--limit | int | 50 | row cap for the —all container dump |
--show-unlimited | bool | — | list each container missing a cpu or memory limit individually (default: one aggregate count) |
--show-unrequested | bool | — | list each container missing a cpu or memory request individually (default: one aggregate count); a missing request is the scheduler-side half of the census, always a subset of —show-unlimited |
--history | duration | — | enrich container findings with max/avg/p95 usage-vs-limit over this window via the cloud provider metrics backend; no provider → explicit unavailable finding + summary marker, point-in-time output unaffected |
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 |
|---|---|---|
top.saturation | critical, warning, info | a container’s usage is close to its limit — critical near the limit, info for an —all row below the threshold |
top.node | critical, warning, info | a node’s allocatable is close to committed — critical near the limit, info for an —all row below the threshold |
top.unlimited | info | how many containers in scope set no cpu/memory limit, and are therefore invisible to saturation analysis |
top.unlimited_container | info | one container that sets no cpu/memory limit (—show-unlimited) |
top.unrequested | info | how many containers in scope set no cpu/memory request, so the scheduler bin-packs them as zero |
top.unrequested_container | info | one container that sets no cpu/memory request (—show-unrequested) |
cloud.unavailable | info | the cloud capability this check needs is unavailable, so nothing was examined — an explicit degradation record, never silence |
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 |
|---|---|
resource | the judged dimension: cpu or memory |
usage | current usage in the dimension’s natural unit (millicores for cpu, IEC bytes for memory) |
limit | the container’s configured limit (top.saturation), same unit as usage |
allocatable | the node’s allocatable capacity (top.node), same unit as usage |
pct | usage as a percent of the limit/allocatable, one decimal |
container | container name within the pod |
node | node the pod runs on (top.saturation; top.node carries the node as name) |
pods | top.unlimited/top.unrequested: pods in scope with at least one container missing a cpu or memory limit (resp. request) |
containers | top.unlimited/top.unrequested: containers in scope missing a cpu or memory limit (resp. request) |
missing | top.unlimited_container/top.unrequested_container: which dimensions are absent (cpu, memory, or both) |
limitrange | top.unlimited_container/top.unrequested_container: the namespace LimitRange(s) that default a dimension this container is missing — the pod predates them, so recreating it picks the value up |
limitrange_defaulted | top.unlimited/top.unrequested: how many of the counted containers sit in a namespace whose LimitRange now defaults the dimension they lack |
max_pct | —history: highest usage-vs-limit percent observed in the window |
avg_pct | —history: mean usage-vs-limit percent over the window |
p95_pct | —history: 95th-percentile usage-vs-limit percent over the window |
capability | cloud.unavailable: the provider capability —history needed (metrics) |
provider | cloud.unavailable: the provider that was asked |
history | summary-line note: the —history window the stats cover |
unavailable | summary-line note: why —history could not be served |
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 top --namespace=prodlookout triage top -Alookout triage top --workload=Deployment/prod/apilookout triage top --namespace=prod --all --limit=20lookout triage top -A --top-warn=90 --show-unlimitedlookout triage top -A --show-unrequestedlookout triage top --namespace=prod --history=1h --format=json