Suite de l’article Installer un serveur Puppet scalable – partie 1 : vous avez maintenant un serveur Puppet qui fonctionne. On va rajouter un backend MySQL pour utiliser toutes les fonctionnalités offertes par Puppet et supprimer le serveur web WEBRick pour installer Apache/Passenger ou Nginx/Passenger. Dans cet article, on part donc de la configuration présentée dans la partie 1 pour arriver à un Puppet Master avec un premier niveau de scalabilité.

Apache + Passenger

Installation du module Apache

  • On commence par simplement installer Apache sur notre Puppet Master :
apt-get install apache2-mpm-worker
gem install passenger
  • Il faut maintenant compiler le module pour Apache. On installe les pré-requis pour satisfaire l’installeur :
apt-get install build-essential apache2-threaded-dev libcurl4-openssl-dev libapr1-dev libaprutil1-dev
  • Puis on compile le module Apache :
passenger-install-apache2-module
  • Une fois le module compilé, il faut l’activer au niveau d’Apache. Pour cela on va créer 2 fichiers : un pour gérer le chargement du module (le .so) et un pour gérer la configuration de ce module. On pourrait tout faire au niveau du VirtualHost, mais j’essaie de respecter ici le standard Debian. Pour le fichier /etc/apache2/mods-available/passenger.load :
LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-3.0.11/ext/apache2/mod_passenger.so
  • Pour le fichier /etc/apache2/mods-available/passenger.conf :
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-3.0.11
PassengerRuby /usr/bin/ruby

PassengerHighPerformance on
PassengerUseGlobalQueue on
PassengerMaxPoolSize 15
PassengerPoolIdleTime 300
PassengerMaxRequests 10000

RackAutoDetect On
  • On active le module passenger :
a2enmod  passenger
  • On relance Apache et on vérifie que le module est bien chargé :
# apachectl restart
# apachectl -M|grep passenger
Syntax OK
 passenger_module (shared)

Configuration de l’environnement

Le module Passenger est installé, il nous reste à créer un VirtualHost dédié au Puppet Master.

  • Créer le fichier /etc/apache2/sites-available/puppetmaster. C’est votre VirtualHost dédié à Puppet. Le contenu de ce fichier est disponible sur github pour plus de lisibilité. Remplacez puppetmaster par le nom de votre Puppet Master.
  • Il faut ensuite installer l’environnement pour ce VirtualHost : après avoir créé le DocumentRoot Apache, on récupère la configuration Puppet de la webapp rack. Attention : la configuration doit absolument appartenir à l’utilisateur puppet. Passenger utilisera ces droits pour exécuter Puppet.
mkdir -p /var/www/puppetmaster/public
cp /usr/lib/ruby/gems/1.8/gems/puppet-2.7.9/ext/rack/files/config.ru /var/www/puppetmaster/
chown puppet:puppet /var/www/puppetmaster/config.ru
  • On active ensuite le module SSL et Headers d’Apache ainsi que le VirtualHost tout juste créé :
a2enmod ssl
a2enmod headers
a2ensite puppetmaster
  • Relancez votre serveur Apache. Vous pouvez contrôler que tout fonctionne correctement en vérifiant les logs Apache de ce VirtualHost /var/log/apache2/puppetmaster_error.log et en vous assurant que Passenger et Rack sont bien démarrés. Testez un de vos agents via puppet agent -t. Cela doit fonctionner comme décrit dans la partie 1 de cet article.

Nginx + Passenger

Vous pouvez choisir d’utiliser Nginx plutôt qu’Apache. Je ne rentre pas dans la comparaison, ce n’est pas le but de l’article. A vous de choisir 😉 A savoir quand même : Nginx ne supporte pas le chargement de modules comme on peut le faire avec Apache. Il faut donc compiler Nginx avec le support de Passenger.

Installation de Nginx et Passenger

gem install passenger
  • On installe maintenant Nginx via l’installation de Passenger :
apt-get install build-essential libcurl4-openssl-dev libpcre3-dev
passenger-install-nginx-module

Vous avez deux possibilités : le choix 1 qui va récupérer les sources de Nginx puis les compiler avec le support Passenger ou le choix 2 pour lequel vous pouvez intervenir sur les options de configuration de Nginx. Je vais continuer en choisissant la deuxième option.

passenger-install-nginx-module

  • Pour le deuxième choix, il faut indiquer le répertoire qui contient les sources de Nginx. Récupérez la dernière version stable de Nginx puis décompressez l’archive dans /usr/local/src. A la date de cet article, la dernière version stable est la 1.0.11.
  • A la première question de passenger-install-nginx-module, j’indique le répertoire des sources que je viens de télécharger :
Where is your Nginx source code located?
Please specify the directory: /usr/local/src/nginx-1.0.11
  • Puis le prefix d’installation :
Where do you want to install Nginx to?
Please specify a prefix directory [/opt/nginx]: /usr/local
  • Et enfin, les options de configuration : je force par exemple le chemin de la configuration, des logs, du pid…
Extra Nginx configure options
If you want to pass extra arguments to the Nginx 'configure' script, then
please specify them. If not, then specify nothing and press Enter.

If you specify nothing then the 'configure' script will be run as follows:

  sh ./configure --prefix='/usr/local' --with-http_ssl_module --with-cc-opt='-Wno-error' --add-module='/usr/lib/ruby/gems/1.8/gems/passenger-3.0.11/ext/nginx'

Extra arguments to pass to configure script: --conf-path=/etc/nginx/nginx.conf --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx/nginx_error.log --http-log-path=/var/log/nginx/nginx_access.log
  • Après avoir validé la ligne de configuration, le compilation démarre. Nginx et Passenger sont installés. Reste à configurer Nginx !

Un autre façon de faire…

Vous pouvez installer Nginx et Passenger d’une façon plus classique :

gem install passenger
  • On télécharge l’archive de Nginx que l’on décompresse :
cd /usr/local/src
wget http://nginx.org/download/nginx-1.0.11.tar.gz
tar xvzf nginx-1.0.11.tar.gz
cd nginx-1.0.11
  • On lance la compilation :
./configure --prefix=/usr/local --with-http_ssl_module --with-cc-opt='-Wno-error' --add-module=/usr/lib/ruby/gems/1.8/gems/passenger-3.0.11/ext/nginx --conf-path=/etc/nginx/nginx.conf --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx/nginx_error.log --http-log-path=/var/log/nginx/nginx_access.log

make && make install

Configuration de Nginx

  • Vous trouverez sur github un exemple de configuration (/etc/nginx/nginx.conf) qui fonctionne. Remplacez puppetmaster par le nom de votre Puppet Master et adaptez worker_processes et worker_connections selon votre besoin.
  • Pour démarrer Nginx via un script d’init, vous pouvez utiliser celui là récupéré dans le paquet Debian. A installer sous /etc/init.d/nginx et à activer au démarrage via insserv -v nginx.
  • On installe la configuration pour la webapp. Attention aux droits : elle doit appartenir à Puppet.
mkdir -p /var/www/puppetmaster/public
cp /usr/lib/ruby/gems/1.8/gems/puppet-2.7.9/ext/rack/files/config.ru /var/www/puppetmaster/
chown puppet:puppet /var/www/puppetmaster/config.ru
  • Vous pouvez démarrer Nginx via /etc/init.d/nginx start et vérifier le log d’erreurs /var/log/nginx/puppetmaster.error.log. Lancez ensuite un de vos agents et vérifiez qu’il fonctionne comme décrit dans la partie 1 de cet article.

Monitoring de Passenger

Deux outils sont à votre disposition pour surveiller l’activité de Passenger : passenger-status et passenger-memory-stats. Voici deux captures d’écran pour vous donner une idée de la sortie de ces deux binaires :

passenger-status

passenger-memory-stats

MySQL

Pour utiliser, principalement, les ressources exportées, il faut stocker toute la configuration des agents en base de données en utilisant la notion de Storeconfigs.

Installation du serveur MySQL

  • Sur mon serveur MySQL dédié, j’installe le paquet MySQL :
apt-get install mysql-server
  • Par défaut, MySQL écoute uniquement sur 127.0.0.1. Commentez la ligne suivante dans /etc/mysql/my.cnf et relancez MySQL :
bind-address           = 127.0.0.1
  • Il faut créer la database pour Puppet ainsi que le user/pass pour y accéder. Connectez vous à votre serveur MySQL avec mysql -p :
mysql> create database puppet;
mysql> grant all privileges on puppet.* to puppet@puppetmaster identified by 'puppet';

Changez ici puppetmaster par le nom de votre Puppet Master (en fqdn) et le mot de passe puppet par quelque chose de plus sûr.

Configuration du Puppet Master

  • Sur votre Puppet Master, décommentez les lignes suivantes du fichier de configuration disponible sur github et adaptez les en fonction de votre configuration MySQL :
storeconfigs = true
dbadapter = mysql
dbname = puppet
dbuser = puppet
dbpassword = puppet
dbserver = mysql_server
  • Décommentez également la ligne suivante : cela permet de stocker l’inventaire facter en base de données et d’en profiter avec le dashboard par exemple.
facts_terminus = inventory_active_record
  • Il faut installer quelques gems pour pouvoir communiquer avec la base de données. On force ici la version du module activerecord, sinon, ça ne fonctionnera pas (Bug #9290) ! Si vous n’installez pas la documentation des Gems, vous pouvez passer les deux premières étapes. Dans le cas contraire, il faut le faire pour éviter une erreur de génération de la documentation :
gem install rdoc rdoc-data
rdoc-data --install
gem install --version 3.0.10 activerecord
gem install mysql2
  • Pour terminer et prendre en compte ces changements, relancez Apache ou Nginx.

Test et création d’index

Lancez un client, il ne doit pas y avoir de changement. Après l’exécution d’un premier client, les tables MySQL sont créées :

mysql> show tables;
+------------------+
| Tables_in_puppet |
+------------------+
| fact_names       |
| fact_values      |
| hosts            |
| inventory_facts  |
| inventory_nodes  |
| param_names      |
| param_values     |
| puppet_tags      |
| resource_tags    |
| resources        |
| source_files     |
+------------------+
11 rows in set (0.00 sec)

Il faut rajouter des index qui ne sont pas créés automatiquement :

mysql> use puppet;
mysql> create index exported_restype_title on resources (exported, restype, title(50));

C’est terminé pour cette seconde partie. Nous avons fait un premier pas dans la scalabilité de Puppet. Il utilise maintenant une base de données MySQL et le serveur WEBRick est remplacé par Apache ou Nginx. Dans la 3ème partie, nous verrons comment rajouter un deuxième Puppet Master avec un partage de charge.