Aller au contenu
Infrastructure as Code medium

Notifications et ordre d'exécution en Chef

8 min de lecture

logo chef

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.

  • Déclencher une action avec notifies.
  • Réagir à un changement avec subscribes.
  • Choisir entre :immediately et :delayed.
  • Éviter les redémarrages inutiles.

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 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]', :delayed
end
file '/var/www/html/marqueur.txt' do
content "ressource APRES le template\n"
end
service 'nginx' do
action [:enable, :start]
end

On range ce cookbook webapp dans ~/chef-parc/cookbooks/, on pointe le run list dessus, puis on déploie sur la VM :

Fenêtre de terminal
knife node run_list set web1 'recipe[webapp::default]' -c .chef/config.rb
knife 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 reload
Infra Phase complete, 5/11 resources updated in 03 seconds

Le 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.

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 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]', :delayed
end

Sur un changement du template, le service réagit :

* template[/etc/nginx/conf.d/app.conf] action create
* service[nginx] action reload
Infra Phase complete, 2/5 resources updated in 01 seconds

Quand 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.

La preuve que la notification est bien conditionnelle : relancez la convergence sans rien modifier.

Fenêtre de terminal
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.

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.

  • Une notification déclenche une action (:reload, :restart) seulement quand une ressource change.
  • notifies se pose sur la ressource source ; subscribes sur la ressource cible. Effet identique.
  • :delayed (défaut) exécute l'action une fois, à la fin, et dédoublonne ; :immediately l'exécute tout de suite.
  • Préférez :delayed sauf 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é.

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