Aller au contenu
Infrastructure as Code medium

Ohai et portabilité : une recette, plusieurs distributions

10 min de lecture

Logo Chef

On répète partout que Chef s'adapte à la machine. C'est vrai, mais à moitié : Chef choisit tout seul le bon gestionnaire de paquets, il ne devinera jamais que le serveur web s'appelle apache2 chez Debian et httpd chez Red Hat. Ce module écrit une recette réellement portable grâce à Ohai et à platform_family, et la prouve : la même recette, le même test, convergés sur Debian et sur RHEL, tous les deux au vert. Public visé : intermédiaires ayant écrit des recettes.

  • Comprendre ce qu'Ohai collecte avant la convergence.
  • Distinguer platform et platform_family.
  • Écrire une recette portable avec value_for_platform_family.
  • Valider la même recette sur deux familles.

Avant toute convergence, Chef lance Ohai, qui interroge la machine et remplit l'objet node : distribution, version, noyau, mémoire, réseau, disques. Ces valeurs s'appellent les attributs automatiques, et vous n'avez rien à faire pour les obtenir.

Le plus simple pour les explorer est cinc-shell, qui charge le nœud sans rien converger :

Fenêtre de terminal
cinc-shell
node['platform']
node['platform_family']
node['kernel']['release']
=> "ubuntu"
=> "debian"
=> "6.8.0-134-generic"

platform ou platform_family : la distinction qui change tout

Section intitulée « platform ou platform_family : la distinction qui change tout »

Regardez bien les deux premières valeurs : platform vaut ubuntu, mais platform_family vaut debian. Ce n'est pas une redondance, c'est la notion clé de la portabilité.

AttributCe qu'il donneExemples
platformLa distribution préciseubuntu, debian, rocky, almalinux, fedora
platform_familyLa famille, qui partage les mêmes outilsdebian, rhel, suse, windows

Écrire une condition sur platform vous condamne à l'énumérer sans fin : ubuntu, puis debian, puis Ubuntu 22 mais pas 24, puis quelqu'un déploie sur Rocky, puis sur AlmaLinux... Chaque nouvelle distribution casse votre recette.

Écrire une condition sur platform_family couvre toute la famille d'un coup : debian prend Ubuntu et Debian ; rhel prend Rocky, AlmaLinux, CentOS Stream et RHEL.

Une bonne nouvelle avant le travail : la ressource package est déjà portable. Vous écrivez package, et Chef choisit le fournisseur adapté à la machine. La preuve, dans la sortie de convergence :

* apt_package[apache2] action install ← sur Ubuntu
* dnf_package[httpd] action install ← sur Rocky Linux

Vous n'avez jamais écrit apt ni dnf. Chef a traduit votre intention. Il en va de même pour service, user, group : l'outil est choisi pour vous.

En revanche, Chef ne peut pas savoir que votre serveur web s'appelle apache2 ici et httpd là. Ce n'est pas un outil, c'est une donnée, et elle change d'une famille à l'autre.

C'est exactement le rôle de value_for_platform_family : une table de correspondance entre la famille et la valeur.

# La famille décide du nom du paquet
paquet = value_for_platform_family(
'debian' => 'apache2',
'rhel' => 'httpd'
)
package paquet
file '/var/www/html/index.html' do
content "Servi par #{paquet} sur #{node['platform']} (famille #{node['platform_family']})\n"
mode '0644'
end

Le nom du service suivrait la même variable, puisqu'il porte le même nom que le paquet dans les deux familles.

Test Kitchen sait converger plusieurs plateformes à partir du même cookbook. Il suffit de les déclarer :

platforms:
- name: ubuntu-24.04
driver:
image: dokken/ubuntu-24.04
- name: rockylinux-9
driver:
image: dokken/rockylinux-9

Le même fichier de test vérifie l'intention, pas le nom du paquet :

paquet = os.debian? ? 'apache2' : 'httpd'
describe package(paquet) do
it { should be_installed }
end
describe file('/var/www/html/index.html') do
its('content') { should match(/Servi par #{paquet}/) }
end

Sur Ubuntu :

* apt_package[apache2] action install
✔ is expected to be installed
✔ content is expected to match /Servi par apache2/
Test Summary: 2 successful, 0 failures, 0 skipped

Sur Rocky Linux, sans changer une seule ligne de la recette :

* dnf_package[httpd] action install
✔ is expected to be installed
✔ content is expected to match /Servi par httpd/
Test Summary: 2 successful, 0 failures, 0 skipped

Deux familles, deux gestionnaires de paquets, deux noms de paquets, une seule recette. C'est la portabilité que Chef promet, à condition de lui donner la table de correspondance qu'il ne peut pas deviner.

Ohai en collecte des centaines, mais une poignée suffit au quotidien.

AttributCe qu'il donne
node['platform_family']La famille : le premier réflexe de portabilité
node['platform']La distribution précise
node['platform_version']Sa version (24.04, 9.4)
node['os']linux, windows, darwin
node['kernel']['release']La version du noyau
node['ipaddress']L'adresse principale
node['memory']['total']La mémoire, pour dimensionner

Le dernier est souvent sous-estimé : il permet de calculer une valeur de configuration au lieu de la coder en dur, par exemple le nombre de processus d'un serveur web selon la mémoire réellement disponible.

Les erreurs de portabilité se ressemblent toutes : Chef a fait son travail, mais la donnée ne correspondait pas à la machine.

SymptômeCause probableSolution
No candidate version available for apache2Nom de paquet en dur, machine RHELvalue_for_platform_family
La recette casse sur une nouvelle distributionCondition écrite sur platformPasser à platform_family
undefined method '[]' for nil sur un attribut OhaiL'attribut n'existe pas sur cette plateformeVérifier avec cinc-shell, prévoir un repli
Le chemin de configuration est fauxIl diffère selon la familleLe sortir dans une table comme le nom du paquet
Le service échoue en conteneurPas d'init, symptôme variable selon la familleValider les services sur une VM
  1. Ohai interroge la machine avant la convergence et remplit node : vous n'avez rien à faire pour l'obtenir.
  2. platform est la distribution (ubuntu), platform_family est la famille (debian). Testez la famille.
  3. Chef choisit déjà le bon outil : package devient apt_package ou dnf_package sans que vous l'écriviez.
  4. Mais il ne devinera jamais vos données : apache2 chez Debian, httpd chez RHEL.
  5. value_for_platform_family est la table de correspondance qui rend la recette portable.
  6. Un nom de paquet en dur est une bombe à retardement : invisible tant qu'on ne déploie qu'une famille.
  7. Prouvez la portabilité en convergeant les deux familles dans Test Kitchen : même recette, même test, deux verts.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn