Configurer un serveur, c'est surtout déployer des fichiers au bon endroit,
avec le bon propriétaire, le bon mode et le bon contenu. Le module
file de Salt fait tout cela de façon idempotente et sait rendre des
templates. Ce module déploie un site web complet, du fichier unique à
l'arborescence. Public visé : intermédiaires à l'aise avec states et Jinja.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Déployer un fichier avec propriétaire, mode et contenu vérifié.
- Déployer une arborescence avec
file.recurse. - Rendre un fichier depuis un template Jinja.
- Déclencher un rechargement de service sur changement.
Prérequis
Section intitulée « Prérequis »file.managed : le fichier unique
Section intitulée « file.managed : le fichier unique »file.managed déploie un fichier depuis une source servie par le master
(protocole salt://) ou depuis un contenu inline. Il gère en une déclaration
le propriétaire, le groupe, le mode (toujours quoté pour éviter
l'interprétation YAML), et vérifie le contenu à chaque passage.
Deux réflexes de sécurité valent pour tout fichier système. Le mode
reste entre guillemets : écrit "0644", jamais 0644 non quoté, que YAML
lirait comme un entier décimal et non comme une valeur octale. Le
user et le group sont explicites dès que vous écrivez hors du
répertoire personnel : ne laissez pas un fichier de /etc hériter du compte
qui exécute Salt, nommez le propriétaire attendu.
# mode quoté, propriétaire explicite/etc/nginx/sites-available/appsite.conf: file.managed: - source: salt://webdeploy/site.conf.j2 - user: root - group: root - mode: "0644"Templates Jinja
Section intitulée « Templates Jinja »Pour un fichier qui varie selon le serveur, on active le rendu Jinja avec
template: jinja. La source peut alors lire grains et pillars : un seul
gabarit produit la bonne configuration partout. Voici la source
site.conf.j2 du TP, un bloc serveur Nginx paramétré par les grains du minion :
# Généré par Salt depuis un template Jinja - ne pas éditer à la main# Minion : {{ grains['id'] }} ({{ grains['os'] }} {{ grains['osrelease'] }})server { listen 8088; server_name {{ grains['fqdn'] }};
root /var/www/appsite; index index.html;
location / { try_files $uri $uri/ =404; }}Le state qui rend ce fichier active simplement template: jinja :
/etc/nginx/sites-available/appsite.conf: file.managed: - source: salt://webdeploy/site.conf.j2 - template: jinja - user: root - group: root - mode: "0644"À l'application sur le minion web1, Salt résout les grains dans le fichier
déployé. On le vérifie directement sur la machine :
# Généré par Salt depuis un template Jinja - ne pas éditer à la main# Minion : web1 (Debian 13)server {Le même gabarit produirait server_name et commentaires différents sur un autre
minion, sans toucher au state : c'est tout l'intérêt du rendu par données.
file.recurse : l'arborescence
Section intitulée « file.recurse : l'arborescence »Quand il faut déployer tout un répertoire (le contenu d'un site, un ensemble
de scripts), file.recurse copie l'arborescence entière depuis une source
salt:// en conservant permissions et structure.
# déployer le contenu d'un site/var/www/appsite: file.recurse: - source: salt://webdeploy/public - user: www-data - group: www-data - dir_mode: "0755" - file_mode: "0644"Le répertoire source webdeploy/public du master contient l'index.html et le
style.css du site. Après application, ils atterrissent sur le minion avec le
bon propriétaire et le bon mode, file_mode s'appliquant à chaque fichier :
644 www-data:www-data /var/www/appsite/index.htmlValider une configuration avant de la recharger
Section intitulée « Valider une configuration avant de la recharger »Recharger un service avec une configuration invalide le laisse cassé ou
l'empêche de redémarrer. Quand un fichier managé peut casser un service,
insérez un état de vérification dédié entre le fichier et le rechargement,
plutôt que de compter sur l'argument check_cmd. L'état de contrôle exécute
la commande de test du service, déclenché par onchanges sur le fichier :
il n'agit que si le fichier a bougé, et son échec stoppe le state avant
que le service ne recharge une conf fautive.
# vérifier la conf avant le rechargement/etc/nginx/sites-available/appsite.conf: file.managed: - source: salt://webdeploy/site.conf.j2 - template: jinja - user: root - group: root - mode: "0644"
verifier-conf-nginx: cmd.run: - name: nginx -t - onchanges: - file: /etc/nginx/sites-available/appsite.conf
nginx-appsite: service.running: - name: nginx - watch: - file: /etc/nginx/sites-available/appsite.conf - require: - cmd: verifier-conf-nginxCet ordre donne une barrière claire : le fichier change, la vérification s'exécute, et le service ne recharge qu'ensuite. Un test qui échoue fait remonter l'erreur au bon endroit, sans laisser le service redémarrer sur une configuration invalide.
Travaux pratiques : déployer un site web
Section intitulée « Travaux pratiques : déployer un site web »Assemblons tout dans un state webdeploy.sls qui déploie un site complet sur
le minion web1 : la configuration Nginx rendue depuis un template Jinja, le
contenu du site copié avec file.recurse, un état de vérification
nginx -t déclenché par onchanges, et le service rechargé par watch
uniquement sur changement.
/etc/nginx/sites-available/appsite.conf: file.managed: - source: salt://webdeploy/site.conf.j2 - template: jinja - user: root - group: root - mode: "0644"
/etc/nginx/sites-enabled/appsite.conf: file.symlink: - target: /etc/nginx/sites-available/appsite.conf - require: - file: /etc/nginx/sites-available/appsite.conf
/var/www/appsite: file.recurse: - source: salt://webdeploy/public - user: www-data - group: www-data - dir_mode: "0755" - file_mode: "0644"
verifier-conf-nginx: cmd.run: - name: nginx -t - onchanges: - file: /etc/nginx/sites-available/appsite.conf
nginx-appsite: service.running: - name: nginx - watch: - file: /etc/nginx/sites-available/appsite.conf - file: /var/www/appsite - require: - cmd: verifier-conf-nginxAu premier passage, chaque brique agit et le service redémarre une fois la conf validée :
sudo salt web1 state.apply webdeploy ID: /etc/nginx/sites-available/appsite.conf Function: file.managed Comment: File /etc/nginx/sites-available/appsite.conf updated ID: /var/www/appsite Function: file.recurse Comment: Recursively updated /var/www/appsite ID: verifier-conf-nginx Function: cmd.run Comment: Command "nginx -t" run ID: nginx-appsite Function: service.running Comment: Service restarted
Summary for web1Succeeded: 5 (changed=5)Failed: 0Le site répond alors sur le port choisi dans le template :
sudo salt web1 cmd.run 'curl -s http://localhost:8088/ | grep h1'web1: <h1>Déploiement piloté par Salt</h1>Prouver l'idempotence
Section intitulée « Prouver l'idempotence »Le second passage ne doit rien changer : la conf est déjà en place, donc
onchanges ne déclenche pas la vérification et watch ne recharge pas le
service.
sudo salt web1 state.apply webdeploy Comment: State was not run because none of the onchanges reqs changedSummary for web1Succeeded: 5Failed: 0Aucun changement, nginx -t non rejoué, service non redémarré : la boucle
fichier - vérification - rechargement est idempotente. Elle ne s'active que
le jour où le template ou le contenu du site bouge réellement.
À retenir
Section intitulée « À retenir »file.manageddéploie un fichier avec propriétaire, mode quoté et contenu vérifié.template: jinjarend un fichier à partir des grains et pillars.file.recursedéploie une arborescence complète.- Un
watchrecharge le service uniquement quand le fichier change.