lookout state storage
When a PersistentVolumeClaim sits Pending and the pod behind it will not schedule — name the reason: a StorageClass that does not exist, no class and no cluster default, a static-only class with nothing pre-provisioned, plus the default-class ambiguity and stranded volumes behind it.
MCP tool: k8s_storage_binding
lookout state storage [flags]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 |
|---|---|---|
storage.missing_class | critical | the claim names a StorageClass that does not exist — it will stay Pending forever |
storage.no_default_class | critical | the claim names no class and the cluster has no default StorageClass |
storage.no_provisioner | warning | the claim’s class is static-only (kubernetes.io/no-provisioner) and no matching PV is available |
storage.multiple_defaults | warning | more than one StorageClass is annotated as the cluster default; which one wins is not defined |
storage.pv_failed | warning | a PersistentVolume is Failed: its reclaim did not complete, so the backing disk stays allocated and the volume cannot be reused |
storage.pv_released | info | a PersistentVolume is Released — retained on purpose, but its capacity is unusable until spec.claimRef is cleared |
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 |
|---|---|
storage_class | StorageClass the claim names, or the class the finding is about |
classes | StorageClasses the cluster does have, sorted (empty when there are none) |
defaults | StorageClasses annotated as the cluster default, sorted |
provisioner | the class’s spec.provisioner |
phase | the claim’s or volume’s status.phase at scan time |
requested | storage the claim requests (spec.resources.requests.storage) |
capacity | the volume’s spec.capacity.storage |
reclaim_policy | the volume’s spec.persistentVolumeReclaimPolicy |
claim | the claim the volume was bound to, as namespace/name |
binding_mode | the class’s volumeBindingMode (Immediate when unset) |
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 state storagelookout state storage --namespace=prodlookout state storage --format=json