Bcfg2 : la gestion de conf du bout des doigts
Il n'y a pas si longtemps que ça, je vous avais parlé d'un gestionnaire de conf, Puppet, qui s'appuyait sur son propre langage descriptif et jouait avec du Ruby.
Après quelques essais ma foi assez pertinents, je me suis aperçue que Puppet était somme toute un peu lent : pour 3 packages (certes, il y avait du java dans le tas) et 2 conf, plus de 20 minutes étaient nécessaires pour mettre à niveau les nodes.
Un autre fâcheux défaut est que, par défaut, il agrège toutes les instructions dans un même espace, sans tenir compte de la séquence selon laquelle ils sont définis.
Pour le coup, les résultats sont pour le moins inattendus, surtout si on est dans un cas de figure où l'on doit passer une instruction (exemple : définition des dépôts officiels) avant une autre (installation de package).
Au final, l'organisation des manifests finit, par défaut en un gigantesque mashup d'instructions. Pas trop sympa quand, naif, on n'y a pas pensé et passé des heures à tout bien organiser. Le seul moyen d'échapper à ce mécanisme est de passer par de lourdes définitions de dépendances.
Il était temps de faire jouer AlternativeTo... Et de tomber sur bcfg2, un gestionnaire de conf s'appuyant sur du python ! Retour sur une conf aux petits oignons !
Principes de fonctionnement
Dans l'absolu, le fonctionnement de bcfg2 est assez similaire à celui de Puppet : on a un agent qui interroge le serveur, et exécute -ou pas- les modifications. Après, étant un peu flemmarde et n'étant pas trop pour la copie illégitime de contenu, je vous renvoie sur le fonctionnement détaillé au poil du projet !Un peu de technique
Installation
Comme d'habitude, on partira des sources : fraîches, dispo, et surtout dernière version :)$ cd /usr/local/src $ wget ftp://ftp.mcs.anl.gov/pub/bcfg/bcfg2-1.1.2.tar.gz $ tar zxvf bcfg2-1.1.2.tar.gz $ python setup.py build $ python setup.py install
$ bcfg2-admin init Store bcfg2 configuration in [/etc/bcfg2.conf]: Location of bcfg2 repository [/var/lib/bcfg2]: Input password used for communication verification (without echoing; leave blank for a random): What is the server's hostname [bcfg2-server]: Input the server location [https://bcfg2-server:6789]: Input base Operating System for clients: 1: Redhat/Fedora/RHEL/RHAS/Centos 2: SUSE/SLES 3: Mandrake 4: Debian 5: Ubuntu 6: Gentoo 7: FreeBSD : 5 Generating a 2048 bit RSA private key .......+++ ........+++ writing new private key to '/etc/bcfg2.key' ----- Signature ok subject=/C=US/ST=Illinois/L=Argonne/CN=bcfg2-server.k-tux.com Getting Private key Repository created successfuly in /var/lib/bcfg2Bon, certificat un peu faussé parce que K-Tux, dans l'Illinois, c'est un peu tiré par les cheveux, mais bon, en s'en contentera :)
Configuration du service
La configuration du serveur en lui-même (je veux dire par là, le paramétrage du service, hein, pas celui concernant les nodes qui vont le solliciter) se situe tout simplement sous /etc et se compose de 3 éléments : la conf, la clé et le certificat en lui-même.bcfg2-server $ ls /etc/bc* bcfg2.conf bcfg2.crt bcfg2.keyUn petit start du service pour se rendre compte du truc :
bcfg2-server $ bcfg2-server start Handled 14 events in 0.017s service available at https://bcfg2-server.k-tux.com:6789 serving bcfg2-server at https://bcfg2-server.k-tux.com:6789 serve_forever() [start]...Qui reste en foreground, mais c'est pas plus mal pour voir ce qui se passe ! La première conf est celle du Hello World : tester le service en local. Notre serveur sera donc, pour cette fois-ci du moins, également notre node. On lance donc la partie cliente, avec les options qui vont bien : -q (query) -v (verbose) -n (dry-run mode)
bcfg2-server $ bcfg2 -q -v -n Loaded tool drivers: Action Chkconfig POSIX RPMng Phase: initial Correct entries: 0 Incorrect entries: 0 Total managed entries: 0 Unmanaged entries: 2754 Phase: final Correct entries: 0 Incorrect entries: 0 Total managed entries: 0 Unmanaged entries: 2754C'est un peu violent de se prendre 2754 Unmanaged entries dans la tronche, mais pas d'erreur, le serveur nous renvoie tout simplement un :
Generated config for bcfg2-server.k-tux.com in 0.001s Client bcfg2-server.k-tux.com reported state cleanEn clair, il nous reste 2754 packages à configurer.
Configuration du client en local
Il faut savoir, et c'est intéressant car c'est là que vous allez bosser, que la configuration des paramétrages pour les nodes tapant sur votre bcfg2-server se situe par défaut sous /var/lib/bcfg2. Là-dedans, vous avez tout une arborescence qui a été mise en place lors de l'installation :bcfg2-server $ ls -lsaR /var/lib/bcfg2 /var/lib/bcfg2: total 40 4 drwxr-xr-x 10 root root 4096 2011-07-06 16:14 . 4 drwxr-xr-x 48 root root 4096 2011-07-06 16:14 .. 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 Base 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 Bundler 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 Cfg 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 etc 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 Metadata 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 Pkgmgr 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 Rules 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 SSHbase /var/lib/bcfg2/Base: total 8 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 . 4 drwxr-xr-x 10 root root 4096 2011-07-06 16:14 .. /var/lib/bcfg2/Bundler: total 8 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 . 4 drwxr-xr-x 10 root root 4096 2011-07-06 16:14 .. /var/lib/bcfg2/Cfg: total 8 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 . 4 drwxr-xr-x 10 root root 4096 2011-07-06 16:14 .. /var/lib/bcfg2/etc: total 8 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 . 4 drwxr-xr-x 10 root root 4096 2011-07-06 16:14 .. /var/lib/bcfg2/Metadata: total 16 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 . 4 drwxr-xr-x 10 root root 4096 2011-07-06 16:14 .. 4 -rw-r--r-- 1 root root 111 2011-07-06 16:14 clients.xml 4 -rw-r--r-- 1 root root 354 2011-07-06 16:14 groups.xml /var/lib/bcfg2/Pkgmgr: total 8 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 . 4 drwxr-xr-x 10 root root 4096 2011-07-06 16:14 .. /var/lib/bcfg2/Rules: total 8 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 . 4 drwxr-xr-x 10 root root 4096 2011-07-06 16:14 .. /var/lib/bcfg2/SSHbase: total 8 4 drwxr-xr-x 2 root root 4096 2011-07-06 16:14 . 4 drwxr-xr-x 10 root root 4096 2011-07-06 16:14 ..Et par défaut, et bien vous avez vraiment peu de choses :) En fait, seuls /var/lib/bcfg2/Metadata/clients.xml et groups.xml sont définis. Soit dit en passant, ce sont ces fichiers qui vont permettre d'associer un profil à un node, le profil pouvant ensuite se moduler à l'infini, par le biais de Bundle et d'autres subtilités. Jetons-y un oeil, pour le coup :
bcfg2-server $ cat /var/lib/bcfg2/Metadata/clients.xml <Clients version="3.0"> <Client profile="basic" pingable="Y" pingtime="0" name="bcfg2-server.k-tux.com"/> </Clients>Ici, notre client (qui est aussi le serveur) est associé au profil par défaut; "basic". pinguable et pingtime parlent d'eux même. Pour ce qui est de groups.xml, c'est la même trame : une série de <Group> sont définis, par défaut vides et fonction de la distribution du client.
bcfg2-server $ cat /var/lib/bcfg2/Metadata/groups.xml <Groups version='3.0'> <Group profile='true' public='true' default='true' name='basic'> <Group name='ubuntu'/> </Group> <Group name='ubuntu'/> <Group name='debian'/> <Group name='freebsd'/> <Group name='gentoo'/> <Group name='redhat'/> <Group name='suse'/> <Group name='mandrake'/> <Group name='solaris'/> </Groups>
A noter que 2 types de groupes existent : les publics, qui sont en fait les entrées par lesquelles les clients accèdent à leur catalogue, et les autres, qui ne sont pas directement visibles par les clients mais servent à mieux organiser les catégories.
Jouer avec les conf
Le premier jeu va consister à mettre à jour une conf sur un client.Les conf, les fichiers texte e, général sont toujours stockés dans /var/lib/bcfg2/Cfg. Pour jouer donc, tapons et modifions d'abord nos jolis xml :bcfg2-server:/var/lib/bcfg2 $ cat Metadata/groups.xml <Groups version='3.0'> <Group profile='true' public='true' default='true' name='basic'> <Group name='ubuntu'/> </Group> <Group name='debian'/> <Group name='ubuntu'> <Bundle name='release'/> </Group> </Groups> /var/lib/bcfg2 $ cat Bundler/release.xml <Bundle name='release' version='2.0'> <Path name="/etc/ubuntu-release"/> </Bundle>Bien sûr, il faut tout de même mettre la conf dans un endroit précis, distinct du système (que se passerait-il si ce ne sont pas les mêmes OS ?). Pour cela, il suffit de créer un dir portant le path et le nom de la conf sous /var/lib/bcfg2/Cfg/. Par exemple, ici, on va :
bcfg2-server $ mkdir -p /var/lib/bcfg2/Cfg/etc/ubuntu-release/ bcfg2-server $ cp /etc/ubuntu-release /var/lib/bcfg2/Cfg/etc/ubuntu-release/Enfantin, n'est-ce pas ? Le plus embêtant, c'est que j'ai dû redémarrer le service pour qu'il prenne en compte les changements.
bcfg2-server $ bcfg2-server start service available at https://bcfg2.k-tux.com:6789 serving bcfg2-server at https://bcfg2.k-tux.com:6789 serve_forever() [start] Handled 30 events in 0.020sLançons le client,qui dispose de son ubuntu-release correctement paramétré :
bcfg2-server $ bcfg2 -q -v -n Loaded tool drivers: Action Chkconfig POSIX RPMng Phase: initial Correct entries: 1 Incorrect entries: 0 Total managed entries: 1 Unmanaged entries: 2754 Phase: final Correct entries: 1 Incorrect entries: 0 Total managed entries: 1 Unmanaged entries: 2754Et cette fois, qui a volontairement le ubuntu-release tronqué :
bcfg2-server $ bcfg2 -q -v -n Loaded tool drivers: Action Chkconfig POSIX RPMng Phase: initial Correct entries: 0 Incorrect entries: 1 Total managed entries: 1 Unmanaged entries: 2759Le dry-run mode ne faisant rien de spécial sur le système, il se contente de nous broncher une Incorrect entry. Virons le dry-run et voyons si la conf redescend bien comme il faut !
bcfg2-server $ bcfg2 -q -v Loaded tool drivers: Action Chkconfig POSIX RPMng Phase: initial Correct entries: 0 Incorrect entries: 1 Total managed entries: 1 Unmanaged entries: 2759 Installing ConfigFile /etc/ubuntu-release The Following Bundles have been modified: release Phase: final Correct entries: 1 Incorrect entries: 0 Total managed entries: 1 Unmanaged entries: 2759Clair, net, concis : notre conf est bien redescendue ! C'est bien joli tout ça, mais tant qu'à y être, autant voir les choses en grand :) Passons donc en multi clients !
Client - Serveur distincts
Notre client, lui, n'est plus sous ubuntu comme le serveur mais sur une autre machine , en Debian 6.0.1. En réalité, que se passe-t-il qui est différent de notre mode client=serveur ? Et bien, rien de spécial, si ce n'est qu'on a rajouté une entrée dans le clients.xml.bcfg2-server $ /var/lib/bcfg2 $ cat Metadata/clients.xml <Clients version="3.0"> <Client profile="basic" pingable="Y" pingtime="0" name="bcgf2-server.k-tux.com"/> <Client profile="deb" pingable="Y" pingtime="0" name="bcfg2cli-deb.k-tux.com"/> </Clients>Notre groups.xml est aussi enrichi, puisque l'OS est différent et qu'il existe pile poil la bonne catégorie pour ce type de machine : bcfg2-server<Groups version='3.0'> <Group profile='true' public='true' default='true' name='basic'> <Group name='ubuntu'/> </Group> <Group profile='true' public='true' default='true' name='deb'> <Group name='debian'/> </Group> <Group name='ubuntu'> <Bundle name='release'/> </Group> <Group name='debian'/> </Groups> Au niveau du client, c'est un peu plus palpable :
bcfg2cli-deb $ apt-get update && apt-get upgrade bcfg2cli-deb $ apt-get install bcfg2 Creating config file /etc/bcfg2.conf with new versionForcément, la conf par défaut n'est pas valide, puisque pour fonctionner doit d'ailleurs directement taper sur le serveur (logique). Avant, on avait donc ça :
bcfg2cli-deb $ cat /etc/bcfg2.conf [communication] protocol = xmlrpc/ssl password = foobat # certificate = /etc/bcfg2.key # key = /etc/bcfg2.key [components] bcfg2 = https://localhost:6789Et après modification du general password et du serveur sur lequel taper :
bcfg2cli-deb $ cat /etc/bcfg2.conf [communication] protocol = xmlrpc/ssl password = sF9Xlpuv # certificate = /etc/bcfg2.key # key = /etc/bcfg2.key [components] bcfg2 = https://bcfg2-server.k-tux.com:6789On lance le client :
bcfg2cli-deb $ bcfg2 -qvn No ca is specified. Cannot authenticate the server with SSL. No ca is specified. Cannot authenticate the server with SSL. Loaded tool drivers: APT Action DebInit POSIX Phase: initial Correct entries: 0 Incorrect entries: 0 Total managed entries: 0 Unmanaged entries: 365 Phase: final Correct entries: 0 Incorrect entries: 0 Total managed entries: 0 Unmanaged entries: 365 No ca is specified. Cannot authenticate the server with SSL.Au niveau du serveur, il existe des outils permettant de bien visualiser ce que l'on a, sans forcément rentrer dans le xml. Un peu comme... bcfg2-info :
bcfg2-server $ bcfg2-info "clients" Handled 31 events in 0.012s cli Client | Profile ============================ bcfg2cli-deb | deb bcfg2-server | basic
Installer des packages via bcfg2
Forcément, la conf ne fait pas tout, et on aimerait -moi en tout cas- pouvoir monter un noeud qui aurait été victime d'une installation très basique pour en faire un noeud fonctionnel, prêt à brasser du code. Contrairement à son petit nom qui sonne un peu restrictif somme toute, bcfg2 peut, comme Puppet, prendre en charge cette opération, aussi facilement que pour la partie configuration. Attaquons de suite par un exemple on ne peut plus simple ! Je rappelle que le noeud en question rentre dans le profil deb qui fait appel au group debian. Pour pouvoir accéder à la fonctionnalité installation / gestion des packages, il faut retoucher la conf de bcfg2 et rajouter le plugin Packages au bon endroit. Votre conf deviendra donc :bcfg2-server $ cat /etc/bcfg2.conf [server] repository = /var/lib/bcfg2 plugins = Base,Bundler,Cfg,Metadata,Pkgmgr,Packages,Rules,SSHbase [statistics] sendmailpath = /usr/lib/sendmail database_engine = sqlite3 # 'postgresql', 'mysql', 'mysql_old', 'sqlite3' or 'ado_mssql'. database_name = # Or path to database file if using sqlite3. #<repository>/etc/brpt.sqlite is default path if left empty database_user = # Not used with sqlite3. database_password = # Not used with sqlite3. database_host = # Not used with sqlite3. database_port = # Set to empty string for default. Not used with sqlite3. web_debug = True [communication] protocol = xmlrpc/ssl password = sF9Xlpuv certificate = /etc/bcfg2.crt key = /etc/bcfg2.key ca = /etc/bcfg2.crt [components] bcfg2 = https://bcfg2-server.k-tux.com:6789Il faut également créer le répertoire et la configuration qu'il contiendra et qui permettra d'indiquer les dépôts sur lesquels chercher les packages. Dans ma config.xml, comme c'est une Debian Squeeze à qui je m'adresse, les dépôts sont spécifiques. Donc à modifier pour aligner sur vos noeuds.
bcfg2-server:/var/lib/bcfg2 $ mkdir /var/lib/bcfg2/Packages bcfg2-server:/var/lib/bcfg2 $ vim Packages/config.xml <Sources> <APTSource> <Group>debian-squeeze</Group> <URL>http://ftp.de.debian.org/debian/</URL> <Version>squeeze</Version> <Component>main</Component> <Component>multiverse</Component> <Component>restricted</Component> <Component>universe</Component> <Arch>amd64</Arch> </APTSource> </Sources>A présent, il faut indiquer quels packages, et pour qui.
bcfg2-server $ cat /var/lib/bcfg2/Metadata/groups.xml <Groups version='3.0'> <Group profile='true' public='true' default='true' name='basic'> <Group name='ubuntu'/> </Group> <Group profile='true' public='true' default='true' name='deb'> <Group name='debian'/> </Group> <Group name='debian'> <Bundle name='python'/> </Group> <Group name='ubuntu'> <Bundle name='release'/> </Group> </Groups>Voila pour qui. Maintenant, le quoi en question. Pour les packages, on utilise ce que bcfg2 appelle des Bundles, qui permettent de grouper plusieurs définitions pour actions. Le tout étant, bien entendu, stocké à sa place dans /var/lib/bcfg2/Bundler/. Nous avons indiqué un Bundle nommé python, nous allons le mettre en forme :
bcfg2-server $ cat /var/lib/bcfg2/Bundler/python.xml <Bundle name="python" version="2.0"> <Package name="python-openssl"/> <Package name="python-pytools"/> <Package name="python-setuptools"/> </Bundle>Le restart du service n'est pas très rassurant :
bcfg2-server:/var/lib/bcfg2 $ bcfg2-server start Failed to read file /var/lib/bcfg2/Packages/cache/http:@@ftp.de.debian.org@debian@dists@squeeze@multiverse@binary-amd64@Packages.gz Packages: File read failed; falling back to file download Packages: Updating http://ftp.de.debian.org/debian/dists/squeeze/main/binary-amd64/Packages.gz Packages: Updating http://ftp.de.debian.org/debian/dists/squeeze/multiverse/binary-amd64/Packages.gz Packages: Failed to fetch url http://ftp.de.debian.org/debian/dists/squeeze/multiverse/binary-amd64/Packages.gz. code=404 Packages: Updating http://ftp.de.debian.org/debian/dists/squeeze/restricted/binary-amd64/Packages.gz Packages: Failed to fetch url http://ftp.de.debian.org/debian/dists/squeeze/restricted/binary-amd64/Packages.gz. code=404 Packages: Updating http://ftp.de.debian.org/debian/dists/squeeze/universe/binary-amd64/Packages.gz Packages: Failed to fetch url http://ftp.de.debian.org/debian/dists/squeeze/universe/binary-amd64/Packages.gz. code=404 Failed to read file /var/lib/bcfg2/Packages/cache/http:@@ftp.de.debian.org@debian@dists@squeeze@multiverse@binary-amd64@Packages.gz Failed to update source Traceback (most recent call last): File "/usr/lib/python2.6/site-packages/Bcfg2/Server/Plugins/Packages.py", line 120, in setup_data self.read_files() File "/usr/lib/python2.6/site-packages/Bcfg2/Server/Plugins/Packages.py", line 406, in read_files raise File "/usr/lib/python2.6/site-packages/Bcfg2/Server/Plugins/Packages.py", line 403, in read_files reader = gzip.GzipFile(fname) File "/usr/lib/python2.6/gzip.py", line 79, in __init__ fileobj = self.myfileobj = __builtin__.open(filename, mode or 'rb') IOError: [Errno 2] No such file or directory: '/var/lib/bcfg2/Packages/cache/http:@@ftp.de.debian.org@debian@dists@squeeze@multiverse@binary-amd64@Packages.gz' The following plugins conflict with Packages;Unloading ['Pkgmgr'] Loading experimental plugin(s): Packages NOTE: Interfaces subject to change Handled 32 events in 0.012s service available at https://bcfg2-server.k-tux.com:6789 serving bcfg2-server at https://bcfg2-server.k-tux.com:6789 serve_forever() [start]Par contre, le service est opérationel ! Le client en dry-run, nous renvoie :
bcfg2cli-deb $ bcfg2 -qvn No ca is specified. Cannot authenticate the server with SSL. No ca is specified. Cannot authenticate the server with SSL. Loaded tool drivers: APT Action DebInit POSIX Package python-openssl not installed Package python-pytools not installed Package python-setuptools not installed Phase: initial Correct entries: 0 Incorrect entries: 3 Total managed entries: 3 Unmanaged entries: 364 In dryrun mode: suppressing entry installation for: Package:python-openssl Package:python-pytools Package:python-setuptools Phase: final Correct entries: 0 Incorrect entries: 3 Package:python-openssl Package:python-pytools Package:python-setuptools Total managed entries: 3 Unmanaged entries: 364 No ca is specified. Cannot authenticate the server with SSL.Et en mode non dry-run, on a effectivement les installations qui se déroulent comme prévu :
bcfg2cli-deb $ bcfg2 -qv No ca is specified. Cannot authenticate the server with SSL. No ca is specified. Cannot authenticate the server with SSL. Loaded tool drivers: APT Action DebInit POSIX Package python-openssl not installed Package python-pytools not installed Package python-setuptools not installed Phase: initial Correct entries: 0 Incorrect entries: 3 Total managed entries: 3 Unmanaged entries: 364 The Following Bundles have been modified: python Phase: final Correct entries: 3 Incorrect entries: 0 Total managed entries: 3 Unmanaged entries: 364 No ca is specified. Cannot authenticate the server with SSL. bcfg2cli-deb $ dpkg -s python-openssl Package: python-openssl Status: install ok installed [...]Et voilà ! Il ne reste plus qu'à gérer les 364 entrées restantes, plus celles que vous allez rajouter pour enrichir vos nodes :) Pour ma part, je dois encore paufiner la conf sur la partie authentification par certificat SSL et tant qu'à faire résoudre le pourquoi-qu'il-me-crache-des-erreurs-python-au-start. Mais tout ceci est une autre histoire ! Ah ! Et à toujours garder en tête : garder la conf par défaut est trèèèèèèèèèèèès dangereux (je pense au port 6789 en question) !!! Enjoy !!!