kubectl, la télécommande du cluster

13 min
Public
débutant, Kubernetes de Docker Desktop activé (leçon 02)
Durée
35 à 45 min
Module
1/8
Compétence visée
savoir quel binaire kubectl répond et vers quel cluster il parle, corriger un avertissement de version, lire une commande kubectl comme une phrase (verbe, ressource, nom, options) et créer ton premier namespace

En une image

kubectl est une télécommande universelle. Elle ne fait rien par elle-même : elle envoie des ordres à un appareil, l'API server de la leçon 01, en HTTPS sur le port 6443. Elle a un sélecteur de source, le contexte, qui dit quel cluster viser (docker-desktop, un vieux minikube, la production de ton entreprise) : appuie sur « Play » en visant le mauvais appareil et rien ne bouge, tu crois la télécommande cassée. Elle a des piles d'une certaine tension : un kubectl 1.30 devant un cluster 1.34 marche à peu près, mais te prévient qu'il ne garantit plus rien. Et elle parle une grammaire fixe : un verbe (get), une ressource (pods), parfois un nom, puis des options (-n premiers-pas -o wide). Dans quarante minutes tu sauras lire cette phrase du premier coup, tu auras corrigé un vrai piège de version, et tu auras ouvert ton propre tiroir dans le cluster : le namespace premiers-pas, où tout le module va se passer.

Comment ça marche

kubectl lit un seul fichier au démarrage : ~/.kube/config (C:\Users\<toi>\.kube\config sous Windows), le kubeconfig. Il contient trois listes : des clusters (une adresse d'API et le certificat qui permet de la reconnaître), des users (les identifiants : ici un certificat client généré par Docker Desktop) et des contexts, qui associent un cluster à un utilisateur, avec éventuellement un namespace par défaut. La ligne current-context désigne celui qu'utilise chaque commande. Docker Desktop y écrit docker-desktop à l'activation ; minikube, kind ou un fournisseur cloud ajoutent les leurs, et c'est ainsi qu'un même kubectl pilote plusieurs clusters.

Chaque commande se lit comme une phrase : kubectl <verbe> <ressource> [nom] [options]. Le verbe dit quoi faire ; la ressource, sur quel type d'objet ; le nom cible un objet précis (sans nom, le verbe s'applique à tous ceux du namespace) ; les options précisent le tiroir (-n), le format (-o), la portée (-A) ou le suivi en direct (-w). Les ressources acceptent des raccourcis que kubectl api-resources liste dans sa colonne SHORTNAMES.

MorceauExemplesRôle
verbeget, describe, create, apply, delete, logs, exec, scale, explainl'action demandée à l'API
ressourcepods (po), deployments (deploy), services (svc), namespaces (ns), nodes (no)le type d'objet ; pod/api équivaut à pod api
nomapi, api-9bfb55fc6-988xh, docker-desktopun objet précis ; absent = tous les objets du namespace
-n <ns>-n premiers-pasle namespace visé ; sans lui, default (le cours ne s'en sert jamais)
-Akubectl get pods -Atous les namespaces (ajoute une colonne NAMESPACE)
-o wide / -o yaml / -o json / -o namekubectl get pods -o wideplus de colonnes / l'objet complet tel que l'API le stocke / idem en JSON / seulement type/nom
-wkubectl get pods -n premiers-pas -wreste connecté et affiche chaque changement (Ctrl+C pour sortir)
--helpkubectl get --helpl'aide de n'importe quel verbe, avec exemples

Les namespaces sont les tiroirs du cluster : un même nom de Pod ou de Service peut exister dans deux namespaces sans conflit, les quotas et les droits s'attachent au namespace, et kubectl delete namespace vide tout d'un coup. Le cluster naît avec default, kube-system (le control plane), kube-public et kube-node-lease. Ce cours n'écrit jamais dans default : chaque module a son namespace, et chaque commande porte -n. Oublier -n, c'est chercher ton Pod dans le mauvais tiroir : il « n'existe pas », alors qu'il tourne très bien à côté. Tu provoqueras cette erreur en pratique guidée pour ne plus jamais t'y faire prendre.

Ce que tu veux savoirCommandeParle au cluster ?
quel binaire répondwhere.exe kubectl (Windows) / which -a kubectl (bash)non
version du client et du serveurkubectl versionoui
vers quel cluster je pointekubectl config current-contextnon
tous les clusters connuskubectl config get-contextsnon
que contient un champ YAMLkubectl explain deployment.spec.replicasoui
tous les types d'objets et leurs raccourciskubectl api-resourcesoui

Pas à pas

Sous PowerShell, la machine du cours garde volontairement un piège : trois kubectl dans le PATH, dont un vieux 1.30 installé à la main avant Docker Desktop. Chez toi il n'y en a sans doute qu'un ; fais quand même les étapes 1 à 3, elles t'éviteront une heure de confusion le jour où tu installeras un second outil.

  1. Trouver quel kubectl répond. Le shell prend le premier binaire trouvé dans l'ordre du PATH.

    powershell
    where.exe kubectl
    bash
    which -a kubectl

    Sortie réelle (Windows) :

    text
    C:\Program Files\Docker\Docker\resources\bin\kubectl.exe
    C:\Users\<toi>\Documents\kubectl\kubectl.exe
    C:\kubectl\kubectl.exe

    Ce qu'il faut voir : la première ligne est celle qui s'exécute quand tu tapes kubectl. Ici c'est celle de Docker Desktop, parce que le PATH a été réordonné ; l'étape 2 montre ce qui se passe quand ce n'est pas le cas. Sous macOS, attends-toi à /usr/local/bin/kubectl (Docker Desktop) et peut-être /opt/homebrew/bin/kubectl (Homebrew).

  2. Regarde bien ce qui va se passer : lancer le vieux kubectl exprès. Sur la machine du cours, le deuxième binaire est un 1.30. Appelé par son chemin complet devant le cluster 1.34 :

    powershell
    & "C:\Users\<toi>\Documents\kubectl\kubectl.exe" version

    Sortie réelle :

    text
    Client Version: v1.30.0
    Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
    Server Version: v1.34.1
    WARNING: version difference between client (1.30) and server (1.34) exceeds the supported minor version skew of +/-1

    Ce qu'il faut voir : la commande répond quand même (le cluster est joignable), mais l'avertissement est explicite : Kubernetes ne garantit kubectl qu'à une version mineure d'écart du serveur (1.33, 1.34 ou 1.35 pour un cluster 1.34). Au-delà, certaines sous-commandes se comportent bizarrement ou ignorent des champs récents. Si tu vois cette ligne chez toi, c'est ce piège : un vieux kubectl (Homebrew, Chocolatey, téléchargement manuel) passe devant celui de Docker Desktop.

  3. Corriger l'ordre du PATH. Pour la session PowerShell en cours, puis vérifier :

    powershell
    $env:Path = "C:\Program Files\Docker\Docker\resources\bin;" + $env:Path
    kubectl version

    Sortie réelle :

    text
    Client Version: v1.34.1
    Kustomize Version: v5.7.1
    Server Version: v1.34.1

    Ce qu'il faut voir : client et serveur alignés sur v1.34.1, plus d'avertissement. Pour rendre le changement permanent sous Windows : Paramètres → Système → Informations système → Paramètres système avancés → Variables d'environnement → Path de ton utilisateur → remonte C:\Program Files\Docker\Docker\resources\bin en tête (ou supprime l'entrée du vieux kubectl), puis rouvre le terminal. Sous macOS/Linux, supprime le doublon (brew uninstall kubectl) ou mets /usr/local/bin avant dans ton ~/.zshrc. Le script du kit le vérifie pour toi : .\labo.ps1 prerequis affiche ✘ kubectl client v1.30.0 trop ancien (minimum 1.33) — … tant que l'ordre est mauvais.

  4. Lire le kubeconfig et le contexte courant. Deux commandes qui ne touchent pas au cluster.

    bash
    kubectl config get-contexts
    kubectl config current-context

    Sortie réelle :

    text
    CURRENT   NAME             CLUSTER          AUTHINFO         NAMESPACE
    *         docker-desktop   docker-desktop   docker-desktop
              minikube         minikube         minikube         default
    docker-desktop

    Ce qu'il faut voir : l'étoile sur docker-desktop. La machine du cours garde un contexte minikube d'un ancien cluster éteint : c'est le genre de reste qui fait dire « kubectl ne marche plus » quand il devient courant par accident. Si chez toi l'étoile est ailleurs, kubectl config use-context docker-desktop la déplace (ne le tape pas si elle est déjà au bon endroit : la commande réécrit ~/.kube/config). La colonne NAMESPACE vide signifie « default sauf si je passe -n » ; on ne la remplira pas, le cours veut que -n soit un réflexe.

  5. Lire une commande comme une phrase, avec explain. Le manuel est dans le cluster : kubectl explain demande à l'API server la documentation d'un type ou d'un champ, pour la version exacte que tu utilises.

    bash
    kubectl explain deployment.spec.replicas

    Sortie réelle :

    text
    GROUP:      apps
    KIND:       Deployment
    VERSION:    v1
    
    FIELD: replicas <integer>
    
    
    DESCRIPTION:
        Number of desired pods. This is a pointer to distinguish between explicit
        zero and not specified. Defaults to 1.

    Puis descends d'un niveau dans un Pod :

    bash
    kubectl explain pod.spec.containers

    Sortie réelle (raccourcie : la liste complète compte une trentaine de champs) :

    text
    KIND:       Pod
    VERSION:    v1
    
    FIELD: containers <[]Container>
    
    
    DESCRIPTION:
        List of containers belonging to the pod. Containers cannot currently be
        added or removed. There must be at least one container in a Pod. Cannot be
        updated.
        A single application container that you want to run within a pod.
    
    FIELDS:
      args	<[]string>
        Arguments to the entrypoint. The container image's CMD is used if this is
        not provided. …
    
      image	<string>
        Container image name. More info:
        https://kubernetes.io/docs/concepts/containers/images …
    
      imagePullPolicy	<string>
      enum: Always, IfNotPresent, Never
        Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if
        :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. …
    
      name	<string> -required-
        Name of the container specified as a DNS_LABEL. Each container in a pod must
        have a unique name (DNS_LABEL). Cannot be updated.
    
      ports	<[]ContainerPort>
        List of ports to expose from the container. …

    Ce qu'il faut voir : <[]Container> dit « une liste », -required- marque les champs obligatoires (name ; image ne l'est pas formellement, mais un conteneur sans image ne démarre pas), et la ligne imagePullPolicy … Defaults to Always if :latest tag is specified explique pourquoi ce cours n'écrit jamais :latest : tu ne saurais plus quelle version tourne, et Kubernetes irait la retélécharger à chaque démarrage.

  6. Découvrir les ressources et leurs raccourcis. La liste complète dépasse cinquante lignes ; filtre les types que tu croiseras dans les trois premiers modules.

    powershell
    kubectl api-resources | Select-String -Pattern '^(pods|deployments|services|namespaces|nodes|configmaps|secrets|replicasets|jobs|cronjobs|ingresses)\s'
    bash
    kubectl api-resources | grep -E '^(pods|deployments|services|namespaces|nodes|configmaps|secrets|replicasets|jobs|cronjobs|ingresses) '

    Sortie réelle :

    text
    configmaps                          cm           v1                                true         ConfigMap
    namespaces                          ns           v1                                false        Namespace
    nodes                               no           v1                                false        Node
    pods                                po           v1                                true         Pod
    secrets                                          v1                                true         Secret
    services                            svc          v1                                true         Service
    deployments                         deploy       apps/v1                           true         Deployment
    replicasets                         rs           apps/v1                           true         ReplicaSet
    cronjobs                            cj           batch/v1                          true         CronJob
    jobs                                             batch/v1                          true         Job
    ingresses                           ing          networking.k8s.io/v1              true         Ingress

    Ce qu'il faut voir : la colonne SHORTNAMES (po, deploy, svc, ns, no, cm, rs), la colonne APIVERSION que tu recopieras en tête de chaque YAML (v1 pour un Pod, apps/v1 pour un Deployment), et surtout NAMESPACED : true pour un Pod ou un Service (ils vivent dans un tiroir, -n obligatoire), false pour namespaces et nodes (ils appartiennent au cluster entier, -n n'a pas de sens).

  7. Créer ton tiroir : le namespace premiers-pas. Première commande qui écrit dans le cluster.

    bash
    kubectl create namespace premiers-pas
    kubectl get namespace premiers-pas
    kubectl get pods -n premiers-pas

    Sortie réelle :

    text
    namespace/premiers-pas created
    NAME           STATUS   AGE
    premiers-pas   Active   0s
    No resources found in premiers-pas namespace.

    Ce qu'il faut voir : la réponse type d'une création, type/nom created ; un namespace Active immédiatement ; et le message d'un tiroir vide, No resources found in premiers-pas namespace. : ce n'est pas une erreur, c'est la réponse correcte à « qu'y a-t-il ici ? » quand il n'y a rien. Si la première commande répond Error from server (AlreadyExists), le namespace existe déjà (tu as peut-être pris de l'avance sur la leçon 04) : continue.

  8. Se faire la vie facile : alias et autocomplétion. k à la place de kubectl et la touche Tab qui complète verbes, ressources et noms d'objets. Ajoute ces lignes à ton profil pour qu'elles se rechargent à chaque terminal.

    powershell
    notepad $PROFILE

    Colle dans le fichier ouvert (crée-le si Notepad le propose) :

    powershell
    $env:Path = "C:\Program Files\Docker\Docker\resources\bin;" + $env:Path
    kubectl completion powershell | Out-String | Invoke-Expression
    Set-Alias k kubectl

    Sous bash (fichier ~/.bashrc) :

    bash
    source <(kubectl completion bash)
    alias k=kubectl
    complete -o default -F __start_kubectl k

    Sous zsh (~/.zshrc, le shell par défaut de macOS) :

    bash
    source <(kubectl completion zsh)
    alias k=kubectl
    compdef __start_kubectl k

    Rouvre le terminal, puis tape kubectl get dep et appuie sur Tab. Résultat réel sous PowerShell : la ligne devient kubectl get deployments.apps. Tape ensuite k get nodes :

    text
    NAME             STATUS   ROLES           AGE   VERSION
    docker-desktop   Ready    control-plane   18d   v1.34.1

    Ce qu'il faut voir : k répond exactement comme kubectl. Le cours continue d'écrire kubectl en entier pour rester lisible ; toi, tape k. Rien à nettoyer : le namespace premiers-pas reste en place, la leçon 04 s'en sert tout de suite.

Si ça coince

  • WARNING: version difference between client (1.30) and server (1.34) exceeds the supported minor version skew of +/-1 → un vieux kubectl passe devant celui de Docker Desktop dans le PATH. where.exe kubectl / which -a kubectl pour le voir, étape 3 pour corriger. La commande a quand même fonctionné : l'avertissement ne bloque pas, il prévient.
  • Unable to connect to the server: dial tcp 127.0.0.1:6443: connectex: No connection could be made because the target machine actively refused it. → Docker Desktop est arrêté ou Kubernetes est désactivé (leçon 02). Ce n'est jamais kubectl lui-même : kubectl version --client répond toujours, kubectl version non.
  • Error in configuration: context was not found for specified context: … ou kubectl config current-context qui renvoie error: current-context is not set → le contexte demandé n'existe pas dans le kubeconfig lu, ou ce fichier est vide (un autre outil a réécrit ~/.kube/config, ou la variable KUBECONFIG pointe ailleurs : messages provoqués en visant un contexte bogus puis un fichier vide). Vérifie echo $env:KUBECONFIG (PowerShell) / echo $KUBECONFIG (bash) : elle doit être vide ; sinon désactive puis réactive Kubernetes dans Docker Desktop, il réécrit le contexte.
  • Error from server (NotFound): pods "api-…" not found alors que le Pod apparaît dans kubectl get pods -n premiers-pas → tu as oublié -n premiers-pas : kubectl a cherché dans default. Ajoute l'option. kubectl get pods -A montre tous les Pods avec leur namespace quand tu ne sais plus où tu as rangé quelque chose.
  • kubectl : Impossible de charger le fichier … completion ou Invoke-Expression : … n'est pas reconnu dans $PROFILE → la ligne kubectl completion … s'exécute avant que le PATH contienne kubectl. Mets la ligne $env:Path = … en premier dans le profil, comme à l'étape 8 ; et si PowerShell refuse d'exécuter le profil, Set-ExecutionPolicy -Scope CurrentUser RemoteSigned.
  • Error from server (AlreadyExists): namespaces "premiers-pas" already exists → le namespace est déjà là, rien à faire. Pour repartir de zéro : kubectl delete namespace premiers-pas, attends qu'il disparaisse de kubectl get ns (10 à 30 s), recrée-le.

À retenir

  • kubectl <verbe> <ressource> [nom] [options] : kubectl get pods -n premiers-pas -o wide se lit « montre les Pods du tiroir premiers-pas, avec les colonnes en plus ».
  • where.exe kubectl / which -a kubectl révèle le binaire qui répond ; kubectl version doit afficher un client à au plus une version mineure du serveur (v1.34.1 des deux côtés sur Docker Desktop 4.68), sinon corrige l'ordre du PATH.
  • kubectl config current-context doit dire docker-desktop ; kubectl config get-contexts liste les autres clusters connus ; use-context ne se tape que si l'étoile est au mauvais endroit.
  • Un namespace est un tiroir : kubectl create namespace premiers-pas, puis -n premiers-pas sur chaque commande ; kubectl api-resources te dit quelles ressources sont NAMESPACED.
  • kubectl explain pod.spec.containers est le manuel intégré, exact pour ta version ; kubectl get --help donne des exemples pour chaque verbe.
  • Prochaine leçon : ton premier déploiement en cinq minutes, avec un Service qui répond sur http://localhost:8080 et un Pod qui renaît quand tu le supprimes.

Pour aller plus loin

Le kubeconfig n'est pas réservé à Docker Desktop : le jour où ton équipe te donne accès à un cluster de test dans le cloud, tu recevras un fichier du même format (az aks get-credentials, aws eks update-kubeconfig, gcloud container clusters get-credentials l'écrivent pour toi) et kubectl config get-contexts affichera une ligne de plus. Prends dès maintenant l'habitude de vérifier current-context avant tout delete : la commande ne demande jamais « es-tu sûr ? ». La référence complète des verbes, options et formats de sortie est sur kubectl Quick Reference (kubernetes.io), avec en tête de page les mêmes lignes d'autocomplétion qu'à l'étape 8.