Skip to content

Unmanaged (kubeconfig-only) Clusters

KSail can see and operate on any cluster in your kubeconfig, even one it did not provision — a managed cloud cluster (EKS/GKE/AKS), a kubeadm cluster, or a colleague’s cluster shared with you. These appear as unmanaged clusters: KSail surfaces them clearly marked, never hidden and never shown as a normal managed cluster, and refuses ksail-only lifecycle actions on them with a documented message instead of failing silently.

ksail cluster list includes kubeconfig contexts KSail did not provision, each shown with an explicit unmanaged marker:

Terminal window
ksail cluster list

Unmanaged clusters appear with blank distribution and provider columns (there is no KSail spec to read) and a STATUS of Unmanaged. Discovery reads the kubeconfig that KUBECONFIG names, or ~/.kube/config when it is unset. When KUBECONFIG lists several files, only the first is read.

The web UI and desktop app mark these clusters Unmanaged too, and identify their distribution and provider from the cluster’s own nodes. The node’s OS image names Talos, the kubelet version names K3s, EKS or GKE, well-known node labels and annotations name AKS and KWOK, and a kind:// node ID names Vanilla. The node ID also names the provider: hcloud:// is Hetzner, and aws://, gce://, azure:// and kind:// name AWS, GCP, Azure and Docker. A value found this way is dotted-underlined, and hovering it reads “Detected from the cluster’s nodes”, so it is never mistaken for a configured value. Every node has to agree on the distribution. The provider works differently: a node whose ID has not been filled in yet supplies no evidence rather than a disagreement, so it is every node that has an ID that must name the same provider. When the evidence that exists conflicts, or the cluster can’t be reached, the field shows — instead of a guess.

In the web UI and desktop app, every row acts on its own context, even when two contexts share a cluster name. With unmanaged contexts prod and kind-prod, the prod row targets prod and the kind-prod row targets kind-prod; only when KSail manages a cluster named prod does that name mean kind-prod. A name that several contexts share and none owns outright, such as kind-prod and k3d-prod for a managed prod, is refused as ambiguous rather than guessed.

KSail uses the credentials and external authentication command configured in the selected kubeconfig context. For cloud or SSO-backed contexts, that command must be installed and its login session must be valid. The desktop app imports the macOS login-shell environment on startup so those commands can be found.

Check the connection without changing cluster resources or your active context:

Terminal window
ksail workload get --context my-cloud-context --request-timeout=10s --raw=/version

For a direct AWS SSO profile, KSail can start the provider’s browser sign-in without a separate terminal login command. This recovery is experimental and opt-in:

  • Desktop / local web UI: enable AWS SSO renewal (experimental) in Settings → Credentials. When the selected context’s SSO session expires, choose Sign in to AWS SSO on its overview. Complete AWS sign-in in your browser; KSail then refreshes monitoring. Cancel sign-in stops the pending flow.

  • Interactive CLI: pass --experimental to a read command such as workload get, describe, logs, explain or wait. If its selected AWS SSO session is expired, KSail asks for confirmation, starts AWS sign-in and then performs the original read without switching contexts. The terminal shows the AWS CLI’s sign-in address and code, so you can finish from another device when the terminal’s machine has no browser; this needs AWS CLI 2.22 or newer and a terminal for both input and error output:

    Terminal window
    ksail workload get --experimental --context my-cloud-context pods

Both legacy SSO profiles and profiles using a named sso-session are supported when the kubeconfig directly invokes aws eks get-token. The configured AWS CLI must be installed. Custom wrappers, assume-role/source-profile chains and static credentials retain their normal authentication path; they are not automatically renewed. Background monitoring, scripts and CI never initiate sign-in. A forbidden resource read means your identity lacks permission for that resource, not that SSO needs renewal.

The overview reports failed reads and shows unavailable counts as —, not zero. Expand Failed resource reads for details. Data from successful reads remains visible; if live metrics cannot be read, resource-usage charts use requested resources only when both nodes and pods were read successfully. After restoring access, select Refresh to reload monitoring data.

Much of KSail’s read/operate surface is client-go-backed, so it works against the selected kubeconfig context — managed or not. Switch to the unmanaged cluster first, then use it like any other:

Terminal window
ksail cluster switch my-eks-prod # switch the active kubeconfig context
ksail cluster connect # open k9s against the selected context
ksail cluster info --name my-eks-prod # endpoint + kubeconfig access for a named cluster
ksail cluster diagnose --name my-eks-prod # diagnoses the ACTIVE context; --name only labels the report
ksail cluster backup ./snapshot # snapshot Kubernetes resources over the API server
ksail cluster restore ./snapshot # restore them

Within the ksail workload group, the commands that work against any selected unmanaged context are the API-backed ones: the kubectl-style wrappers (get, logs, apply, exec, describe, wait, forward, …) plus watch, edit, validate, scan, and debug. Helm-based workload install works too — all resolve the kubeconfig and need no KSail metadata. (Backup and restore are ksail cluster subcommands, shown above, not workload ones.)

Anything that needs KSail-managed provisioning or a spec.cluster.* configuration is clearly refused on an unmanaged cluster — never a silent no-op or a stack trace:

Terminal window
ksail cluster delete --name my-eks-prod
# Error: "my-eks-prod" is an unmanaged cluster: cluster is not managed by ksail;
# read-only operations (list, resource browsing, logs, exec) still work

The refusal covers the lifecycle operations KSail cannot drive without a provider:

  • Lifecycle — delete, update, start, stop are refused with the unmanaged message (no provider/distribution to act on). create is not a selected-context action — it provisions from ksail.yaml, so it is unaffected by this guard.
  • Component installation — CNI, CSI, metrics-server, GitOps/Flux, policy engine (all driven from spec.cluster.*).
  • GitOps reconciliation — workload reconcile targets GitOps-managed workloads and needs a Flux/GitOps-configured cluster, not just a kubeconfig.
Capability Managed cluster Unmanaged (kubeconfig-only) cluster
List / switch / connect ✅ ✅ (marked unmanaged)
Info ✅ ✅ with a resolvable --name
Diagnose ✅ ⚠️ diagnoses the active context — switch first (#6117)
workload API-backed (get, logs, exec, apply, watch, forward, install, …) ✅ ✅
workload network / images / push ✅ ⚠️ also need a local ksail.yaml
workload export / import ✅ (Docker) ⛔ Docker-backed nodes only
cluster backup / cluster restore ✅ ✅
Web UI / desktop resource browsing ✅ ✅
Delete / update / start / stop ✅ ⛔ refused with a documented message
Component install (CNI, CSI, GitOps, policy) ✅ ⛔ requires spec.cluster.*
GitOps reconcile ✅ ⛔ requires a GitOps-configured cluster
Distribution / provider reported CLI: blank (no KSail spec). Web UI / desktop: detected from the nodes, or —