Bug de Salt 3007.4 et 3006.12
Salt est l’outil que j’utilise chez Framasoft pour gérer la configuration des serveurs, y pousser des commandes, etc.
Il est de plus une pierre angulaire de Framaspace car on passe par lui pour déployer de nouveaux espaces (ou en supprimer) sur les serveurs.
D’habitude, ça fonctionne très bien, mais les dernières versions des deux versions disponibles (3007 et 3006) ont bien fichu le bazar : les minions tombait en timeout régulièrement. Ils étaient encore connectés au master, mais ne répondaient plus.
Bonne nouvelle : le problème a déjà été rapporté sur Github.
Meilleure nouvelle : il semblerait que deux des patchs suggérés dans la discussion règlent le problème !
Maintenant, comment appliquer ces patchs à tous ses minions ? Personnellement, j’en ai 126 et j’avais tout sauf envie d’aller sur chaque serveur 
La réponse est relativement simple : en faisant comme d’habitude et en utilisant salt 
Premièrement, préparer un script pour appliquer les patchs, dans le dossier des recettes salt. Dans mon cas, je l’ai mis à /srv/salt/fix-salt.sh
:
cat <<EOF > /srv/salt/fix-salt.sh#!/bin/bashsed -i -e 's/^ elif self._creds\["aes"\] != creds\["aes"\]:/ elif (self._creds["aes"] != creds["aes"]) or (self._creds["session"] != creds["session"]):/' \\ '/opt/saltstack/salt/lib/python3.10/site-packages/salt/crypt.py'# Avoid patching again if already patchedif ! grep -q 'if data and data == b"bad load"' '/opt/saltstack/salt/lib/python3.10/site-packages/salt/channel/client.py'; then sed -i -e 's/upload the results to the master/&\n if data and data == b"bad load":\n yield self.auth.authenticate()\n data = yield self.transport.send(\n self._package_load(load, nonce),\n timeout=timeout,\n )/' \\ '/opt/saltstack/salt/lib/python3.10/site-packages/salt/channel/client.py'fiEOFchmod +x /srv/salt/fix-salt.sh
Ensuite, on redémarre le master, pour forcer les minions à se reconnecter et donc à de nouveau répondre.
systemctl restart salt-master
Après quelques minutes, on vérifie que tout le monde répond :
salt \* test.ping
Puis on exécute le script partout :
salt \* cmd.script salt://fix-salt.sh
On s’assure que le logiciel at
est bien installé partout, car on va en avoir besoin, petit à petit pour éviter que la commande soit lancée partout en même temps et que des machines virtuelles sur le même hôte ne fassent gratter les disques :
salt -b 5 \* pkg.install at
Enfin on programme un redémarrage des minions :
salt \* cmd.run 'echo "systemctl restart salt-minion" | at now + 1 minute'
Pourquoi passer par at
pour redémarrer les minions et pas par la commande salt \* minion.restart
ou salt \* cmd.run "systemctl restart salt-minion"
?
Et bien tout simplement parce que le minion n’aime pas être redémarré par une commande à laquelle il doit répondre. Chez moi, ce genre de commande finit toujours par me retourner une erreur, soit que le minion n’a pas répondu (puisqu’il redémarre), soit qu’il ne redémarre pas correctement. Avec at
, au moins, je suis tranquille 