L'admin pressé - RVM

Posté par (page perso) . Édité par Benoît Sibaud, Nÿco, Katyucha, frayd, palm123, NeoX et ariasuni. Modéré par Nÿco. Licence CC by-sa
Tags :
23
25
nov.
2013
Ruby

Mais qui est donc ce Hervé M. ? Ruby Version Manager est un ensemble de scripts qui va permettre d'installer différents environnements Ruby. On va tout d'abord voir d'un point de vue général ce que c'est et à quoi ça peut servir. Dans un second temps, on va voir les commandes de base pour s'en sortir sans trop de difficulté, et puis s'il y a encore du monde, on verra peut-être un exemple.

RVM

Sommaire

Introduction

Ruby, c'est une techno qui monte, et en tant qu'admin-sys, je suis bien obligé de m'y coller. Pour ceux qui aiment bien un récap visuel, cette petite inforgraphie vous aidera peut-être à visualiser la place de ce langage aux cotés et PHP et de Python (source) :

Cet article a vocation à vous donner les grandes lignes et le fonctionnement général de la mise en place de cette technologie. Il s'adresse donc aux non-spécialistes de Ruby, qui veulent rapidement mettre en place un environnement Ruby.

Cet article n'a pas vocation à être exhaustif, il veut juste donner les billes pour démarrer rapidement sans faire trois jours de recherche. Celui qui veut plus de détails aura au moins une direction pour mener les bonnes recherches dans notre ami Google. J'essayerai également de mettre en avant les bonnes pratiques (du moins les miennes), et quelques retours d'expérience; d'où le titre de cette série: L'admin pressé.

Bonne lecture!

RVM, à quoi donc?

RVM est un ensemble de scripts qui vont permettre d'installer différents environnements Ruby dans des versions variées. Par exemple, on va pouvoir installer les environnements suivants sur une seule et unique machine:

  • Ruby 1.8.7
  • Ruby 1.9.2
  • Ruby 1.9.3-p484
  • Ruby 2.0.0-p353
  • JRuby 1.5.1
  • JRuby 1.5.6
  • Rubinius …

Le principal atout est que l'on peut tous les installer sans qu'ils rentrent en conflit les uns les autres et en toute indépendance avec la distribution. Les fans de Debian apprécieront de ne pas jouer avec le pinning.

Gem

Ensuite, les gems interviennent. Qu'est ce qu'une gem (gemme en français) ? C'est tout simplement une bibliothèque Ruby. Concrètement, on trouvera de tout et de rien, mais par exemple, on pourra trouver des bibliothèques :

  • MySQL : pour se connecter à mysql
  • json : pour analyser des fichiers JSON
  • Allocine Parser : pour récupérer des infos sur allociné
  • Nokogiri : une bibliothèque pour lire différents formats de fichiers comme du HTML, XML ou du SAX.

Le seul problème de ces gems, c'est leur évolution dans le temps. Tandis que certains auront besoin d'utiliser Ruby 2.0.0-p353, un autre devra utiliser JRuby en version 1.5.1. De plus, certains gems peuvent être dépendants d'un autre gem sous une version différente. Tout cela peut devenir assez compliqué : un système de gestion de dépendance devint vite indispensable.

Gemset et Gemfile

La notion de gemset apparaît alors. Un gemset est un ensemble de gems lié à un environnement. Prenons l'exemple d'un cas où nous voudrions Redmine et Gitlab sur la même machine, on sera amené à créer deux gemsets différents :

  • Le gemset mon_redmine, qui supporte la version 1.9.3 de ruby, avec quelques gems nécessaires qui ne fonctionnent qu'avec Ruby 1.9
  • Le gemset mon_gitlab, qui doit au minimum avoir une version 2.0.0-p247 de ruby, et pleins d'autres gems qui ne fonctionnent qu'avec Ruby 2.

On va donc avoir deux gemsets, qui vont fournir deux environnements distincts et utilisables par nos deux applications.

Une fois qu'on a nos deux gemsets, il va falloir y installer des gems dedans. Bah oui, quand on crée un gemset, à part le fait qu'on précise la version de Ruby que l'on veut utiliser, bah il n'y a aucune gem dedans. On verra plus tard que l'installation d'une gem est similaire à n'importe quel gestionnaire de packet (apt, yum, pacman …). En attendant, comment savoir quels gems il faut installer et sous quelles versions? C'est à ce moment-là qu'on fait un bisou au développeur, car il y a normalement dans chaque application Ruby un fichier Gemfile. Ce fichier Gemfile est juste une liste de gems, avec la version nécessaire à installer. Concrètement, ça ressemble à ça :

source 'http://rubygems.org'

gem 'mysql2', '~> 0.3.11' 
gem 'devise', '~> 2.2.3' 
gem 'devise-encryptable' 
gem 'devise_aes_encryptable', git: 'https://github.com/virudson/devise_aes_encryptable.git'
gem 'cancan', '~> 1.6.9' 
gem 'ransack', '~> 0.7.2' 
gem 'jquery-rails' 
gem 'jquery-ui-rails' 
gem 'underscore-rails'

Le format est effectivement d'une simplicité déconcertante. Le truc magique de ce fichier, c'est qu'en lançant une seule commande, il va installer toutes les gems nécessaires.

RVM pour les poilus

À ce stade du document, on a vu les grandes notions clés de RVM, maintenant, qu'est ce que ça donne en pratique pour l'admin pressé que je suis ?

Installation

Pour installer rvm, c'est tout simple, on suit la procédure recommendée sur le site.

  • Alors pour le sys-admin consciencieux, ce type d'installation peut paraître assez immonde, car il n'utilise pas le système de distribution de binaire du système. Mais il se trouve que l'installeur fait les choses bien, et qu'il installe tout dans /usr/local/rvm. Il ne restera qu'un fichier à mettre manuellement dans le /etc/profile.d/. Et c'est tout.
  • En tant qu'admin-sys, je recommande l'installation du type Multi-User installations. En effet, c'est ce qu'il y a de plus adapté pour la prod, et ça permet de ne pas m'embêter avec des applications installées dans le répertoire home des utilisateurs. Il reste néanmoins possible et conseillé de lancer chaque application avec un utilisateur Unix dédié et restreint.
  • Si vous êtes un développeur, l'installation par utilisateur sera sûrement plus adaptée.

RVM

Lister les environnements et versions de Ruby installables :

rvm list known

Installer une version spécifique de ruby, listée au dessus grâce à la commande ci-dessus :

rvm  install ruby-1.8.7-p160    

Lister les environnements actuellement installés sur le système :

rvm list

Changer d'environnement actuel et définir celui par défaut :

rvm use 1.9.3
rvm --default use 1.9.3

Supprimer un environnement Ruby :

rvm remove <dist>

Gestion des gemsets

Créer un gemset. Bien sur, vous pouvez lui donner le nom que vous voulez :

rvm gemset create <gemset> [<gemset>]

Syntaxe un peu plus rapide, qui permet d'utiliser un environnement avec la bonne version de Ruby, après l'avoir créé s'il n'existait pas :

rvm use 1.9.2-head@albinochipmunk --create

Lister les gemsets créés. La dernière commande permet d'avoir une bonne visualisation sur les gemsets créés, les versions de Ruby installées ainsi que le chemin des binaires :

rvm gemset list
rvm gemdir
rvm gemset list_all

Remarque : il faut noter que tous les gemsets sont listés, indépendamment des versions de Ruby. Ça peut être confus au début, mais un gemset n'est techniquement pas dépendant de la version de Ruby installée. On peut changer la version, mais après gare aux incompatibilités de version des gems.

Changer de gemset :

rvm gemset use <gemset>
rvm gemset use <version>@<gemset>

Supprimer un gemset, et tous les gemsets liés à une version de Ruby :

rvm gemset delete <gemset>
rvm <version> do gemset delete <gemset>

Gem

C'est l'outil qui permet d'installer des bibliothèques ruby. En général, le dépôt officiel est http://rubygems.org/, mais on peut en rajouter d'autres.

Installer et désinstaller :

gem install <gem>
gem install <gem> -v <version>
gem uninstall <gem>
gem uninstall <gem> -v <version>

Lister les gems installés localement. L'option -a permet d'afficher toutes les versions disponibles, ce qui peut être pratique pour trouver une version spécifique :

gem list --local -all
gem list -l -a

Faire une recherche pour trouver les gem disponibles :

gem search <pattern> --remote gems.rubyforge.org
gem list --remote --all
gem list -r -a

Faire une liste des gems qui ne sont plus à jour, pour les mettre toutes à jour. On peut aussi les mettre à jour de manière individuelle. La dernière commande permet de désinstaller les anciennes versions :

gem outdated
gem update
gem update <gem>
gem clean

Supprimer toutes les gems d'un gemset, sans supprimer le gemset. En gros, ça sert si on s'est planté, et qu'on veut repartir d'un gemset propre, sans vouloir le recréer :

for i in `gem list --no-versions`; do gem uninstall -aIx $i; done

Bundle

Bundle, c'est le programme qui va automatiser l'installation des gems pour une application donnée. Il faut lui donner un Gemfile à manger, et il digère le reste tout seul, pour créer un environnement. En gros, c'est une sorte d'apt, qui va lancer les bonnes commandes gem, etc …

Utiliser Ruby avec un serveur Apache2

Il y a plusieurs approches différentes :

  • la première consiste à utiliser le Phusion Passenger, qui va un peu fonctionner sur le principe du mod_php5 d'Apache2. Je ne connais pas en détail son fonctionnement, que les puristes me pardonnent donc.
  • La deuxième approche consiste à utiliser le serveur web fournit par l'applicatif lui-même. En effet, certains gems implémentent des serveur web : Unicorn, Thin, Puma, Pow, Mongrel, . Le serveur écoute donc sur un port différent du 80, mais on peut facilement faire un Reverse Proxy pour pouvoir y accéder sur le port 80, avec toute la configuration des vhosts qui va bien.

Le choix à faire n'est pas évident, et la solution qui m'a paru la plus simple, c'est celle du Reverse Proxy, et sinon celle de Phusion Passenger. En effet, certains applicatifs sont plus ou moins optimisés et performant avec leur propre serveur web qu'avec Phusion Passenger. D'un point de vue sysadmin, la solution Phusion Passenger est plus élégante si l'on héberge plusieurs applicatifs sur le même serveur. Il faut aussi noter que Passenger semble également poser des problèmes de stabilités et/ou de performances (il faut toutefois approfondir sur ce point, je n'ai pas vraiment d'arguments à avancer).

Concernant l'installation en tant que telle, voici un petit récapitulatif. Imaginons-nous sous le plus beau système d'exploitation du monde, Debian :-D

  • Utiliser les dépôts Debian : solution toute prête, qui va installer le module Passenger dans Apache2.
  • Utiliser le gem Passenger : on va pouvoir installer une version spécifique (et plus récente que celle des dépôts). Il faudra compiler cette version (pour générer le module .so nécessaire à Apache2) ainsi que configurer Apache2 pour aller chercher le module.
  • Utiliser la solution fournie par l'applicatif : c'est la solution la plus simple, tout est déjà configuré, il ne restera plus qu'à faire un Reverse Proxy pour avoir un truc propre au final.

Message de fin

Ruby est donc une technologie que nos clients nous demandent de plus en plus d'installer, à travers des applicatifs comme Redmine, GitlabHQ, ClockingIT… Et, il est important de s'ouvrir à d'autres technologies autres que le bien connu PHP, d'où la rédaction de cet article.

J'espère que cette dépêche vous a plu, elle a mis beaucoup de temps à sortir (désolé d'avoir pollué l'espace de rédaction pendant plus d'un mois). Je souhaite remercier des gens que je connais pas (encore ?) : Nÿco, sinma, Katyucha, frayd et NeoX. Leur participation à cet article m'a grandement motivé à le finir. Merci beaucoup à eux :-)

Je m'excuse d'avance pour les fautes d'orthographes et les petites erreurs techniques, mais je ne demande aucune indulgence et surtout je suis largement ouvert aux critiques constructives.

Heeuuu … à la prochaine ? :-)

  • # Bundler et gemsets

    Posté par (page perso) . Évalué à 4.

    Les gemsets n'ont justement plus vraiment d'intérêt depuis l'utilisation de Bundler. Les gems de plusieurs applications peuvent très bien être tous installés au même endroit, Bundler ne chargera, et/ou ne rendra disponible, que ceux indiqués dans le Gemfile, pour peu que l'application l'utilise correctement (2 lignes en début de programme). De plus en production, un bundle install --deployment va installer les gems dans un dossier vendor/ ce qui isole bien du reste et rend aussi les gemsets inutiles. Ils ne sont utiles que pour les (vieilles) applications ne suivant pas les pratiques modernes.

    Ceci dit, RVM reste très pratiques pour gérer X versions différentes oui et il fait un super job pour la gestion des dépendances de build sur pas mal d'OS. On peut noter aussi rbenv, un peu plus brut de pomme, qui cherche à faire la même chose plus simplement et sans gemsets (en incitant à l'utilisateur de Bundler justement).

  • # Merci

    Posté par . Évalué à 1.

    Merci beaucoup pour cette dépêche, moi qui cherche à me mettre à Ruby cela va grandement m'aider à la mise en place d'un environnement de test. Pour l'instant je fait mes armes sur RubyMonk mais l'utilisation de ce que tu nous a présenté ne saurais tarder ;-)

  • # En comparaison à RBENV...

    Posté par . Évalué à 1. Dernière modification le 25/11/13 à 10:36.

    Salut, et merci pour cette explication claire et fonctionnelle,
    je tiens à ajouter en passant que rvm est tout de même réputé pour son usage presque excessif du 'cd' système lorsqu'il installe les version de ruby.

    Cependant, les deux se valent, et la comparaison entre RVM et RBENV est presque la même qu'entre deux frameworks comme Ruby on Rails et Sinatra.
    L'installation des versions ruby se fait via RBENV directement, via le plugin installer.

    Alors pour aller plus loin et creuser : Rbenv and Bundler (anglais)

  • # Typo

    Posté par . Évalué à 3.

    Le format est effectivement du simplicité déconcertante.

    "Le format est effectivement d'une simplicité déconcertante."

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.