lookout stab drain
Before draining a node, list everything that will block the drain (PDBs at disruptionsAllowed=0) or be destroyed by it (bare pods, emptyDir data, single-replica workloads); —node details one node, -A means all nodes here (pods are always examined across all namespaces); scanned counts pods examined after the standard-drain skips (mirror/DaemonSet/completed pods).
MCP tool: k8s_drain_blockers
lookout stab drain [flags]| Flag | Type | Default | Meaning |
|---|---|---|---|
--node | string | — | analyze one node in detail: every blocker on it becomes its own finding. Exactly one of —node or -A (all-nodes summary) is required. |
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 |
|---|---|---|
drain.pdb_gridlock | critical | a PodDisruptionBudget covering pods on this node allows zero disruptions: the eviction API refuses and the drain hangs |
drain.bare_pod | warning | a pod on this node has no owner, so eviction deletes it permanently and nothing recreates it |
drain.local_storage | warning | a pod on this node has emptyDir volumes: the drain needs —delete-emptydir-data and the data is lost |
drain.singleton | warning | a pod on this node is the only replica of its controller — evicting it is an outage |
drain.node | critical, warning | the -A roll-up: this node is not cleanly drainable, with the blocker classes counted; critical when a PDB gridlock is among them |
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 |
|---|---|
node | the node the blocker sits on (stamped on every —node-mode finding) |
pods | pods on the node covered by the gridlocked PDB |
pod_names | names of the covered pods, capped at 8 with a +N more tail |
disruptions_allowed | PDB status.disruptionsAllowed (always 0 in a gridlock finding) |
current_healthy | PDB status.currentHealthy |
desired_healthy | PDB status.desiredHealthy |
volumes | emptyDir volume names on the pod; memory-backed ones marked (medium=Memory) |
workload | the single-replica controller as <Kind>/<namespace>/<name> |
replicas | the controller’s spec.replicas (always 1 in a singleton finding) |
blockers | total drain blockers on the node (also a —node-mode summary note) |
pdb_gridlock | gridlocked-PDB blocker count on the node (-A per-node finding; zero counts omitted) |
bare_pods | bare-pod blocker count on the node (-A per-node finding; zero counts omitted) |
local_storage | emptyDir blocker count on the node (-A per-node finding; zero counts omitted) |
singletons | single-replica blocker count on the node (-A per-node finding; zero counts omitted) |
drainable | summary note (—node mode): yes when the node has no blockers, else no |
nodes | summary note (-A mode): nodes examined |
blocked | summary note (-A mode): nodes with at least one blocker |
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 stab drain --node=gke-prod-pool-a-x1z2lookout stab drain -Alookout stab drain --node=gke-prod-pool-a-x1z2 --format=json