Il y a quelques semaines, j’ai étais confronté à une problématique assez basique et pourtant ignoré jusque là. On m’a demandé d’exécuter un script sur quelque 300 machines *nix et de parser deux fichiers HTML générés. Jusqu’ici, c’est un travail d’admin système de base. Or voilà, moi, j’ai 300 machines réparties sur des réseaux qui sont HERMETIQUEMENT fermés de ma station d’administration. Il a donc fallu scripter une partie et traiter l’autre manuellement en urgence.
Tout cela m’a fait me pencher sur des solutions de gestion de configurations et d’administration de masse. Parmi toutes ces solutions, j’ai retenu celles proposées par PuppetLabs (http ://www.puppetlabs.com/). La suite de trois outils est infaillible :
- Puppet permettant la gestion centralisée des services et configurations
- MCollective qui permet l’administration et l’exécution de commandes centralisé
- Facter qui permet de dresser une véritable fiche d’identité du server
Aujourd’hui je vous propose une petite initiation à Puppet et quelques tips qui vous feront gagner du temps.
Prérequis :
- Deux machines (OSEF de l’unix, ici il y aura une Debian 6 et une FreeBSD 8.2)
- Une liaison sur le port 8140 (port de communication Puppet) entre les deux
Installation du Server (Puppet Master) :
Le serveur tournera ici sous Debian 6. Pour installer, le très habituel :
aptitude install puppetmaster
Une fois installer, il faut éditer le fichier fileserver.conf qui permet d’autoriser l’accès aux dépôt de fichier Puppet. Pour cela, voici la syntaxe :
[files] #Chemin du partage path /etc/puppet/files #Machines autorisés allow *.madeinsyria.fr #Ici tout les réseau en 192.168.X.X sont autorisés. allow 192.168.0.0/16
Il faut aussi créer le fichier /etc/puppet/puppet.conf et y ajouter :
[master] certname=puppet.madeinsyria.fr
La valeur de certname est celle du hostname de la machine (obtenu via la commande « hostname »).
Pour finir, il faut éditer le fichier /etc/hosts/ afin de spécifier les noms et IP des machines clientes (à supposer que leur noms ne peut être résolu via DNS).
A ce niveau, je préconise un bon reboot de la machine. En effet, un simple restart ne prend pas très bien en compte le certname. Or cela peut devenir un gros problème, car comme nous allons le voir, les certificats permettant de communiquer ne pourront pas être transmis.
Installation du client (Puppet Agent) :
A ce niveau rien d’extraordinaire. On déploie l’agent Puppet avec un classique (oui, mon client est une FreeBSD) :
pkg_add –r puppet
Le paquet est installé et un fichier de configuration /usr/local/etc/puppet/puppet.conf est généré. Je conseil de le vider entièrement et de remplacer son contenu par :
[puppetd] server=FQDN-DU-SERVER-PUPPET [main] logdir = /var/puppet/log vardir = /var/puppet ssldir = /var/puppet/ssl rundir = /var/run/puppet factpath = /var/puppet/lib/facter:/var/puppet/facts templatedir = /var/puppet/templates
En effet, par défaut le fichier contient TOUS les éléments de configuration aussi bien pour la partie cliente que serveur. Et comme je suis gentil comme tout, voici la même chose pour Debian :
[puppetd] server=FQDN-DU-SERVER-PUPPET [main] logdir=/var/log/puppet vardir=/var/lib/puppet ssldir=/var/lib/puppet/ssl rundir=/var/run/puppet factpath=$vardir/lib/facter templatedir=$confdir/templates
Initialisation de la relation entre le maitre et l’agent :
Puppet utilise le chiffrement SSL pour ses communications sur le port 8140. Or qui dit SSL, dit certificats. Le server maitre sera en fait une autorité de certification et permettra de délivrer des certificats aux agents. Ce processus se déroule en deux parties :
- L’agent demande un certificat via un CSR
- Le maitre signe le client
Pour faire la demande du coté de l’agent, il suffit de taper la commande :
root@OAF-PRJ-SYSLOG:~# puppet agent --test info: Creating a new SSL key for oaf-prj-syslog.madiensyria.fr warning: peer certificate won't be verified in this SSL session info: Caching certificate for ca warning: peer certificate won't be verified in this SSL session warning: peer certificate won't be verified in this SSL session info: Creating a new SSL certificate request for oaf-prj-syslog.madiensyria.fr info: Certificate Request fingerprint (md5): 8A:03:E3:57:53:8B:91:FC:89:61:B8:A0:E0:F4:F0:EC warning: peer certificate won't be verified in this SSL session warning: peer certificate won't be verified in this SSL session warning: peer certificate won't be verified in this SSL session Exiting; no certificate found and waitforcert is disabled
Cette commande est celle que vous utiliserez le plus. Elle permet de demander un update manuel coté serveur. Si le client n’a pas de certificat, il demandera par la même son certificat.
Coté maitre, il ne reste plus qu’à signer le client. Pour visualiser les demandes en cours, il faut faire :
root@puppet:~# puppetca --list oaf-prj-syslog.madiensyria.fr
Puis pour signer le client :
root@puppet:~# puppetca --sign --all notice: Signed certificate request for oaf-prj-syslog.madiensyria.fr notice: Removing file Puppet::SSL::CertificateRequest oaf-prj-syslog.madiensyria.fr at '/etc/puppet/ssl/ca/requests/oaf-prj-syslog.madiensyria.fr.pem'
Pour finir, l’agent va récupérer son certificat :
root@OAF-PRJ-SYSLOG:~# puppet agent --test warning: peer certificate won't be verified in this SSL session info: Caching certificate for oaf-prj-syslog.madiensyria.fr info: Caching certificate_revocation_list for ca info: Caching catalog for oaf-prj-syslog.madiensyria.fr info: Applying configuration version '1306778426' notice: Finished catalog run in 0.23 seconds
Après la configuration, un petit déploiement test :
Un exemple Puppet, est le déploiement NTP. Ce service si simple et pourtant crucial est l’exemple parfait du service à industrialiser et maitriser. Nous allons donc voir comment configurer tout ça.
Création du module :
D’un point de vu Puppet, le NTP ne sera qu’un simple module. Je ne vais pas entrer dans le détail de la structure des modules Puppet, c’est assez complexe d’un point de vu hiérarchique (mais simple fonctionnellement parlant). Pour plus d information sur le sujet, il existe : http://docs.puppetlabs.com/learning/modules1.html.
Dans un premier temps j’ajoute la commande suivante qui me permettra de créer toute l’arborescence d’un module en une commande à mon .bashrc :
mkmod() { mkdir "$1" mkdir "$1/files" "$1/lib" "$1/manifests" "$1/templates" "$1/tests" }
Je me rends par la suite dans /etc/puppet/modules/ ou je crée ma hiérarchie de module avec ma nouvelle commande :
root@puppet:/etc/puppet/modules# mkmod ntp
Puis je crée le fichier de module en lui-même (une class Puppet) dans le sous répertoire manifests avec un nom de fichier init.pp :
root@puppet:/etc/puppet/modules# cd ntp/manifests root@puppet:/etc/puppet/modules/ntp/manifests # vim init.pp class ntp { #En fonction de l’OS, je defini des paramètres spécifiques case $operatingsystem { freebsd: { $service_name = 'ntpd' $conf_file = 'ntp.conf.bsd' $ntppath = '/etc/ntp/ntp.conf' } debian: { $service_name = 'ntp' $conf_file = 'ntp.conf.debian' $ntppath = '/etc/ntp.conf' } } #Je m’assure que le service NTP est installé sur la machine package { 'ntp': ensure => installed, } #Je m’assure que le service tourne, mais uniquement si le fichier ntp.conf est dispo service { 'ntp': name => $service_name, ensure => running, enable => true, subscribe => File['ntp.conf'], } #Je m’assure que ntp.conf existe, mais seulement si le service NTP est installé file { 'ntp.conf': path => $ntppath, ensure => file, require => Package['ntp'], #Le fichier est récupérable dans : /etc/puppet/modules/ntp/files/ source => "puppet:///modules/ntp/${conf_file}", } }
En cadeau, mon fichier NTP de démo à placer dans /etc/puppet/modules/ntp/files/ :
root@puppet:~# cat /etc/puppet/modules/ntp/files/ntp.conf.bsd serveur time.intrinsec.com driftfile /var/db/ntp.drift
Il ne reste plus qu’à utiliser cette classe en l’appelant dans les fichiers de base de Puppet à savoir :
- /etc/puppet/manifests/modules.pp qui contient tout les modules utilisables
- /etc/puppet/manifests/nodes.pp qui contient tout les agents et leur configuration
- /etc/puppet/manifests/site.pp qui fait appel à nodes.pp et modules.pp
Voici donc le contenu de modules.pp :
root@puppet:/etc/puppet/manifests# cat modules.pp import "ntp"
Celui de nodes.pp :
root@puppet:/etc/puppet/manifests# cat nodes.pp #n défini un ensemble de service de base node basenode { include ntp } #Et on fait hérité mon agent de cet configuration node 'oaf-prj-syslog.madeinsyria.fr' inherits basenode { } #Tout les agents non cité auront la configuration du default node default inherits basenode { }
Pour finir, on appel tout le monde dans site.pp :
root@puppet:/etc/puppet/manifests# cat site.pp import "modules.pp" import "nodes.pp"
Déploiement :
Tout ce beau monde est prêt à déployer, alors testons tout cela ! Sur le client, executons notre commande magique :
root@OAF-PRJ-SYSLOG:~# puppet agent --server puppet.madeinsyria.fr --test warning: peer certificate won't be verified in this SSL session info: Caching certificate for oaf-prj-syslog.madiensyria.fr info: Caching certificate_revocation_list for ca info: Caching catalog for oaf-prj-syslog.madiensyria.fr info: Applying configuration version '1306778426' notice: /Stage[main]/Ntp/Package[ntp]/ensure: ensure changed 'purged' to 'present' --- /etc/ntp.conf 2010-10-17 15:35:26.000000000 +0200 +++ /tmp/puppet-file20110601-1931-glkc6r-0 2011-06-01 15:28:22.000000000 +0200 @@ -1,55 +1,2 @@ -# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help - +serveur time.intrinsec.com driftfile /var/lib/ntp/ntp.drift - - -# Enable this if you want statistics to be logged. -#statsdir /var/log/ntpstats/ - -statistics loopstats peerstats clockstats -filegen loopstats file loopstats type day enable -filegen peerstats file peerstats type day enable -filegen clockstats file clockstats type day enable - - -# You do need to talk to an NTP server or two (or three). -#server ntp.your-provider.example - -# pool.ntp.org maps to about 1000 low-stratum NTP servers. Your server will -# pick a different set every time it starts up. Please consider joining the -# pool: <http://www.pool.ntp.org/join.html> -server 0.debian.pool.ntp.org iburst -server 1.debian.pool.ntp.org iburst -server 2.debian.pool.ntp.org iburst -server 3.debian.pool.ntp.org iburst - - -# Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for -# details. The web page <http://support.ntp.org/bin/view/Support/AccessRestrictions> -# might also be helpful. -# -# Note that "restrict" applies to both servers and clients, so a configuration -# that might be intended to block requests from certain clients could also end -# up blocking replies from your own upstream servers. - -# By default, exchange time with everybody, but don't allow configuration. -restrict -4 default kod notrap nomodify nopeer noquery -restrict -6 default kod notrap nomodify nopeer noquery - -# Local users may interrogate the ntp server more closely. -restrict 127.0.0.1 -restrict ::1 - -# Clients from this (example!) subnet have unlimited access, but only if -# cryptographically authenticated. -#restrict 192.168.123.0 mask 255.255.255.0 notrust -# If you want to provide time to your local subnet, change the next line. -# (Again, the address is an example only.) -#broadcast 192.168.123.255 -# If you want to listen to time broadcasts on your local subnet, de-comment the -# next lines. Please do this only if you trust everybody on the network! -#disable auth -#broadcastclient info: FileBucket adding /etc/ntp.conf as {md5}3e250ecaf470e1d3a2b68edd5de46bfd info: /Stage[main]/Ntp/File[ntp.conf]: Filebucketed /etc/ntp.conf to puppet with sum 3e250ecaf470e1d3a2b68edd5de46bfd notice: /Stage[main]/Ntp/File[ntp.conf]/content: content changed '{md5}3e250ecaf470e1d3a2b68edd5de46bfd' to '{md5}9b52a60a69ca6c82e9c8fdb96458e7cb' info: /Stage[main]/Ntp/File[ntp.conf]: Scheduling refresh of Service[ntp] notice: /Stage[main]/Ntp/Service[ntp]: Triggered 'refresh' from 1 events notice: Finished catalog run in 1.13 seconds root@OAF-PRJ-SYSLOG:~# /etc/init.d/ntp status NTP server is running. root@OAF-PRJ-SYSLOG:~# cat /etc/ntp.conf serveur time.intrinsec.com driftfile /var/lib/ntp/ntp.drift
C’est gagné et en moins de 2 seccondes ! Je posterai sous peu plein de classes de base pour déployer des Apache, PHP5, MySQL (et MySQL Cluster), NTP, etc.
J’espère que vous voyez mieux le potentiel d’une telle solution ! Pour info, j’ai déployé via Puppet un LAMP configuré et optimisé en 34 secondes…
N’hésitez à poser des questions ou à commenter si vous rencontrer des problèmes
More From MadeInSyria
No related posts.
passionant c que tu viens de dire là … moi mon travail s’intitule “Administration centralisée et automatisée ” et comme application j’hésite entre puppet et cfengine mais je crois que je prefère puppet parce que j’ai pu implémenter son interface web(puppet-dashboard) mais je veux demander si tu peux m’aider à réaliser un déployement des configurations optimisées sur mes marionnettes(serveurs apache) comme tu l’a fais avec le ntp mais avec plus de details??parce que j’ai pas trop d’idées. Merci
Super ton HowTo !
Dommage que j’ai pas ca à faire ca m’aurait “boté” (oui jeux de mots) en tout cas trés bonnes explications comme toujours sur ton blog ! Continue comme ca ^^
Merci Juju ! Rien de t’empêche de le maquetter et de le tester en mode geek
[...] : les classes Puppet (le tuto puppet est déjà disponible : http://madeinsyria.fr/2011/06/howto-puppet-administration-et-industrialisation-de-masse/ [...]