Gérer plusieurs versions de certains outils en ligne de commande

closeCet article a été publié il y a 4 ans 11 jours, il est donc possible qu’il ne soit plus à jour. Les informations proposées sont donc peut-être expirées.

C’est un problème qu’on rencontre pas forcément quand on gère que du perso, mais quand on bosse sur une quantité importante de projets clients, il arrive qu’on doive jongler, pour différentes raisons, avec plusieurs versions différentes d’outils divers et variés. Et souvent les « procédures d’installation » (télécharger, copier dans /usr/local/bin, j’appelle pas ça une procédure), ne prennent pas ce cas d’usage en compte. je vais donc faire un inventaire de ce que j’ai pu faire et que je fais encore aujourd’hui pour gérer ça.

Les utilitaires que je manipule ces derniers mois ne sont pas obscurs : terraform, ansible, git, kubernetes, helm, pour ne citer qu’eux, évoluent constamment, et apportent toujours plus de nouvelles possibilités. Sauf que ces outils ne servent qu’à exécuter du code qui a été écrit à un instant T, donc avec la version disponible alors. Ou pas, j’ai eu à bosser sur un projet terraform dont certains modules étaient encore figés à la syntaxe 0.11, donc pas le choix, sauf qu’en parallèle, un projet interne utilisait la syntaxe 0.12. Il a donc fallu trouver une solution simple.

Vous avez donc maintenant une meilleure idée, et quand le problème s’est reproduit pour d’autres outils, j’ai cherché et trouvé d’autres solutions.

Terraform : tfenv

C’est en effet probablement le premier pour lequel j’ai eu à chercher une solution qui n’était pas utilisable nativement, comme on le verra avec Ansible plus tard. Quand vous regardez la doc, c’est « téléchargez, copiez dans un dossier du PATH, enjoy ». Et démerdez vous avec ça. Remarquez qu’on trouve beaucoup trop cette solution basique avec les outils développés en Go, qui effectivement ne s’embarrassent pas trop de bibliothèques partagées car ils sont majoritairement compilés en statique, donc avec tout ce dont ils ont besoin. Ça vous fait un fichier binaire de plus de 100Mo, mais on va dire que c’est un détail (regardez pas de trop près les providers terraform, vous allez vite vous pendre).

Donc, pour pouvoir facilement switcher entre les versions de Terraform, et même gérer facilement les versions installées sur mon poste, j’ai découvert un petit utilitaire très pratique : tfenv. Il est utilisable sous Linux et Mac (et apparemment sous Windows, dans git-bash), et permet d’installer et de switcher facilement entre les versions de terraform. Le genre d’outil qu’on aurait aimé avoir en natif plutôt que du bête download de binaire, mais bon, on peut pas tout avoir.

Pour l’installation j’ai fait le feignant et je suis passé par yay sur Manjaro, mais les instructions disponibles sur le README sont faciles à suivre.

Ansible : les virtualenv à la rescousse !

Eh oui, Ansible est un outil écrit en Python, et j’avais parlé de comment utiliser les virtualenv très récemment pour utiliser youtube-dl sur le NAS de ma môman. Dans le cas d’Ansible, j’ai eu à jouer avec plus que la version, car là c’était en fonction de la version de Python directement que j’avais à switcher entre les virtualenv, certains modules utilisés n’étant compatibles qu’avec Python 2 (le mainteneur sait qu’il doit repasser dessus pour les passer en python 3, mais ça demande du temps qu’on facture pas au client, donc personne le fait – une sacrée connerie contre laquelle on se bat de plus en plus souvent…).

Sur une machine où vous avez les deux versions de Python d’installés, il faut donc vérifier si vous avez python2-virtualenv (souvent seulement appelé python-virtualenv) et python3-virtualenv, ou alors pour Python 3, reprendre la méthode avec le module intégré python3 -m venv.

Pour certains projets, comme le code repose aussi sur des sdk de cloud provider, je crée un venv dédié qui embarque à la fois ansible et le sdk/cli concerné, aws et azure majoritairement pour l’instant (j’ai commencé à découvrir Google Cloud Platform très récemment, rien de transcendant). L’aspect paradoxal de tout ça c’est que je peux avoir plusieurs fois la même version d’Ansible d’installée, pour différentes versions de Python et des dépendances associées. Ça consomme plus de disque, mais bon, j’ai plus de Windows pour m’emmerder avec ça et le SSD est loin d’être saturé, le coût est donc plus que supportable.

Kubernetes/helm, j’ai sorti l’artillerie lourde

Pour Kubernetes et Helm, je n’ai pas trouvé de méthode maison ou un outil léger adapaté comme pour Terraform. Par contre, je suis tombé sur la rolls, de celles qui pourraient au final remplacer aussi tfenv pour terraform, car elle repose sur un système de plugins.

asdf Version Manager est cette rolls. Je vous laisse regarder la liste des plugins pour comprendre la palette de possibilités de gestion d’outils, j’ai donc pour ma part pour l’instant utilisé ceux de kubectl et d’helm. kubectl parce que l’utilitaire pour manipuler ses cluster Kubernetes a une palette certes large de compatibilité entre versions serveur et client, mais y’a des limites, et si vous avez un kubectl en 1.16.x, et que vous avez le malheur de devoir manipuler un cluster qui est encore installé en 1.12.x, vous vous engagez sur une pente plus que glissante, car la version 1.16 a mis à la retraite bon nombre d’API qui étaient en service sur l’ancien. Helm parce qu’entre la version 2 et la version 3 c’est le jour et la nuit sur le fonctionnement, et que des packages installés avec la version 2 ne peuvent pas être gérés simplement de manière transparente du jour au lendemain avec la version 3. D’autant plus quand vous utilisez le provider pour terraform.

Et ça ce ne sont que les utilitaires, mais dans les plugins vous pouvez aussi bosser carrément avec des versions différentes de langages de programmation, comme nodejs, ruby, et j’en passe, c’est donc très pratique dans un environnement de développement, et pour se passer de docker qui a ses propres contraintes. Attention toutefois, asdf est vraiment pensé pour un usage sur poste local, ce n’est pas un outil de déploiement en production, je recommande vivement soit de passer par Docker, soit d’adapter l’environnement pour votre application en installant plus proprement (idéalement via package manager pour gérer les mises à jour auto). Je pense par exemple aux software collections sur Redhat/CentOS qui permettent de multiplier les versions de certains langages (coucou PHP).

Bref, s’il ne devait en rester qu’un, ça serait probablement celui-là. Surtout que si le plugin dont vous auriez besoin n’existe pas encore, vous avez tout à fait la possibilité de l’écrire vous-même 🙂

Et vous, vous faites comment ?

Mon manager repose désormais exclusivement sur Docker pour ce genre de besoins. Il garde soigneusement quantité de containers et d’images qu’il redémarre à la volée quand il en a besoin, mais je trouve la solution plus lourde et moins naturelle par rapport au reste de l’usage du système.

Mais vous avez probablement vos propres routines pour ce genre de situation, je suis curieux de les découvrir, alors, comment ça jongle ?

PS : le très partageur Cascador, qui a fait un petit namedrop sur systemd-nspawn, sans préciser qu’il a carrément fait un article dessus 🙂

4 Commentaires
Le plus ancien
Le plus récent
Commentaires en ligne
Afficher tous les commentaires
said
said
15/04/2020 20:00

Ce que je ferai:

Soit j’utilise un container (mais ca suppose que tu peux travailler avec ssh, tmux, emacs):
Sinon un petit ansible pour chaque client avec les versions deployees. Lorsque tu en as besoin, tu deploies la VM. Un peu lourd mais au moins t’es sur que tu as pas de soucis de versions, etc ..

Nicolas K.
16/04/2020 08:06

À peu près comme ton manager, dans chaque projet j’ai un .devcontainer/ qui décrit un environnement conteneurisé avec les outils nécessaires. Et je gère ça avec un outil que j’ai écrit: https://github.com/nikaro/devc

Cascador
16/04/2020 17:33

Yo camarade,

J’attendais de voir un peu les retours que tu avais, sujet assez intéressant même si j’ai pas ce besoin perso. En effet comme les autres j’aurais tendance à faire du podman (docker) mais en priorité j’ai une préférence pour systemd-nspawn/systemd-container.

Tcho !

Rémy
Rémy
17/04/2020 14:14

Bonjour, Si le but n’est que de gérer des versions différentes de packages, tu as plusieurs solutions : Conda (qui peut être utilisé avec des virtualenvs ou pyenv par exemple), Guix, Nix, Spack, Easybuild… Bref, je t’encourage à regarder les slides de cette conf de Kenneth Hoste (développeur de EasyBuild) au FOSDEM : https://archive.fosdem.org/2018/schedule/event/installing_software_for_scientists/ Ensuite, tu peux jongler entre les versions avec environment modules ou lmod. C’est ce qui fait de manière classique dans le monde du HPC, où, sur un même système, il faut souvent de nombreuses versions pour satisfaire tous les utilisateurs… Si tu dois jongler entre des… Lire la suite »