Aller au contenu
Infrastructure as Code medium

Déployer un cookbook sur une vraie VM avec knife-zero

10 min de lecture

logo chef

Le conteneur Docker était parfait pour apprendre vite, mais il n'a pas de vrai systemd : il ne reflète pas une machine de production. Pour déployer sur une vraie VM (systemd complet, service géré comme en prod), on pousse le cookbook en SSH avec knife-zero, sans serveur Chef, à la manière d'Ansible. On réutilise le cookbook webserver de votre premier cookbook, mais cette fois sur une VM créée par Terraform et libvirt. Public visé : lecteur ayant réussi son premier cookbook. Testé avec CINC Client 19.3.14, knife-zero 2.6.0 et une VM Debian 13.

  • Comprendre pourquoi passer du conteneur à une vraie VM.
  • Installer et configurer knife-zero.
  • Bootstrapper une VM en SSH, sans serveur Chef.
  • Reconverger et vérifier le service sous systemd.

Le driver dokken (Docker) est imbattable pour la boucle de développement : quelques secondes par cycle. Mais un conteneur n'est pas une machine complète.

Conteneur Docker (dokken)Vraie VM
VitesseSecondesDizaines de secondes
systemdAbsent (PID 1 n'est pas systemd)Complet
Test d'un servicePartiel (via init.d)Réel (systemctl)
Représente la prodNonOui

Sur un conteneur, la ressource service fonctionne par des chemins détournés, mais un contrôle systemctl échoue faute de systemd. Pour valider un déploiement comme en production, il faut une vraie VM. Et Incus n'est pas une option ici : Chef n'a pas de connecteur pour Incus, contrairement à Docker (dokken) ou au SSH. La voie propre vers une vraie machine, c'est donc le SSH.

C'est exactement ce que fait knife-zero : il se connecte en SSH, installe l'agent, et applique le cookbook, sans serveur Chef. Le modèle est proche d'Ansible, mais avec les cookbooks Chef.

On ne détaille pas la création de VM ici : suivez le guide Terraform + libvirt, qui produit une VM joignable en SSH avec votre clé. À la fin, vous avez son IP (par exemple 192.168.122.167) et vous vous y connectez :

Fenêtre de terminal
ssh ubuntu@192.168.122.167 hostname

Notez cette IP : knife-zero en aura besoin pour le SSH.

knife-zero est un plugin de knife. On l'installe dans l'environnement Ruby de CINC Workstation avec cinc gem install.

Fenêtre de terminal
cinc gem install knife-zero
Successfully installed knife-zero-2.6.0
1 gem installed

Vérifiez que la commande est disponible :

Fenêtre de terminal
knife zero bootstrap --help

La sortie doit décrire knife zero bootstrap [SSH_USER@]FQDN.

knife-zero travaille depuis un petit dépôt Chef local : un dossier cookbooks/ et un dossier nodes/ (où il enregistre chaque machine gérée).

  1. Créer le dépôt et le cookbook :

    Fenêtre de terminal
    mkdir -p ~/chef-parc/cookbooks/webserver/recipes ~/chef-parc/nodes ~/chef-parc/.chef
    cd ~/chef-parc
  2. Écrire la recette cookbooks/webserver/recipes/default.rb. On ajoute une ressource apt_update en tête : c'est le pendant idempotent du module Ansible apt: update_cache, qui rafraîchit le cache des paquets avant l'installation.

    apt_update 'mise a jour du cache' do
    action :update
    end
    package 'nginx'
    file '/var/www/html/index.html' do
    content "Servi par Chef via knife-zero\n"
    mode '0644'
    end
    service 'nginx' do
    action [:enable, :start]
    end
  3. Déclarer le nom du cookbook dans cookbooks/webserver/metadata.rb :

    name 'webserver'
    version '0.1.0'
  4. Centraliser les options de connexion dans .chef/config.rb, pour que toutes les commandes knife-zero restent courtes. On y met le mode local, l'utilisateur SSH, la clé, l'attribut d'IP du nœud et le sudo :

    local_mode true
    cookbook_path [File.join(File.dirname(__FILE__), '..', 'cookbooks')]
    node_path File.join(File.dirname(__FILE__), '..', 'nodes')
    knife[:ssh_user] = 'ubuntu'
    knife[:ssh_identity_file] = File.expand_path('~/.ssh/id_ed25519')
    knife[:ssh_attribute] = 'ipaddress'
    knife[:use_sudo] = true
    knife[:ssh_verify_host_key] = 'never'

Le bootstrap est la première prise en main d'une machine : knife-zero s'y connecte en SSH, installe l'agent cinc-client, puis applique le cookbook. Remplacez l'IP par celle de votre VM.

Fenêtre de terminal
knife zero bootstrap 192.168.122.167 -c .chef/config.rb \
--alter-project cinc \
--node-name web1 \
--run-list 'recipe[webserver]' \
--yes

-c .chef/config.rb fournit les options de connexion (utilisateur SSH, clé, sudo). Les options propres au bootstrap : --alter-project cinc installe CINC (et non Chef) sur la cible, --node-name nomme la machine, --run-list désigne le cookbook. La convergence s'affiche en direct :

[192.168.122.167] Converging 4 resources
[192.168.122.167] * apt_update[mise a jour du cache] action update
[192.168.122.167] * apt_package[nginx] action install
[192.168.122.167] - install version 1.26.3-3+deb13u7 of package nginx
[192.168.122.167] * service[nginx] action enable
[192.168.122.167] * service[nginx] action start
[192.168.122.167] Infra Phase complete, 5/9 resources updated in 37 seconds

Vérifiez la page servie par la vraie VM :

Fenêtre de terminal
curl http://192.168.122.167/
Servi par Chef via knife-zero

C'est tout l'intérêt de la vraie VM : le service est géré par systemd, exactement comme en production.

Fenêtre de terminal
ssh ubuntu@192.168.122.167 'systemctl is-active nginx; systemctl is-enabled nginx; ps -p 1 -o comm='
active
enabled
systemd

systemd est bien PID 1, et nginx est active et enabled. Sur le conteneur Docker, cette vérification systemctl échouait : le déploiement est désormais fidèle à la production.

Le nœud est maintenant enregistré (dans nodes/web1.json). Pour rejouer le cookbook après une modification, on utilise knife zero converge : un push en SSH, sans repasser par le bootstrap.

Fenêtre de terminal
knife zero converge 'name:web1' -c .chef/config.rb
192.168.122.167 * apt_package[nginx] action install (up to date)
192.168.122.167 * service[nginx] action enable (up to date)
192.168.122.167 * service[nginx] action start (up to date)
192.168.122.167 Infra Phase complete, 2/9 resources updated in 01 seconds

Les ressources du service sont up to date : l'idempotence tient sur la vraie VM comme dans le conteneur.

  • Le conteneur Docker (dokken) est fait pour la boucle rapide, mais il n'a pas de vrai systemd ; Incus n'a pas de connecteur Chef. Pour une vraie machine, on passe par SSH.
  • knife-zero pousse un cookbook en SSH, sans serveur Chef : bootstrap (install + première convergence), puis converge (re-push).
  • On installe le plugin avec cinc gem install knife-zero, jamais en sudo.
  • --alter-project cinc installe l'agent CINC sur la cible ; apt_update rafraîchit le cache des paquets (le « module » idempotent, comme Ansible).
  • La vraie VM offre systemd complet : systemctl is-active nginx renvoie active, ce que le conteneur ne permettait pas.

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