Puppet, outil de gestion de configurations – Partie 2

Bonjour à tous,

Ceci est le deuxième billet du volet « Puppet ». Ici, on passe à la pratique.

Mais (y’a toujours un mais), il faut un peu de notions supplémentaires pour pas faire un tuto à copier coller sans rien comprendre.

Puppet a une syntaxe particulière propriétaire. C’est un langage déclaratif qui n’est interprétable que par Puppet. Une très bonne rétrocompatibilité garantie le passage d’une version n1 à une version n. Pour autant, tout ce que vous ferez avec Puppet ne fonctionnera qu’avec cet outil.

 

Généralités

Vocabulaire

• Node > un client

• Manifest > un fichier de configuration

• Module > une configuration autonome, composée de manifests

• Class > ce que défini un manifest

• Inherits > les classes peuvent s’appeler les unes aux autres : c’est de l’héritage

• Fact > valeur spécifique de l’environnement client (hostname, ip, taille des HDD, système d’exploitation, etc.)

• Catalogue > Les configurations d’un node. Chaque node à son catalogue, même s’ils peuvent être identiques. Les catalogues sont compilés par le serveur par rapport aux fichiers de manifests, de modules et aux facts récupérés sur le node.

 

Les dossiers

• manifests/ > Les fichiers de configuration du serveur

• modules/ > Les configurations interprétées par Puppet (là où on met nos modules)

• modules/<nom_module>/manifests/ > Configuration du module

• modules/<nom_module>/files/ > Les fichiers liés au module

• modules/<nom_module>/templates/ > Fichiers liés au module, mais qui contiennent un bout de code Ruby interprété par Puppet

• modules/<nom_module>/lib/facter/ > Script Ruby exécuté par le client, qui permet de récupérer des facts.

 

 

Mise en pratique (enfin! cré boudiou !)

On télécharge la dernière version du soft sur apt.puppetlabs.com ou yum.puppetlabs.com ou directement ajouter ces repos. (facile, sur ces mêmes adresses, vous avez un fichier de repos pré-rempli)

Je vous préviens tout de suite, ce tuto s’adresse à des admin systèmes, c’est pas un cours Linux, mais Puppet.

 

Configuration pour mes tests de Puppet 3 :

J’ai deux VM de tests pour vous : une Centos 6.4 et une debian 7.1. Elles sont les deux à jours et j’ai ajouté mes repos ci-dessus. Ma VM « debian1 » me servira en tant que client. Ma VM « centos6 » me servira comme client et serveur (oui, même le serveur Puppet se doit d’être administré par Puppet).

 

Installation de Puppet :

On va commencer par installer le client, car c’est plus simple! Exemple sur ma VM centos1 :

On installe le client Puppet :

Comme vous le voyez, y’a pas mal de dépendances avec Puppet. C’est un peu pareil avec Chef, y’a pleins de trucs qui viennent avec. CFEngine a cet avantage d’être composé que d’un seul paquet.

Ce qui nous intéresse a été mis là :

Ce sont les fichiers clients. On a juste besoin du fichier « puppet.conf ». Tout le reste est inutile au client.

Le deuxième endroit où regarder est : /var/lib/puppet. Pour l’instant, c’est vide car le client ne s’est jamais connecté à un serveur. On y retrouvera le cache des catalogues, les rapports d’exécutions, les clés SSL, etc.

 

Installation d’un serveur Puppet :

Le serveur de Puppet s’appelle un « puppetmaster ». C’est le nom du démon. Le paquet s’appelle pourtant « puppet-server » …

L’arborescence est un peu plus complète et surtout, on voit l’apparition du dossier « manifests ».

On lance le serveur en mode console pour la première fois, pour voir ce qu’il se passe. Pour les bidouilleurs, on peut faire plein de choses avec la commande Puppet, qui prend pas mal d’arguments, « puppet help » vous en dira plus

Voila, le serveur s’est lancé pour la première fois avec tout par défaut et il est fonctionnel.

J’explique ce qu’il s’est passé :
– J’ai lancé le serveur en mode console (–no-daemonize) et qu’il soit verbeux (-v ou –verbose). Si on veut vraiment tout voir, il y a le mode –debug ou -d.
– Le serveur a vérifié tout ses dossiers et fichiers et a appliqué les options.
– Il a alors essayé de trouver sa clé SSL, celle qui va permettre aux clients d’être authentifiés mais ne l’a pas trouvé.
– Par défaut, le serveur Puppet est une autorité de certification, une CA. Vu qu’il n’y avait aucun certif, il a tout créé.
– Pour autant, chaque nouveau node fait une demande de certificat qui doit être manuellement autorisée par le CA. Cette opération est automatisable pour les nouveaux nodes, mais pour vous montrer, j’ai laissé le truc par défaut.

 

Lorsque le serveur Puppet se lance pour la première fois, il crée donc un certificat CA et se valide lui-même son certificat client. Pour lui il n’y a rien à faire, ça marche tout seul. On peut aussi jouer sur la durée des certificats, on verra peut être plus tard 🙂

Vu qu’il crée son certificat CA et que ce dernier sera utilisé par tous les nodes, il faut être certain de son hostname et avoir configuré son nom FQDN …

Tout ce petit monde se trouve  dans :

 

Connexion d’un client au serveur Puppet :

On va connecter notre client debian1 au master centos1. Par défaut, le client, s’il n’y a pas d’option de serveur, va essayer de se connecter à la machine « puppet.mespotesgeek.fr ». Moi j’ai appelé différemment mes machines car je suis un warrior.

L’auteur de cet article est un professionnel, s’il vous plait, ne faites pas ça à la maison ! Il décline toute responsabilité en cas d’accident.

Ici, j’utilise une sortie verbeuse et c’est pour le lancer une seule fois (-t = tests), le temps que je valide mon certificat sur le ca.

On regarde du coté serveur :
– Sur la console active du puppetmaster, on voit la connexion du node :

– On regarde cette demande de certificat :

– On regarde dans l’arborescence et on remarque bien sa présence dans les dossiers du CA :

Et oui, vous pouvez directement supprimer ce fichier pour refaire une nouvelle request si vous le voulez, sans passer par les commandes unix de Puppet !
– On n’est pas comme ça, on valide la demande de certificat de notre client :

– On regarde le changement dans l’arborescence :

– Ca marche alors ? Relançons le client !

Voilà, on vient de connecter le client au master. Il ne se passe rien et c’est normal. Reste plus qu’à écrire des configurations sur le master et le client les appliquera ensuite.

 

 

Création d’un module simple

Je vous propose pour ce premier module quelque chose de très simple qui fera appelle aux éléments de langage de Puppet. On va juste dire que les clients doivent avoir le fichier de conf puppet qu’on leur donnera, qu’ils vérifient que le client Puppet est à jour et qu’il soit bien lancé au démarrage de la machine.

Création de l’arborescence :

On se déplace dans : /etc/puppet/modules/ :

J’ai décidé d’appeler le module ‘puppet_agent’. Ensuite, ce module doit obligatoirement avoir un dossier ‘manifests’ qui doit obligatoirement contenir ‘init.pp’.

Le truc est simple : on dira au puppetmaster de charger la classe ‘puppet_agent’. Pour qu’il la trouve, il faut que cette classe soit défini dans le fichier init.pp du module de même nom que la classe.

Je crée aussi un dossier ‘files’ qui va contenir notre fichier de conf client.

 

Création de la configuration avec la syntaxe Puppet (la fameuse) :

Copiez-collez le contenu suivant dans le fichier puppet_agent/manifests/init.pp

Explications de ce code très simple :

#0 : Je crée une classe, que je pourrai ensuite appeler pour la « donner » à un node, pour dire à notre node qu’il charge cette classe dans sa config.

#1 : Je crée une ressource de type ‘fichier’. Il y a plusieurs arguments, j’ai rien inventé : http://docs.puppetlabs.com/references/latest/type.html#file.

Je dis en gros :

– j’ai une ressource de type fichier,

– elle s’appellera dans un catalogue Puppet « /etc/puppet »,

– c’est un dossier,

– le propriétaire du dossier est « root »,

– le groupe du dossier est « root »,

– les droits du dossier sont « 755 ».

Ca veut dire qu’à chaque fois que votre client Puppet va charger sa conf auprès du serveur, il vérifiera que ce fichier existe, que c’est bien un dossier, que le propriétaire et le groupe est root et pour finir que les droits sont ‘755’. A chaque fois.

Ici, j’utilise une astuce de Puppet : normalement je devrais écrire en argument de la ressource : « name => le_nom_du_fichier ». Puppet reconnait pour autant que s’il n’y a pas de ‘name’, le nom du fichier est le nom de la ressource. Vous comprendrez juste après.

 

#2 :

Je crée une nouvelle ressource de type ‘fichier’ pour gérer le fichier de conf  du client Puppet. Rien de bien particulier par rapport au #1 si ce n’est la fin :

–  Le « source => » permet de spécifier à Puppet que le fichier qu’on défini, il le copie depuis le serveur. Ce fichier sur le serveur se trouvera dans : « /etc/puppet/modules/puppet_agent/files/puppet.conf.client ».

– Le « require => » permet de faire des liens entre les ressources. Juste avant en #1, j’ai créé un dossier, reconnu par Puppet sous le nom ‘/etc/puppet’. En utilisant le ‘require’, je fais appelle à cette ressource, par son nom unique ‘/etc/puppet’ et je dis alors qu’il faut traiter le dossier avant ce fichier.

 

#3 :

Là c’est une autre ressource que j’utilise, le type ‘service’. Je dis :

– J’ai un service qui doit tourner, il s’appelle « puppet »,

– il est sensé être lancé, (c’est inutile ici de mettre ça, car bien sur que le client tourne vu que c’est lui qui appliquera ça … mais c’est pour l’exemple)

– ce démon a une directive « restart » si j’essaie de faire « service puppet restart », ça marchera

– « enable => true » permet de dire qu’il est dans les runlevels 3,4 et 5, donc démarré au boot de la machine,

– comme dans le #2, le require permet de dire que le démon devra être lancé après qu’on ait copié le fichier de conf client.

 

#4 :

Pour le paquet, je dis que je veux que Puppet soit à jour. Bien sur, si le paquet n’est pas installé, il le sera.

– Petit particularité : je vous montre ici que l’ordre d’écriture d’un fichier Puppet n’a AUCUNE importance. Puppet va créer un ordre d’application de ces ressources sans se soucier de l’ordre dans lequel elles ont été écrites. C’est la base d’un langage déclaratif. Cependant, pour garantir l’ordre d’exécution et pour pas qu’on essaie de lancer le démon avant que le paquet soit à jour, on met ces directives d’ordonnancement.

Ce ‘before’ est donc comme un ‘require’.

Plus d’infos sur : http://docs.puppetlabs.com/puppet/2.7/reference/lang_relationships.html

 

Pour être sur que vos fichiers puppet (qui se terminent par ‘.pp’) sont valides :

–> pas de réponse ? C’est bon ! Si vous voyez du rouge, faut corriger.

NB : cet outil est un parseur assez bête. Si vous faites des références à des ressources extérieurs, ou des trucs un peu funky, ca ne sera pas détecté !

 

Edition du fichier de conf client qui sera téléchargé par tous les nodes :

Il suffit de copier coller votre fichier de conf et d’y ajouter le nom du serveur. Voici :

 

Ajout de notre module au catalogue par défaut :

Un module, ou plus précisement une classe, peut être intégrée dans le catalogue spécifique d’une machine, d’un groupe, d’une famille d’os, etc. Ici, vu que c’est la base de Puppet, on veut gérer ce fichier sur toutes nos machines ! Il sera donc par défaut.

Un module dans Puppet doit toujours contenir un fichier site.pp. De la même manière, le démon puppetmaster chargera toujours un et un seul fichier : « /etc/puppet/manifests/site.pp ». C’est dans ce fichier qu’on dit quelles machines chargent quelles classes.

En vrai, dés qu’on a pas mal de machines, ça devient vite fouilli de tout mélanger ici, on utilise donc site.pp pour des configurations générales, définir des groupes de machines, des variables globales, etc. On utilise ensuite nodes.pp pour définir les nodes. C’est partit !

La partie ‘serveur’ de puppet se gère dans le dossier ‘manifests’, au même niveau que ‘modules’. Ne pas confondre avec les dossiers « manifests » que l’on trouve aussi dans les modules. Ceux-ci concernent les modules et non le démon serveur.

Pour un truc minimal qui marche, mettez ceci dans le fichier manifest/site.pp :

Puis, ceci dans le fichier nodes.pp :

 

Lancement du client

Bon, normalement, ça devrait marcher.

On test en lançant puppet sur le client (on force son exécution en réalité) :

Et voilà ! il applique bien la conf sur Debian et Centos. C’est pareil sur les deux, donc rien à faire.

Vous voulez changer la conf du client ? Pas de soucie, elle est maintenant centralisée, changez la directement sur le puppetmaster et les clients l’appliqueront dans les 30mns max ! (temps par défaut).

Vous pouvez dès à présent avec ces quelques billes commencer à copier d’autres fichiers, créer vos propres modules et installer et optimiser vos clients. Avec le module que je vous ai donné, vous avez déjà de quoi faire pas mal de choses !

 

 

C’est fini pour cette deuxième partie. Il y aura normalement une troisième plus poussée où on va rentrer plus en détails dans la syntaxe, faire de l’héritage, de la surcharge de méthodes, créer notre propre fact, utiliser ces variables dans Puppet, etc.

 

Vincent

Tags:

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *