Installation et premiers pas avec le gestionnaire de configurations Chef

Update de l'article du 19/04/11 : Nombreuses corrections, améliorations, ajouts... L'article n'a plus grand chose à voir avec l'original, c'est pourquoi la date de publication est actualisée.

Après avoir essayé Puppet, voyons maintenant une alternative, Chef. Chef est un gestionnaire de configurations. Tout comme Puppet, Chef va permettre d'établir des configurations de référence, que les clients appliqueront. Le modèle de fonctionnement est identique : un agent sur le poste client (chef-client) vérifie la configuration demandée par le serveur (chef-server), et applique les changements nécessaires pour matcher cette configuration. Ou pas, si le client est déjà bien configuré. Toujours comme Puppet, Chef est idempotent.

Un peu de vocabulaire culinaire


Les actions que Chef doit effectuer sont définies dans des recipes (recettes). Ces recipes sont écrites en Ruby (ça change des recettes de Grand-Mère). L'ensemble des recipes est contenu dans un cookbook. Les recettes peuvent être groupées dans des roles. Le client est appelé un node. Ainsi, lorsque l'on applique un role à un node, le node lira chaque recipe contenu dans ce role. Les recettes peuvent s'inclure dans d'autres recettes, afin de satisfaire des pré-requis. Exemple, une recette WordPress peut inclure une recette Apache.

Ah et quand on cuisine, forcément, on utilise un couteau. Ainsi, nous disposons d'un outil en ligne de commande pour interagir avec Chef : Knife.

Pour pouvoir travailler sur Chef, nous allons avoir besoin d'un Chef Repository dans lequel nous allons stocker des configurations, comme les cookbook. Les développeurs de Chef nous conseillent vivement d'utiliser un outil de versioning pour les dépôts. Ça ne peut effectivement pas faire de mal, et facilitera le travail à plusieurs. Nous pouvons résumer tout cela par un schéma (nous n'avons pas tout vu, pas de panique, c'est normal):

De quoi est composé Chef Server ?


Analysons un peu ce que nous allons installer. En effet, Chef est loin d'être monolithique, il est composé de nombreux processus.

API Service

C'est ce que le client va utiliser pour interagir avec le serveur pour gérer la configuration des nodes. Nous avons deux possibilités pour contacter cette API : utiliser Knife (client en ligne de commande), ou la Management Console (interface web)

Management Console

Une interface web qui permet de gérer simplement notre Chef Server, dont : les nodes, les roles, les cookbooks, les data bags, et l'API. Elle est accessible par navigateur web à l'adresse http://your-server-FQDN:4040

File Indexer

Apache SOLR, un moteur de recherche.

Data Store

CouchDB est utilisé pour stocker des données JSON des nodes, roles, et data bag. Il envoie ces données à SOLR, en passant par AMQP.

AMQP Server

Utilisé par CouchDB en tant que file, que SOLR videra.

En résumé, ça donne ça :

Une base de travail saine


Avant de nous jeter corps et âme dans l'installation de Chef, prenons le temps de réfléchir à la meilleure manière de l'utiliser.

Nous avons vu que nous écrirons nos cookbooks dans un dépôt Chef. Mais où est ce dépôt Chef ? En local sur le poste de travail de l'administrateur. Oui, sur Chef, on travaille 80% du temps en local, avant d'uploader nos configurations sur le serveur chef via des commandes. S'il n'y a qu'un seul admin, tout va bien. S'il y en a plusieurs, comment s'y retrouver ? Avec un outil de versioning. Git, parce que c'est le meilleur. Pour plus de clarté, un schéma, et les explications :



Notre administrateur travaille sur sa workstation. Il récupère la dernière version du dépôt Chef depuis le serveur Git. Il ajoute/modifie des cookbooks sur son dépôt local. Quand il a terminé, il commit et pousse les modifications vers le dépôt distant du serveur Git. Git a donc toujours la dernière version. De plus, les commit correctement commentés permettent d'avoir un suivi des modifications que chacun apporte. Dernière étape enfin, uploader son cookbook vers le serveur Chef.

À propos de Git : vous pouvez bien entendu choisir n'importe quel VCS. Je n'aborde pas dans cet article l'installation du serveur de versioning, seulement son utilisation conforme au schéma précédent. Ce sera peut être le cas dans un prochain billet.
Si vous n'êtes pas du tout familier avec Git, je vous recommande en préambule de lire ceci.

Installation de Chef Server

Note : Installation réalisée sur Debian Squeeze avec Chef 0.10.2

Nous allons maintenant configurer les dépôts d'Opscode, l'éditeur de Chef, puis l'installer.

# echo "deb deb http://apt.opscode.com/ squeeze-0.10 main" > /etc/apt/sources.list.d/opscode.list
# wget -qO - http://apt.opscode.com/packages@opscode.com.gpg.key | apt-key add -
# aptitude update
# aptitude install chef chef-server

Le script d'installation vous demandera d'entrer quelques informations.
chef-install3 chef-install2 chef-install1

Stop. Arrêtons-nous quelques instants pour étudier le contenu du dossier /etc/chef.

/etc/chef# tree
.
??? certificates
?   ??? cert.pem
?   ??? key.pem
??? client.rb
??? server.rb
??? solr-jetty
?   ??? jetty-web.xml
?   ??? jetty.xml
?   ??? start.config
?   ??? webdefault.xml
??? solr.rb
??? validation.pem
??? webui.pem
??? webui.rb

On trouve ici quelques fichiers intéressants, comme la clé de validation validation.pem ainsi que la clé de l'admin de l'interface web de Chef webui.pem, générées à l'installation. Ces clés vont nous servir dès l'étape suivante.

Configuration de Knife

Initialisation de Knife sur le serveur

Nous allons devoir effectuer la configuration initiale de knife sur le serveur. Ceci est à faire avec votre compte non-privilégié (rassurez moi, vous ne travaillez pas tout le temps en root !). Dans un premier temps, on crée un dossier personnel dans lequel on copie les clés de validation et web du serveur.

$ mkdir ~/.chef
$ su
# cp /etc/chef/validation.pem /etc/chef/webui.pem ~/.chef
# chown -R your-user-account .chef/

Puis on configure knife, le client en ligne de commande qui communiquera avec l'API Chef en REST.

# knife configure -i
No knife configuration file found
Where should I put the config file? [~/.chef/knife.rb]
Please enter the chef server URL: [http://localhost:4000]
Please enter a clientname for the new client: [myname]
Please enter the existing admin clientname: [chef-webui]
Please enter the location of the existing admin client's private key: [/etc/chef/webui.pem] ~/.chef/webui.pem
Please enter the validation clientname: [chef-validator]
Please enter the location of the validation key: [/etc/chef/validation.pem] ~/.chef/validation.pem
Please enter the path to a chef repository (or leave blank):
WARN: Creating initial API user...
INFO: Created (or updated) client[myname]
WARN: Configuration file written to /home/$USER/.chef/knife.rb

Un client Knife pour la workstation

Nous configurons à présent knife sur la machine de l'administrateur. Nous allons pour cela créer un nouveau compte sur le serveur Chef.

Attention : Le nom de ce compte doit être différent du compte ayant servi à initialiser Knife sur le serveur Chef, sous peine de provoquer une erreur.

chef-server$ knife client create my-username -n -a -f /tmp/my-username.pem
Created client[my-username]

Il faut ensuite copier la clé privé de l'utilisateur que nous avons exporté vers /tmp/my-username.pem sur la workstation.

workstation$ mkdir ~/.chef
workstation$ scp chef-server.com:/tmp/my-username.pem ~/.chef/my-username.pem

Puis on lance la configuration de Knife.

workstation$ knife configure
No knife configuration file found
Where should I put the config file? [~/.chef/knife.rb]
Please enter the chef server URL: [http://localhost:4000] http://chef-server.example.com:4000
Please enter an existing username or clientname for the API: [my-username] my-username
Please enter the validation clientname: [chef-validator]
Please enter the location of the validation key: [/etc/chef/validation.pem] ~/.chef/validation.pem
Please enter the path to a chef repository (or leave blank):
WARN: *****
WARN:
WARN: You must place your client key in:
WARN:   /home/$USER/.chef/my-username.pem
WARN: Before running commands with Knife!
WARN:
WARN: *****
WARN:
WARN: You must place your validation key in:
WARN:   /home/$USER/validation.pem
WARN: Before generating instance data with Knife!
WARN:
WARN: *****
WARN: Configuration file written to /home/$USER/.chef/knife.rb

Enfin, dans le fichier knife.rb qui vient d'être créé, nous spécifions le path des cookbooks (qui n'existent pas encore, c'est ce dont nous allons nous occuper juste après).

$ vim ~/.chef/knife.rb
...
cookbook_path   '/home/$USER/chef-repo/cookbooks/'
...

Création du dépôt Chef


C'est le moment de récupérer un dépôt Chef pour la workstation. Rappelez-vous du schéma de tout à l'heure : la workstation récupère le dépôt via le serveur Git. Il faut donc avoir préalablement téléchargé sur, le serveur Git, l'archive fournie par Opscode (http://github.com/opscode/chef-repo/tarball/master), l'avoir détarré, initialisé pour git et correctement configuré pour le serveur.

Une fois cela fait, on clone le dépôt sur notre workstation. Par exemple, depuis un serveur gitolite :

$ git clone ssh://user@chef-server-FQDN/chef-repo

Installation de Chef Client


Copiez le fichier validation.pem (normalement situé dans /etc/chef) du serveur vers le client (au même endroit). Copiez également le fichier client.rb du serveur vers le client. Il doit ressembler à ceci :

/etc/chef/client.rb

log_level          :info
log_location       STDOUT

ssl_verify_mode    :verify_none

chef_server_url "http://localhost:4000"

file_cache_path    "/var/cache/chef"
file_backup_path   "/var/lib/chef/backup"

pid_file           "/var/run/chef/client.pid"

cache_options({ :path => "/var/cache/chef/checksums", :skip_expires => true})

signing_ca_user "chef"

Mixlib::Log::Formatter.show_time = true

Puis lancez le script suivant depuis le client. Il automatise l'installation, la configuration sommaire et l'enregistrement du node. (Attention, ce script s'auto-détruit)

chef-server-setup.sh

#!/bin/bash
### VARIABLES
chef_server="your chef server FQDN"
chef_client=/usr/bin/chef-client
chef_client_config="/etc/chef/client.rb"

opscode_apt="deb http://apt.opscode.com/ squeeze-0.10 main"

### ACTIONS
aptitude update
aptitude install -y curl git-core

echo $opscode_apt > /etc/apt/sources.list.d/opscode.list
curl http://apt.opscode.com/packages@opscode.com.gpg.key | apt-key add -
aptitude update
aptitude install -y rubygems ohai chef libshadow-ruby1.8

### SETUP CHEF CLIENT AND REGISTER
sed -i "s/localhost/$chef_server/g" $chef_client_config
$chef_client

### REMOVE THYSELF
rm $0

Vous pouvez vérifier que votre client est bien pris en compte par Chef Server en vous connectant sur l'interface web (http://fqdn-de-chef-server:4040/nodes ou http://fqdn-de-chef-server:4040/status). Vous devirez retrouver votre client.

Création d'un cookbook


Nous allons créer un cookbook qui, ce sera notre exemple, gérera les paramètres DNS. Dans ce cookbook, nous créerons une recette resolvconf, qui gérera le fichier /etc/resolv.conf. Si l’intérêt de l'exemple est quasi-nul, vu que le contenu de resolv.conf est alimenté par DHCP, c'est qu'il s'agit justement d'un exemple. En utilisant Knife, créons donc un cookbook. C'est très simple :

$ knife cookbook create dns
** Creating cookbook dns
** Creating README for cookbook: dns
** Creating metadata for cookbook: dns

Cela vous crée une arborescence de la sorte :

~/chef-repo/cookbooks/dns$ tree
.
??? attributes
??? definitions
??? files
?   ??? default
??? libraries
??? metadata.rb
??? providers
??? README.rdoc
??? recipes
?   ??? default.rb
??? resources
??? templates
    ??? default

Nous allons définir des attributs. Ce sont des sortes de variables que nous pourrons utiliser dans nos recettes. À propos des attributs, il faut savoir que chef en génère un certain nombre automatiquement, grâce à ohai. Pour les visualiser : la commande ohai ou la page http://your-chef-server-FQDN/status. Voici donc nos attributs :

~/chef-repo/cookbooks/dns/attributes/default.rb

default[:dns][:server_1]        = "8.8.8.8"
default[:dns][:server_2]        = "8.8.4.4"

Maintenant, nous allons créer un template de notre fichier resolv.conf, dans lequel nous appellerons nos attributs. Les template sont écrits en ERB.

~/chef-repo/cookbooks/dns/templates/default/resolv.conf

nameserver <%= @node[:dns][:server_1] %>
nameserver <%= @node[:dns][:server_2] %>

Définissons à présent une recette.

~/chef-repo/cookbooks/dns/recipes/default.rb

#
# Cookbook Name:: dns
# Recipe:: default
#

template "/etc/resolv.conf" do
        source "resolv.conf"
        mode 0644
        owner "root"
        group "root"
        backup false
end

Enfin, mettons à jour le numéro de version du cookbook dans les métadonnées. Ce n'est pas anecdotique, puisqu'il est possible de gérer différentes versions d'un cookbook sur le serveur Chef.

$ vim ~/chef-repo/cookbooks/dns/metadata.rb
maintainer       "jeyg"
maintainer_email "jeyg@jeyg-pc.net"
license          "WTFPL"
description      "Configures dns entries"
long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
version          "1.0.0"

Création d'un role


Il nous reste à définir un role, qui recensera quelles recettes un node devra appliquer. Nous pouvons le faire de deux façons : soit par Knife, soit par l'interface web (la Management Console).

Méthode Knife :

$ knife role create test

Si votre variable d'environnement $EDITOR est renseignée, Knife ouvre votre éditeur de texte par défaut.

Vous pouvez compléter la description, ajouter des attributs ou remplir la run_list avec des recettes. Puis sauvegardez et quittez. Le role est créé.

Méthode Management Console :

  • Loggez-vous.
  • Cliquez sur l'onglet Roles
  • Cliquez sur Create
  • Remplissez les champs name et description, puis glissez-déposez (drag'n'drop) les recettes de Available Recipes à Run List.
  • En bas de page, cliquez sur Save Role

Git it


Nous avons fini de modifier nos fichiers, faisons un commit :

# cd ~/home/$USER/chef-repo
# git add .
# git commit -am "Ajout du premier cookbook : dns"

Puis synchronisons notre dépôt local avec le dépôt Git distant.

$ git push origin master

Application des configurations


Tout est prêt, il n'y a plus qu'à passer à l'action. On upload le cookbook sur le serveur Chef :

# knife cookbook upload dns

Assignons le role à un node. La aussi, ceci est faisable de deux manières.

Méthode Knife :

# knife node run_list add your-node "role[base]"

Méthode Management Console :

  • Loggez-vous.
  • Cliquez sur l'onglet Nodes
  • Cliquez sur Edit, à côté du node que vous voulez modifier
  • Glissez-déposez (drag'n'drop) le role de Available Roles à Run List.
  • En bas de page, cliquez sur Save Node

Et voilà, le node a son role assigné, il va pouvoir exécuter les recipes présentes dans celui-ci. Le démon chef-client présent sur le node se chargera de contacter le serveur toutes les 30 minutes par défaut. Vous pouvez forcer cela depuis le client avec la commande suivante (avec l'option debug, parce que la première fois ça ne fait jamais de mal) :

# chef-client -l debug

Vous pouvez aussi modifier l'intervalle de vérification du démon. Pour cela, direction le fichier /etc/default/chef-client, qui contient des variables qui seront lues par le script init de chef-client :

/etc/default/chef-client

# vim /etc/default/chef-client
...
LOGFILE=/var/log/chef/client.log
CONFIG=/etc/chef/client.rb
INTERVAL=900
...

Ici, l'intervalle sera de 15 minutes. Aucune autre modification n'est nécessaire, la variable est déjà gérée dans le script init.

Pour appliquer les changements, on redémarre le démon.

# /etc/init.d/chef-client restart

Les environnements


Une nouveauté de Chef 0.10.2 : l'apparition des environnements. Cela va nous permettre de bien séparer les envrionnements de production et de test.

On assigne un environnement à un node ou un role. Nous pourrons par exemple ainsi avoir une run_list distincte pour chaque environnement, ou des versions de cookbooks différentes.

Créer un environnement

Avec Knife :

$ knife create environment testing

Avec la Management Console :

  • Cliquez sur l'onglet Environments
  • Cliquez sur Create
  • Complétez les champs name et description
  • Vous pouvez définir des contraintes de version pour les cookbooks
  • En bas de page, cliquez sur Save Environment



Changer l'environnement d'un node


Par défaut, un node est assigné à l'environnement _default. Voici donc comment changer son environnement.

Avec Knife :

$ knife node edit NODE_NAME

puis modifier la ligne

"chef_environment":

Avec la Management Console :

  • Cliquez sur l'onglet Node
  • Cliquez sur le Edit du node cible
  • Sélectionnez l'environnement dans la liste déroulante
  • Cliquez sur Save Node en base de page



Conclusion


Vous voilà désormais prêt à profiter de toute la puissance de Chef ! Si ce billet peut paraître effrayant à première vue, il faut garder en tête qu'il s'agit ici des tâches les plus pénibles : appréhender un nouvel outil au fonctionnement assez particulier, l'installer et le configurer. Maintenant que tout cela est fait, place au plus intéressant : l'écriture des cookbooks.

Chef est un outil extrêmement puissant. Mais il est à mon sens capital de prendre le temps de lire beaucoup de documentation et de s'entrainer un bon moment dans un environnement de test.

Pour la doc, en plus des indispensables man et --help, je vous recommande l'excellent wiki d'Opscode, l'entreprise derrière Chef. Il est difficile de s'y retrouver au début, mais au fil du temps vous ne pourrez plus vous en passer. Vous verrez qu'il y a beaucoup de fonctionnalités qui n'ont pas été abordées dans cet article (Il y en a tellement, il est impossible de tout aborder !).

Enfin, dernière chose à savoir : pour ne pas avoir à réinventer la roue à chaque fois, il est possible de partager des cookbooks. Vous trouverez donc des cookbooks déjà écrits susceptibles de vous intéresser ici : http://community.opscode.com/cookbooks

Assez parlé, à vos fourneaux !


Sources :

Vus : 2630
Publié par Jeyg : 33