Aller au contenu
Infrastructure as Code medium

Test Kitchen : boucler avec verify, et ce que le conteneur ne peut pas prouver

10 min de lecture

Logo Chef

Depuis votre premier cookbook, le fichier kitchen.yml contient une ligne verifier: inspec... que vous n'avez jamais utilisée. Vous avez convergé sans jamais vérifier ce que la machine est réellement devenue. Ce module ferme la boucle avec kitchen verify et kitchen test. Il vous réserve surtout une surprise instructive : le conteneur va échouer sur un contrôle, et cet échec est la meilleure démonstration de la limite du terrain 1. Public visé : débutants ayant convergé leur premier cookbook.

  • Lancer kitchen verify sur un cookbook convergé.
  • Enchaîner le cycle complet avec kitchen test.
  • Comprendre ce qu'un conteneur ne peut pas valider.
  • Répartir les tests entre conteneur et VM.

kitchen converge applique le cookbook, et vous affiche une conclusion rassurante : « 3/4 resources updated ». Mais cette phrase ne dit qu'une seule chose : Chef a exécuté ce qu'il avait à faire. Elle ne dit rien de l'état réel de la machine ensuite.

C'est le rôle de kitchen verify : il lance les tests InSpec du cookbook contre la machine convergée, et vous répond sur ce qu'elle est, pas sur ce que Chef a cru faire.

Le générateur a d'ailleurs créé un fichier de test, mais il est inerte : ses deux contrôles portent un :skip.

# test/integration/default/default_test.rb (généré)
describe user('root'), :skip do
it { should exist }
end

Remplaçons-le par de vrais contrôles, qui décrivent ce que la recette promet :

describe package('nginx') do
it { should be_installed }
end
describe file('/var/www/html/index.html') do
it { should exist }
its('mode') { should cmp '0644' }
its('content') { should match(/Bonjour depuis Chef via CINC/) }
end
describe service('nginx') do
it { should be_enabled }
it { should be_running }
end
Fenêtre de terminal
kitchen verify default-ubuntu-2404
System Package nginx
✔ is expected to be installed
File /var/www/html/index.html
✔ is expected to exist
✔ mode is expected to cmp == "0644"
✔ content is expected to match /Bonjour depuis Chef via CINC/
Service nginx
× is expected to be enabled
× is expected to be running
Test Summary: 4 successful, 2 failures, 0 skipped

Deux échecs. Le paquet est installé, le fichier est parfait, mais le service n'est ni activé ni démarré. Pourtant, la convergence s'était terminée sans la moindre erreur.

Votre premier réflexe sera de chercher un bug dans la recette. Il n'y en a pas. Regardons dans le conteneur :

Fenêtre de terminal
docker exec <conteneur> ps -p 1 -o comm=
docker exec <conteneur> test -d /run/systemd/system && echo systemd || echo "pas de systemd"
docker exec <conteneur> pgrep nginx >/dev/null && echo "processus nginx présent"
sh
pas de systemd
processus nginx présent

Tout s'éclaire. PID 1 est un simple sh, il n'y a aucun gestionnaire de services. Le processus nginx existe bel et bien, mais systemd ne le connaît pas, puisqu'il n'existe pas. InSpec, qui interroge systemd pour répondre à « ce service tourne-t-il ? », répond donc non.

Personne ne ment. Chef a fait ce qu'il pouvait, InSpec a dit la vérité, et le conteneur n'a tout simplement pas d'init.

Prenons exactement les mêmes contrôles, et lançons-les contre la machine convergée avec knife-zero, qui a un systemd complet :

Fenêtre de terminal
cinc-auditor exec profil -t ssh://ubuntu@<ip-de-la-vm> --sudo
✔ is expected to be installed
✔ is expected to be enabled
✔ is expected to be running
Test Summary: 3 successful, 0 failures, 0 skipped

Mêmes contrôles, résultat inverse. Sur la vraie VM, le service est activé et démarré, et InSpec le confirme. La différence ne vient pas de votre cookbook, elle vient du terrain.

La conclusion pratique est simple : testez dans le conteneur ce que le conteneur sait valider, et réservez à la VM ce qui exige une vraie machine.

À validerTerrain
Paquet installéConteneur (rapide)
Fichier, contenu, mode, propriétaireConteneur
Template rendu correctementConteneur
Service activé et démarréVM
Port en écoute, réponse HTTPVM

En retirant le contrôle de service du profil du conteneur, la boucle redevient verte, et elle reste utile :

Test Summary: 4 successful, 0 failures, 0 skipped

kitchen test enchaîne tout : il détruit l'ancienne instance, en crée une neuve, converge, vérifie, puis détruit. C'est la commande à lancer avant de pousser votre code, car elle garantit que le cookbook fonctionne depuis zéro, et pas seulement sur une machine déjà à moitié configurée.

Fenêtre de terminal
kitchen test default-ubuntu-2404
Test Summary: 4 successful, 0 failures, 0 skipped
Finished verifying <default-ubuntu-2404> (0m1.08s).
Finished destroying <default-ubuntu-2404> (0m10.33s).
Finished testing <default-ubuntu-2404> (0m32.59s).

32 secondes pour un cycle complet, machine jetable comprise. C'est ce qui rend le conteneur si précieux malgré sa limite : à ce prix-là, vous pouvez le lancer à chaque modification.

Les échecs de kitchen verify sont utiles, à condition de savoir les lire : beaucoup n'indiquent pas un bug de recette, mais une limite du terrain.

SymptômeCause probableSolution
Le contrôle de service échoue en conteneurAucun systemd dans dokkenAttendu : valider le service sur une VM
Les tests sont tous « skipped »Le fichier généré porte des :skipÉcrire de vrais contrôles
kitchen converge passe, verify échoueConverger n'est pas vérifierLire l'échec : il dit ce que la machine est
Le cookbook marche en converge mais pas en testL'instance gardait un état accumuléC'est le but de kitchen test : repartir de zéro
Verify failed on instanceAu moins un contrôle a échouéLe détail est au-dessus du message d'exception
  1. kitchen converge dit ce que Chef a fait ; kitchen verify dit ce que la machine est. Ce n'est pas la même chose.
  2. Le fichier de test généré est inerte (des :skip) : il faut écrire de vrais contrôles.
  3. Dans un conteneur dokken, PID 1 est un sh et il n'y a pas de systemd : le contrôle de service échoue, et c'est normal.
  4. Le processus peut exister sans que systemd le connaisse : Chef ne ment pas, InSpec non plus, il n'y a simplement pas d'init.
  5. Mêmes contrôles sur une vraie VM : tout passe. La différence vient du terrain, pas du cookbook.
  6. Validez le déclaratif (paquet, fichier, mode, contenu) en conteneur ; les services et les ports sur une VM.
  7. kitchen test enchaîne le cycle complet depuis une machine vierge : c'est la commande à lancer avant de pousser.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn