Guide

k9s piloter Kubernetes au terminal sans écrire trois fois la même commande

Tuto k9s complet : installation, navigation, logs, shell, port-forward, configuration, skins, hotkeys et plugins. Basé sur k9s 0.51.

Par Cyril · Publié le

Sommaire

Il y a deux façons de regarder un cluster Kubernetes. La première consiste à taper kubectl get pods -n production, lire la sortie, repérer le pod qui pose problème, copier son nom, taper kubectl describe pod ce-nom -n production, ne pas trouver ce qu'on cherchait, taper kubectl logs ce-nom -n production -c le-bon-conteneur, se tromper de conteneur, recommencer. La seconde consiste à lancer k9s et à appuyer sur l.

Les deux approches sont légitimes et cet article ne va pas vous expliquer que la première est ridicule. kubectl reste l'interface de référence, celle qui se scripte, celle qui existe partout, celle dont la sortie est stable. k9s est un confort de lecture et d'exploration, pas un remplacement.

Ce guide est écrit pour k9s 0.51, sorti en juin 2026. Les raccourcis de k9s bougent d'une version à l'autre, plus souvent qu'on ne le voudrait, donc vérifiez votre version avec k9s version avant de vous étonner qu'une touche ne fasse pas ce qui est écrit ici.

Au programme : installer k9s sur Linux, macOS et WSL2, comprendre ce qu'affiche l'écran de départ, naviguer avec la barre de commande et les alias, lire des logs et ouvrir un shell dans un conteneur, faire du port-forward, changer de contexte et de namespace, puis configurer l'outil à votre main - skin transparent, hotkeys, plugins. Aucun prérequis au-delà d'un kubeconfig fonctionnel et d'un cluster auquel vous avez accès.

k9s et kubectl - ce que chacun fait bien

Poser k9s contre kubectl comme deux concurrents est une erreur de cadrage. k9s utilise votre kubeconfig, vos contextes, vos droits RBAC. Il parle à la même API. Ce qu'il change, c'est la boucle entre votre question et sa réponse.

Ce que kubectl fait mieux

  • Il se scripte. Un pipeline CI, un runbook, un Makefile : rien de tout ça ne peut passer par une interface interactive. Tout ce que vous automatisez restera en kubectl.
  • Sa sortie est un contrat. -o json, -o jsonpath, -o custom-columns produisent des formats stables que vous pouvez traiter avec jq. Un TUI n'offre rien de comparable.
  • Il est partout. Sur un bastion minimal, dans un conteneur de debug, sur la machine d'un collègue, kubectl est là. k9s est un binaire de plus à installer.
  • Il documente ce que vous avez fait. Une commande kubectl se copie dans un ticket, se relit dans un historique de shell, se rejoue à l'identique. Une suite de frappes dans un TUI ne laisse aucune trace exploitable.
  • Il ne cache rien. Vous voyez exactement la requête que vous envoyez. Dans k9s, une touche déclenche parfois plusieurs appels API et vous ne les voyez pas.

Ce que k9s fait mieux

  • L'exploration. Quand vous ne savez pas encore ce que vous cherchez, parcourir des ressources avec des touches bat très largement l'enchaînement de commandes. C'est le cas d'usage principal, et il est réel.
  • Le rafraîchissement automatique. Un rollout qui se déroule, des pods qui passent de Pending à Running, un HPA qui scale : k9s rafraîchit tout seul toutes les deux secondes par défaut. Pas de watch -n2 kubectl get pods.
  • Le passage d'une ressource à ses voisines. D'un deployment vers ses replicasets, d'un replicaset vers ses pods, d'un pod vers son node, d'un pod vers ses logs. Trois touches, aucun copier-coller de nom de ressource.
  • Le choix du conteneur. Sur un pod multi-conteneurs avec des sidecars, k9s vous présente la liste. Vous ne mémorisez plus les noms.
  • Les logs, tout de suite. l sur un pod, et vous y êtes, avec l'autoscroll, le wrap et les timestamps sur des touches.

Comment les deux cohabitent en pratique

La répartition qui fonctionne, et que la plupart des gens finissent par adopter sans se le formuler :

  • k9s pour comprendre. L'investigation, le diagnostic, le "qu'est-ce qui se passe sur ce cluster".
  • kubectl pour agir et pour tracer. Les applications de manifeste, les commandes qui finiront dans un post-mortem, tout ce qui doit être reproductible.

Ce partage n'est pas un compromis mou, c'est le bon découpage. La lecture est interactive par nature, l'écriture doit être traçable.

Le point de friction honnête

k9s facilite des actions destructrices. ctrl-d supprime, ctrl-k tue sans confirmation, r redémarre un deployment. Sur un cluster de prod, un raccourci mal placé au mauvais moment se paie. La section mode lecture seule plus bas traite du mode lecture seule, et ce n'est pas une option cosmétique : c'est le prix d'entrée pour utiliser un TUI sur de la prod.

Autre réserve, plus discrète : k9s interroge l'API en continu. Sur un très gros cluster, plusieurs dizaines de sessions k9s ouvertes en permanence sur des vues coûteuses représentent une charge non nulle sur l'API server. La 0.51 a d'ailleurs relevé le QPS client par défaut de 5 à 50 et paginé les appels à l'API de métriques, ce qui va dans le bon sens côté réactivité, mais ne rend pas la question caduque.

Les alternatives à k9s

k9s n'est pas seul, et selon votre contexte un autre outil peut mieux vous convenir.

Headlamp est le choix par défaut côté interface graphique depuis 2026. Projet CNCF maintenu sous kubernetes-sigs, il s'utilise en desktop ou déployé dans le cluster, gère plusieurs clusters dans la même fenêtre et s'étend par plugins. C'est ce qu'il faut proposer à des développeurs qui ne vivent pas dans un terminal.

Kubernetes Dashboard, l'ancienne interface web officielle, est archivée depuis le 21 janvier 2026, faute de mainteneurs. Le projet Kubernetes recommande explicitement de migrer vers Headlamp et a publié deux billets pour accompagner la bascule : la transition et le guide pas à pas. Si vous trouvez un tutoriel qui vous propose encore de la déployer, il est périmé. Le dépôt est en lecture seule.

Lens a longtemps été la référence GUI. Son passage sous licence commerciale en 2022 a fait naître OpenLens puis, celui-ci s'étant essoufflé, le fork Freelens, qui est aujourd'hui le plus actif des deux. L'écosystème est vivant mais fragmenté, vérifiez l'état de maintenance avant de vous engager.

Aptakube est une interface graphique commerciale, multi-cluster, avec un vrai travail d'ergonomie. Payante, ce qui se défend si l'outil vous fait gagner du temps tous les jours.

kubectl augmenté reste une option sérieuse et sous-estimée : kubectx et kubens pour jongler entre contextes et namespaces, stern pour agréger les logs de plusieurs pods, kube-ps1 pour afficher le contexte courant dans votre prompt zsh. Vous gardez la traçabilité de kubectl et vous éliminez l'essentiel de la friction. Beaucoup de gens n'ont jamais eu besoin d'aller plus loin.

Le vrai critère de choix n'est pas la richesse fonctionnelle, c'est votre mode de travail. Si vous vivez déjà dans un terminal avec tmux, k9s s'y intègre sans rupture. Si vous préférez une fenêtre séparée avec une souris, une GUI vous servira mieux, et il n'y a rien à défendre là-dedans.

Installer k9s sur Linux, macOS et WSL2

k9s est un binaire Go unique, sans dépendance. L'installation est triviale, la seule question est celle de la fraîcheur : les dépôts de distribution sont souvent en retard de plusieurs versions mineures, et sur un outil dont les raccourcis bougent, c'est un vrai sujet.

Installer k9s sur Linux

Le plus simple, et celui qui vous donne la dernière version :

# Récupérer la dernière release depuis GitHub
curl -sS https://webi.sh/k9s | sh

Ou manuellement, si vous préférez voir ce que vous téléchargez :

K9S_VERSION="v0.51.0"
curl -sL "https://github.com/derailed/k9s/releases/download/${K9S_VERSION}/k9s_Linux_amd64.tar.gz" \
  | tar xz -C /tmp k9s
install -m 0755 /tmp/k9s ~/.local/bin/k9s

Sur Arch, le paquet officiel suit correctement les releases :

sudo pacman -S k9s

Sur Debian et Ubuntu, il n'y a pas de paquet officiel à jour. Passez par le .deb de la release GitHub ou par le binaire, plutôt que par un dépôt tiers dont vous ne contrôlez pas le rythme.

Installer k9s sur macOS

brew install derailed/k9s/k9s

Le tap officiel est plus à jour que la formule de homebrew-core. Utilisez-le.

Installer k9s sur Windows avec WSL2

Dans votre distribution WSL2, suivez la procédure Linux. C'est la seule qui vaille : k9s existe en binaire Windows natif, mais il devra alors lire un kubeconfig côté Windows, avec les problèmes de chemins et de fins de ligne que ça implique. Si votre workflow Kubernetes est déjà dans WSL2, gardez tout au même endroit.

Une précision qui évite une heure de perplexité : votre terminal doit gérer correctement les couleurs 256 et les caractères Unicode. Windows Terminal le fait, cmd.exe non.

Vérifier l'installation

k9s version

Vous devez voir le logo ASCII, la version, le commit et la date de build. Puis :

k9s info

C'est la commande la plus utile du lot, et personne ne la connaît. Elle vous dit exactement où k9s lit et écrit ses fichiers :

Version:           v0.51.0
Config:            /home/vous/.config/k9s/config.yaml
Custom Views:      /home/vous/.config/k9s/views.yaml
Custom Jumps:      /home/vous/.config/k9s/jumps.yaml
Plugins:           /home/vous/.config/k9s/plugins.yaml
Hotkeys:           /home/vous/.config/k9s/hotkeys.yaml
Aliases:           /home/vous/.config/k9s/aliases.yaml
Skins:             /home/vous/.config/k9s/skins
Context Configs:   /home/vous/.local/share/k9s/clusters
Logs:              /home/vous/.local/state/k9s/k9s.log
Benchmarks:        /home/vous/.local/state/k9s/benchmarks
ScreenDumps:       /home/vous/.local/state/k9s/screen-dumps

Notez la répartition XDG : la configuration dans ~/.config, l'état par cluster dans ~/.local/share, les logs et les artefacts jetables dans ~/.local/state. Les guides plus anciens parlent de ~/.k9s/, c'est obsolète depuis la 0.30. Si vous trouvez encore ce dossier chez vous, il ne sert plus à rien.

Quand quelque chose ne marche pas, ~/.local/state/k9s/k9s.log est le premier endroit à regarder. On y revient dans la section dépannage.

Lire l'écran au premier lancement

Lancez k9s. Après l'écran de démarrage, vous arrivez sur une vue de ressources. Trois zones à distinguer.

Vue nodes de k9s 0.51 : bloc d'information à gauche avec contexte, cluster, versions et charge, raccourcis contextuels au centre, table des quatre nodes du cluster avec leur statut et leur consommation

En haut à gauche, le bloc d'information. Contexte courant, cluster, utilisateur, version de k9s, version du cluster, consommation CPU et mémoire. C'est ici que vous vérifiez sur quel cluster vous êtes avant de faire une bêtise. Prenez l'habitude de le lire, sérieusement.

Le marqueur [RW] accolé au contexte indique que la session est en écriture. En lecture seule il affiche [RO]. C'est le seul endroit où l'information apparaît, et elle vaut le coup d'œil avant toute action sur un cluster que vous ne connaissez pas.

Vous aurez aussi remarqué la ligne K8s Rev de ces captures : v1.31.14. Une version sortie en août 2024 et hors support depuis octobre 2025. Le cluster tourne parfaitement, merci de vous en inquiéter. C'est là toute la cruauté de ce bandeau : il affiche votre dette technique en orange, en haut à gauche, à chaque lancement, tous les jours, sans jamais se lasser ni proposer de plan de migration. kubectl version a au moins la décence d'attendre qu'on la sollicite.

En haut au centre, les namespaces favoris. Numérotés de 0 à 9. 0 est toujours all. Appuyer sur le chiffre bascule le namespace actif. La liste se construit toute seule au fil de vos visites, les namespaces les plus fréquentés remontent. Sur la capture ci-dessus cette zone est absente : les nodes sont une ressource de portée cluster, pas de portée namespace, donc k9s n'affiche pas les favoris. Vous les retrouverez sur toute vue de ressource namespacée, comme les pods.

En haut à droite, les raccourcis contextuels. Cette zone change selon la vue. C'est votre aide-mémoire permanent : ce qui y est listé est ce qui fonctionne ici et maintenant. Quand vous ne savez plus quelle touche fait quoi, regardez à droite avant de chercher ailleurs.

Au centre, la table. Les ressources, avec un titre qui indique le type affiché, le namespace, et un compteur. Le fil d'Ariane en bas de l'écran montre la pile de vues que vous avez ouvertes.

? ouvre l'aide complète des raccourcis de la vue courante. esc revient en arrière, toujours, à tous les niveaux. Ces deux touches suffisent à explorer sans rien casser.

Pour un écran plus dépouillé, trois options qui se cumulent :

k9s --headless      # masque le bloc d'information
k9s --crumbsless    # masque le fil d'Ariane
k9s --logoless      # masque le logo
k9s --splashless    # saute l'écran de démarrage

Je déconseille --headless sur un poste qui accède à de la prod. Le bandeau de contexte est exactement ce qui vous empêche de confondre staging et production.

Tout part de :. Cette touche ouvre la barre de commande, où vous tapez un type de ressource.

:pod          # ou :po, ou :pods
:deploy       # deployments
:svc          # services
:ing          # ingress
:node         # nodes
:cm           # configmaps
:sec          # secrets
:ev           # events, la vue la plus sous-utilisée de k9s

k9s accepte le singulier, le pluriel et les noms courts de kubectl. Il accepte aussi les CRD : :certificates, :prometheusrules, :virtualservices fonctionnent si les ressources existent dans le cluster.

ctrl-a liste tous les alias disponibles. C'est la commande à retenir quand vous cherchez comment atteindre une ressource. Elle affiche la table complète des correspondances, y compris celles des CRD installés.

Quelques vues qui ne correspondent à aucune ressource Kubernetes et qui méritent d'être connues :

CommandeAliasCe que ça affiche
:xray RESSOURCE:xArbre de dépendances d'un type de ressource
:pulse:pu, :hzTableau de bord temps réel du cluster
:workload:wkVue agrégée de toutes les charges de travail
:portforward:pfLes port-forwards actifs de votre session
:context:ctxSélecteur de contexte
:screendump:sdLes captures d'écran sauvegardées
:charts:hmLes releases Helm
:dir CHEMIN:dParcourt des manifestes sur disque
:alias:aLa table des alias
:help:h, :?L'aide
:quit:qQuitter

:wk est arrivée récemment et remplace avantageusement l'aller-retour entre :deploy, :sts et :ds quand vous voulez juste savoir ce qui tourne.

La barre de commande accepte aussi des arguments, ce qui vous évite deux navigations :

:pod monitoring              # les pods du namespace monitoring
:pod /nginx                  # les pods dont le nom contient nginx
:pod app=api,env=prod        # filtrage par labels
:pod @staging                # les pods d'un autre contexte, sans changer le contexte courant

Ce dernier point est méconnu et très utile : @contexte interroge un autre cluster sans quitter celui où vous êtes.

Filtrer et chercher

/ ouvre le filtre sur la vue courante. Le texte saisi est une expression régulière appliquée aux noms.

/api            # les lignes contenant "api"
/-!api          # filtre inverse : tout sauf "api"
/-l app=front   # filtrage par label selector
/-f api         # recherche floue, tolère les fautes de frappe

enter valide le filtre et vous rend la navigation. esc l'efface. La touche q efface aussi le filtre, ce qui surprend au début quand on s'attend à quitter.

Vue pods de k9s filtrée sur le motif up, tous namespaces : le filtre apparaît dans le prompt sous le bandeau et à droite du titre de la table, qui ne conserve que deux pods sur l'ensemble du cluster

Le filtre actif est rappelé à deux endroits : dans le prompt sous le bandeau, et à droite du titre de la table. Ce second rappel est celui qui compte, parce qu'il reste visible après que vous avez validé avec enter et rendu la main à la navigation. Un compteur de lignes vous indique en permanence combien de ressources passent le filtre.

Deux raccourcis de table qui changent la vie sur des listes longues :

  • ctrl-w bascule l'affichage large, l'équivalent de -o wide. Les colonnes supplémentaires apparaissent : node, IP, nominated node.
  • ctrl-z ne montre que les ressources en défaut. Sur un namespace avec deux cents pods dont trois qui crashent, cette touche vous donne la réponse immédiatement.

Pour le tri, shift-n trie par nom, shift-a par âge, shift-s par statut. shift-o trie sur la colonne actuellement sélectionnée, ce qui suppose d'avoir navigué entre colonnes avec shift-flèche gauche et shift-flèche droite. La 0.51 a ajouté des indications visuelles pour cette navigation par colonnes, qui était jusque-là parfaitement invisible.

Enfin, la sélection multiple : espace marque une ligne, ctrl-espace marque une plage, ctrl-\ efface les marques. Les actions s'appliquent alors à toutes les lignes marquées. Utile pour supprimer une série de pods d'un coup, et dangereux exactement pour la même raison.

Les raccourcis du quotidien

Voici ceux qui couvrent l'essentiel du travail. Ils sont vérifiés sur la 0.51.

La touche ? affiche à tout moment la liste complète de ce qui est actif dans la vue courante, répartie en quatre colonnes : les actions sur la ressource, les commandes générales, la navigation, et vos hotkeys personnalisées.

Écran d'aide de k9s ouvert sur une vue pods, quatre colonnes : RESOURCE avec les actions Attach, Describe, Kill, Logs et Port-Forward, GENERAL avec les commandes Aliases, Filter mode et Mark, NAVIGATION avec les déplacements clavier, et HOTKEYS

C'est la source à privilégier sur toute documentation en ligne, la vôtre incluse : elle correspond exactement à votre version et à vos personnalisations.

Sur n'importe quelle ressource

ToucheAction
dDescribe
yAfficher le YAML
eÉditer dans $EDITOR
cCopier le nom de la ressource
nCopier le namespace
wBasculer vers le namespace de la ressource sélectionnée
shift-jRemonter au propriétaire de la ressource
enterDescendre dans la ressource
ctrl-rRafraîchir manuellement
ctrl-dSupprimer, avec confirmation
ctrl-sSauvegarder la vue dans un fichier
0 à 9Basculer de namespace
escRemonter d'un niveau
?Aide de la vue courante

w est le raccourci que personne ne connaît et qui fait gagner le plus de temps : depuis une vue all namespaces, il vous téléporte dans le namespace du pod sélectionné. shift-j fait le trajet inverse de enter : depuis un pod, il remonte au replicaset, puis au deployment.

La navigation au clavier

k9s reprend les déplacements de vi, ce qui évite les allers-retours vers les flèches.

ToucheAction
j et kDescendre et monter
h et lGauche et droite
g et shift-gAller en haut, aller en bas
ctrl-f et ctrl-bPage suivante, page précédente
[ et ]Reculer et avancer dans l'historique des vues
Rappeler la dernière commande utilisée
ctrl-uEffacer la saisie de la barre de commande
tab et shift-tabChamp suivant, champ précédent dans un dialogue

L'historique [ et ] est le plus rentable des huit : il rejoue votre parcours de vues sans retaper une seule commande.

Spécifiques aux pods

ToucheAction
lLogs du conteneur
pLogs de l'instance précédente, après un crash
sOuvrir un shell dans le conteneur
aS'attacher aux flux du conteneur
tTransférer des fichiers vers ou depuis le pod
oAfficher le node qui héberge le pod
zNettoyer les pods terminés ou en erreur
ctrl-kTuer le pod, sans confirmation

p est le réflexe à acquérir face à un CrashLoopBackOff : les logs du conteneur courant sont vides ou inutiles, ceux de l'instance précédente contiennent l'erreur qui a tué le processus.

ctrl-k ne demande rien. C'est délibéré, c'est documenté, et c'est la première raison d'activer le mode lecture seule sur les contextes de production.

Spécifiques aux deployments

ToucheAction
sScaler, avec saisie du nombre de replicas
rRedémarrer, l'équivalent de kubectl rollout restart
zAfficher les replicasets associés

Spécifiques aux nodes

ToucheAction
cCordon, marquer le node non planifiable
uUncordon
rDrain, évacuer les pods
sShell sur le node, si le feature gate est activé
yYAML du node

Le shell sur node mérite une note. Il n'est pas actif par défaut : k9s lance un pod privilégié sur le node pour vous y donner accès, ce qui est une opération sensible. Il faut l'activer explicitement par contexte, voir la section configuration.

Logs, shell et transfert de fichiers

Lire des logs correctement

l sur un pod ouvre la vue logs. Si le pod a plusieurs conteneurs, k9s vous fait d'abord choisir. Les raccourcis de cette vue :

ToucheAction
sBasculer l'autoscroll
wBasculer le retour à la ligne
tAfficher ou masquer les timestamps
fPlein écran
aAfficher tous les conteneurs à la fois
mPoser un marqueur dans le flux
shift-cEffacer l'écran
shift-lVerrouiller les colonnes
ctrl-sSauvegarder les logs dans un fichier
cCopier
/Filtrer le flux
esc ou qRevenir en arrière

Trois de ces touches méritent d'être retenues. m pose un repère visuel : vous marquez avant de reproduire un bug, et vous savez ensuite exactement où commence ce qui vous intéresse. a agrège les conteneurs d'un pod, ce qui économise l'installation de stern pour les cas simples. s coupe l'autoscroll, indispensable pour lire tranquillement un flux bavard.

Le nombre de lignes chargées au démarrage et la taille du buffer se règlent dans la configuration, section logger. Les valeurs par défaut, 100 lignes affichées et 5000 en buffer, sont un peu justes sur une application verbeuse.

Vue logs de k9s sur le conteneur portainer du namespace apps : barre d'état affichant Autoscroll On, ColumnLock Off, FullScreen Off, Timestamps Off et Wrap Off, puis les lignes de log colorisées par niveau

La barre d'état sous le titre donne l'état des cinq bascules en un coup d'œil, ce qui évite de tâtonner. Le titre rappelle le namespace, le pod et le conteneur affichés, ainsi que le mode de lecture entre crochets.

Ouvrir un shell

s sur un pod ouvre un shell dans le conteneur. Comme pour les logs, k9s vous demande le conteneur s'il y en a plusieurs. Il détecte le shell disponible, bash puis sh, et la 0.51 gère même le cas des conteneurs Windows NanoServer.

Si le conteneur n'a pas de shell du tout, ce qui est la norme sur une image distroless ou scratch, s échoue. La réponse correcte n'est pas de gonfler votre image, c'est un conteneur éphémère de debug :

kubectl debug -it mon-pod --image=busybox:1.37.0 --target=mon-conteneur

k9s 0.51 a amélioré la configuration des conteneurs de debug avec des champs de saisie, mais l'opération reste plus lisible en kubectl.

t ouvre le transfert de fichiers, dans les deux sens, ce qui remplace kubectl cp avec une interface qui vous évite de vous tromper de sens dans la syntaxe.

Le pod de debug configurable

Pour le shell sur node, k9s lance un pod dont vous contrôlez l'image et les limites :

k9s:
  shellPod:
    image: busybox:1.37.0
    namespace: default
    limits:
      cpu: 100m
      memory: 100Mi

Si votre cluster tire ses images depuis un registre privé, remplacez l'image par une des vôtres. Sinon le shell sur node échouera silencieusement sur un ImagePullBackOff que vous ne verrez pas.

Le port-forward

Le port-forward de k9s est plus agréable que celui de kubectl sur un point précis : il survit à la navigation. Vous le lancez, vous continuez à travailler dans k9s, il tourne en arrière-plan.

  • shift-f ouvre le dialogue de port-forward. Vous y choisissez le port du conteneur, le port local et l'adresse d'écoute. La touche fonctionne directement depuis la liste des pods ; descendre d'abord dans les conteneurs avec enter ne sert que si le pod en a plusieurs et que vous voulez choisir lequel exposer.
  • f affiche les port-forwards déjà actifs sur la ressource sélectionnée.
  • :pf liste tous les port-forwards de la session, depuis n'importe quelle vue.

Depuis la vue :pf, ctrl-d coupe un forward.

Vue conteneurs de k9s sur un pod du namespace apps : colonne PF indiquant l'état du port-forward, colonne PORTS affichant 5000, et raccourcis shift-f PortForward et f Show PortForward dans le bandeau supérieur

Un point qui déroute au premier essai : :pf n'affiche que les forwards que vous avez créés dans la session courante. Sur une session neuve, la vue est vide, et ce n'est pas un bug. La colonne PF de la vue conteneurs, elle, marque les conteneurs qui en ont un d'actif, et la colonne PORTS vous donne le port à saisir dans le dialogue.

Deux limites à connaître. D'abord, les port-forwards meurent avec la session k9s. Si vous quittez, tout tombe. Pour un tunnel qui doit durer, un kubectl port-forward dans une fenêtre tmux détachée est plus adapté. Ensuite, l'adresse d'écoute par défaut est localhost, ce qui est le bon défaut. Si vous devez exposer sur toutes les interfaces, c'est dans la configuration :

k9s:
  portForwardAddress: 0.0.0.0

Réfléchissez à deux fois avant. Sur un poste connecté à un réseau d'entreprise, ça expose votre base de données de production à tout le monde sur le segment.

Contextes et namespaces

:ctx ouvre le sélecteur de contexte. enter bascule. C'est tout, et c'est nettement plus rapide que kubectl config use-context avec un nom de contexte de quarante caractères à taper.

Pour démarrer directement sur un contexte :

k9s --context staging
k9s --context prod -n monitoring
k9s -A                          # tous les namespaces
k9s -c deploy                   # démarrer sur la vue deployments

La combinaison --context et -c est celle que je mettrais dans un alias zsh pour chaque cluster que vous fréquentez.

Côté namespaces, :ns liste, les touches 0 à 9 basculent entre les favoris. Cette liste de favoris est persistée par contexte, dans ~/.local/share/k9s/clusters/<cluster>/<contexte>/config.yaml :

k9s:
  cluster: kubernetes
  namespace:
    active: all
    lockFavorites: false
    favorites:
      - apps
      - all
      - default
  view:
    active: v1/nodes
  featureGates:
    nodeShell: false
  proxy: null

Ce fichier est intéressant à connaître pour trois raisons. view.active définit la vue d'ouverture pour ce contexte précis : si vous ouvrez toujours ce cluster pour regarder les nodes, posez-le ici. lockFavorites: true fige la liste des namespaces, ce qui empêche k9s de la réorganiser au fil de vos visites - appréciable quand vous avez fini par mémoriser que 3 est monitoring. Et featureGates.nodeShell est l'interrupteur du shell sur node évoqué plus haut.

Vue namespaces de k9s : les douze namespaces du cluster avec leur statut et leur age, un signe plus marquant ceux enregistres en favoris, et le raccourci u Use dans le bandeau superieur

Dans cette vue, le signe + accolé à un nom signale un namespace enregistré en favori, et all+(*) la ligne qui les couvre tous. La touche u, pour Use, bascule sur le namespace sélectionné, ce qui revient au même que enter mais s'applique aussi depuis une ligne non favorite.

Au-delà des pods : xray, pulses, workloads

Trois vues qui n'existent pas dans kubectl et qui justifient à elles seules d'ouvrir k9s.

:xray RESSOURCE affiche un arbre de dépendances. :xray deploy vous montre chaque deployment, ses replicasets, ses pods, ses conteneurs, avec l'état de santé propagé. C'est la vue qui répond en un coup d'œil à "quel deployment est en train de mal se passer". espace déplie ou replie un nœud, x déplie ou replie l'arbre entier, enter saute à la ressource sélectionnée dans sa vue normale. Les actions habituelles restent disponibles sur les nœuds. Depuis la 0.51, xray respecte correctement le mode lecture seule, ce qui n'était pas le cas avant.

:pulse est un tableau de bord temps réel : compteurs par type de ressource, cadrans de santé, événements récents. C'est ce qu'on laisse tourner sur un second écran pendant un déploiement. La 0.51 permet de cycler dans la grille dans les deux sens, ce qui rend la vue réellement navigable.

:workload agrège deployments, statefulsets, daemonsets, jobs et cronjobs dans une seule table. Quand vous cherchez "ce qui tourne" sans savoir sous quel type c'est déclaré, c'est le point d'entrée.

Vue xray de k9s sur les deployments, tous namespaces : arbre depliant deployment vers namespace vers replicaset vers conteneurs, avec les compteurs de replicas prets entre crochets

Configurer k9s

Le fichier principal est ~/.config/k9s/config.yaml. k9s le crée au premier lancement avec tous les champs et leurs valeurs par défaut, ce qui en fait sa propre documentation. Voici les réglages qui valent le détour.

k9s:
  refreshRate: 2
  apiServerTimeout: 2m0s
  maxConnRetry: 5
  readOnly: false
  noExitOnCtrlC: false
  portForwardAddress: localhost
  liveViewAutoRefresh: false
  skipLatestRevCheck: false
  disablePodCounting: false
  ui:
    enableMouse: false
    headless: false
    logoless: false
    crumbsless: false
    splashless: false
    reactive: false
    noIcons: false
    defaultsToFullScreen: false
    useFullGVRTitle: false
    skin: transparent
  logger:
    tail: 100
    buffer: 5000
    sinceSeconds: -1
    textWrap: false
    disableAutoscroll: false
    showTime: false
  thresholds:
    cpu:
      critical: 90
      warn: 70
    memory:
      critical: 90
      warn: 70

Ceux qui changent vraiment quelque chose :

  • refreshRate : deux secondes par défaut. Sur un gros cluster ou une connexion lente, montez à 5 ou 10. Vous soulagez l'API server et vous arrêtez de voir la table clignoter.
  • noExitOnCtrlC: true : empêche ctrl-c de fermer k9s. Si vous avez le réflexe ctrl-c du shell, activez-le, vous perdrez moins de sessions.
  • ui.noIcons: true : remplace les emoji par du texte. Nécessaire si votre police de terminal ne gère pas les glyphes, et honnêtement plus lisible.
  • ui.reactive: true : recharge la configuration et le skin à chaud dès que le fichier change sur disque. Indispensable pendant que vous mettez au point un skin, vous voyez le résultat sans relancer.
  • logger.tail : passez à 500 ou 1000. Cent lignes, c'est peu quand l'erreur est déjà remontée.
  • skipLatestRevCheck: true : coupe la vérification de nouvelle version au démarrage. Un appel réseau de moins, et vous n'êtes plus tenté de mettre à jour au milieu d'un incident.
  • thresholds : les seuils de coloration CPU et mémoire. À ajuster selon ce que vous considérez comme normal chez vous.

Un mot sur enableMouse. La souris fonctionne, mais elle entre en conflit avec la sélection de texte du terminal : avec la souris activée, vous ne pouvez plus surligner pour copier. Sur un TUI qu'on utilise justement pour lire, c'est un mauvais marché. Laissez à false.

Le tuning visuel : skins et transparence

C'est la partie qui rend l'outil agréable, et elle est très souvent négligée.

Les skins vont dans ~/.config/k9s/skins/, un fichier YAML par thème, et vous le référencez par son nom de fichier sans extension dans ui.skin. k9s embarque plusieurs thèmes, dont un One Light ajouté en 0.51.

Le skin transparent

Si vous avez configuré un fond de terminal avec de la transparence ou une image, k9s le recouvre par défaut avec sa propre couleur de fond, ce qui annule tout votre travail. La solution est un skin qui utilise default partout où une couleur de fond est attendue : default signifie "n'écris rien, laisse passer le terminal".

Créez ~/.config/k9s/skins/transparent.yaml :

k9s:
  body:
    fgColor: default
    bgColor: default
    logoColor: blue
  prompt:
    fgColor: default
    bgColor: default
    suggestColor: dodgerblue
  info:
    fgColor: orange
    sectionColor: default
  frame:
    border:
      fgColor: dodgerblue
      focusColor: aliceblue
    menu:
      fgColor: default
      keyColor: dodgerblue
      numKeyColor: dodgerblue
    crumbs:
      fgColor: default
      bgColor: default
      activeColor: dodgerblue
    status:
      newColor: '#00ff00'
      modifyColor: aqua
      addColor: lightskyblue
      errorColor: orangered
      highlightColor: aquamarine
      killColor: mediumpurple
      completedColor: gray
    title:
      fgColor: aqua
      bgColor: default
      highlightColor: fuchsia
      counterColor: papayawhip
      filterColor: seagreen
  views:
    charts:
      bgColor: default
      defaultDialColors: [dodgerblue, orangered]
      defaultChartColors: [dodgerblue, orangered]
    table:
      fgColor: default
      bgColor: default
      header:
        fgColor: default
        bgColor: default
        sorterColor: orange
    xray:
      fgColor: default
      bgColor: default
      cursorColor: aqua
      graphicColor: dodgerblue
    yaml:
      keyColor: steelblue
      colonColor: default
      valueColor: papayawhip
    logs:
      fgColor: default
      bgColor: default
      indicator:
        fgColor: dodgerblue
        bgColor: default

Puis dans config.yaml :

k9s:
  ui:
    skin: transparent

La règle est simple : tout bgColor doit valoir default, y compris dans table.header, logs et xray. Il suffit d'en oublier un pour voir un rectangle opaque traverser votre écran. Les couleurs de premier plan peuvent être nommées (dodgerblue, papayawhip) ou en hexadécimal (#00ff00), les deux formes cohabitent sans problème.

Activez ui.reactive: true pendant que vous ajustez : chaque sauvegarde du fichier se voit immédiatement.

Un skin par contexte

Le détail qui vaut de l'or en prod : le skin peut être défini par contexte, dans le fichier de contexte sous ~/.local/share/k9s/clusters/. Un skin rouge sur production, un skin neutre sur staging, et votre cerveau vous prévient avant votre lucidité.

k9s:
  cluster: prod-eu-west
  skin: danger

C'est le seul garde-fou visuel réellement efficace contre l'erreur de cluster. Le bandeau texte, on finit par ne plus le lire ; une couleur qui change, non.

Inverser un skin

k9s --invert

Bascule un skin sombre en clair, ou l'inverse, en préservant les teintes. Pratique quand vous passez d'un terminal sombre à une projection en salle de réunion.

Alias, hotkeys, vues personnalisées et plugins

Quatre mécanismes d'extension, quatre fichiers, souvent confondus. Voici la distinction.

Les alias : raccourcir une commande

~/.config/k9s/aliases.yaml associe un nom court à un type de ressource :

aliases:
  dp: deployments
  sec: v1/secrets
  jo: jobs
  cr: clusterroles
  crb: clusterrolebindings
  ro: roles
  rb: rolebindings
  np: networkpolicies

Vous tapez ensuite :dp au lieu de :deployments. C'est particulièrement utile pour les CRD, dont les noms sont interminables : un alias :vs pour virtualservices.networking.istio.io se rentabilise vite.

Les hotkeys : une touche vers une vue

~/.config/k9s/hotkeys.yaml associe une touche à une commande complète :

hotKeys:
  shift-0:
    shortCut: Shift-0
    description: Pods en erreur, tous namespaces
    command: pod /-!Running
    keepHistory: true
  shift-1:
    shortCut: Shift-1
    description: Events du cluster
    command: events
  shift-2:
    shortCut: Shift-2
    description: Nodes
    command: node

Les champs disponibles sont shortCut, description, command, keepHistory et override. Ce dernier permet d'écraser un raccourci existant de k9s, à manier avec précaution : écraser d ou l vous privera de Describe ou de Logs sans prévenir.

Les vues personnalisées : choisir les colonnes

~/.config/k9s/views.yaml définit les colonnes affichées par type de ressource :

views:
  v1/pods:
    columns:
      - NAME
      - READY
      - STATUS
      - RESTARTS
      - NODE
      - AGE
    sortColumn: AGE:desc

Si vous en avez assez de taper ctrl-w à chaque ouverture pour voir la colonne NODE, mettez-la ici une fois pour toutes.

Les plugins : appeler une commande externe

C'est le mécanisme le plus puissant. Un plugin lie une touche, dans un contexte donné, à une commande shell qui reçoit la ressource sélectionnée.

~/.config/k9s/plugins.yaml :

plugins:
  stern:
    shortCut: Ctrl-L
    description: Logs stern
    scopes:
      - pods
    command: stern
    background: false
    args:
      - --tail
      - "50"
      - $NAME
      - -n
      - $NAMESPACE
      - --context
      - $CONTEXT

  dive:
    shortCut: Ctrl-I
    description: Inspecter l'image
    scopes:
      - pods
    command: sh
    background: false
    args:
      - -c
      - "dive $(kubectl get pod $NAME -n $NAMESPACE --context $CONTEXT -o jsonpath='{.spec.containers[0].image}')"

  rollout-undo:
    shortCut: Ctrl-U
    description: Rollback du deployment
    scopes:
      - deployments
    command: kubectl
    background: true
    dangerous: true
    confirm: true
    args:
      - rollout
      - undo
      - deployment/$NAME
      - -n
      - $NAMESPACE
      - --context
      - $CONTEXT

Les variables disponibles sont $NAME, $NAMESPACE, $CONTEXT, $CLUSTER, $USER, $RESOURCE_NAME, $COL-<NOM> pour la valeur d'une colonne, et $FILTER pour le filtre courant.

Les champs qui comptent :

  • scopes : les vues où le plugin s'active. pods, deployments, ou all.
  • background : true exécute sans reprendre le terminal, false rend la main à la commande.
  • dangerous: true : le plugin est désactivé en mode lecture seule. Posez-le sur tout ce qui écrit.
  • confirm: true : demande confirmation avant exécution.
  • overwriteOutput : remplace la sortie plutôt que de l'ajouter.
  • inputs : nouveauté 0.51, permet de demander des valeurs à l'utilisateur avant l'exécution, avec name, label, type, required, default et options. C'est ce qui rend possible un plugin de redimensionnement de PVC, livré en exemple dans cette version.

Un point qui piège : dangerous: true sans confirm: true désactive le plugin en lecture seule mais l'exécute sans rien demander en mode écriture. Mettez les deux.

Le mode lecture seule et l'accès à la production

C'est la section à ne pas sauter si k9s doit toucher un cluster de production.

En mode écriture, k9s expose ctrl-d pour supprimer, ctrl-k pour tuer sans confirmation, e pour éditer en direct, r pour redémarrer un deployment, s pour scaler. Toutes ces actions sont à une frappe. Une main mal placée sur un clavier suffit.

Le mode lecture seule s'active de trois manières, par ordre de robustesse croissante :

k9s --readonly

Le drapeau, à mettre dans un alias shell. Facile à oublier.

k9s:
  readOnly: true

Le réglage global dans config.yaml. Plus fiable, mais il s'applique aussi à vos clusters de développement, où vous voulez pouvoir agir. Le drapeau --write permet de le lever ponctuellement, ce qui est le bon compromis : par défaut on lit, on demande explicitement à écrire.

k9s:
  cluster: prod-eu-west
  readOnly: true

Le réglage par contexte, sous ~/.local/share/k9s/clusters/. C'est le bon endroit. Il suit le cluster, pas votre humeur.

Quelques principes qui vont avec :

  • Le vrai garde-fou est RBAC, pas k9s. Un ServiceAccount en lecture seule côté cluster empêche l'action ; un réglage local dans un fichier YAML de votre poste ne fait que masquer un bouton. k9s affiche d'ailleurs les vues :rbac, :usr et :grp pour vérifier vos droits effectifs.
  • Un skin distinct par environnement, comme vu plus haut. La couleur passe avant le texte.
  • Ne mettez pas k9s sur un bastion partagé en mode écriture avec un kubeconfig d'admin. La combinaison est mauvaise.
  • --as et --as-group permettent d'usurper une identité pour tester des droits RBAC. Excellent pour valider une politique avant de la livrer.

Dépannage

k9s ne trouve pas mon cluster

Vérifiez d'abord que kubectl fonctionne :

kubectl config current-context
kubectl get nodes

Si kubectl passe et pas k9s, c'est un problème de kubeconfig lu. k9s suit $KUBECONFIG puis ~/.kube/config. En cas de doute, forcez :

k9s --kubeconfig ~/.kube/prod-config

Les métriques sont vides

Les colonnes CPU et mémoire affichent n/a ou restent vides. Ce n'est pas un bug de k9s : le metrics-server n'est pas installé ou ne répond pas. Vérifiez avec kubectl top nodes. Si cette commande échoue, k9s ne peut rien afficher de plus.

Les caractères sont cassés ou les icônes illisibles

Deux causes possibles. Soit TERM n'annonce pas les couleurs :

export TERM=xterm-256color

Soit votre police ne contient pas les emoji utilisés. Dans ce cas :

k9s:
  ui:
    noIcons: true

Un raccourci ne fait pas ce qui est documenté

Le premier réflexe est ?, qui affiche les raccourcis réellement actifs dans la vue courante. Le deuxième est k9s version : les raccourcis changent entre versions mineures, et beaucoup de tutoriels en ligne datent de la série 0.2x.

Vérifiez aussi que vous n'avez pas un hotKeys ou un plugin avec override: true qui écrase la touche.

k9s est lent ou fait ramer l'API server

Montez refreshRate à 10, désactivez disablePodCounting si vous avez des namespaces énormes, et évitez de laisser :pulse ouvert en permanence. Sur un cluster à plusieurs milliers de pods, une vue all namespaces est coûteuse par nature.

Le shell sur node ne marche pas

Le feature gate est désactivé par défaut. Activez-le dans le fichier du contexte concerné :

k9s:
  featureGates:
    nodeShell: true

Et vérifiez que l'image de shellPod est accessible depuis le cluster. Si votre registre est privé, busybox:1.37.0 depuis Docker Hub ne sera peut-être pas tirable.

Tableau des erreurs courantes

SymptômeCause probableCorrection
Unable to connect to contextkubeconfig invalide ou expiréRenouveler les credentials, tester avec kubectl
Colonnes CPU/MEM videsmetrics-server absentInstaller metrics-server
s ne fait rien sur un podImage sans shell, ou mode lecture seulekubectl debug, ou lever le readOnly
Rectangles opaques avec un skin transparentUn bgColor oubliéMettre default sur tous les bgColor
You don't have enough RBAC permissionsDroits insuffisantsVérifier avec :rbac
Port-forward qui tombeSession k9s ferméeUtiliser kubectl port-forward pour un tunnel durable
Vue vide sur un CRD existantAlias mal résoluctrl-a pour retrouver le bon nom
k9s se ferme sur ctrl-cComportement par défautnoExitOnCtrlC: true

Et quand rien de tout ça ne suffit, les logs :

k9s --logLevel debug
tail -f ~/.local/state/k9s/k9s.log

À retenir

Commande ou touchePour quoi
k9s infoOù k9s lit et écrit tous ses fichiers
?Les raccourcis actifs dans la vue courante
ctrl-aTous les alias de ressources disponibles
:ctxChanger de contexte
:pfLes port-forwards actifs
:xray deployArbre de dépendances des deployments
:wkVue agrégée de toutes les charges de travail
/-!RunningTout ce qui n'est pas dans l'état Running
ctrl-zNe montrer que les ressources en défaut
ctrl-wColonnes larges, équivalent de -o wide
wBasculer dans le namespace de la ligne sélectionnée
l puis pLogs courants, puis logs de l'instance précédente
shift-fPort-forward depuis un conteneur
--readonlyLe mode par défaut sur un cluster de production

FAQ

Comment installer k9s sur Linux ?

Le plus simple est de télécharger le binaire depuis les releases GitHub et de le poser dans ~/.local/bin : curl -sL https://github.com/derailed/k9s/releases/download/v0.51.0/k9s_Linux_amd64.tar.gz | tar xz -C /tmp k9s && install -m 0755 /tmp/k9s ~/.local/bin/k9s. Sur Arch, pacman -S k9s suit correctement les releases. Sur Debian et Ubuntu, il n'y a pas de paquet officiel à jour, prenez le .deb de la release ou le binaire. Sur macOS, brew install derailed/k9s/k9s avec le tap officiel, plus frais que homebrew-core.

Où se trouve le fichier de configuration de k9s ?

~/.config/k9s/config.yaml depuis la version 0.30. Les skins sont dans ~/.config/k9s/skins/, les plugins, hotkeys, alias et vues personnalisées dans des fichiers séparés du même dossier. L'état par cluster est ailleurs, dans ~/.local/share/k9s/clusters/, et les logs dans ~/.local/state/k9s/k9s.log. La commande k9s info affiche tous ces chemins pour votre installation, ne les devinez pas. Les tutoriels qui parlent de ~/.k9s/ sont obsolètes.

Comment voir les logs d'un pod dans k9s ?

Sélectionnez le pod et appuyez sur l. Si le pod a plusieurs conteneurs, k9s vous fait choisir. Dans la vue logs, s bascule l'autoscroll, w le retour à la ligne, t les timestamps, f le plein écran, et a affiche tous les conteneurs du pod à la fois. Pour un pod qui redémarre en boucle, p affiche les logs de l'instance précédente : c'est là que se trouve l'erreur qui a tué le processus, pas dans les logs courants.

Comment ouvrir un shell dans un conteneur avec k9s ?

Touche s sur le pod. k9s détecte le shell disponible, bash puis sh. Si l'image est distroless ou scratch, il n'y a pas de shell et l'action échoue : passez alors par un conteneur éphémère avec kubectl debug -it mon-pod --image=busybox:1.37.0 --target=mon-conteneur. La touche s est désactivée en mode lecture seule, c'est une action classée dangereuse.

Comment faire un port-forward dans k9s ?

Sélectionnez le pod et appuyez sur shift-f : le dialogue vous demande le port du conteneur, le port local et l'adresse d'écoute. Si le pod a plusieurs conteneurs et que vous voulez choisir lequel exposer, descendez d'abord avec enter. f affiche les forwards actifs sur la ressource sélectionnée, :pf les liste tous depuis n'importe quelle vue, et ctrl-d en coupe un depuis cette liste. Si :pf semble vide, c'est normal : elle ne montre que les forwards créés dans la session en cours. Attention aussi, les port-forwards meurent avec la session k9s. Pour un tunnel qui doit durer, utilisez kubectl port-forward dans une fenêtre tmux détachée.

Comment changer de namespace dans k9s ?

Les touches 0 à 9 basculent entre les namespaces favoris affichés en haut de l'écran, 0 étant toujours all. :ns ouvre la liste complète. La touche w vous téléporte dans le namespace de la ressource sélectionnée, ce qui est le moyen le plus rapide depuis une vue tous namespaces. La liste des favoris est mémorisée par contexte et se réorganise selon vos visites ; lockFavorites: true dans le fichier du contexte la fige.

Comment rendre k9s transparent pour voir le fond de mon terminal ?

Créez un skin dans ~/.config/k9s/skins/transparent.yamltous les champs bgColor valent default, y compris ceux de table.header, logs, xray et charts. La valeur default indique à k9s de ne rien peindre et de laisser passer le terminal. Référencez ensuite le skin dans config.yaml sous ui.skin: transparent. Activez ui.reactive: true pendant la mise au point pour voir chaque modification sans relancer. Un seul bgColor oublié suffit à produire un rectangle opaque.

Comment passer k9s en lecture seule ?

Trois façons. Le drapeau k9s --readonly pour une session. Le champ readOnly: true dans config.yaml pour tous les clusters, avec --write pour lever la restriction ponctuellement. Et surtout readOnly: true dans le fichier de contexte sous ~/.local/share/k9s/clusters/<cluster>/<contexte>/config.yaml, qui applique la restriction au seul cluster concerné. C'est cette dernière forme qu'il faut utiliser pour la production, parce qu'elle suit le cluster et non votre configuration globale. Rappelez-vous que le vrai garde-fou reste RBAC côté cluster.

k9s remplace-t-il kubectl ?

Non, et ce n'est pas son objectif. k9s utilise votre kubeconfig, vos contextes et vos droits RBAC : il parle à la même API avec les mêmes permissions. Il excelle pour explorer et diagnostiquer, là où kubectl reste indispensable pour tout ce qui doit être scripté, tracé ou reproduit. Le découpage qui fonctionne est k9s pour comprendre, kubectl pour agir et pour laisser une trace.

Quelles sont les alternatives à k9s ?

Headlamp d'abord : projet CNCF maintenu sous kubernetes-sigs, utilisable en desktop ou déployé dans le cluster, c'est le successeur officiellement recommandé de Kubernetes Dashboard, lui-même archivé depuis janvier 2026. Ensuite Lens et son fork communautaire le plus actif, Freelens. Aptakube pour une GUI commerciale multi-cluster soignée. Et l'option souvent suffisante : kubectl augmenté de kubectx, kubens et stern, qui élimine l'essentiel de la friction sans renoncer à la traçabilité.

Pour aller plus loin