Table des matières

Introduction

Puppet est un outil permettant la centralisation et le déploiement de configuration sur un parc de machines plus ou moins hétérogène, du moment qu'un client puppet a été développé pour le système d'exploitation utilisé.

Le besoin se résume ainsi :

Gérer de manière efficace et centralisée la configuration de plusieurs machines tout en ayant la souplesse de s'adapter aux spécificités de chacune d'entre elles.

Quand il faut gérer un nombre important de serveurs, il est intéressant (voire indispensable) de disposer d'un outil permettant de déployer et de mettre à jour facilement leur configuration. Bien entendu le but ici n'est pas de copier sur X machines une configuration identique, mais bien d'adapter celle-ci au cas par cas. Cela se résume en partie par l'utilisation de modèles de fichiers de configuration, utilisant des variables qui seront adaptées sur chaque machine cible. Certains administrateurs développent leurs propres scripts de configuration, arrivant à peu près à ce genre de résultat, mais avec les inconvénients que cela peut avoir (temps, ressource, maintenance, robustesse, etc). Heureusement, il existe depuis un certain temps des outils plus aboutis répondant à ce besoin particulier, le plus connu étant cfEngine. Mais bien que cfEngine réponde parfaitement à cette tâche, il est un peu trop complexe, ne serait-ce que dans sa syntaxe, le rendant quelque peu hermétique pour le débutant.

Le réel avantage de Puppet est de proposer des fichiers de configuration clairs et lisibles, facilement compréhensibles.

Qu'est ce que Puppet ?

Puppet permet :

En tant qu'administrateur, vous utiliserez le langage de configuration de Puppet pour déclarer l'état final de vos systèmes.

Ainsi, nous décrivons Puppet comme «déclaratif».

Comment fonctionne Puppet

Sur tout nœud que vous contrôlez, une application nommée “Puppet Agent”. L'agent évalue et implémente les manifestes Puppet, ou les fichiers contenant le langage de configuration Puppet qui déclare l'état souhaité du noeud. L'agent évalue l'état de chaque composant décrit dans un manifeste et détermine si un changement est nécessaire ou non. Si le composant doit être modifié, l'agent apporte les modifications demandées et enregistre l'événement.

Si Puppet est configuré pour utiliser un maître centralisé, Puppet envoie les données du nœud au maître et reçoit un catalogue précompilé contenant uniquement la stratégie à appliquer du nœud. Vous pensez peut-être à présent: - « Et si je ne souhaite exécuter que la commande sur un sous-ensemble de nœuds ? » , Puppet propose différentes méthodes pour classifier et catégoriser les nœuds afin de limiter les ressources à appliquer sur des nœuds.

Vous pouvez utiliser des informations de noeud telles que le nom d’hôte, le système d’exploitation, le type de noeud, la version de Puppet et bien d’autres. Mieux encore, il est facile de créer de nouveaux critères personnalisés pour votre environnement.

L'agent Puppet évalue l'état d'un seul nœud. Dans ce modèle, vous pouvez avoir des agents sur des dizaines, des centaines ou des milliers de noeuds pour évaluer leurs catalogues et implémenter les modifications sur leurs noeuds exactement au même moment.

Pourquoi utiliser Puppet

Comme nous l'avons vu précédemment, Puppet fournit une infrastructure bien conçue pour gérer l'état de plusieurs nœuds simultanément.

Voici quelques raisons de l'utiliser:

Puppet Plateforme

Puppet master

System Requirements

Puppet Server est configuré pour utiliser 2 Go de RAM par défaut. Si vous souhaitez simplement jouer avec une installation sur une machine virtuelle, cette quantité de mémoire n'est pas nécessaire.

Note:

Pour modifier l'allocation de mémoire, voir l'aide : Allocation de mémoire.

Pour changer la valeur de l'allocation de mémoire, éditez le fichier ci-dessous :

[ user@puppet ~]$ sudo nano /etc/sysconfig/puppetserver

Modifiez la valeur affichée comme ci-dessous.

JAVA_ARGS="-Xms2g -Xmx2g"

par

JAVA_ARGS="-Xms512m -Xmx512m"

Redémarrez le service “puppetserver” après toute modification de ce fichier.

Ajout du référentiel de paquets

Nous allons maintenant installer et activer le référentiel de la collection de paquets de Puppet sur notre nouveau système.

En commençant par le répertoire de base, suivez les étapes suivantes.

[ user@puppet ~]$ sudo yum localinstall https://yum.puppet.com/puppet5-release-el-7.noarch.rpm

Cette commande installera et activera le référentiel du paquet “puppet” de Puppet.com, qui contient le paquet Puppet 5.

Une fois l'installation terminée, vous pouvez confirmer qu'il est activé avec la commande suivante.

[ user@puppet ~]$ sudo yum repolist

Installation de Puppet Master

Puppet Server est le logiciel serveur qui s'exécute sur le nœud principal “Puppet Master”. Puppetmaster pousse les configurations vers les nœuds gérés (puppet-agent).

Installez le serveur Puppet en utilisant la commande ci-dessous.

[ user@puppet ~]$ sudo yum install -y puppetserver

Puppet Master ne nécessite aucune configuration. Nous pouvons simplement démarrer le service “puppetserver”. Il utilisera les paramètres par défaut.

[ user@puppet ~]$ sudo systemctl start puppetserver
[ user@puppet ~]$ sudo systemctl enable puppetserver

Firewall

Le Puppet Master écoute sur le port 8140, configurez donc le pare-feu de manière à ce que les nœuds gérés puissent se connecter au maître.

[ user@puppet ~]$ sudo firewall-cmd --permanent --add-port=8140/tcp
success
[ user@puppet ~]$ sudo firewall-cmd --reload
success

Puppet agent

Ajout du référentiel de paquets

Nous allons maintenant installer et activer le référentiel de la collection de paquets de Puppet sur notre nouveau système.

En commençant par le répertoire de base, suivez les étapes suivantes.

[ user@agent ~]$ sudo yum localinstall https://yum.puppet.com/puppet5-release-el-7.noarch.rpm

Cette commande installera et activera le référentiel du paquet “puppet” de Puppet.com, qui contient le paquet Puppet 5.

Une fois l'installation terminée, vous pouvez confirmer qu'il est activé avec la commande suivante.

[ user@agent ~]$ sudo yum repolist

Installation de Puppet agent

Installez l'agent Puppet sur client à l'aide de la commande ci-dessous.

[ user@agent ~]$ yum -y install puppet-agent

Note:

CN du certificat client

Lors du premier démarrage du client puppet, ce dernier génère une demande de signature avec un certificat utilisant comme CN son FQDN. Il est possible de forcer ce nom dans /etc/puppet/puppet.conf avec la clef certname. Les certificats déjà existant ne seront pas refait, il faut les supprimer de /var/lib/puppet/ssl/* et relancer le client (pour régénérer les certificats).

Il faudra aussi les re-signer sur le serveur.

Configuration de Puppet agent

L'agent de puppet utilise également certains paramètres par défaut pour se connecter au nœud principal (Puppet Master). Cependant, nous devons modifier le fichier de configuration de l'agent et définir les informations relatives à son maître.

[root@agent ~]# vi /etc/puppetlabs/puppet/puppet.conf

Définir comme ci-dessous.

[main]
certname = agent.oowy.lan
server = puppet.oowy.lan
environment = production
runinterval = 30m

Note:

Définissez la valeur “server” selon le nom de votre nœud maître.

Définissez la valeur “certname” selon le nom d’hôte client.

Démarrez l'agent de puppet sur le nœud et faites-le démarrer automatiquement au démarrage du système.

[ user@agent ~]$ /opt/puppetlabs/bin/puppet resource service puppet ensure=running enable=true
Notice: /Service[puppet]/ensure: ensure changed 'stopped' to 'running'
service { 'puppet':
  ensure => 'running',
  enable => 'true',
}

Gestion des certificats

La première fois que Puppet s'exécute sur un nœud “agent”, il envoie une demande de signature de certificat au maître Puppet. Avant que Puppet Server puisse communiquer avec et contrôler le nœud, il doit signer le certificat de ce même nœud.

Se connecter au server Puppet Master pour la gestion des certificats.

Signer un certificat

Sur le puppet master, exécutez la commande suivante pour répertorier toutes les demandes de certificat non signé :

[ user@puppet ~]# sudo puppetserver ca list
Requested Certificates:
  "agent.oowy.lan" (SHA256) CE:BA:8C:C1:FF:5F:CC:A5:D8:EA:AA:05:29:0C:CF:B0:8F:2C:AB:12:72:99:45:8C:6F:09:61:A1:20:81:05:E6

Pour signer une demande de certificat, utilisez la commande puppetserver ca sign, avec le nom d'hôte du certificat que vous souhaitez signer.

Par exemple, pour signer le certificat de “agent.oowy.lan”, utilisez la commande suivante :

  
[ user@puppet ~]# sudo puppetserver ca sign agent.oowy.lan
Successfully signed certificate request for agent.oowy.lan

Révoquer un certificat

Vous voudrez peut-être supprimer un hôte de Puppet ou reconstruire un hôte puis le rajouter à Puppet.

Dans ce cas, vous souhaiterez révoquer le certificat de l'hôte puppet master. Pour ce faire, vous pouvez utiliser l'action de nettoyage :

 
[ user@puppet ~]$ puppetserver ca clean <_hostname_>

Les certificats associés à l'hôte spécifié seront supprimés de Puppet.

Lister les certificats

Si vous souhaitez afficher toutes les demandes, signées et non signées, exécutez la commande suivante :

[ user@puppet ~]$ sudo puppetserver ca list --all 
Signed Certificates:
    puppet.oowy.lan   (SHA256)  ED:E3:C3:8F:CE:31:27:62:89:28:01:06:E1:FA:92:E1:03:1E:95:5D:2B:45:77:D2:D3:59:B1:2D:74:5F:82:EA	alt names: ["DNS:puppet", "DNS:puppet.oowy.lan"]
    agent.oowy.lan    (SHA256)  4B:F2:86:EB:3C:07:F1:91:5A:BF:38:E1:08:ED:0C:DB:D9:D7:36:3E:E8:C0:F9:93:92:57:98:74:C1:F7:46:76
    agent2.oowy.lan   (SHA256)  7E:43:3E:C5:5A:95:6B:FC:F2:AE:AE:7B:57:4A:31:3C:D4:0F:B8:D5:97:2B:4B:64:84:14:7E:90:A7:73:06:F3

Vérification de l'agent

[ user@agent ~]$  sudo /opt/puppetlabs/bin/puppet agent --test
Info: Using configured environment 'production'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Retrieving locales
Info: Caching catalog for agent.oowy.lan
Info: Applying configuration version '1557064831'
Notice: Applied catalog in 0.01 seconds

Ecrire un Manifest

Le tout premier concept que nous souhaitons présenter est le manifeste Puppet. Un manifeste est un fichier contenant le langage de configuration de Puppet qui décrit comment les ressources doivent être configurées. Le manifeste est ce qui se rapproche le plus de ce que l’on pourrait considérer comme un programme Puppet. Il utilise des ressources pour définir une stratégie à appliquer à un nœud. Il s'agit donc du composant de base de la stratégie de configuration de Puppet et d'un bloc de construction pour les modules Puppet complexes.

L'écriture des manifestes est la partie la plus importante de l’élaboration des politiques relatives aux marionnettes. Commençons par le plus petit composant d’un manifeste.

Mise en œuvre des ressources

Les ressources sont le plus petit élément constitutif du langage de configuration de Puppet. Ils représentent un élément singulier que vous souhaitez évaluer, créer ou supprimer. Puppet comprend de nombreuses ressources intégrées. Ces ressources par défaut manipulent des composants système que vous connaissez déjà, notamment:

… et beaucoup plus. De plus, vous pouvez créer vos propres ressources. Cependant, commençons par l’une des ressources les plus simples - la ressource de notification. Commençons par le premier programme stéréotypé écrit dans toutes les langues.

notify { 'greeting':
  message => 'Hello, world!'
}

Ce code déclare une ressource de notification nommée “greeting”. Il a un attribut unique, “message” qui a la valeur que nous attendions dans notre premier programme.

Les attributs sont séparés de leurs valeurs à l'aide d'une grosse virgule (également appelée “Hash rocket”), qui est un moyen très courant d'identifier les paires clé/valeur dans les langages de script Perl, Ruby et PHP.

Ce petit bout de code est un manifeste pleinement fonctionnel et valide. Ce manifeste (avec une seule ressource) ne fait qu'une chose, qui consiste à sortir ce message stéréotypé à chaque appel.

Continuons et utilisons Puppet pour évaluer ce manifeste.

[ user@agent ~]$ cat helloworld.pp
notify { 'greeting':
  message => 'Hello, world!'
}

Comme vous pouvez le voir dans cet exemple, les manifestes sont des fichiers texte portant une extension “.pp” qui décrivent les ressources à l'aide du langage de configuration de Puppet. Vous pouvez créer ou modifier un manifeste Puppet à l'aide de n'importe quel éditeur de texte.

Appliquer un manifeste

L'une des meilleures fonctionnalités de Puppet est la facilité de test de votre code. Puppet ne vous oblige pas à configurer des environnements de test compliqués pour évaluer les manifestes. Il est facile, voire carrément trivial, de tester un manifeste Puppet.

Continuons et implémentons ce manifeste. Pour ce faire, nous utiliserons la commande “puppet apply” qui indique à Puppet de mettre en œuvre un seul manifeste Puppet.

[ user@agent ~]$ puppet apply helloworld.pp

Comme vous pouvez le constater, Puppet a implémenté le manifeste. Cela se fait en plusieurs étapes:

  1. Compile le manifeste dans un catalogue Puppet.
  2. Utilise les informations de dépendance (bientôt couvertes) pour déterminer quelles ressources doivent être traitées en premier.
  3. Évalue la ressource pour déterminer si des modifications sont nécessaires.
  4. Crée, modifie ou supprime la ressource - un message de notification est créé.
  5. Fournit des commentaires détaillés sur la mise en œuvre du catalogue.

Ne vous inquiétez pas de la mémorisation de ces étapes à ce stade du processus d’apprentissage. Nous voulions simplement vous présenter les idées que nous allons approfondir.

Pour l’instant, rappelez-vous que vous allez utiliser “puppet apply” pour implémenter les manifestes Puppet. Il vous fournira des informations détaillées sur les actions que Puppet a entreprises pour aligner les ressources cibles sur la stratégie déclarée.

Déclaration de ressources

Il n'y a que quelques règles à retenir lors de la déclaration de ressources.

Le format est toujours le même:

resource_type { 'resource_title':
  ensure => present, # usually 'present' or 'absent'
  attribute1 => 1234, # number
  attribute2 => 'value', # string
  attribute3 => ['red','blue'], # array
  noop => false, # boolean
}

La règle la plus importante pour les ressources est la suivante : il ne peut y en avoir qu'une. Dans un manifeste ou un ensemble de manifestes appliqués ensemble (le catalogue pour un nœud), une ressource d'un type donné ne peut être déclarée qu'une seule fois avec un titre donné. Toute autre ressource de ce type doit faire référence à un composant sous-jacent différent et avoir un titre unique.

Par exemple, le manifeste suivant va échouer car le même titre est utilisé pour les deux ressources de fichier.

[ user@agent ~]$ cat myfile.pp

file { 'my_file':
  ensure => present,
  path => 'my_file.txt',
}

file { 'my_file':
  ensure => present,
  path => 'my_file.csv',
}

notice { 'my_file':
  message => "My file is present",
}

[ user@agent ~]$ puppet apply myfile.pp
Error: Evaluation Error: Error while evaluating a Resource Statement, Duplicate declaration: File[

Vous remarquerez qu'aucune erreur n'a été formulée pour la ressource Notice du même titre. Ce n'est pas un conflit. Seules les ressources du même type ne peuvent pas utiliser le même titre. Nommer les fichiers ci-dessus avec leurs chemins complets ne garantit aucun conflit :

file { '/home/vagrant/my_file.txt':
  ensure => present,
  path => '/home/vagrant/my_file.txt',
}
 
file { '/home/vagrant/my_file.csv':
  ensure => present,
  path => '/home/vagrant/my_file.csv',
}

Affichage des ressources

Une fonctionnalité intéressante de Puppet est qu’elle peut vous montrer une ressource existante écrite en langage Puppet. Cela facilite la génération de code basé sur les configurations existantes.

Voyons cela avec un alias de courrier électronique.

[ user@puppet ~]$ puppet resource mailalias postmaster
mailalias { 'postmaster':
  ensure => 'present',
  recipient => ['root'],
  target => '/etc/aliases',
}

Cette sortie vous fournit la structure, la syntaxe et les attributs permettant de déclarer cet alias dans vos règles Puppet. Vous pouvez écrire cette sortie dans un fichier manifeste, modifier le destinataire, puis utiliser “puppet apply” sur ce manifeste pour modifier l'alias postmaster de ce nœud.

Examinons une autre ressource - l’utilisateur pour lequel vous êtes connecté.

[ user@puppet ~]$ sudo puppet resource user myuser
  user { 'myuser':
  ensure => 'present',
  gid => '500',
  groups => ['wheel'],
  home => '/home/myuser',
  password => '$1$sC3NqLSG$FsXVyW7azpoh76edOfAWm1',
  password_max_age => '99999',
  password_min_age => '0',
  shell => '/bin/bash',
  uid => '500',
}

Si vous examinez la ressource, vous comprendrez pourquoi l'accès root (sudo) est nécessaire. La ressource utilisateur contient le hachage de mot de passe de l'utilisateur, qui requiert le privilège root pour pouvoir être lu à partir du fichier reflet. Comme avec l'alias ci-dessus, vous pouvez l'écrire dans un fichier, remplacer le mot de passe haché et utiliser “sudo puppet apply” pour changer le mot de passe root.

Exécution de programmes

Examinons d’autres types de ressources: commandes ou exécutables. Vous pouvez utiliser une ressource “exec” pour exécuter des programmes dans le cadre de votre manifeste. Voyons cela maintenant.

exec { 'echo-holy-cow':
  path => ['/bin'],
  cwd => '/tmp',
  command => 'echo "holy cow!" > testfile.txt',
  creates => '/tmp/testfile.txt',
  returns => [0],
  logoutput => on_failure,
}

Maintenant, lorsque vous appliquez ce manifeste, le fichier “testfile.txt” sera créé. Notez que nous utilisons des guillemets simples pour encapsuler les valeurs attribuées aux attributs.

La ressource “exec” définie ci-dessus utilise l'attribut “create”. Cet attribut définit le résultat attendu de l'exécution de la commande. Lorsque le fichier nommé existe, la commande n'est pas exécutée. Cela signifie que le manifeste peut être exécuté à plusieurs reprises et que rien ne changera après la création initiale du fichier.

Voyons cela ici:

[ user@puppet ~]$ puppet apply tmp-testfile.pp
Notice: Compiled catalog for puppet.oowy.lan in environment production in 0.03 seconds
Notice: /Stage[main]/Main/Exec[echo-holy-cow]/returns: executed successfully
Notice: Finished catalog run in 0.07 seconds

[ user@puppet ~]$ puppet apply tmp-testfile.pp
Notice: Compiled catalog for puppet.oowy.lan in environment production in 0.03 seconds
Notice: Finished catalog run in 0.01 seconds

Si vous examinez la ressource “exec” ci-dessus, vous remarquerez que nous devons déclarer comment effectuer le changement et également s’il faut ou non le faire. Cela ressemble beaucoup à la programmation procédurale et peut être très difficile à maintenir.

Il est généralement plus difficile d'écrire du code déclaratif à l'aide d'un “exec”. On a tendance à revenir en arrière dans un style de programmation procédurale. Sauf dans les cas où aucune autre méthode n'est possible, un “exec” est généralement une indication d'une stratégie mal écrite.

Note:

Évitez d'utiliser “exec” chaque fois que cela est possible, en particulier lorsqu'une ressource native Puppet peut faire le travail.

Gérer les fichiers

Sinon, comment pourrions-nous créer ce fichier ? Nous aurions pu utiliser la ressource “file”.

Voyons un maintenant.

file { '/tmp/testfile.txt':
  ensure => present,
  mode => '0644',
  replace => true,
  contents => 'holy cow!',
}

C'est une politique proprement déclarative. Nous déclarons que le fichier doit exister et quel doit en être le contenu. Nous n'avons pas besoin de nous demander comment et quand apporter des modifications au fichier. De plus, nous avons pu nous assurer que le contenu du fichier reste cohérent, ce qui n’est pas possible avec une commande “echo”.

Note:

Vous remarquerez également que le manifeste déclaratif utilise moins de lignes de texte et garantit une sortie plus cohérente.

Annexe

https://puppet.com/docs/puppet/5.5/puppet_index.html

https://puppet.com/docs/puppet/5.5/configuration.html

https://puppet.com/docs/puppet/5.5/config_important_settings.html