Skip to content

lookout state gateway

When traffic through the Gateway API does not arrive — walk GatewayClass → Gateway → listener → HTTPRoute → Service and report every hop that is rejected, unprogrammed, or points at something that is not there. Silent, and cheap, on clusters without the Gateway API installed.

MCP tool: k8s_gateway_routes

Terminal window
lookout state gateway [flags]
FlagTypeDefaultMeaning
--namespacestring—limit the scan to one namespace
-Abool—scan all namespaces
--workloadstring—target one workload as <Kind>/<namespace>/<name>, e.g. Deployment/prod/api
--sinceduration—how far back to look (0 = command default)
--formatstringlogfmtoutput format: logfmt|json (one record per line either way)
--timeoutduration10sabort the invocation after this long (exit 1)
--kubeconfigstring—path to a kubeconfig file, instead of $KUBECONFIG / ~/.kube/config
--contextstring—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
--exemptionsstring—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

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.

KindSeverityClaim
gateway.missing_classcriticalthe Gateway names a GatewayClass that does not exist — nothing will program it
gateway.class_not_acceptedcriticalthe Gateway’s GatewayClass is not Accepted by its controller
gateway.not_acceptedcriticalthe Gateway itself is not Accepted
gateway.not_programmedcriticalthe Gateway is Accepted but not Programmed: no data plane is carrying its traffic
gateway.listener_invalidwarningone listener of an otherwise working Gateway is not resolved or not programmed
route.missing_parentcriticalthe route’s parentRef names a Gateway that does not exist
route.not_acceptedcriticalthe Gateway refused the route’s attachment (listener, hostname, or namespace policy)
route.missing_backendcriticalthe route’s backendRef Service does not exist
route.backend_portcriticalthe route’s backendRef Service exists but does not expose the named port
crd.unavailableinfothe API group this check reads is not served by the cluster, so nothing was examined (no coverage lies)

Beyond the shared envelope fields (kind, severity, namespace, kind_of_object, name, reason, message, fingerprint, exempt_reason, exempt_expires):

FieldMeaning
gateway_classGatewayClass the Gateway names
controllerthe GatewayClass’s spec.controllerName — which implementation owns it
gatewayGateway the route attaches to, as namespace/name
listenerlistener name within the Gateway
portlistener port, or the backendRef port the Service does not expose
protocollistener protocol
conditionthe status condition that is not True
servicebackend Service the route names, as namespace/name
service_portsports the backend Service does expose, sorted
classesGatewayClasses the cluster does have, sorted
api_groupcrd.unavailable: the API group-version this command needed
resourcescrd.unavailable: the resources it would have read
unavailablesummary-line note: why the group could not be read (absent CRDs, or discovery denied)

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= findings= elapsed= — findings=0 with a summary present means “scanned and healthy”; a stream without a summary line is void. Exit 0 data, 1 runtime error (diagnostics on stderr only), 2 usage.

Terminal window
lookout state gateway
lookout state gateway --namespace=prod
lookout state gateway --format=json