
On ne recharge un service que lorsque sa configuration a vraiment changé, jamais à chaque convergence. Redémarrer nginx à chaque passage casserait l'idempotence et couperait le service pour rien. Les notifications relient une ressource qui change à une action à déclencher : notifies part de la source, subscribes part de la cible, et le timing (:immediately ou :delayed) décide quand l'action s'exécute. On déploie sur la vraie VM web1 avec knife-zero, où le rechargement systemd est réel. Public visé : lecteur ayant vu les templates et le rechargement. Testé avec CINC Client 19.3.14 et knife-zero 2.6.0 sur une VM Debian 13.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Déclencher une action avec
notifies. - Réagir à un changement avec
subscribes. - Choisir entre
:immediatelyet:delayed. - Éviter les redémarrages inutiles.
Prérequis
Section intitulée « Prérequis »- Les templates et fichiers compris (vous avez déjà vu
notifies :reload). - La VM
web1et le dépôt~/chef-parcavec son.chef/config.rb(du guide de déploiement).
Le problème : agir seulement au changement
Section intitulée « Le problème : agir seulement au changement »Une config nginx vit dans un template. Quand elle change, il faut recharger nginx pour qu'il la prenne en compte. Mais si on rechargeait à chaque convergence, on casserait l'idempotence et on perturberait le service sans raison. La bonne règle : recharger uniquement quand le template a changé. C'est exactement ce que fait une notification.
notifies : depuis la ressource source
Section intitulée « notifies : depuis la ressource source »notifies se pose sur la ressource qui change (le template). Il désigne l'action, la ressource cible, et le timing :
template '/etc/nginx/conf.d/app.conf' do source 'app.conf.erb' variables(port: node['webapp']['port']) notifies :reload, 'service[nginx]', :delayedend
file '/var/www/html/marqueur.txt' do content "ressource APRES le template\n"end
service 'nginx' do action [:enable, :start]endOn range ce cookbook webapp dans ~/chef-parc/cookbooks/, on pointe le run list dessus, puis on déploie sur la VM :
knife node run_list set web1 'recipe[webapp::default]' -c .chef/config.rbknife zero converge 'name:web1' -c .chef/config.rbÀ une convergence où le template change, la notification déclenche le reload :
* template[/etc/nginx/conf.d/app.conf] action create* file[/var/www/html/marqueur.txt] action create* service[nginx] action start (up to date)* service[nginx] action reloadInfra Phase complete, 5/11 resources updated in 03 secondsLe reload apparaît en dernier : c'est l'effet de :delayed, sur lequel on revient tout de suite. Si le template ne change pas, aucune ligne reload n'apparaît.
:immediately ou :delayed
Section intitulée « :immediately ou :delayed »Le troisième argument décide quand l'action notifiée s'exécute.
:delayed(le défaut recommandé) : l'action est mise en file et exécutée une seule fois, à la fin du run. Plusieurs templates qui notifient le même service ne déclenchent qu'un reload.:immediately: l'action s'exécute tout de suite, avant la ressource suivante. À réserver aux cas où la suite du run dépend de ce reload.
La différence se voit dans l'ordre de la sortie. Avec :immediately, sur un changement du template :
* template[/etc/nginx/conf.d/app.conf] action create* service[nginx] action reload* file[/var/www/html/marqueur.txt] action create (up to date)Le reload passe juste après le template, avant le file[marqueur]. Comparez avec :delayed plus haut, où il passait tout à la fin. Dans le doute, gardez :delayed : il regroupe les rechargements et évite les redémarrages en cascade.
subscribes : depuis la ressource cible
Section intitulée « subscribes : depuis la ressource cible »subscribes fait la même chose, mais déclaré à l'envers : c'est la ressource cible (le service) qui dit « surveille ce template, et recharge-toi s'il change ».
service 'nginx' do action [:enable, :start] subscribes :reload, 'template[/etc/nginx/conf.d/app.conf]', :delayedendSur un changement du template, le service réagit :
* template[/etc/nginx/conf.d/app.conf] action create* service[nginx] action reloadInfra Phase complete, 2/5 resources updated in 01 secondsQuand choisir l'un ou l'autre ? notifies quand la ressource source connaît sa cible (un template sait quel service il configure). subscribes quand la cible doit surveiller plusieurs sources, ou quand la source ne doit pas connaître la cible. L'effet est identique.
Vérifier : pas de reload sans changement
Section intitulée « Vérifier : pas de reload sans changement »La preuve que la notification est bien conditionnelle : relancez la convergence sans rien modifier.
knife zero converge 'name:web1' -c .chef/config.rb* template[/etc/nginx/conf.d/app.conf] action create (up to date)* service[nginx] action start (up to date)Le template est up to date, donc aucune ligne reload n'apparaît : la notification ne s'est pas déclenchée. On ne perturbe le service que lorsque c'est réellement nécessaire.
Exercice : notifier un restart
Section intitulée « Exercice : notifier un restart »Adaptez la notification. Cherchez la solution avant d'ouvrir la réponse.
Un changement de port d'écoute ne peut pas se faire par un simple reload : il faut un restart. Modifiez la notification du template pour déclencher un :restart de nginx (toujours en :delayed) quand la config change.
Indice : seul le premier argument de notifies change.
On remplace l'action notifiée :reload par :restart :
template '/etc/nginx/conf.d/app.conf' do source 'app.conf.erb' variables(port: node['webapp']['port']) notifies :restart, 'service[nginx]', :delayedendÀ un changement de config, la sortie affiche service[nginx] action restart au lieu de reload. Le reste du mécanisme est identique : rien ne se déclenche sans changement. Retenez la nuance : reload relit la config à chaud, restart coupe puis relance, nécessaire quand un simple rechargement ne suffit pas (changement de port, de socket).
À retenir
Section intitulée « À retenir »- Une notification déclenche une action (
:reload,:restart) seulement quand une ressource change. notifiesse pose sur la ressource source ;subscribessur la ressource cible. Effet identique.:delayed(défaut) exécute l'action une fois, à la fin, et dédoublonne ;:immediatelyl'exécute tout de suite.- Préférez
:delayedsauf si la suite du run dépend de l'action. - Sans changement, aucune notification : l'idempotence est préservée, le service n'est pas perturbé.