Puppet en mode solo avec supply-drop

27 Mai 2014

On ne s’improvise pas administrateur réseau, gérer des serveurs est un travail à plein temps d’autant plus si l’on doit refaire la configuration de son serveur parce que l’on change de serveur tous les six mois. C’est pour ces raisons (et certainement d’autres) que les outils d’orchestration ont été créés et ont vu naître le mouvement «devops»…

Je ne vais pas vous présenter entièrement comment générer la configuration d’un serveur web, si vous n’êtes pas très à l’aise avec Puppet, commencez par lire cet article et la documentation officielle qui présente très bien le principe standard de Puppet.

Ce qui va nous intéresser est le processus de déploiement d’une configuration Puppet afin que vous soyez capable de modifier votre configuration Puppet, de la tester et finalement de la déployer sur votre serveur. L’objectif est relativement restreint puisque nous allons juste créer un VirtualHost pour Apache, mais cela permettra de facilement vous mettre le pied à l’étrier.

On va partir d’un répertoire vide et on va progressivement créer les fichiers nécessaires, vous pouvez retrouver l’arborescence final des fichiers sur Github.

Surtout, ne déployer pas sur un serveur fonctionnel surtout si vous avez des sites importants. Prenez un petit VPS pour faire des tests, puis lorsque vosu êtes prêt, vous pourrez migrer sans trop de soucis, c’est comme ça que j’ai fait !

Installation des composants

Pour atteindre notre objectif, nous n’allons pas nous reposer uniquement sur Puppet, nous allons utiliser supply_drop, mais également librarian-puppet, mais également capistrano. Tous ces composants sont développés en ruby, l’installation de tout ce petit monde est donc très simple :

gem install puppet supply_drop librarian-puppet capistrano

Si vous pensez que vous aurez besoin de réinstaller ces gems plus tard n’hésitez pas à créer un fichier Gemfile et je vous conseille même de le faire. Ainsi vous n’aurez plus qu’une commande à éxecuter pour réinstaller ces gems :

bundle install

Voici une petite présentation rapide de ces composants :

Il est possible de se passer de librarian-puppet, mais ce serai dommage de s’en passer. Une fois votre environnement prêt, on peut passer au choses sérieuses.

Au passage, nous utiliserons Vagrant pour tester notre configuration en local, installer Vagrant si ce n’est pas déjà le cas sur votre machine.

La configuration Puppet

Installation du module apache

Avec Puppet, on ne va pas réinventer la roue, on va utiliser l’un des très nombreux modules développés par la communauté.

On ne va pas utiliser puppet module install (voir la documentation) mais librarian-puppet pour installer le module apache qui nous intéresse. Je préfère utiliser librarian-puppet puisqu’il permet de facilement réinstaller les modules et de gérer les versions, chose impossible avec le binaire puppet.

Créez un fichier PuppetFile, c’est lui qui va stocker les différents modules que l’on veut utiliser ainsi que leur version. Une fois le fichier créé, copiez-y le contenu suivant :

forge 'http://forge.puppetlabs.com'
mod 'puppetlabs/apache', '1.0.1'

Pour installer le module dans notre environnement, il suffit de dire à librarian-puppet de le faire :

librarian_puppet install

En patientant quelques longues secondes, vous devriez maintenant avoir un répertoire «modules» dans l’arborescence de votre projet. Je vous invite à regarder cet utilitaire qui est vraiment pratique pour gérer ses modules.

Création d’un manifest

Créer un répertoire manifests et ajouter un fichier init.pp, ce sera le point d’entrée de Puppet pour notre configuration. Ajoutez le contenu suivant :

import 'web'
include 'web'

Ce fichier indique à Puppet qu’il doit charger un autre fichier nommé web.pp et qui doit être présent dans le même répertoire. Créez donc ce nouveau fichier toujours dans manifests et collez-y ce snippet :

class web {

  # Need to update packages before install apache
  exec { 'apt-get update':
    command => 'apt-get update',
    path    => '/usr/bin/',
    timeout => 60,
    tries   => 3
  }

  class {'apache':
    service_enable => true,
    default_vhost => false,
    mpm_module => "prefork",
    serveradmin => "admin@monserveur.fr",
    keepalive => "On",
  }
  apache::listen { '80': }

  apache::mod{'expires':}
  apache::mod{'headers':}

  apache::vhost { 'monserveur.fr':
    ensure        => present,
    priority      => '1',
    port          => '80',
    docroot       => '/var/www/monserveur.fr',
    directories => [{ path => '/var/www/monserveur.fr', allow_override => ['All']}],
    options => ['-Indexes','FollowSymLinks','MultiViews'],
    access_log_file => 'access.monserveur.fr.log',
    error_log_file => 'error.monserveur.fr.log'
  }

}

Quelques explications relatives au précédent snippet ne seront pas inutiles : tout d’abord on défini une classe web dans laquelle on va mettre la configuration de notre serveur web. Si on avait voulu configurer une base de données, la classe aurai pu s’appeler db.

Ensuite, quelques détails pour chaque block : le premier block est juste une précaution, on s’assure d’avoir des paquets à jour pour installer la dernière version d’apache. Le second block permet de configurer quelques réglages standard d’apache et d’être sur qu’apache soit installé. Le troisième block active deux mods d’apache et enfin le dernier block correspond à notre VirtualHost.

Voilà une configuration presque minimale pour notre objectif.

Test de la configuration dans Vagrant

Vagrant est un outil qui permet de créer des environnements virtuels de développement. Si vous ne connaissez pas trop, je vous conseille d’aller lire cet article sur PutainDeCode qui explique ce que fait Vagrant.

Comme on ne veut pas déployer n’importe quoi sur notre serveur, Vagrant va nous permettre de vérifier les modifications effectuées par Puppet.

Configuration de Vagrant

Nous allons créer notre environnement virtuel de tests, pour cela créez un fichier VagrantFile et copiez-y le contenu :

Vagrant.configure("2") do |config|
  server = [
    {
      id: :web1,
      ip: "192.168.33.176",
      hostname: "monserveur.fr"
    }
  ]

  servers.each do |server_settings|
    config.vm.define server_settings[:id] do |box|

      box.vm.box = "base"
      box.vm.hostname = server_settings[:hostname]
      box.vm.network :private_network, ip: server_settings[:ip]

      box.vm.network :forwarded_port, guest: 80, host: 8080

      box.vm.provision :puppet do |puppet|
        puppet.manifests_path = "manifests"
        puppet.manifest_file  = "init.pp"
        puppet.module_path = "modules"
      end

      config.vm.synced_folder './', '/tmp/puppet/'
    end
  end
end

Ce snippet dira à Vagrant de créer un serveur virtuel avec la configuration présente dans la variable servers tout en haut du snippet. Vagrant utilisera Puppet comme provisionner, mappera le port 8080 de votre machine locale vers le port 80 de la VM et enfin il créera un répertoire partagé sur la machine virtuel du répertoire courant de la machine locale vers /tmp/puppet sur la VM (c’est l’endroit ou notre configuration Puppet sera déployé).

Si vous voulez modifier la configuration de la VM, modifiez uniquement les variables du tableau servers.

Création de la VM

Une fois le fichier de configuration ajusté, nous allons pouvoir créer la VM de test. Ce qui est bien, c’est qu’une fois que Vagrant aura terminé la création, il va automatiquement lancé le provisionning Puppet et le VirtualHost sera déjà configuré.

La première initialisation peut prendre pas mal de temps, mais ensuite cela prendra moins d’une minute de recréer une VM de tests. Pour créer l’environnement de tests, saisissez la commande suivante :

vagrant up

Une fois que Vagrant a terminé, vous pourrez ouvrir votre navigateur sur http://localhost:8080 et vous devriez avoir une belle erreur 403. C’est tout à fait normal, nous avons configuré notre vhost mais il n’y a pas de données à servir. Connectez-vous sur la machine virtuelle avec la commande vagrant ssh, naviguez vers /var/www/monserveur.fr et créer un fichier index.html de test. Rafraichissez votre navigateur et vous devriez voir la belle page que vous aurez créé.

Lancer le provisionning

Si, vous voulez faire des modifications de votre configuration Puppet, il n’est pas nécessaire de créer une nouvelle VM à chaque modifications. Il suffit de lancer la commande suivante pour que Vagrant lance le provisionning Puppet sur le serveur.

vagrant provision

Ce processus est très rapide et permet de vite tester la configuration d’un environnement avant de déployer en prod.

Déploiement sur le serveur

Voilà, nous atteignons l’objectif final de cet article déployer notre configuration sur notre serveur.

La configuration de supply_drop

Puisque supply_drop est un module de capistrano, la configuration du module se fait via un fichier Capfile. Créer un fichier Capfileet copiez-y la configuration suivante :

load 'deploy'
require "supply_drop"

# =======================================
# deployment helpers
def datacenter_tasks(datacenter, servers)
  task datacenter do
    role :server, *servers
  end

  servers.each do |server|
    task server do
      role :server, server
    end
  end
end

# =======================================
# Servers
datacenter_tasks :prod, [
  "XXX.XXX.XXX.XXX"
]

# =======================================
# supply_drop and capistrano configuration
set :user, 'deploy'
set :puppet_destination, '/tmp/puppet'
set :puppet_parameters, './manifests/init.pp'

Il y a quatres choses importantes avec ce fichier :

  1. Il faut remplacer «XXX.XXX.XXX.XXX» par l’IP de votre serveur,
  2. L’utilisateur «deploy» devra exister sur le serveur,
  3. Notre serveur est configuré dans un tableau nommé «prod»,
  4. Le fichier d’entrée de Puppet se nomme bien ./manifests/init.pp.

Veillez à ne pas utiliser une version «< 3.x» de capistrano car supply_drop ne fonctionne pas avec les versions «> 3.x».

Bootstrap du serveur

Maintenant que la configuration de supply_drop est terminée, il est nécessaire de préparer notre serveur, on va supposé que vous avez un accès root à votre serveur. Cette configuration n’était pas nécessaire en local, puisque c’est Vagrant qui s’occupe de la faire pour nous.

Si vous vous posez la question : «Pourquoi faire une telle préparation ?» Tout simplement parce que Puppet a quelques pré-requis sur le serveur et supply_drop utilise rsync, il faut disposer d’un accès simple, sécurisé au serveur.

On va créer l’utilisateur «deploy» comme précisé auparavant, on va lui adjoindre une clé ssh afin de ne pas avoir à saisir de mot de passe lorsque l’on déploiera la conf du serveur et on va installer les dépendances de Puppet.

ssh root@monserveur.fr
adduser deploy
mkdir -p /home/deploy/.ssh
touch /home/deploy/.ssh/authorized_keys
chown -R deploy:deploy /home/deploy

Dans un terminal local, créer une clé SSH avec la commande suivante, puis copiez votre clé publique :

ssh-keygen -t rsa -C "your_email@example.com"

Ajouter cette clé publique dans le ficheir /home/deploy/.ssh/authorized_keys sur votre serveur. Essayer de vous connecter en tant qu’utilisateur «deploy», normalement vous devriez être connecté et vous n’avez pas eu de prompt pour un mot de passe.

Voilà, l’utilisateur nécessaire au déploiement existe, il faut maintenant qu’il puisse installer des packages, redémarrer des services, on va lui «donner les droits sudo». Reconnectez-vous sur votre serveur en root puis lancez la commande visudo et ajouter la ligne suivante à la fin du fichier :

deploy  ALL=(ALL) NOPASSWD: ALL

Dernière étape, on va maintenant installer tous les binaires nécessaires au fonctionnement de Puppet et cela se fait très simplement, supply_drop fournit une suite de commandes qui va installer les dépendances de Puppet en fonction de l’OS de votre serveur. Personnellement j’aime avoir mes serveurs sous Debian du coup la commande est :

cap prod puppet:boostrap:debian

Allez voir la documentation, pour voir si votre OS est supporté.

Voilà, tout est prêt, on peut maintenant déployer notre conf Puppet sur notre serveur.

Déploiement sur le serveur

C’est maintenant que l’on va utiliser suply_drop à proprement parler, c’est l’étape finale de l’article. Dans un terminal local, saisissez la commande suivante :

cap prod puppet:apply

Cette commande est très verbeuse, elle précise toutes les actions de Puppet sur votre serveur, si tout ce passe bien, au bout de quelques longues secondes, vous devriez voir un message vous indiquant que Puppet a bien déployé la configuration sur votre serveur.

Conclusion

Après rédaction, je trouve cet article trop long, je ne sais pas si beaucoup de lecteurs auront la patience de suivre entièrement l’article. Si vous voulez quand même tester sans devoir créer tous les fichiers nécessaires, j’ai crée un petit dépôt Git, avec tous les fichiers mentionnés dans l’article. Clonez le dépôt et vous n’aurez qu’à faire un vagrant up pour tester vous-même.

Si vous voulez aller plus loin lors de vos tests, vous pouvez essayer de faire les actions suivantes très facilement avec les modules de Puppet et avec un peu d’aide de Google :

Personnellement, je gère ce serveur avec cette technique depuis le mois de novembre et j’en suis vraiment très satisfait, je n’ai plus peur de faire de migrations puisque maintenant tout est scripté et il me faut moins de 30 minutes pour retrouver mon serveur configurer comme avant c’est un peu plus long pour les données mais ce n’est pas bien grave.

Bon j’espère que cet article vous aura plu et que cela vous donnera envie de vous lancer simplement dans la gestion de configuration…

Charger les commentaires…