Contents
- Aperçu
- Préparation des participant.e.s
- Préparation de la part de l'animateur.trice
- Qu'est-ce que c'est Puppet et quel est son rôle?
- L'infrastructure en tant que code (Infrastructure as Code)
- Quels autres outils accompagnent généralement Puppet?
- Jargon utilisé autour du logiciel Puppet
- Exercice: Découvrir de l'information à propos d'une machine à l'aide de facter
- Comment est-ce que Puppet communique avec les différents outils?
- Exercice: Se familiariser avec l'agent (client) Puppet
- Quelques exemples simples de structures du langage Puppet
- Quelques outils alternatifs à Puppet
- Exercice: Ecrire un premier script
- Rétrospective
- Information complémentaire
Aperçu
Formations préalables
- Aucune
Être minimalment familier avec l'utilisation de la ligne de commande est nécessaire (pour des participant.e.s externes, il faut savoir comment se connecter à un serveur via ssh)
Avoir une connaissance des concepts des logiciels de gestion de versions de code comme git peut aider. Par contre, nous n'utiliserons pas ces logiciels de manière pratique dans cette formation-ci.
Temps estimé
Objectifs
- Apprendre qu'est-ce que c'est l'outil Puppet, quelle est sa fonction
- Apprendre le jargon qui est utilisé autour de l'outil pour représenter certains concepts
- Situer Puppet dans l'écosystème d'outils avec lequel on peut l'intégrer pour permettre la gestion d'infratructures complexes
- Se familiariser avec le client Puppet et ses différences facettes
- Modifier directement une machine avec puppet sans script
- Avoir un premier contact en surface avec le format du code Puppet
- Ecrire un premier script (manifeste) qui permet
- d'installer un logiciel à l'aide d'un package de la distribution Linux
- de créer un fichier de configuration
- de s'assurer qu'un certain service est bien démarré
Préparation des participant.e.s
Avant la formation, chaque participant.e devrait valider ses accès aux machines virtuelles.
Si vous participez à la formation et que vous ne faites pas partie de l'équipe sysadmin de Koumbit, assurez-vous d'avoir un client ssh qui soit fonctionnel: les exercices seront exécutés sur des machines virtuelles accessibles sur internet via SSH.
Préparation de la part de l'animateur.trice
Pour une formation à l'équipe infra de Koumbit:
- Prendre du temps avec chaque personne pour s'assurer
qu'elle a vagrant d'installé selon les instructions du control repository
pm_buster est bien démarrée
On peut voir les fichiers en NFS à partir de pm_buster
pm_buster peut appliquer un changement qui se trouve dans le control repository
Créer une branche dans le control repository qui contient un fichier brise.pp à la racine avec comme contenu:
file { '/root/le_script_n_est_plus_brise': content => 'vous avez reussi!' mode => '0600', owdner => 'root', }
Pour les formations externes à Koumbit:
- créer une VM pico pour chaque participant.e
installer sudo, tmux et vim-nox
créer un compte formation avec un mot de passe facile à communiquer et qui a un accès sudo
installer puppet en suivant l'étape 2 (seulement) de PuppetConfiguration#bootstrap
important: la VM ne devrait pas être branchée au serveur puppet en production de Koumbit
- Créer une VM chiquito additionnelle qui servira de serveur puppet pour les VMs de formation
installer sudo, tmux et vim-nox
- pas besoin d'un setup git pour le control repos.. on va monter qqch d'ultra simple
Créer une série de fichiers sous /etc/puppet/code/environments/production
manifests/*.pp : un fichier pour chaque VM de participant.e pour décrire sa node.
chaque node devrait contenir une ligne include formation
modules/formation/manifests/init.pp : une classe nommée formation qui a une seule ressource file { '/home/formation/hello_world_agent': content => 'le serveur veut que votre agent ait ce fichier sur disque' }
- signer les certificats des VMs des participant.e.s
- Sur chaque VM
créer un fichier /etc/puppet/code/environments/production/brise.pp avec le même contenu que brise.pp dans les instructions pour l'équipe infra
- valider que puppet roule bien contre le serveur, mais en noop seulement. ne pas laisser puppet appliquer les changements (sinon deleter le fichier que ça produit)
- désactiver l'agent puppet
Qu'est-ce que c'est Puppet et quel est son rôle?
Puppet c'est un logiciel qui sert de service de gestion centralisée de configurations. Comme le terme l'indique, grâce à ce logiciel on peut imposer une configuration sur des serveurs et avoir un seul point à partir d'où exercer ce contrôle. C'est une des idées fondamentales de l'infrastructure en tant que code (nous en verrons un peu plus sur ce terme dans la prochaine section).
Dans l'idée précédente, par configuration on veut dire tout ce qui défini qu'est-ce qui s'exécute sur une machine et comment. Donc quels logiciels sont installés, quels fichiers sont créés et quel est leur contenu pour que les logiciels se comportent de la façon dont on l'espère, mais également quels services (daemons) doivent être actifs.
La gestion centralisée de configurations permet donc en fait d'automatiser l'installation et la configuration de serveurs. Quelques avantages remarquables par rapport à ça sont:
- permet de gérer beaucoup de machines sans tout conserver la configuration de chacune dans notre mémoire d'humain (qui a tendance à oublier des choses, surtout quand une tâche est répétitive) -- ou même dans des pages de wiki qui ont un grand risque de ne pas être à jour.
- représente (et documente) qu'est-ce qui est installé dans l'infrastructure
- quand une machine est complètement gérée par puppet (situation idéale), on peut lire le code Puppet qu'on a écrit pour facilement voir qu'est-ce qui est installé sur cette machine là et comment.
- permet la reprise en charge graduelle des serveurs, pour automatiser de manière itérative
- lorsqu'on adopte Puppet comme outil de gestion, ou si on commence l'automatisation d'une machine qui n'était pas sous notre charge initalement, on peut automatiser seulement certains services et en laisser d'autres pas gérés
puppet ne gère que ce qui est déclaré dans le code
- permet ainsi une reprise graduelle, un service ou un aspect de la machine à la fois. on peut donc petit à petit se rapprocher de l'objectif de la gestion automatisée complète de la machine
- standardise la configuration des ordinateurs
- l'installation et la configuration sont toujours faites de la même façon sans oublier d'étape
- retire le besoin de configurer les systèmes à la main, donc on retire un grand risque d'erreur de manipulations
Le problème de gestion automatisée de machines n'est pas un problème simple. Puppet rembli bien le rôle de représenter une configuration désirée sous forme de code, envoyer ce code du serveur aux clients, puis appliquer ce code pour que l'état désiré sur la machine soit bien en place.
Par contre il nous faudra utiliser quelques logiciels additionnels pour certaines autres tâches spécifiques. Donc en fait quand on commence à utiliser Puppet, on plonge en fait dans une suite de logiciels inter-reliés qui permettent de remplir au total la fonction complexe de gestion de configuration. Nous verrons dans une section plus bas quels sont les autres logiciels qui accompagnent généralement Puppet et un peu plus bas encore comment Puppet interagit avec ces outils (nous n'aurons pas besoin nécessairement d'interagir directement avec chacun mais il est tout de même important de connaître leur existance et leur rôle).
Serveur vs. client
Puppet utilise un modèle de diffusion d'information où les agents (clients) "tirent" ("pull") leur état en demandant au serveur de leur fournir. C'est alors l'agent qui appliquera la configuration fournie par le serveur et qui fera les changements nécessaire. Donc si l'agent ne fonctionne pas, les changements ne se font pas (donc il est important de s'assurer que ce mécanisme est en bon état).
Par contraste, certains autres outils qui remplissent la même fonction que puppet utiliseront un modèle où l'outil lui-même se connectera sur la machine pour y imposer ("push") la configuration et les changements.
Donc puppet utilise le concept de serveur vs. client pour que les clients obtiennent leur configuration d'un seul point central.
l'agent se connecte de manière périodique au serveur, obtient les facts de la part de facter et les envoie au serveur pour lui demander s'il y a des changements à appliquer
le serveur compile le code, qu'on appellera manifestes, écrit par les administratrices.teurs sous un format plus compacte et facile pour le programme client à utiliser. Le code compilé, qu'on appellera catalogue, est alors envoyé à l'agent ainsi que tout contenu de fichier nécessaire pour que l'agent puisse appliquer les changements requis.
- l'agent applique le catalogue sur la machine où il s'exécute, puis envoie au serveur un rapport d'exécution qui indique s'il y a eu des erreurs d'application et combien, et aussi combien de temps ça aura pris à l'agent pour appliquer les changements qui amènent la machine à l'état décrit par le catalogue.
le serveur peut réacheminer le rapport d'exécution à un service de stockage tel que PuppetDB
Dans le cas de Puppet, il existe des clients pour *nix (e.g. FreeBSD, OpenBSD, etc), Linux, MacOS X et Windows, donc on peut contrôler des machines de toutes ces plateformes là sous un même serveur central!
Configuration sans serveur
Comme on le verra un peu plus tard, Puppet fournit une commande qui applique des changements sans les demander à un serveur central. On peut appliquer des changements soit en donnant le code directement via un argument, soit en pointant l'outil vers un fichier qui contient le code que l'on veut appliquer.
Ça veut donc dire qu'il est possible d'utiliser puppet sans le serveur centralisé. Ce genre de configuration là ne permettra par contre pas, ou bien avec plus de difficulté, l'échange d'information entre les serveurs (comme par exemple avec le modèle serveur-client on peut configurer automatiquement un service de monitoring selon quels services sont installés par puppet sur d'autres machines)
Code déclaratif
Les développeurs du logiciel Puppet ont fait un choix important dès la conception initiale de l'outil, et qui se démarque encore des outils alternatifs: l'outil s'attend à recevoir une déclaration de quel est l'état final d'une machine, et non quelles sont les instructions pour se rendre à l'état final. Donc le code Puppet utilise un modèle déclaratif -- ça veut dire que lorsqu'on écrit des manifestes on veut spécifier ce qui doit être présent sur la machine.
Tout l'aspect procédural de comment changer les choses pour se rendre à l'état déclaré est caché "sous le capot". Il y du code pour chaque type de ressource qui sait comment créer, retirer et modifier les choses sur la machine pour pouvoir se rendre à l'état désiré. Donc on n'a pas besoin de savoir comment faire les changements, mais seulement de demander à puppet de les faire pour nous. Donc quand on écrit du code Puppet, on se soucie seulement de qu'est-ce que l'état final doit être.
Le code à nature déclaratif utilise une propriété très importante pour éviter de toujours apporter des changements à une machine: Le code a une idempotence d'exécution: on peut lancer Puppet autant de fois qu'on veut et celui-ci ne devrait pas refaire les modifications si elles ne sont pas nécessaires. En d'autre mots, si une ressource correspond déjà à l'état souhaité, elle ne subira pas de changements.
L'infrastructure en tant que code (Infrastructure as Code)
Voir: https://fr.wikipedia.org/wiki/Infrastructure_as_code
L'idée qui a été nommée Infrastructure as code est un concept relativement simple mais qui a permis de complètement refaçonner la nature du travail d'administration de serveurs. C'est une des idées fondatrices de ce qui est souvent appelé DevOps.
Au lieu de gérer une infrastructure à l'aide d'une série de procédures manuelles, on représente ce que cette infrastructure devrait être dans des instructions (du code) qui est exécuté par des logiciels. Le travail de gestion d'une infrastructure devient donc en partie du travail de développement de logiciel -- d'où l'idée du nom DevOps, ou la fusion entre le développement et les opérations!
L'idée d'abstraire la représentation d'une infrastructure en tant que code apporte les avantages suivant:
- on retire la partie répétitive de toujours faire les mêmes configurations à la main. donc moins de travail long et ennuyeux
- on peut utiliser les mêmes techniques de travail que les développeurs de code comme:
- la gestion de versions de code (e.g. git, svn)
- les tests unitaires
- l'intégration continue
- la revue de code
- les merge requests
- réduit énormément le temps nécessaire pour la gestion d'une machine, puisque l'installation et la configuration sont automatisées
- on peut donc gérer des infrastructures beaucoup plus grandes que si on le faisait manuellement
- permet à toute l'équipe de lire quel est l'état des machines, et ensuite d'y apporter des changements
- en général le code se trouve dans un dépôt central et donc toute l'équipe devient en mesure de voir quels changements ont été apportés à l'infrastructure en relisant les commits
- si un problème survient, on peut revenir sur les modifications à la configuration via le dépot de code
- surtout: comme les changements apportés aux machines sont en fait du code, les changements peuvent être répétés souvent et rapidement exactement de la même manière
- donc par exemple: une fois qu'on a décrit la configuration d'un desktop, on peut en installer 10 exactement de la même manière en très peu de temps, et pourquoi pas 100, 1000!
- le code peut être partagé avec d'autres pour créer des outils puissants et surtout avec moins de bugs
- le partage de code est une des idées centrales du devops: favoriser la réutilisation du code plutôt que de garder ses "recettes secrètes" et réinventer la roue dans chaque compagnie différente
un outil en particulier, hiera, nous permettra de séparer les données spécifiques à notre infrastructure du code pour éviter de partager toutes sortes d'informations sensibles en même temps que le code.
Quels autres outils accompagnent généralement Puppet?
Comme on l'a déjà mentionné plus tôt, Puppet est généralement accompagné d'outils additionnels qui remplissent une fonction spécifique complémentaire. On peut utiliser plusieurs des outils plus bas directement sur la ligne de commande pour interroger les informations spécifiques que chacun permet d'obtenir, mais lors de l'utilisation de Puppet ces outils seront intégrés de manière transparente. Voici une liste des outils les plus communs et importants qui se rattachent à Puppet:
facter
extrait de l'information, nommée facts, par rapport à la machine qui devrait être immuable lors de l'exécution des changements par puppet
- c'est un peu comme une mini base de données d'informations propres à chaque machine. Quelques exemples d'information sont: les modèles de CPUs et leur nombre, la quantité de mémoire vive, les disques et les partitions, la version du noyau Linux, la version de la distribution Linux, est-ce qu'une machine est virtuelle ou physique, etc.
hiera
- permet de séparer le code des données, donc le paramétrage particulier à notre infrastructure se retrouve dans des fichiers à part.
- le code reste ainsi plus facile à lire: on décrit seulement qu'est-ce qu'on veut sur une machine selon les données qui seraient présentes
- le code n'a donc pas de données sensibles et spécifiques à notre infrastructure, ce qui veut donc dire qu'on peut partager ce code avec d'autres personnes et ainsi recevoir des commentaires et patches pour corriger certaines configurations
PuppetDB
- note: c'est un outil qui n'est pas obligatoire, mais sans lui certaines fonctions de Puppet comme les ressources exportées ne sont pas accessibles. c'est donc un outil qu'on retrouve la grande majorité du temps en accompagnement à Puppet.
- Interface abstraite sur une base de données
- Permet de stocker plusieurs types d'informations comme:
les facts (voir facter) des clients
- des ressources qu'on aurait exportées de certains clients et qu'on pourrait ainsi importer sur d'autres
- les catalogues des clients
- Offre un langage de recherche spécialisé via une interface (API) REST
- On peut ainsi récupérer plusieurs informations et les combiner pour avoir une meilleure compréhension de notre infrastructure
- permet de créer des rapports avec une vue globale par rapport à l'état de l'infrastructure
- On peut ainsi tisser des liens entre les données de toutes les machines
- Comme on peut inspecter les catalogues (code compilé), on peut également connaître qui et combien de machines utilisent certaines portion du code (e.g. certaines classes)
super outil pour quantifier certaines portions de notre infrastructure p-e par rapport à des projets en cours ou bien qu'on voudrait commencer dans pas longtemps (e.g. Nous visons terminer la mise à jour vers la version X du logiciel foo. Nous avons déjà terminé la mise à jour de Y serveurs mais il nous en reste encore Z de la version précédente)
- Deux exemples de requête pour puppetdb, en mots:
- Combien existe-t-il de machines qui utilisent la version 9 de debian, et ce sont lesquelles?
- Combien de plateformes physiques différentes existent dans l'infrastructure et ce sont lesquelles? Est-ce qu'on utilise plusieurs fabricant, plusieurs modèles différents?
- permet de créer des rapports avec une vue globale par rapport à l'état de l'infrastructure
git
Il est très fortement conseillé de conserver le code puppet dans un outil de gestion de versions de code et git est le plus populaire
- C'est grâce à ce type d'outil qu'on peut réutiliser plusieurs méthodes bien établies dans le domaine du développement logiciel
puppet-strings (pas obligatoire)
Outil qui cumule les commentaires qui sont au haut des fichiers et qui suivent un certain format particulier (format YARD) pour produire des pages HTML de documentation technique du code.
Puppet Bolt (pas obligatoire)
- permet l'exécution de scripts sur les serveurs sans avoir absolument besoin de la présence de Puppet
Bolt permet d'automatiser les changements qui sont plus ponctuels. Par exemple:
- redémarrer un serveur
- créer un snapshot LVM
- remplacer un disque par un autre dans un array RAID
Puppet Dashboard (pas obligatoire)
Interface web pour visualiser les agents puppet et leur configuration. Permet de consulter différentes informations par rapport aux agents comme les rapports d'exécution et les facts
- Peut également être utilisé pour la configuration des agents via l'assignation d'un rôle pour un agent
- Koumbit n'utilise pas cette interface
Jargon utilisé autour du logiciel Puppet
- agent
- Client Puppet. C'est le logiciel qui roule sur la majorité des machines et qui demande au serveur de lui fournir son code de configuration. C'est également l'agent qui applique les modifications nécessaires selon ce que le serveur a spécifié.
- serveur
(était anciennement nommé puppet master) point central de l'infrastructure qui fournit aux clients la configuration. Cette machine est spéciale et contient beaucoup d'information sensible (puisqu'elle connaît toute la configuration, les mots de passe, les certificats, etc.) de toutes les machines. On veut donc s'assurer de la protéger de manière stricte!
- manifest
nom donné aux fichiers qui contiennent du code Puppet. Ces fichiers auront normalement une extension .pp. Les manifests sont utilisés pour décrire plus qu'une seule machine: le même code peut s'adapter selon différentes valeurs, soit provenant des facts, soit de hiera
- catalogue
C'est le code Puppet qui est propre à une seule machine et qui a été compilé à partir des manifests. un catalogue est un format de type byte-code du code Puppet. L'agent peut utiliser le catalogue pour appliquer les changements qui lui sont nécessaires. Comme un catalogue est spécifique à une machine, chaque agent ne connaît pas les configurations des autres machines
- fact
une donnée extraite par l'outil facter. cette donnée ne changera pas durant la compilation du catalogue et elle peut être utilisée par le code pour créer des configurations différentes selon les valeurs des facts. Les facts sont disponible dans le code sous la variable globale $facts (tableau de données)
- ressource
- Bloc de construction de base dans le code Puppet. Chaque ressource représente une chose qui doit être présente sur la machine où l'agent s'exécute. Plusieurs types de ressources existent déjà dans Puppet, et on peut en créer des nouveaux.
- ressource exportée
Représentation d'une ressource dans une structure de données qui est sauvegardée dans la base de données de PuppetDB. On peut ensuite importer cette ressource sur une ou plusieurs autres machines. (dans la documentation, l'importation est nommée collecting resources)
- paramètre
- une paire de clef et valeur qui modifie le comportement d'une ressource. C'est un peu comme un paramètre de fonction dans du code: la clef identifie ce qu'on modifie, et la valeur nous permet de donner une valeur différente pour chaque ressource.
- classe
type de ressource de base qui est utilisé dans les manifests pour regrouper plusieurs autres ressources ensemble dans un bloc logique. Identifié dans le code par le mot class. C'est un conteneur pour du code plus précis. Une classe n'est traitée qu'une seule fois par machine lors de la compilation des catalogues -- ça nous assure ainsi qu'un certain groupe de ressources est présent, mais pas plus d'une fois. Les classes peuvent avoir des paramètres, défini dans le code lors de la construction de la classe, pour modifier son comportement.
- types de données
les paramètres des ressources peuvent être contraint à utiliser un certain type de données en particulier. si on rend le type de données le plus spécifique possible, ça nous permet de réduire les imprévus dans le code. Il existe plusieurs types de données de base dans Puppet, et on peut également en créer de nouveaux en combinant les types de bases. Le module stdlib écrit par Puppetlabs contient plusieurs types complexes additionnels qui sont très pratiques (par exemple pour représenter une chaîne de caractères qui devrait être une adresse IP)
- type défini
type de ressource de base qui regroupe plusieurs autres ressources ensemble. attention! ici on se réfère à un type de ressource alors que les types de données se réfèrent à des paramètres (la surcharge du mot "type" peut facilement devenir mélangeante). identifié dans le code par le mot define. C'est très similaire à une classe! Mais la différence est qu'un type défini peut être utilisé plusieurs fois dans une même machine dans le but de déclarer plusieurs choses différentes. Un exemple de cas d'utilisation pourrait être un vhost apache. tout comme pour les classes, les types défini peuvent avoir des paramètres définis dans le code qui permettent d'en modifier le comportement
- fonction
Code, généralement écrit en ruby, qui permet de modifier une certaine donnée. Par exemple on pourrait utiliser la fonction join() pour prendre toutes les valeurs d'un tableau de données et les coller ensemble dans une seule chaîne de caractères avec chaque valeur séparée par un délimiteur. Les fonctions sont exécutées sur le serveur puppet lors de la compilation du catalogue.
- module
regroupement de manifests, de définitions de fonctions, et d'autres fichiers pour former un bloc logique de code. Le plus souvent un module représente tout ce qui est nécessaire pour l'installation et la configuration d'un logiciel particulier. Par exmple le module mysql installe et configure mysql.
Exercice: Découvrir de l'information à propos d'une machine à l'aide de facter
On peut lancer manuellement l'outil facter pour découvrir les mêmes informations à propos d'une machine que Puppet trouverait lors de son exécution.
On peut demander une information précise:
facter processors.count
On peut séparer les noms des valeurs demandées par un . ce qui veut dire dans l'élément de gauche, chercher l'élément de droite, e.g. l'élément processors est en fait un tableau de données qui contient un élément qui s'appelle count.
facter
Sans donner de nom de valeur, on obtient toutes les valeurs connues par facter.
Trouver dans la réponse de la commande:
- la taille des différentes partitions de disques sur la machine
- le modèle de CPU
Demander à facter seulement la valeur de la version majeure de la distribution linux du système.
quel argument avez-vous donné à la commande facter pour obtenir cette information?
Lorsque puppet demande de l'information à facter, certaines informations additionnelles sont affichées. On peut demander à facter de nous les afficher en ajoutant un argument:
facter -p
Identifier la version de puppet dans la réponse de l'outil
Il est à noter: toutes les valeurs qui sont présentes dans la réponse de la commande facter sont accessibles au code puppet à travers la variable globale $facts.
Pour accéder à un fact spécifique dans du code puppet, on doit utiliser des crochets pour accéder à un élément du tableau.
Dans les quelques exemples suivant, on utilise la ressource de type notify pour afficher le contenu de la variable sur le terminal dans la réponse du client puppet:
notify { $facts['package_provider']: } # identifie le logiciel qui est utilisé pour l'installation de packages
notify { $facts['processors']['count']: } # le nombre de processeurs dans la machine
Comment est-ce que Puppet communique avec les différents outils?
Communication entre agent et serveur
HTTPS sur le port 8140 avec l'aide de certificats clients pour l'authentification en plus d'un certificat serveur
- exactement le même type de certificats qu'on utilise pour HTTPS. Par contre les certificats des clients doivent être signés par le serveur
- le serveur agit comme Certificate Authority (CA) envers les agents
facter
- lancé localement par l'agent puppet
hiera
- utilisé localement par le serveur puppet lors de chaque compilation de catalogue
- hiera version 5 est en fait du code ruby qui est inclus dans Puppet
PuppetDB
- Le serveur Puppet communique avec PuppetDB via HTTPS sur le port 8081
git
- Puppet n'interagit pas directement avec l'outil, mais utilise simplement les fichiers que celui-ci présente dans un répertoire donné sur le serveur
Exercice: Se familiariser avec l'agent (client) Puppet
L'outil de ligne de commande de Puppet s'appelle puppet (tout en minuscules). puppet offre des détails sur comment on peut l'utiliser:
# Cette commande vous offre une série de sous-commandes possibles à utiliser.
puppet --help
# Pour obtenir de l'aide à propos d'une des sous-commandes, on peut utiliser la sous-commande 'help':
puppet help agent
puppet help apply
Comme le nom de la sous-commande l'implique, agent permet de rouler en tant qu'un agent, et donc d'obtenir les modifications à partir d'un serveur central.
# en premier lieux, on veut activer l'agent, qui a été désactivé pour le début de la formation
# en temps normal, l'agent devrait rester activé en tout temps, sauf si on veut explicitement
# mettre l'agent sur pause pour investiguer quelque chose sur la machine et éviter que puppet ne
# change quelque chose pendant notre investigation
puppet agent --enable
# lancer l'agent. l'option -t active la trace des activités de l'agent à l'écran
puppet agent -t`
## Constater ici dans la réponse les différentes étapes suivies par l'agent ainsi que qu'est-ce qui a été modifié
La sous-commande apply permet de faire des modifications sur la machine en utilisant du code soit passé en argument, soit via un fichier qui se trouve sur la machine même (contrairement au cas de l'agent où les fichiers de code se trouvent obligatoirement sur le serveur).
# -e permet de donner le code sur la ligne de commande
puppet apply -e 'file { "/tmp/hello_world": ensure => present, content => "mon premier fichier"}'
## Constatez que le fichier a bel et bien été modifié sur la machine.
# Donc il faut faire attention si on test quelque chose via `puppet apply` puisque le changement est vraiment appliqué.
# on peut ajouter --noop à la commande pour que `puppet apply` n'effectue pas les changements de mandés sur la machine.
# l'outil affiche alors seulement quels seraient les changements qui auraient été appliqués, mais sans les faire.
# ici au lieu d'utiliser -e, on donne un nom de fichier (qui existe présentement sur disque)
# pour que le code dans ce fichier soit appliqué
puppet apply /etc/puppet/code/environments/production/brise.pp
## Ce fichier nous donne une erreur! Constater quel est le format de cette erreur et tenter de corriger cette erreur
## Le fichier comprend en effet plusieurs erreurs. Continuez d'appeler `puppet apply` pour vérifier quelles nouvelles erreurs
## l'outil affiche et tentez de les corriger dans le fichier, jusqu'à ce que puppet effectue les changements sans erreur
En utilisant puppet apply -e '...' comme plus haut, et en vous basant sur les exemples dans la section d'exercice par rapport à facter, affichez la capacité totale de mémoire système (RAM).
Quelques exemples simples de structures du langage Puppet
On plongera beaucoup plus en détail dans le langage de programmation Puppet dans la FormationPupppetDSL. Cependant, pour pouvoir commencer à explorer puppet tout de suite, nous verrons ici quelques idées de base qui nous permettront d'exprimer les choses les plus imporantes: déclarer une ressource et ordonnancer l'application des changements pour chacune.
Commentaires
Comme dans tous les langages de programmation, il est très utile d'ajouter des commentaires dans le code que l'on écrit pour offrir des explications additionnelles comme par exemple pourquoi certains cas spéciaux devraient être présent ou encore quel est le comportement qu'un paramètre modifie et quelles en sont les valeurs possibles.
Les commentaires dans le code Puppet commencent par un dièse #. On peut placer un dièse en début de ligne pour avoir toute une ligne en commentaire, ou alors placer un dièse à la droite d'une ligne de code pour ajouter un commentaire sur la même ligne que le code.
Par exemple (ici les mots @summary et @param sont utilisés par l'outil puppet-strings pour créer la documentation pour un fichier de code):
# @summary Ce commentaire décrit en général ce que le bloc de code fait, et comment on peut
# modifier son comportement.
#
# @param blah
# Nombre entier qui permet de spécifier combien de `blah` se retrouvent dans le fichier de configuration `foo`
#
class foo (
Integer $blah = 1, # 1 ici c'est la valeur par défaut si "blah" n'est pas spécifié
)
{
# ...
}
Ressources de base dans Puppet
Puppet contient déjà du code pour représenter plusieurs types de choses dans un ordinateur. La liste complète est visible dans la documentation de puppet (C'est une page très utile à garder en marque-page)
Avec les types de ressources de base, on peut déjà configurer une grande majorité des services possibles. On peut également créer des types de ressources plus complexes qui contiennent plusieurs ressources de base d'une certaine façon spécifique (à l'aide de classes et types définis). Nous verrons ces ressources complexes dans une formation future.
Les ressources de base qui sont utilisées de manière la plus commune sont, en ordre:
- file
- un fichier ou un répertoire qui devrait être présent sur le serveur ou absent sous un certain chemin. on peut gérer ses permissions, p-e définir son contenu
file { '/chemin/vers/le/fichier': ensure => present, owner => 'root', mode => 0700, content => 'Cette chaîne de caractères remplacera entièrement le contenu du fichier', } file { '/etc/logiciel/configuration_bogus.conf': ensure => absent, }
- un fichier ou un répertoire qui devrait être présent sur le serveur ou absent sous un certain chemin. on peut gérer ses permissions, p-e définir son contenu
- package
- un logiciel devrait être présent sur l'ordinateur. on peut l'installer à l'aide des packages de la distribution
package { 'borg': ensure => present, }
- un logiciel devrait être présent sur l'ordinateur. on peut l'installer à l'aide des packages de la distribution
- service
- un service devrait être soit actif, soit désactivé sur une machine
service { 'apache2': ensure => running, }
- un service devrait être soit actif, soit désactivé sur une machine
- user
- un certain utilisateur devrait être présent sur la machine
user { 'farah': ensure => present, uid => 1030, gid => 901, groups => ['adm', 'sudo', 'libvirt'], home => '/home/farah', shell => '/bin/bash', password => '$6$.....', }
- un certain utilisateur devrait être présent sur la machine
- group
- un certain groupe d'utilisateurs devrait exister sur la machine
group { 'admins': ensure => present, gid => 901, }
- un certain groupe d'utilisateurs devrait exister sur la machine
- cron
- une tâche périodique devrait exister et appeler une certaine commande à un horaire défini
cron { 'cleanup': ensure => present, command => '/usr/local/bin/cleanup_my_mess', user => 'root', hour => 1, minute => 35, }
- une tâche périodique devrait exister et appeler une certaine commande à un horaire défini
- ssh_authorized_key
- une clef publique SSH devrait permettre l'accès à un certain utilisateur de la machine
ssh_authorized_key { 'gontrand@desktop301': ensure => present, user => 'adminweb', type => 'ssh-rsa', key => 'AAA......qXfdaQ==', }
- une clef publique SSH devrait permettre l'accès à un certain utilisateur de la machine
- exec
- une commande devrait être exécutée sur la machine
- dernier recours: il est très facile de représenter une commande qui sera exécutée à chaque fois que le client Puppet s'exécute malgré que celà n'est pas nécessaire. Il est généralement préférable d'utiliser un des types de base ou même un type plus complexe pour représenter l'état des choses sur une machine. quelques fois par contre c'est inévitable.
exec { 'activate_license': command => '/opt/proprietary_softwareY/bin/active_license', creates => '/opt/proprietary_softwareY/etc/license_file', }
Relations d'ordre entre les ressources
Dans le code Puppet on déclare qu'est-ce qui devrait être contenu dans une machine. Mais des fois, il faut absolument qu'une chose existe avant qu'une autre puisse exister.
Par exemple, avant de pouvoir configurer un logiciel, il faut que celui-ci soit installé.
On peut déclarer l'ordre entre deux ressources en utilisant l'opérateur -> (flèche à droite) entre les deux ressources. Ça indique à Puppet que la ressource qui précède (est à gauche de) la flèche doit être traitée avant celle qui suit la flèche.
Par exemple:
# Le répertoire my.conf.d doit exister pour qu'on puisse créer des fichiers dedans
file { '/etc/mysql/my.conf.d':
ensure => directory,
owner => 'root',
group => 'mysql',
mode => '0700',
}
-> file { '/etc/mysql/my.conf.d/tuning.conf':
ensure => present,
owner => 'root',
group => 'root',
mode => '0640',
}
On peut également avoir une relation d'ordre qui en plus envoie un signal à la ressource qui suit la flèche. On utilise pour ceci une flèche avec un tilde au lieu du tiret, ~>.
Ce ne sont pas tous les types de ressources qui réagissent à un signal. Le plus commun type de ressource utilisé avec ce type d'ordonnancement est service.
Lorsqu'un changement est apporté à la ressource précédent un service dans une relation de flèche avec tilde (avec signal), le service sera alors redémarré automatiquement. Ça nous assure ainsi que les changements que puppet a apporté à la configuration seront pris en compte immédiatement par un service.
Le service dans ce cas ne sera pas redémarré dans les cas où Puppet considère qu'aucun changement n'a été nécessaire aux ressources précédent les flèches avec tilde (donc si la configuration ne change pas, on ne redémarre pas le service pour rien)
Par exemple:
file { '/etc/apache2/conf-enabled/security.conf':
ensure => link,
target => '/etc/apache2/conf-available/security.conf',
}
~> service { 'apache2':
ensure => running,
}
Avec les deux types de flèches, on peut utiliser l'opérateur flèche plusieurs fois pour définir des relations de plusieurs ressources avec une seule ressource finale. On peut donc par exemple s'assurer que plusieurs fichiers de configuration devront exister avant qu'un service soit lancé et également que le service soit redémarré si n'importe lequel des fichiers de configuration subit une modification.
Nous verrons les relations d'ordonnancement plus en détail dans une formation future.
Quelques outils alternatifs à Puppet
- ansible
- mgmt
- salt stack
- chef
Exercice: Ecrire un premier script
créer un fichier test.pp et utiliser les ressources de base pour:
installer le package mariadb
créer le fichier de configuration /etc/mysql/conf.d/my_config.cnf avec comme contenu
[mysqld] max_connections=100
s'assurer que le service mariadb est bien en marche
- Assurez-vous d'ordonnancer les ressources entre elles pour que les opérations puissent toutes se faire en une seule passe. L'ordre devrait être le même que les points plus haut.
- la relation d'ordonnancement entre le fichier de configuration et le service devrait utiliser un signal pour redémarrer le service lorsqu'il y a un changement au fichier de configuration
appliquer le script test.pp avec puppet apply test.pp
- Constater dans la réponse que les changements attendus ont bel et bien eu lieu.
Voilà, vous avez reproduit le pattern qui est utilisé dans environs 80 à 90% des cas pour la gestion de différents logiciels sur les serveurs!
Dans le cas de la gestion via le serveur, la différence c'est simplement que le fichier manifeste, test.pp, devrait se trouver au bon endroit sur le serveur au lieu du client, et à ce moment on l'applique en appelant puppet agent -t.
Rétrospective
Pendant un maximum de 15 minutes, les participant.e.s sont invité.e.s à partager les éléments qui ont bien ou moins bien fonctionnés et les idées qui pourraient survenir pour des manières d'améliorer le processus.
Quelques éléments qui peuvent faire partie de la rétrospective, dépendant de la grosseur du projet ou de la formation:
- Sommaire collectif (e.g. résumé rapide en termes que tout le collectif peut comprendre)
Pas trop utile pour les projets vraiment simples ou les formations.
- Chronologie des événements marquant pour le projet
Surtout utile pour les projet qui se sont étalés sur plusieurs jours ou plus ou bien quand beaucoup de choses se sont produites simultanément, ce qui a rendu la compréhension des influences de chaque événement complexe.
- Les bons coups -- qu'est-ce qui a bien fonctionné et qu'on veut tenter de reproduire
- Les problèmes
- échecs -- avec l'aide de la chronologie (si elle a été faite), tenter de situer les échecs dans un contexte selon ce qui était connu des participant.e.s aux moments qui ont mené à l'échec
- problèmes techniques
- manques de ressources
- perturbations externes
- Une liste d'actions à court et/ou à plus long terme pour améliorer les choses telles que soulignées pendant les points précédents
- Transférer les actions dans redmine pour qu'elles puissent être suivies!
N'hésitez pas à partager les échecs à l'extérieur de l'équipe puisqu'on peut apprendre beaucoup de ceux-ci, mais surtout évitez de les formuler comme un blâme sur la/les personne(s) ayant échoué.
Une rétrospective est surtout utile quand on la partage: ça permet aux autres d'apprendre de nos erreurs et aussi de nos idées d'améliorations. On peut par exemple envoyer une forme écrite par email, ou bien sauvegardée comme page wiki.
Information complémentaire
- formations suivantes: