Navigate a Kubernetes cluster with k9s

Browse pods, deployments and services with k9s: switch contexts, filter views, read logs, open a shell, port-forward, and run it read-only.

how-to8 steps

Updated

in short

Run k9s --context <name>, type : and a resource name such as pod or deploy to switch views, / to filter, then l for logs, s for a shell and Shift-F to port-forward.

k9s is a terminal UI over the Kubernetes API. It reads the same kubeconfig as kubectl and shows live tables of resources that you move through with the keyboard, so you can go from a failing deployment to its pod logs without typing resource names.

This guide covers starting k9s against the right cluster, the command and filter prompts, logs, shells, port-forwards, read-only mode and where the configuration files live.

Tools used

Before you start

  • A working kubeconfig: kubectl get pods succeeds against the cluster
  • kubectl on your PATH (k9s calls it for shells and edits)
  • A terminal with 256-color support

Steps

  1. Step 1: Install k9s

    Install from a package manager or download a release tarball from GitHub. k9s version confirms the install.

    sh
    # macOS or Linux with Homebrew
    brew install derailed/k9s/k9s
    
    # Arch Linux
    sudo pacman -S k9s
    
    # Windows
    winget install k9s
    sh
    k9s version
  2. Step 2: Start it against the right cluster and namespace

    With no flags, k9s uses the current context from your kubeconfig. --context picks another context, -n a namespace, -A all namespaces, and --kubeconfig a different kubeconfig file. -c sets the first view, for example -c deploy.

    Inside k9s, :ctx lists contexts and :ns lists namespaces; select one and press Enter to switch.

    sh
    k9s --context staging -n payments
    sh
    k9s --kubeconfig ~/.kube/prod-config -A -c deploy
  3. Step 3: Switch views with :

    Press : and type a resource name, then Enter. Singular, plural and short names all work: :pod, :deploy, :svc, :ing, :cm, :secret, :node. Add a namespace after the name to scope it, as in :pod kube-system. Ctrl-A lists every resource and alias the cluster offers.

    In a table, Enter drills down (deployment to its pods, pod to its containers), d describes, y shows YAML, and Esc goes back. ? shows all key bindings for the current view.

    text
    :deploy
    :pod kube-system
    :svc
  4. Step 4: Filter with /

    Press / and type a regular expression to filter the current table by name, for example api|worker. Prefix with ! to invert the match, use -l to filter by labels, and -f for a fuzzy match. Esc clears the filter.

    Since k9s 0.30.0, the command prompt also takes filters directly: :pod /api or :pod app=web,env=prod.

    text
    /api|worker
    /! Running
    /-l app=web
    /-f chkout
  5. Step 5: Read logs

    Select a pod, container or deployment and press l to stream its logs; p shows the previous container's logs after a restart. In the log view, 0 follows the tail, 2 to 6 show the last 1m, 5m, 15m, 30m or 1h, w toggles line wrap, t toggles timestamps, s toggles autoscroll and f toggles full screen. Press / to filter log lines.

    How many lines k9s loads by default is set under k9s.logger in config.yaml (tail, buffer, sinceSeconds).

  6. Step 6: Open a shell and port-forward

    Select a pod and press s to open a shell. If the pod has several containers, k9s asks which one. It runs kubectl exec with bash, falling back to sh, so images without a shell (such as distroless images) cannot be entered this way. Exit the shell to return to k9s.

    Shift-F on a pod, container or service opens a port-forward dialog for the local and container ports. :pf lists active forwards, and Ctrl-D there stops one. Port-forwards end when k9s exits.

  7. Step 7: Use read-only mode on production clusters

    --readonly disables commands that change the cluster: delete, kill, edit, and shell or attach into pods. Viewing, logs and port-forwards still work. To make it the default, set readOnly: true in config.yaml, or in a single context's config file to protect only that cluster. --write overrides the setting for one session.

    sh
    k9s --context prod --readonly
    yaml
    # $XDG_CONFIG_HOME/k9s/config.yaml (~/.config/k9s/config.yaml on Linux)
    k9s:
      readOnly: true
  8. Step 8: Find the config files and set a skin

    Since k9s 0.30.0, the main config is config.yaml (not config.yml) in the k9s config directory: ~/.config/k9s on Linux, ~/Library/Application Support/k9s on macOS and %LOCALAPPDATA%\k9s on Windows, unless XDG_CONFIG_HOME or K9S_CONFIG_DIR points elsewhere. aliases.yaml, plugins.yaml, hotkeys.yaml, views.yaml and the skins/ directory live there too. Per-context settings live under clusters/ in the data directory (~/.local/share/k9s on Linux). k9s info prints the exact paths on your machine.

    To apply a skin, copy a YAML file from the skins directory of the k9s repository into skins/ and set its name, without the extension, in k9s.ui.skin. K9S_SKIN overrides it for one run.

    sh
    k9s info
    yaml
    # config.yaml
    k9s:
      ui:
        skin: dracula   # loads skins/dracula.yaml

Troubleshooting

  • Colors look wrong or missing: k9s needs 256 colors. Set TERM=xterm-256color.
  • kubectl command is not in your path when pressing s: install kubectl or add it to PATH.
  • s and e do nothing: k9s is in read-only mode. Start it with --write, or set readOnly: false.
  • Settings ignored after an upgrade: 0.30.0 moved files and renamed .yml to .yaml. Compare with k9s info.
  • e opens the wrong editor: set KUBE_EDITOR or EDITOR.
  • Something else fails: k9s info shows the log file path; start with k9s -l debug for more detail.

Tips

  • - jumps back to the previous view, like cd -. [ and ] move through command history.
  • :xray dp shows deployments as a tree of their related resources. It also takes po, svc, rs, sts and ds.
  • Shift-J on a pod jumps to its owner, such as the replica set or job that created it.

FAQ

Where does k9s keep per-cluster settings?
Under `clusters/<cluster>/<context>/config.yaml` in its data directory (`~/.local/share/k9s` on Linux). That file holds the active namespace, favorites, last view and per-context options such as `readOnly`.
Can k9s show resources from custom resource definitions?
Yes. CRDs appear in `Ctrl-A` and can be opened with `:` and their name or short name, like built-in resources.
Why can I not open a shell in some pods?
k9s runs `bash` or `sh` inside the container. Images that ship neither, such as distroless images, have no shell to open.

related