Utilité de cfengine

La problématique sur des architectures dont le nombre de serveurs croît, est que cela ralentit notablement les taches d'administration:

  1. Tests: les phases de test comprennent des journées d'installation/désinstallation, qui, si rien n'est automatisé, peuvent engendrer des erreurs ou des retards.
  2. Installation: les mises en production deviennent des successions de taches répétitives, occasionnant des fautes de frappe, pouvant aller jusqu'à la coupure de service.
  3. Maintenance: lors d'une intervention d'urgence, vérifier l'état de 16 serveurs devient très fastidieux et fait perdre beaucoup de temps à l'ingénieur d'astreinte.

L'intéret de cfengine est de centraliser les efforts de configuration et de maintenance des packages, d'automatiser la distribution de ces fichiers sur toute la plate-forme, enfin de vérifier quotidiennement ou ponctuellement que la plate-forme est dans un état nominal.

Philosophie

Description d' « état parfait » de serveurs

Cfagent comprend la syntaxe de cfagent.conf, son fichier de configuration principal. Dans cfagent.conf, l'intégrateur aura accès à un système de variables, de classes et d'actions qui lui permettront de définir quel est l'état parfait d'un serveur. Ensuite, selon la volonté de l'intégrateur, cfagent:

  1. l'avertira d'un écart de cet état: très pratique lors d'une opération de maintenance
  2. ou bien fera en sorte que le serveur converge vers cet état: idéal pour les mises en production ou les phases de test. Soit cfengine sait le faire tout seul, comme vérifier la version d'un package Solaris, soit l'administrateur pourra lui expliquer comment faire.

L'effet Skynet

Il faut toujours garder en tête qu'un serveur cfengine est capable de modifier n'importe quel fichier dans une multitude de serveurs. Autant dire qu'un bon serveur cfengine a la main sur toute une plateforme (d'où un raccourci vers Skynet, le célèbre logiciel qui prit en main le système de défense Américain avant d'envoyer des bombes nucléaires vers les russes). Cela a deux conséquences importantes:

  1. Tous les administrateurs de cette plateforme, des intégrateurs aux ingénieurs chargés de la maintenance, doivent être au courant de ce que fait cfengine sur la plateforme, et doivent savoir l'utiliser (pas forcément administrer cfengine, mais comprendre le repository utilisé).
  2. Une erreur de manipulation sur un quelconque fichier de configuration dans le repository peut entraîner une perte de service, du fait que cette erreur sera reproduite sur tous les serveurs administrés.

Les binaires importants de cfengine

cfagent

Sera lancé sur les serveurs de production. C'est lui qui, d'après un fichier de configuration descriptif, fera en sorte que le serveur tende vers un état parfait.

cfservd

Cfservd a pour principal but de recevoir des requetes venant de cfagent, et de lui répondre si cfagent en a le droit. Il est possible de crypter cette partie de la communication. Les requetes usuelles sont:

  1. Demande de signature MD5 d'un fichier particulier dans le repository
  2. Demande d'envoi d'un fichier

cfrun

Cfrun peut aussi envoyer des requetes vers cfservd, mais cette fois-ci uniquement pour demander à ce que cfagent soit lancé sur la machine sur laquelle tourne cfservd. Cela permettra donc de lancer en une ligne de commande cfagent sur plusieurs serveurs distants (sur lesquels cfservd doit tourner)

Configuration de cfagent

La configuration de cfagent représente 95 % du travail du Cf-ingénieur.

Les fichiers de configuration de cfagent

update.conf

Update.conf est le premier fichier de configuration lu par cfagent. Il définit la manière dont cfagent doit récupérer son fichier de configuration principal, cfagent.conf. C'est le seul fichier qui ne puisse ou ne doive pas etre transmis automatiquement entre cfagent et cfservd. Cela garanti que cfagent pourra toujours communiquer avec cfservd.

cfagent.conf

C'est le fichier dans lequel l'administrateur peut décrire l'état parfait d'une machine. Il doit toujours commencer par l'action « control ». Il peut inclure d'autres fichiers de configuration grace à l'action « import ». Les fichiers de configuration importés pourront contenir les memes actions, leur contenu sera alors concaténé avec celui de cfagent.conf.

Syntaxe usuelle

Commençons tout de suite avec un exemple:

copy:
	solaris::
		/etc/inet/hosts	dest=/var/backup/hosts

« copy: » est une action. Comme son nom l'indique, elle demande à cfengine de copier des fichiers. « solaris » est une classe. Elle définit une condition d'action. Les “::” après “solaris” veulent dire “SI la classe est définie, ALORS …” . « /etc/inet/hosts » est le fichier source de copie et /var/backup/hosts est le fichier destination. On dit que « dest= » est un mot clé de « copy ». Donc dans ce cas précis, si la classe « solaris » est définie, cfagent copiera /etc/inet/hosts dans /var/backup.

Actions

Il existe un grand nombre d'actions disponibles pour cfagent. Les plus utilisées sont les suivantes:

  1. control: obligatoire, on y définit les variables internes et les variables utilisateur. Voir ici pour les différentes variables internes que vous pourrez configurer.
  2. copy: permet de copier des fichiers localement ou bien d'un serveur repository, mais pas vers un repository.
  3. links: vérification des liens, symboliques ou non
  4. directories: vérification des répertoires
  5. shellcommands: définition de commandes shell à exécuter
  6. editfiles: édition de fichiers grace à un langage évolué
  7. packages: gestion des packages
  8. import: permet d'inclure des fichiers de configuration secondaires

La grande liste d'actions disponibles permet de configurer l'ensemble du système.

La variable actionsequence

La variable spéciale « actionsequence » définit quelles actions seront lancées et dans quel ordre. Par exemple:

control:
	actionsequence = ( links shellcommands copy )

Ici, seules les actions « links », « shellcommands », puis « copy » seront interprétées par cfagent. Si plus tard dans la configuration vous avez définit une autre action, « directories » par exemple, elle ne sera pas prise en compte.

NOTE: Les actions « control » et « alerts » sont automatiquement ajoutées à l'actionsequence par cfagent.

Variables

Utilisation

On peut accéder au contenu d'une variable n'importe où dans la configuration. La manière de le faire est la suivante:

${nom_de_variable}

Vous pouvez aussi ne pas utiliser les accolades, mais je vous le déconseille, car elles seraient mal interprétées lors des appels de vos commandes shell.

Initialisation

Il existe deux types de variable:

  1. les variables définies par cfagent à son lancement, comme « host », « ipaddress » ou « arch ».
  2. les variables définies par l'administrateur dans l'action « control ».

On définit une variable de la façon suivante:

control:
	site = ( production )

ATTENTION respectez scrupuleusement les espaces avant et après les parenthèses !
On peut utiliser des fonctions cfengine pour initialiser les variables. Voir Setting-variables-with-functions pour la liste complète des fonctions utilisables.

Utilisation de ExecShellResult

ExecShellResult est la fonction la plus utilisée, et elle comporte quelques pièges.

  1. La première commande lancée doit être un chemin complet
  2. Les quotes et double quotes sont automatiquement enlevés (en tout cas pour la v. 2.1.19). Il faut utiliser les variables spéciales ${dblquote} et ${quote}.

Exemple d'utilisation de ““ExecShellResult””:

control:
	admin_ip = ( ExecShellResult(/usr/bin/grep -- -adm /etc/hosts | awk ${quote}{print $1}${quote}) )
	

Classes

Les classes sont des conditions. Leur définition permet de controler ce qui sera fait par la suite. On peut définir une classe de différente manière:

  1. cfagent créé ses propres classes à son lancement selon les informations qu'il sait tirer dun système. Elles sont appellées « hard-class ». Un exemple:
prompt> /opt/cfengine/bin/cfagent -p -v | grep Defined
Defined Classes = ( 192_168_180 192_168_180_14 192_168_180_5 32_bit August Day24 Hr17 Hr17_Q1 Min05 Min05_10 Q1 SUNW_UltraAX_i2 
Wednesday Yr2005 any cfengine_2 cfengine_2_1 cfengine_2_1_14 compiled_on_solaris2_8 ipv4_192 ipv4_192_168 ipv4_192_168_180 
ipv4_192_168_180_14 ipv4_192_168_180_5 loghost mom monitor net_iface_eri1 net_iface_eri1_1 net_iface_lo0 solaris sparc 
sun4u sunos_5_8 sunos_sun4u sunos_sun4u_5_8 sunos_sun4u_5_8_Generic_117000_03 )
  1. L'administrateur définit une classe dans l'action « groups », selon le résultat de fonctions internes. Par exemple:
 
groups:
	radius = ( Strcmp(${hostgroup},"radius") )

Ici, la classe « radius » sera définie si la variable ${hostgroup} est égale à « radius ». Comme avec les variables, il existe des fonctions cfengine qui permettent de définir les classes. La liste complète de ces fonctions.

  1. L'administrateur définit une classe grace aux options « define » et « elsedefine », présentes dans la plupart des actions. Par exemple:
packages:
	SUNWradius version=4.0.4
	define=hasRadius
	elsedefine=needRadius

Dans cet exemple, si le package SUNWradius n'est pas installé ou n'a pas la version 4.0.4, la classe « needRadius » est définie. Si le package est bien installé et a la bonne version, la classe « hasRadius » est définie. Une fois cette étape passée, on pourra par exemple lancer dans la partie “shellcommands” l'installation/l'upgrade du package si needRadius est définie. Le nom d'une classe ne peut contenir ni des points (“.”) ni des tirets (“-”), qui sont remplacés par des underscores (« _ »). Les classes « utilisateur » doivent etre préalablement déclarées dans la variable spéciale « ““AddInstallable”” »:

control:
	AddInstallable = ( hasRadius needRadius )
unix/presentation_cfengine.txt · Last modified: 2010/01/12 13:29 (external edit)