Débutant Chapitre 1-2 / 2

Déclaratif vs impératif & État désiré vs état réel

Le principe fondateur de Kubernetes — déclarer un état désiré plutôt que soumettre des commandes — présenté sans prérequis, avec YAML et kubectl.

Déclaratif vs impératif

L’idée en une phrase

Une approche impérative énumère des actions à exécuter (« lancer 3 conteneurs ») ; une approche déclarative décrit un résultat à atteindre (« il doit exister 3 conteneurs ») et confie au système le soin de l’atteindre, puis de le maintenir. Kubernetes est déclaratif par construction : ce choix fonde la réconciliation, fil conducteur de ce livre.

Analogie : Considérons un chantier. L’approche impérative revient à dicter chaque geste aux ouvriers ; si un mur s’effondre après le départ du donneur d’ordres, aucun ordre ne le reconstruit. L’approche déclarative revient à afficher le plan du bâtiment : les ouvriers comparent en continu la construction au plan et corrigent tout écart constaté. Le plan joue le rôle du fichier YAML.

Points clés

  • Une commande impérative est consommée à son exécution. Si une action échoue, ou si l’environnement change ensuite (panne, redémarrage), aucun mécanisme ne corrige : l’ordre n’existe plus.
  • Une déclaration reste en vigueur après son application. Le système compare en continu ce qui existe avec ce qui est déclaré, et agit sur tout écart.
  • Kubernetes accepte des commandes impératives (kubectl run, kubectl scale), utiles pour expérimenter. Son cœur reste déclaratif : chaque objet porte une spec, la description du résultat attendu.
  • Une opération déclarative est idempotente : appliquer deux fois le même fichier produit le même résultat. Rejouer un script impératif double les effets ou échoue.
  • L’état désiré étant exprimé dans des fichiers, il est versionnable : l’infrastructure se gère dans Git. Ce point est développé au chapitre 37-38 (GitOps).

Exemple concret

Sur une machine virtuelle classique, 3 conteneurs sont lancés manuellement (docker run, exécuté 3 fois). La machine redémarre : au retour, 0 conteneur. Les commandes ont été exécutées la veille ; rien ne les rejoue.

Avec Kubernetes, un Deployment déclare replicas: 3. Le nœud redémarre : les 3 pods sont recréés sans intervention, éventuellement sur d’autres nœuds. La déclaration, elle, n’a jamais cessé d’être en vigueur.

Impératif vs déclaratif

CritèreImpératifDéclaratif
Ce qui est expriméLe comment (les étapes)Le quoi (le résultat)
Durée de vieConsommé à l’exécutionEn vigueur en continu
Après une panneAucune correctionAuto-réparation (réconciliation)
Rejouer 2 foisEffets doublés ou erreurMême résultat (idempotence)
Exemple kubectlkubectl run web --image=nginxkubectl apply -f deployment.yaml

Code kubectl — les deux styles

# Style impératif : un ordre, exécuté une fois
kubectl run web --image=nginx:1.27
# pod/web created
# → pod isolé, sans déclaration associée : s'il meurt, rien ne le recrée

# Style déclaratif : enregistrement d'un état désiré
kubectl apply -f deployment.yaml
# deployment.apps/hello created

# Rejouer le même apply est sans effet — l'état désiré est inchangé
kubectl apply -f deployment.yaml
# deployment.apps/hello unchanged   ← idempotence observable

Piège courant : « kubectl apply exécute le YAML » est inexact. apply n’exécute rien : il enregistre un état désiré dans le cluster, puis rend la main. Les actions sont décidées ensuite — et en continu — par les boucles de contrôle. La distinction devient concrète à la première panne de nœud : aucune commande n’est rejouée, et le système converge pourtant.


État désiré vs état réel

L’idée en une phrase

L’état désiré est ce qui a été déclaré (la spec des objets) ; l’état réel est ce qui existe dans le cluster à un instant donné (reflété dans le status). Le fonctionnement de Kubernetes se résume à un ensemble de boucles qui mesurent l’écart entre les deux et agissent pour le réduire : observe → diff → agit.

Analogie : Considérons un thermostat. La consigne (21 °C) représente l’état désiré ; la température mesurée (18 °C) représente l’état réel. Le thermostat constate l’écart et déclenche le chauffage jusqu’à convergence. Si une fenêtre ouverte recrée l’écart, le chauffage repart — sans modification de la consigne. On ne pilote jamais le radiateur : on pilote la consigne.

Points clés

  • L’état désiré est exprimé dans la spec de chaque objet et stocké durablement par le cluster (dans etcd, étudié au chapitre 3-4).
  • L’état réel est observé en permanence par les composants du cluster, qui le consignent dans le status de chaque objet. spec : le contrat ; status : le constat.
  • L’écart entre les deux (le diff) déclenche des actions correctives. Cette boucle s’exécute en continu, pas uniquement au moment du kubectl apply : c’est la boucle de réconciliation.
  • La convergence n’est pas instantanée. Kubernetes est un système à cohérence éventuelle : un écart temporaire entre état réel et état désiré est un fonctionnement normal, tant qu’il se résorbe.
  • Le self-healing n’est pas une fonctionnalité distincte : un pod disparu constitue un écart, et tout écart est réconcilié. La réparation est une conséquence mécanique du modèle.

Exemple concret

Un Deployment déclare replicas: 3. À t₀, un pod est supprimé manuellement (kubectl delete pod hello-7d4b9c-abc12).

  • t₀ — état désiré : 3 ; état réel : 2. Écart détecté.
  • t₀ + 1 s — le contrôleur crée un pod de remplacement, hello-7d4b9c-xk9f2.
  • t₀ + 4 s — le pod est Running. État réel : 3. Écart : 0.

Le cluster n’a pas été « réparé » : la déclaration de 3 replicas n’a jamais cessé d’être en vigueur, et la boucle n’a jamais cessé d’y veiller.

État désiré vs état réel

CritèreÉtat désiréÉtat réel
Où il résidespec (stockée dans etcd)Le cluster, reflété dans status
Qui l’écritL’utilisateur (YAML, kubectl apply, Git)Les composants du cluster
Exemplereplicas: 3readyReplicas: 2
Quand il changeSur décision expliciteEn permanence (pannes, redémarrages, charge)

Code YAML — l’état désiré

# deployment.yaml — le contrat : 3 replicas de nginx
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello
spec:                      # ← l'état désiré commence ici
  replicas: 3              # 3 copies, ni plus ni moins
  selector:
    matchLabels:
      app: hello
  template:                # le modèle des pods à créer
    metadata:
      labels:
        app: hello
    spec:
      containers:
        - name: web
          image: nginx:1.27

Code kubectl — observer les deux états

# La colonne READY se lit "état réel / état désiré"
kubectl get deployment hello
# NAME    READY   UP-TO-DATE   AVAILABLE   AGE
# hello   2/3     3            2           1m    ← convergence en cours

# spec et status, côte à côte
kubectl get deployment hello -o yaml | grep -A2 -E "^spec:|^status:"
# spec:
#   replicas: 3            ← le contrat
# status:
#   readyReplicas: 2       ← le constat

# Provoquer un écart et observer sa résorption
kubectl delete pod -l app=hello --wait=false && kubectl get pods -w
# hello-7d4b9c-abc12   1/1   Terminating   ...
# hello-7d4b9c-xk9f2   0/1   Pending       ...   ← le remplaçant
# hello-7d4b9c-xk9f2   1/1   Running       ...

Piège courant : « Un pod supprimé est supprimé » est inexact dès lors que le pod est géré par un contrôleur : la suppression ne modifie pas l’état désiré, elle crée un écart — comblé dans les secondes qui suivent. Corollaire : toute modification appliquée directement sur l’état réel (réglage manuel, intervention en SSH dans un conteneur) sera écrasée par la réconciliation. Dans Kubernetes, un changement durable passe toujours par l’état désiré, jamais par l’état réel.


Quiz — validation des acquis
Débutant 7 questions Objectif : 5/7 minimum
0/7
bonnes reponses
Objectif non atteint (minimum 5/7 requis).
Relire la fiche memo ci-dessus en pretant attention aux points manques, puis cliquer sur « Recommencer » pour retenter.