10 octobre 2011

Puppet vs Chef, Fight

Titre tapageur pour faire écho à ce billet, qui compare Opscode Chef à Puppet, deux outils de gestion de parc.

Gestion de quoi ? Bon, commençons par le commencement : nous allons utiliser un petit cas concret pour illuster la chose. Supposons que vous bossez dans une grande SSII en tant que référant "intégration continue" et qu'on vous sollicite donc régulièrement pour mettre en place des forges logicielles sur projet au forfait - toute ressemblance avec une personne existante ou ayant existée, bla bla bla

Option 1 : "la [bip] et le couteau"

Pour chaque projet, fort de votre expérience, vous installez maven + jenkins + nexus + svn/git + sonar + mysql + oracleExpress + lespluginsquivontbient

Comme vous êtes trop trop fort ça ne vous prend que un ou deux jours maximum pour que tout soit carré, et avec l'expérience ça doit même pouvoir se faire dans la journée - si on oublie qu'il a fallu attendre 3 mois la commande de la machine

Option 2 : "la documentation exhaustive"

Jouons la carte ISO-9002 et écrivons ce que nous faisons avant de faire ce que nous avons écrit, voici donc le manuel d'installation d'une forge logiciel, document de 148pages détaillant les commandes d'installation, oh que c'est beau et ... jamais à jour, vu qu'une nouvelle version de Jenkins sort chaque semaine, que chaque plugin évolue et remet tout en cause, et que les pratiques d'une projet ne sont pas nécessairement celles d'un autre.
Accessoirement, en copiant la commande indiquée, on se plante inévitablement à un moment ou à un autre, surtout avec la tendance qu'à Word de remplacer les "-" par des "–".

Option 3 : "Ctrl+C / Ctrl+V"

Partant d'une forge qui marche bien, maintenue avec amour avec tous les bon softs bien configurés, il suffit à chaque nouveau projet de cloner le système, ce qui est d'autant plus facile si tout cela tourne dans un environnement virtualisé.
Un nouveau projet ? Click, la forge est prête
Seul soucis ... dans 6 mois le projet en question aura toujours un Jenkins 1.430 avec des plugins obsolètes et se cassera les dents sur un bug maven à la c.. alors que c'est corrigé depuis longtemps. Il manque un élément crucial : la maintenance

Option 4 : "installation scriptée"

Même concept que l'option 2 , mais cette fois on est malin, plutôt que de décrire l'installation de la forge dans un document word on va le faire dans des shells d'installation automatique. C'est une plutôt bonne idée à priori mais c'est très, très vite galère. La faute au shell, qui est tout de même un outil de très bas niveau, surtout si on veut remédier aux soucis de l'option 3 et gérer non seulement l'installation mais aussi la mise à jour des outils.

Option 4+ : "installation scriptée avec un outil adapté"

On y arrive : un outil adapté, dédié aux installation et (re)configuration d'outils, avec un niveau d'abstraction supérieur au simple shell. Pour un exemple plus concret, je vous renvoi à ce billet d'Octo qui présente Puppet

Ce qui est important de comprendre ici, c'est que même pour une installation unique, un outil de ce type peut avoir son intérêt. Si la démarche est évidemment intéressante pour un déploiement sur un gros datacenter (Chef a été développé par des gars d'Amazon...), une fois les concepts maîtrisés il peut prendre du sens sur des installations plus modestes, vois ouvrir de nouvelles opportunités :

si vous avez automatisé le déploiement de votre appli, il devient possible de mettre en place un déploiement continu sur une infrastructure de test et de faire du test fonctionnel ou de performance en continu. Le même script sera utilisé lors du déploiement en production, script répété des centaines de fois, et en qui vous avez une totale confiance. Est-ce le cas avec votre manuel d'installation.doc ?

Après il y a même quelques allumés qui gèrent leur station de travail avec Chef, et peuvent potentiellement la répliquer ou la restaurer sur une autre machine. Si ça peut paraître un peu délirant, c'est une façon d'adresser une autre problème : la mise en place des environnements de développement. Un nouveau qui arrive sur le projet ? Hop, un coup de Puppet/Chef et il a tous les outils qui vont bien.

Ok, alors Puppet ou Chef (ou...) ?


Les deux outils sont très, très similaires. En dehors des différences de taille de communauté et de documentation, qui ne sont pas énormes, la différence majeure est sur la liberté proposée par le DSL utilisé.
Puppet définit un DSL relativement figé, dans lequel on déclare des éléments de pilotage de l'outil, comme par exemple cet extrait de la recette d'installation de tomcat qui se charge de télécharger+désarchiver tomcat sous /opt :


  common::archive::tar-gz{"/opt/apache-tomcat-${tomcat_version}/.installed":
    source => $tomcaturl,
    target => "/opt",
  }

C'est super concis et très abstrait, exactement ce qu'on cherche pour ce type d'outil.


La même définition avec Chef est assez comparable :

  remote_file "#{params[:location]}/apache-tomcat-#{version}.zip" do
    source "http://archive.apache.org/dist/tomcat/tomcat-6/v#{version}/bin/apache-tomcat-#{version}.tar.gz"
    checksum "2d19ea2b0f3bb"
  end

  execute "unzip-#{params[:location]}-tomcat" do
    cwd params[:location]
    command "/usr/bin/tar xzf #{params[:location]}/apache-tomcat-#{version}.zip"
    creates "#{params[:location]}/apache-tomcat-#{version}"
  end

Ne vous fiez pas au nombre de lignes, ce sont des exemples pompés au hasard sans grande valeur de comparaison. Considérez juste la syntaxe et la compréhension immédiate des actions réalisées


Il y a ici une nuance importante : le script ".pp" de Puppet est un pur DSL, alors que celui de Chef est fichier ruby, qu'on peut donc instrumenter programmatiquement. C'est l'argument avancé par les pro-Chef car il leur permet de gérer simplement des cas de figure un peu moins triviaux, alors que Puppet - étant verrouillé par son DSL - ne leur donne aucune solution simple.

CloudBees utilise Chef, et les quelques scripts/recettes que j'ai écrites jusqu'ici ne me permettent pas vraiment de juger. L'approche "moins" DSL de Chef ne m'a pas gêné pour rédiger mes recettes, ça aurait pu être un argument en faveur de Pupet pour le débutant. Quand à la syntaxe Ruby, on ne peut pas dire que ce soit un frein vu qu'on ne fait qu'effleurer le langage.

Pour l'instant ces outils sont encore peu utilisés, ou considérés avec intérêt sans franchir le pas, aussi plutôt que leurs différences, c'est la démarche qu'ils proposent qu'il nous faut intégrer. C'est un élément clé pour la mise en place d'une chaîne DevOps, de pratiques continuous-*, aussi je vous encourage à y consacrer quelques % de votre temps "veille technologique". Quelque soit l'outil retenu et ses éventuelles limites,  le potentiel offert par cette approche est énorme et mérite d'être exploré.

Post scriptum : 

Je remarque comme beaucoup un parallèle avec le troll que fait Gradle pour se démarque de Maven : structure trop figée, trop restrictive, et qui montre vite ses limites sorti des cas simples. Si je n'ai aucun avis personnel sur Gradle (faute d'avoir essayé), j'admet que devoir passer par les plugins antrun ou groovy dans maven n'est pas super élégant pour répondre à certains cas tordus. Seulement, des cas tordus on en a tous plus ou moins...
En même temps, comme le souligne le blog d'Octo, se heurter à la "psychorigidité" de Puppet, comme à celle de Maven, peut être un signe de mauvaise pratique ou de faiblesse architecturale. 




4 commentaires:

Piwaï a dit…

J'ai un pote qui fait pas mal d'admin, et qui reprend des scripts Chef. Il dit que c'est pas mal, sauf qu'évidemment si les mecs qui ont pondu les scripts sont des gourous du Ruby, ça peut être un peu difficile à maintenant. Dernier message qu'il m'a envoyé : "@interface ||= Interface.new options tu as une idée de ce que ca veut dire (c'est dans un constructeur)" => va chercher "||=" sur Google :)

Nicolas De Loof a dit…

C'est clairement une limite qu'il faut savoir se donner, comme dans tout langage, entre expressivité/concivité et accessibilité pour un newbie.

Sam BESSALAH a dit…

@Piwai
@interface ||= Interface.new n'est rien de magic, il s'agit de l'operateur ternaire qui assigne à la variable d'instance @interface un nouvelle instance de Interface (d'où Interface.new) s'il @interface est nil ou false.

Sinon merci à Nicolas pour l'article, je m'exerce à puppet depuis peu et c'est franchement pas mal. Interessé par le mouvement devops et travaillant dans un contexte très cloud, ce sont des outils qui aident vraiment. Pas besoin d'être expert en ruby pourles apprivoiser.

Jonathan Clarke a dit…

Article très intéressant, merci d'avoir exposé ainsi un vrai besoin qui existe, et les différentes approches (à éviter) avant de rentrer dans le vif du sujet !

La comparaison Chef/Puppet est intéressante, et on retrouve beaucoup de "buzz" sur ce sujet sur le web, mais il ne faudrait pas oublier les autres joueurs du domaine : CFEngine 3, voire bcfg2.

Au niveau utilisation du langage on verra rapidement qu'il n'y a pas grande différence fondamentale. Mais au niveau architecture réseau, autonomie et consommation mémoire, c'est le jour et la nuit. Typiquement, en environnement virtualisé, un point à ne pas négliger !

À bon entendeur pour affecter quelques "% de veille technologique" ;-)