Cuisinez vos serveurs comme un Chef – Définitions, Ressources, Noeuds et Rôles – Troisième partie

Notre dernier article a permis l’installation et la configuration de PHP via Chef, mais il en faut bien plus pour permettre d’avoir un site complet, au minima un serveur Web et une base de données.

Section intitulée le-serveur-webLe serveur Web

Concernant le serveur Web, nous allons installer et configurer Apache. Pour cela, nous allons donc créer une recette dans le fichier cookbooks/php/recipes/apache.rb:

pkgs = value_for_platform(
  %w(centos redhat scientific fedora) => {
    'default' => %w(httpd)
  },
  [ "debian", "ubuntu" ] => {
    "default" => %w{ apache2 }
  },
  "default" => %w{ apache2 }
)

Il est important de rajouter la recette tout juste créée dans le run_list de notre Vagrantfile.

...
chef.add_recipe "php"
chef.add_recipe "php::apache"

La recette d’installation d’Apache est prête ! Il ne reste plus qu’à créer un VirtualHost pour le site.

Section intitulée les-definitionsLes définitions

Pour éviter une duplication du code si plusieurs VirtualHost sont nécessaires (admin et front, par exemple), il convient d’utiliser la notion de définition. Dans Chef, une définition est simplement une fonction prenant des paramètres afin de réaliser une suite d’action.

Le fichier symfony_site.rb est ainsi à créer dans le dossier cookbooks/php/definitions, avec le contenu suivant :

#
# Cookbook Name:: php
# Definition:: symfony_site
#

define :symfony_site do
  template  "/etc/apache2/sites-available/symfony_site" do
    source "symfony_site.erb"
    owner  "root"
    group  "root"
    mode   "0644"
  end

  execute "Activate Symfony site" do
    command "a2ensite symfony_site"
  end
end

Cette définition permet la mise en place de VirtualHosts pour un site Symfony2. On peut voir que deux actions y sont effectuées :

  1. La création du fichier avec un template ;
     template  "/etc/apache2/sites-available/symfony_site" do
       source "symfony_site.erb"
       owner  "root"
       group  "root"
       mode   "0644"
     end
    
  2. L’exécution de la commande a2ensite afin d’activer le VirtualHost.
     execute "Activate Symfony site" do
       command "a2ensite symfony_site"
     end
    

Pour rendre cette définition générique, certains paramètres doivent être définis :

  • server_name : Le nom de domaine pour le site ;
  • docroot : L’emplacement du site sur le serveur ;
  • name : Un paramètre automatique permettant de donner un nom à notre site.

Nous modifions donc notre définition pour ajouter ces variables :

define :symfony_site, :docroot => nil, :server_name => nil do

  template  "/etc/apache2/sites-available/#{params[:name]}" do
    source "symfony_site.erb"
    owner  "root"
    group  "root"
    mode   "0644"
    variables({
      :docroot     => params[:docroot],
      :server_name => params[:server_name],
    })
  end

  execute "Activate Symfony site #{params[:name]}" do
    command "a2ensite #{params[:name]}"  end
end

Pour finir, le template symfony_site.erb est écrit dans le fichier symfony_site.erb du dossier template.

<VirtualHost *:80>
    ServerName  <%= @server_name %>

    DocumentRoot  <%= @docroot %>
    <Directory  <%= @docroot %>>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride None
        Order allow,deny
        allow from all

        <IfModule mod_rewrite.c>
            RewriteEngine On
            RewriteCond %{REQUEST_FILENAME} !-f
            RewriteRule ^(.*)$ /app.php [QSA,L]
        </IfModule>
    </Directory>
</VirtualHost>

Une fois cette définition créée, il suffit de l’appeler dans la recette principale :

symfony_site "monsite" do
  docroot    "/var/www/monsite"
  server_name node['ipaddress']
end

Section intitulée ressourceRessource

La définition que nous venons de créer permet d’être très flexible pour l’ajout de sites sous Symfony2. Cependant, elle possède quelques défauts. Il n’est ainsi pas possible de désactiver notre site, par exemple, ou même de le supprimer. Pour avoir une gestion plus fine de nos sites, Chef permet de créer des ressources avec l’architecture LWRP.

Une ressource est juste un ensemble d’actions qui peuvent être effectuées sur un objet. Par exemple, la ressource service permet le lancement, l’arrêt, le redémarrage, le rechargement d’un service (que ce soit Apache, MySQL, …). Elle représente un objet dans notre système et l’état souhaité de ce dernier.

Chaque ressource Chef se décompose en deux parties :

  1. La définition : dans le dossier ressources du cookbook, un fichier portant le nom de la ressource définit les actions et les paramètres possibles. (cookbooks/ressources/symfony_site.rb)
     actions :enable, :disable
     default_action :enable
     attribute :name, :kind_of => String, :name_attribute => true
     attribute :docroot, :kind_of => String, :default => nil
     attribute :server_name, :kind_of => String, :default => nil
    
  2. L’implémentation de la ressource dans le dossier providers du cookbook : chaque action y est écrite. (cookbooks/providers/symfony_site.rb)
     action :enable do
       template  "/etc/apache2/sites-available/#{new_resource.name}" do
         source "symfony_site.erb"
         owner  "root"
         group  "root"
         mode   "0644"
         variables({
           :docroot     => new_resource.docroot,
           :server_name => new_resource.server_name,
         })
       end
       execute "Activate Symfony site #{new_resource.name}" do
         command "a2ensite #{new_resource.name}"
       end
     end
     action :disable do
       execute "Desactivate Symfony site #{new_resource.name}" do
         command "a2dissite #{new_resource.name}"
       end
     end
    

Lorsqu’une action s’implémente de manière différente selon le système d’exploitation, il ne faut pas inclure cette logique dans le code. À la place, Chef permet de créer une architecture de dossiers spécifiques pour la ressource. Il ira chercher de lui même le bon fichier selon le système cible.

Pour appeler les actions depuis la recette, rien de plus simple :

php_symfony_site "monsite" do
  docroot    "/var/www/monsite"
  server_name node['ipaddress']
  action     :enable
end

php_symfony_site "monsite" do
  action     :disable
end

Remarque : Chef préfixe automatiquement le nom des ressources par le nom du cookbook, ceci afin d’éviter tout conflit avec d’autres ressources.

En fait, vous l’avez peut être remarqué, dans Chef tout est une ressource, que ce soit l’installation de paquets ou bien encore la création de templates : même une définition est transformée en une ressource.

Section intitulée l-infrastructureL’infrastructure

Section intitulée noeudsNoeuds

En plus de gérer l’installation et la configuration des applicatifs, Chef permet la gestion complète de l’infrastructure. Chaque serveur, machine virtuelle ou nuage magique (instance dans le cloud) est un noeud possédant ses propres attributs et une liste de recettes à lui appliquer.

Par exemple pour la machine virtuelle Vagrant, il serait possible de créer sa propre configuration sous le fichier nodes/vagrant.json

{
  "name": "vagrant",
  "run_list": [
    "recipe[php]",
    "recipe[php::apache]",
  ],
  "normal": {
    "php": {
      "memory_limit": "128Mo"
    }
  }
}

Ainsi chaque noeud peut être définit avec des recettes et des attributs différents.

Section intitulée rolesRôles

Mais une recette est simplement la description de comment est installé et configuré un applicatif. Or, les serveurs possèdent généralement plusieurs applicatifs. La notion de rôle permet de regrouper plusieurs recettes et/ou plusieurs rôles et de définir une liste d’attributs.

Pour exemple nous allons créer le rôle front et le rôle worker qui possèdent des applicatifs et des attributs différents.

  • le rôle front roles/front.json, qui inclut les recettes php et apache :
      {
        "name": "front",
        "description": "Mon joli serveur Web",
        "json_class": "Chef::Role",
        "default_attributes": {
        },
        "override_attributes": {
        },
        "chef_type": "role",
        "run_list": [
          "recipe[php]",
          "recipe[php::apache]"
        ]
      }
    
  • le rôle worker roles/worker.json, qui inclut seulement la recette php :
      {
        "name": "worker",
        "description": "Mon joli travailleur",
        "json_class": "Chef::Role",
        "default_attributes": {
        },
        "override_attributes": {
        },
        "chef_type": "role",
        "run_list": [
          "recipe[php]"
        ]
      }
    

Il suffit ensuite de spécifier un rôle à notre VM en remplaçant, dans le Vagrantfile, les lignes sur les recettes :

chef.add_recipe "php"
chef.add_recipe "php::apache"

par une ligne concernant le rôle de la machine :

chef.add_role "front"

La provision de notre VM va exécuter exactement la même chose qu’auparavant. On a simplement gagné en clarté dans la définition de l’infrastructure.

Section intitulée la-surcharge-d-attributsLa surcharge d’attributs

La recette php définit des attributs par défaut (par exemple, la mémoire allouée à PHP). Il est possible de surcharger ces paramètres à différents endroits, pour coller au mieux au besoin du projet. On peut ainsi surcharger les attributs dans un noeud, un Vagrantfile ou dans un rôle, de manière à obtenir une valeur finale au moment de l’exécution de la recette.

Cette liste, classée du moins prioritaire au plus prioritaire, permet de voir quel type d’attribut a la priorité sur l’autre :

  1. default attribut dans un fichier d’attribut ;
  2. default attribut dans une recette ;
  3. default attribut dans un environnement ;
  4. default attribut dans un rôle ;
  5. force_default attribut dans un fichier d’attribut ;
  6. force_default attribut dans une recette ;
  7. normal attribut dans un fichier d’attribut ;
  8. normal attribut dans une recette ;
  9. override attribut dans un fichier d’attribut ;
  10. override attribut dans une recette ;
  11. override attribut dans un rôle ;
  12. override attribut dans un environnement ;
  13. force_override attribut dans un fichier d’attribut ;
  14. force_override attribut dans une recette ;
  15. Attribut automatique généré par Ohai à chaque exécution de Chef.

Par exemple, il est possible dans une recette de forcer la mémoire PHP à un niveau très prioritaire :

node.force_override[‘php’][‘memory_limit’] = “256Mo”

Section intitulée ohaiOhai

Vous aurez certainement remarqué que le type d’attribut le plus prioritaire est celui généré par Ohai, une librairie créée et utilisée par Chef. Ohai définit automatiquement de nombreux paramètres pour chaque noeud comme le nombre de CPU disponible, la mémoire, les utilisateurs du système, le réseau, etc…

Par exemple, l’attribut ipaddress a été utilisé dans la recette front afin de définir le server_name du VirtualHost.

Il est ainsi tout à fait possible d’apporter une logique aux recettes, comme par exemple définir le nombre de threads ou de forks Apache en fonction du nombre de CPUs. On pourrait aussi définir la configuration MySQL en fonction de la mémoire disponible… Les possibilités sont très vastes !

Section intitulée see-youSee you

Vous avez maintenant toutes les cartes en main pour créer de nombreuses recettes et automatiser votre infrastructure de manière efficace. Dans les prochains articles, nous abandonnerons Chef Solo au profit de Chef Server. Nous verrons comment déployer avec Chef et comment gérer les dépendances avec les cookbooks existants.

Commentaires et discussions

Nos articles sur le même sujet