ssh_kubectl_read
Run one allowlisted, read-only kubectl command INSIDE an Ankra-provisioned cluster (Hetzner, OVH, UpCloud, DigitalOcean or Scaleway) by executing it on a control-plane node over SSH-via-bastion, using that node's own admin kubeconfig. REACH FOR THIS ONLY WHEN THE CLUSTER'S AGENT IS NOT ANSWERING. While the agent is checking in, a get, describe, logs or events call here is REFUSED and names the tool to use instead: get_pods or cluster_query, describe_resource, get_pod_logs, get_events. Those answer the same question in one call, while this one dials the bastion, runs kubectl as cluster-admin and holds a scheduler job for up to 90 seconds. When the agent stops checking in they stop being an option - get_pod_logs and query_logs refuse outright, and the resource reads fall back to a cached inventory from before the outage - and this becomes the only live view left, because it does not use the agent at all; every result is stamped source=break_glass_ssh with executed_at. That is the state to use it in: to find out what is actually wrong with the agent itself - is its Deployment rolled out, is its pod Pending or CrashLoopBackOff or bound to a dead node, what do its logs and events say. If the agent IS checking in and you still need this, it is because an agent-path read already failed this turn (CLUSTER_OFFLINE, NO_AGENT or AGENT_TIMEOUT) or the tool it named refuses what you asked it for - get_pod_logs serves previous=true only on agent 2.1.1058 or newer, and refuses below it: set agent_path_unavailable=true, which is honoured and recorded. Verbs: get, describe, logs, events, top, version, api_resources, rollout_status. This is an allowlist, not a shell: there is no exec, port-forward, apply, patch, edit, create, scale, drain, cp, --raw, jsonpath or go-template, and no way to pass raw flags. Structured output (yaml/json) of Secrets is refused, though get and describe of them still report names, types and key names. Output is capped and credential-shaped strings are redacted. The command runs on a control-plane node, chosen automatically unless you pass node_id/node_name. Not available for imported or managed-Kubernetes clusters (they have no bastion), nor (yet) Proxmox/HPE Morpheus. Read-only: use ssh_kubectl_recover to change anything.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Resource type, e.g. 'pods', 'deployments', 'nodes', 'deployments.apps'. Required by get, describe, top and rollout_status. MUST BE OMITTED for logs, events, version and api_resources - for logs the pod name goes in 'name'. Naming the kind a verb already implies (kind=pods on logs, kind=events on events) is accepted and ignored; a kind that contradicts the verb is refused. | |
| name | No | Object name. For get and describe it narrows to one object (omit for a listing); for logs it is the pod name; for rollout_status it is required. | |
| verb | Yes | Which read to perform. get lists or shows resources; describe gives the detailed view including a pod's events and container statuses; logs reads container logs; events lists namespace events newest-last; top reports resource usage (nodes or pods); version reports the server version; api_resources lists available kinds; rollout_status reports whether a rollout completed (it waits up to 30s). | |
| output | No | Output format for get. Omit for a table. 'wide' adds node and IP columns and is usually the right choice. yaml/json of Secrets is refused. | |
| node_id | No | UUID of the control-plane node to run the command on (from list_cluster_nodes). Optional: a healthy control-plane node is chosen automatically. | |
| previous | No | Read the PREVIOUS container instance's logs. This is what shows why a CrashLoopBackOff pod died, since the current instance has usually not started. | |
| selector | No | Label selector in k=v[,k=v] form with NO spaces, e.g. 'app.kubernetes.io/name=ankra-agent'. For logs it selects the pods to read. | |
| container | No | Container name, for logs on a multi-container pod. | |
| namespace | No | Namespace to scope to. Mutually exclusive with all_namespaces. | |
| node_name | No | Exact name of the control-plane node to run the command on. Alternative to node_id. | |
| cluster_id | No | UUID of the cluster. Optional when a cluster is selected. | |
| tail_lines | No | How many log lines to return (default 200, maximum 2000). | |
| cluster_name | No | Exact name of the cluster. Optional when a cluster is selected. | |
| since_seconds | No | Only return log lines from the last N seconds. | |
| all_namespaces | No | Query every namespace. Mutually exclusive with namespace. | |
| field_selector | No | Field selector in path=value[,path=value] form with no spaces, e.g. 'involvedObject.name=ankra-agent-xyz' to get the events for one object, or 'status.phase=Pending' to list only pending pods. | |
| agent_path_unavailable | No | Set true ONLY when the cluster's agent is checking in but the agent path still cannot answer: an agent-path read already failed this turn with CLUSTER_OFFLINE, NO_AGENT or AGENT_TIMEOUT, or you need previous=true (a crashed container's earlier logs) on a cluster whose agent is older than 2.1.1058, where get_pod_logs refuses it. It bypasses the refusal that otherwise sends get/describe/logs/events calls to get_pods, describe_resource, get_pod_logs or get_events, and every call is logged with this flag set. |