Aperçu

Formations préalables

Temps estimé

Environs 60mins

Objectifs

  1. Utiliser les fichiers YAML de hiera pour contrôler la configuration sur un serveur
  2. Comprendre comment les valeurs dans les fichiers YAML sont reliées au code puppet et à quels serveurs les données sont appliquées.
  3. Débugger les valeurs contenues dans un fichier YAML
  4. Se familiariser avec les bonnes pratiques de code puppet et le style déclaratif du langage
  5. Se familiariser avec le stockage additionnel que Koumbit utilise pour la gestion des données sensibles

Préparation des participant.e.s

Pour une formation à l'équipe infra de Koumbit:

Pour faire les exercices dans cette formation, nous utiliserons les machines virtuelles du projet Vagrant dans le control repository. Plus spécifiquement, les exercices seront faits sur un client puppet spécial, pm_buster, donc le puppetmaster lui-même. La raison pour ça c'est que pm_buster contient déjà des données hiera et donc ça donne la chance de chercher une information à travers les niveaux de hiérarchie.

Nous présumerons ici que les participant.e.s ont déjà mis en place vagrant avec libvirt et KVM durant la formation préalable.

Le jour avant la formation, assurez-vous que les VMs fonctionnent toujours bien. Pour démarrer la VM:

vagrant up pm_buster

Pour les formations externes à Koumbit:

Cette formation suppose que le même environnement de VMs que pour FormationPuppetIntroduction existe déjà. Si ça n'est pas le cas, suivre la préparation dans cette autre formation en premier.

Les participant.e.s devraient révérifier que leur accès SSH vers les VMs fonctionne toujours bien. On réutilisera les VMs "client" pour les exercices.

Théorie, concepts et information

TL;DR:

Exemple de stockage en YAML

Un fichier YAML commence toujours par trois tirets ("---") seuls sur une ligne, qui indique à YAML le début du document.

Les clefs sont la partie au début de la ligne, y compris les doubles deux-points ("::"), jusqu'à un simple deux-points suivi d'un espace (": "). Les données sont tout ce qui suit à droite de ce délimiteur. Il est également possible d'avoir une fin de ligne à la place de l'espace pour le délimiteur, puis les lignes suivantes représentent une donnée plus complexe selon un formattage spécial défini par YAML.

Voici un example de fichier YAML formatté pour Hiera:

---

sudo::purge: true

# Some default values for SA to reduce useless requests to URIBLs. It should
# help setups to avoid being banned by URIBLs by keeping volume lower for a
# while longer.
profile::spamassassin::uridnsbl_skip_domain:
  - "googleapis.com"
  - "goo.gl"
  - "googlegroups.com"
  - "docs.google.com"
  - "youtu.be"
  - "linkedin.com"
  - "fbcdn.net"

profile::unattended_upgrades::origins:
  koumbit:
    "origin=koumbit.net,label=koumbit.net"
  debian:
    "origin=Debian,label=Debian"
  debian_security:
    "origin=Debian,codename=${distro_codename},label=Debian-Security"

Les lignes qui commencent par un certain nombre d'espaces, puis un dièse, sont ignorées et donc utilisées comme commentaires.

Dans le fichier, on peut voir trois exemples de formats de données:

Exercice: Utilisez l'outil en ligne https://yamlvalidator.com/ pour vous familiariser avec la syntaxe YAML. Vous pouvez entrer un contenu dans la boîte de texte et le site vérifiera si la syntaxe du fichier est conforme, sinon vous obtiendrez un message vous indiquant ce qui cloche. Vous obtiendrez également une représentation en JSON des données dans la boîte à droite pour vous montrer comment YAML interprète les informations.

N.B.: dans linux, un outil qui donne de l'information similaire sur la ligne de commande est yamllint. Cet outil donne en fait plus d'information puisqu'il vérifie également certaines formes de "bonnes pratiques" comme la longueur des lignes. Il s'agit d'un module python et donc il est également possible de l'utiliser sur MacOS et Windows: https://pypi.org/project/yamllint/

Les niveaux de hiérarchie

Pour définir les niveaux de hiérarchie et le format de stockage utilisé par Hiera, il faut créer un fichier hiera.yaml sous le répertoire de configuration de puppet, donc dans /etc/puppet/hiera.yaml.

Chez Koumbit, ce fichier est présentement géré par puppet lui-même dans le "control repository" sous site/profile/files/puppet/hiera.yaml mais d'autres pourraient décider de ne pas le gérer via Puppet. L'avantage d'imposer la gestion du fichier par puppet lui-même c'est de pouvoir conserver le contenu du fichier au même endroit que toutes les autres configurations, donc dans le "control repository", et de conserver l'historique des modifications sur son contenu dans git.

Voici un exemple d'extrait du fichier, où les niveaux de hiérarchie sont définis:

:hierarchy:
  - "node/%{::fqdn}"
  - "location/%{::location}"
  - "osdistcodename/%{::os.lsb.distcodename}"
  - common

Exercice: Ouvrez le fichier /etc/puppet/hiera.yaml dans votre VM et identifiez quels sont les niveaux de hiérarchie définis et lesquels sont évalués avant quels autres.

Les niveaux de hiérarchie sont parcourus en ordre par puppet, en commençant par le premier élément en haut de la liste et chaque niveau ensuite jusqu'au dernier au bas de la liste.

Si la clef recherchée n'est pas trouvée dans un niveau de hiérarchie, on passe au prochain niveau. Si on trouve la clef recherchée, on obtient cette valeur là et on arrète la recherche à ce niveau là.

On peut utiliser des variables, qui correspondent ici à des valeurs de "facts" des différentes nodes, dans le format %{nom_de_la_variable}. La valeur d'un "fact" peut être différente selon le client puppet qui est en train de s'exécuter. Grâce à ces variables, les noms des différents fichiers consultés pour chaque niveau de hiérarchie peuvent varier selon différentes informations propres à chaque machine.

Exercice: A l'aide de facter -p sur la VM, identifiez un "fact" qui pourrait être utilisé comme un niveau de hiérarchie, et expliquez en vos mots ce que ce niveau de hiérarchie ajouterait comme distinction entre différentes machines.

Toujours dans le fichier hiera.yaml mentionné plus haut, on y défini l'emplacement du répertoire qui contient les différents niveaux de hiérarchie définis plus haut. C'est sous :yaml -> :datadir qu'on retrouve quel répertoire contient le stockage des données selon les niveaux.

Exercice: Identifiez quel répertoire sur la VM contient présentement les données. S'il n'existe pas, créez le répertoire puis créez un des fichiers qui sera consulté par hiera pour obtenir des données.

Le chemin vers les données sous :yaml -> :datadir, tout comme pour les chemins des niveaux hiérarchiques, peut contenir des variables.

Chez Koumbit on utilise cette propriété pour trouver les données dans un répertoire qui dépend du nom de l'environnement de code qu'on utilise. En plaçant le répertoire à cet endroit là, le répertoire de données sera toujours sous le même répertoire que le code puppet et ça veut donc dire qu'on peut conserver les données dans le même dépôt git que tout le reste, le "control repository". Ce n'est pas une pratique obligatoire: on fait ça pour simplifier la gestion et pour conserver les données dans l'historique git. Donc dans le cas de Koumbit, les fichiers de stockage hiera se trouvent sous hieradata/ dans le "control repository".

Sous le répertoire de données de hiera, chaque niveau de hiérarchie a un fichier correspondant, avec une extension .yaml ajoutée à la fin. Donc si on se fie à l'exemple des niveaux de hiérarchie au début de la section, pour une node ayant comme domaine complet (son fqdn) foo.koumbit.net, le fichier correspondant au premier niveau sera, sous le répertoire de données (donc dans hieradata/ dans le "control repository"), node/foo.koumbit.net.yaml.

Pour un serveur particulier, étant donné les niveaux de hiérarchie définis plus haut:

  1. le niveau qui a la plus grande précédence est le nom de domaine complet de la machine.
  2. puis, l'emplacement physique d'une machine peut définir certaines valeurs
  3. ensuite le nom de la version de la distribution linux peut définir certaines valeurs
  4. finalement, le fichier nommé "common.yaml" pourra définir des valeurs communes à toutes les machines.

Cette hiérarchie n'est qu'un exemple. Si vous gérez le contenu du fichier hiera.yaml vous pouvez définir les niveaux de hiérarchie qui vous semblent être utiles pour mieux classifier vos informations.

Motivation pour l'utilisation d'un moteur de stockage de données externe au code

La raison qui a été donnée pour créer l'outil hiera, c'est que quand écrit du code puppet, on aimerait pouvoir réutiliser ce code là le plus possible et même le partager avec d'autres personnes qui voudraient installer les logiciels de manière similaire à nous. Or, si le code utilise plein de valeurs qui sont spécifiques à l'infrastructure très particulière d'un endroit, ce code là ne pourra pas se faire partager.

On veut donc séparer la logique du code (e.g. qu'est-ce qu'on installe et à quel endroit, sous quelles conditions etc) des configurations exactes.

Pour donner un exemple concret, imaginez-vous avoir un module de code qui configure le logiciel HA Proxy. Ce logiciel permet de configurer un load-balancer pour toutes sortes de sites HTTP et de services TCP.

Vous voudriez alors configurer le logiciel pour qu'il réponde à un site web, example.com, mais seul vous avez besoin de configurer le logiciel pour ce site là. Aussi, seul vous avez cinq serveurs HTTP (des "backends") qui répondent spécifiquement à ce site web là et vers où HA Proxy devrait rediriger les visites.

Donc le module de code puppet devrait avoir tous les mécanismes nécessaires pour l'installation de HA Proxy et pour la configuration de sites arbitraires et de "backends" arbitraires.

La configuration précise requise pour le site example.com sera alors placée dans les fichiers hiera et, du coup, donné en paramètre au code puppet qui configurera les choses selon cette information là.

C'est grâce à cette séparation des données qu'on retrouve maintenant des centaines de modules déjà écrits par différentes personnes sous https://forge.puppet.com/ et qu'on peut réutiliser souvent tels quels. Avant que la séparation n'existe, la tendance chez les utilisatrices.teurs était plutôt à conserver tout leur code secret pour éviter d'exposer des information privées (vu qu'il y avait des données spécifiques à chaque organisation directement dans le code puppet, donc p-e des mots de passe ou autres informations sensibles).

Redéfinition (override) de valeur d'un paramètre de classe ou de type défini

attachment:puppet_param_lookup.svg

Dans du code puppet, Puppet ne cherchera pas de valeur pour les paramètres qui ont été spécifiés explicitement dans le code puppet lors de l'appel d'une classe ou d'un type défini. Donc les valeurs qui sont données aux paramètres directement dans le code prennent la plus haute priorité. Par contre, si on utilise une classe ou un type défini sans en spécifier un ou plusieurs paramètres, puppet se mettra alors à chercher la valeur de chaque paramètre qui n'a pas été défini dans le code.

Quand puppet cherche la valeur d'un paramètre, la clef qui est recherchée correspond au nom de la classe ou du type défini suivi d'un double deux-points suivi du nom du paramètre recherché.

Donc supposons que nous avons un fichier dans le module profile nommé manifests/spamassassin.pp et qui commence par une définition comme celle-ci:

class profile::spamassassin (
  $enable,
  $uridnsbl_skip_domain = []
) {
# [...]

On a un paramètre nommé uridnsbl_skip_domain pour la classe nommée profile::spamassassin. Donc puppet cherchera dans le stockage Hiera la clef profile::spamassassin::uridnsbl_skip_domain.

Dans la définition plus haut, on peut noter que la classe profile::spamassassin défini une valeur par défaut pour le paramètre uridnsbl_skip_domain (un tableau vide). La valeur par défaut notée dans la définition de la classe sera la valeur utilisée en dernier recours, donc:

De la même manière que pour uridnsbl_skip_domain, le paramètre enable peut avoir une valeur dans hiera même s'il n'a pas de valeur par défaut dans le code (hiera cherchera alors profile::spamassassin::enable comme clef dans les fichiers YAML). La recherche de données dans hiera se fera exactement de la même manière à l'exception du cas où aucune donnée n'est trouvée (ni dans le code puppet qui appelle la classe profile::spamassassin ni dans hiera): dans ce cas, puppet produira une erreur puisqu'aucune valeur n'a pu être trouvée pour le paramètre enable.

voir https://puppet.com/docs/puppet/5.5/hiera_automatic.html#class_parameters

Exercice: Avec les niveaux de hiérarchie suivant définis dans hiera.yaml:

---
:hierarchy:
  - "node/%{::fqdn}"
  - common

.. et les fichiers suivant sous le répertoire de données hiera:

common.yaml:

---
sudo::users:
  admin:
    host: 'ALL'
    permission: 'ALL'
  webmaster:
    host: '192.168.10.123'
    permission: '/usr/sbin/apache2ctl -S'

asterisk::voicemail::context: "main"
asterisk::voicemail::user_name: "pèrenoël"

node/chou.koumbit.net.yaml:

---
sudo::users:
  admin:
    host: '10.1.1.59'
  webmaster:
    group: 'WEBMASTERS'
  externalfirm:
    host: 'ALL'
    permission: '/usr/sbin/service apache2 restart'

asterisk::voicemail:
  password: "blah, blah, meuh"

asterisk::voicemail::user_name: "yogev"

.. et finalement avec la définition suivante (vous n'avez pas besoin de l'inscrire dans un fichier pour les exercices de cette formation -- c'est simplement pour avoir un exemple de code à utiliser comme exemple pour la recherche de valeurs de paramètres):

class asterisk::voicemail (
  $context,
  $password,
  $user_name = undef,
  $email = undef,
) {
  # ...
}

A l'aide du graphe au début de la section, identifiez le chemin de recherche de données ainsi que la valeur trouvée pour chacun des paramètres de la classe en supposant que cette classe a été utilisée sans spécifier aucune valeur pour les paramètres. Indentifiez les erreurs de recherche de données s'il y en a.

N.B.: Pour vous aider à identifier ce qui fonctionne ou pas, vous pouvez utiliser l'outil puppet lookup nom_de_clef_recherchée sur la ligne de commande dans la VM. Cette commande simule ce que puppet fait lors de l'exécution de code pour retrouver une certaine clef dans son stockage. Si vous recréez les fichiers yaml plus haut (pas besoin de recréer le code puppet) sous le répertoire de données hiera, vous pouvez alors demander à puppet lookup de trouver les informations.

N.B.2: Le même outil a une option qui peut vous permettre de mieux comprendre où les données sont cherchées et trouvées. Si vous ajoutez l'option --explain, donc par exemple puppet lookup --explain nom_de::clef, vous obtiendrez une trace de la recherche d'information.

Obtenir une valeur arbitraire à partir du code

Comme l'objectif d'utiliser Hiera est de retirer le plus possible les données du code, on peut utiliser un deuxième mécanisme pour trouver de l'information qu'on peut utiliser dans du code puppet, donc dans un fichier .pp: une recherche explicite à l'aide de la fonction lookup().

La recherche de données avec la fonction lookup() se comporte exactement de la même manière qu'on l'a vu dans la section précédente.

Dans l'exemple plus bas, on cherche la valeur de la clef dovecot::sudo_rule, puis on utilise le résultat comme valeur de paramètre "content" pour la ressource sudo::conf:

$dovecot_sudo = lookup('dovecot::sudo_rule')
sudo::conf { 'dovecot':
  content => $dovecot_sudo,
}

On peut également donner un paramètre additionnel à la fonction lookup() pour fournir une valeur par défaut si jamais la clef n'est pas trouvée dans hiera:

$chose = lookup('quelquechose', 'pas trouve')

Si hiera ne trouve pas une clef et une valeur par défaut n'est pas sécifiée, une erreur sera produite.

Méthodes de recherche d'information

Hiera offre différentes méthodes pour "trouver et combiner" l'information. Dans la documentation officielle de puppet, c'est appelé "merge behavior".

Celle qui est utilisée par défaut (first) est celle que l'on a vue à date: la première valeur trouvée dans les niveaux de hiérarchie est celle qui est retournée.

Il existe cependant d'autres méthodes qui permettent de répondre à des cas plus spécifiques.

Voir: https://puppet.com/docs/puppet/7/hiera_merging.html#merge_behaviors

Exercice: En réutilisant les fichiers YAML de l'exercice de la section #Redéfinition (override) de valeur d'un paramètre de classe ou de type défini, vérifiez les résultats des recherches avec différentes stratégies de recherche:

# first
puppet lookup asterisk::voicemail::user_name
# unique
puppet lookup --merge unique asterisk::voicemail::user_name

# first
puppet lookup --merge hash sudo::users
# hash
puppet lookup --merge hash sudo::users
# deep
puppet lookup --merge deep sudo::users

En plus de l'argument --merge sur la commande comme plus haut, la méthode de recherche peut être spécifiée lors de l'appel à la fonction lookup() dans le code puppet en passant un dictionnaire qui spécifie le nom de la méthode:

$quelquechose = lookup('ressource::param', {'strategy' => 'unique'})

On peut également configurer une méthode de recherche pour chaque clef à l'intérieur même d'un fichier YAML de hiera. Cette configuration se fait à l'aide de la clef spéciale lookup_options. Par exemple, dans le fichier node/chou.koumbit.net.yaml le contenu suivant définira la méthode de recherche pour la clef sudo::users:

# la clef spéciale au premier niveau:
lookup_options:
  # au second niveau, on utilise comme clef le nom de la clef pour
  # laquelle on applique la méthode de recherche
  "sudo::users":
    merge:
      strategy: deep

Mots de passe et valeurs sensibles

Koumbit utilise un outil additionnel pour le stockage de données sensibles: trocla.

trocla est un outil qui permet non seulement de sortir les données sensible des fichiers hiera, mais également d'automatiser la génération de mots de passe formattés pour plusieurs applications et aussi d'autres formes de données sensibles comme le contenu des certificats TLS.

Cet outil nous permet donc:

  1. De séparer les données sensibles dans un endroit qui n'est pas accessible par le même mécanisme d'accès que le dépot git du "control repository". On peut donc restreindre qui a accès à ces données sensibles.
  2. D'ajouter les données hiera qui ne sont pas sensibles dans le "control repository" sans peur de fuites de données.
  3. De complètement nous retirer la tâche de générer et maintennir certains mots de passe et de déléguer ce détail au serveur puppet.
    • Ces valeurs sont générées lors d'une exécution de l'agent puppet. Lors de la compilation du catalogue pour cet agent, quand trocla est appelé pour obtenir l'information sensible, celle-ci sera générée automatiquement si elle n'existe pas déjà puis le résultat sera ajouté au stockage de trocla. On obtiendra donc le même mot de passe dans les exécutions futures de l'agent après la génération initiale.

Sur les puppetmasters, donc sur pm_buster et sur le serveur en production, Koumbit stocke présentement les donnés sensibles de trocla sous /var/lib/trocla/trocla_data.yaml. L'emplacement de ce fichier peut être déterminé via le ficher de configuration /etc/troclarc.yaml (celui-ci n'existe pas par défaut et il faut le créer pour modifier l'emplacement). Si le fichier de configuration n'existe pas, trocla va utiliser un fichier sous /tmp et donc c'est important de configurer l'outil avant de l'utiliser pour la première fois.

On peut utiliser trocla de trois manières:

  1. via l'outil de ligne de commande trocla

  2. dans un lookup à travers un fichier hiera

  3. dans un appel de fonction dans le code puppet (dans un fichier .pp)

Exercice: Découvrir les formats de stockage de mots de passe

trocla formats

trocla utilise toujours à la fois une clef de stockage et un nom de format. L'outil peut reformatter un mot de passe pour qu'il soit dans un format qui est directement utilisable par certains outils. Par exemple si on utilise le format 'sha512crypt', le mot de passe sera transformé en un hash de mot de passe avec l'algorythme sha512 dans un format utilisable par la fonction crypt (donc par exemple c'est le format de stockage par défaut des mots de passe pour les comptes linux dans le fichier /etc/shadow).

Si le format demandé n'est pas présent dans le stockage, alors si le format 'plain' existe trocla transformera celui-ci dans le format demandé et l'ajoutera au stockage avant de le retourner. Par contre dans la même situation si le format 'plain' n'existe pas trocla ne saura pas quoi transformer dans le bon format et ne retournera alors rien.

Si une clef de stockage contient un mot de passe sous un format qui n'est pas 'plain' et qu'on demande le mot de passe sous le format qui existe présentement dans le stockage, celui-ci sera retourné. Il n'est donc pas nécessaire d'avoir les mots de passe en "plain text" dans le stockage: on peut insérer dans le stockage des mots de passe déjà transformés.

Exercice: Utilisez l'outil de ligne de commande pour ajouter un mot de passe, puis le consulter:

# Ajouter un mot de passe avec une valeur conue sous la clef 'nouveau_mot_de_passe'.
# Le mot de passe sera demandé à l'écran
trocla set 'nouveau_mot_de_passe' 'plain'
# Consulter le mot de passe
trocla get 'nouveau_mot_de_passe' 'plain'
# Créer le mot de passe au format utilisable pour un utilisateur mysql
# le mot de passe 'plain' existe déjà et donc il sera utilisé pour le formattage
trocla create 'nouveau_mot_de_passe' 'mysql'
# Obtenir le mot de passe sous format mysql
# le même mot de passe que précédemment sera retourné
trocla get 'nouveau_mot_de_passe' 'mysql'
# Créer un mot de passe alléatoire, le reformatter en sha512crypt et le retourner
trocla create 'un_autre_mot_de_passe' 'sha512crypt'
# A noter: la commande précédente a d'abord créé un mot de passe "plain text"
# alléatoire sous le format 'plain', et l'a ajouté au stockage.
# Donc on peut maintenant obtenir le mot de passe "plain text".
trocla get 'un_autre_mot_de_passe' 'plain'
# On peut également reformatter le même "plain text" pour un autre outil avec
# une commande similaire à plus haut (e.g. avec trocla create).
# Ici on reformatte le mot de passe pour l'utiliser via un utilisateur PostgreSQL
trocla create 'un_autre_mot_de_passe' 'pgsql'
# Si on utilise un pass déjà formatté, on veut pouvoir utiliser le bon type sans re-formatter
# Pour ça on peut utiliser --no-format
# Ex.: setter nouveau_pass avec un hash sha512crypt connu
trocla set nouveau_pass sha512crypt --no-format
# Pour effacer un mot de passe
trocla delete nouveau_pass

Dans hiera, on peut récupérer une donnée sensible et l'utiliser comme valeur pour la clef hiera associée. Pour faire ça, dans le fichier YAML de hiera, on utilise un appel de la forme suivante:

profile::example::secret: "%{hiera('trocla_lookup::plain::example_com_secret')}"

La valeur donnée à la clef hiera profile::example::secret est une chaîne de texte avec un format spécial: on appelle la fonction puppet hiera() pour lancer une recherche pour une autre information via hiera.

Par contre, l'appel à la fonction hiera() utilise une clef spéciale qui commence par trocla_lookup::, ce qui permet d'obtenir l'information via trocla au lieu de hiera.

Le reste de la clef demandée donne de l'information essentielle à trocla:

Dans les manifests puppet (.pp), on peut appeler la fonction trocla() pour obtenir une donnée sensible:

$db_mail_password = trocla("${facts['fqdn']}_mysql_alternc_user", 'plain', 'length: 32')

Dans l'appel de fonction plus haut le troisième argument détermine certaines options passées à trocla. Ici on spécifie que le mot de passe généré devrait avoir une longueur de 32 caractères.

Les cléfs de trocla peuvent contenir des points si la fonction trocla est apellée dans un manifest puppet. Par contre, une clé avec un point ne pourra pas être utilisée dans un fichier hiera.

C'est donc généralement mieux d'utiliser des tirets bas au lieu des points quand on crée des clés, parce que sinon on ne peut pas faire de lookups dans les données hiera. Eg:

# invalide, puppet va donner une erreur
profile::example::secret: "%{hiera('trocla_lookup::plain::example.com_secret')}"
# valide, donc la clé dans trocla ne doit pas avoir de points pour pouvoir être utilisable dans hiera
profile::example::secret: "%{hiera('trocla_lookup::plain::example_com_secret')}"

Voir la documentation de trocla: https://github.com/duritong/trocla

Bonnes pratiques à suivre

Koumbit a établi une série de recommandations pour l'organisation des fichiers et le standard de formattage du code puppet. Le formattage du code puppet est basé sur le formattage recommandé par la communauté puppet, avec quelques recommandations additionnelles pour que notre code garde un aspect similaire partout.

Pour trouver les recommandations, référez-vous à PuppetGuide#Donn.2BAOk-es_dans_Hiera

Le code puppet envoyé dans le "control repository" devrait suivre toutes ces recommandations si possible.

L'outil qu'on utilise pour valider la syntaxe et le bon formattage des fichiers YAML s'appelle yamllint. On peut l'utiliser pour vérifier un fichier directement:

yamllint hieradata/common.yaml

ou alors vérifier tous les fichiers qui se trouvent sous un répertoire:

yamllint hieradata/node/

Par défaut, nos hooks git sur le puppet master refuseront les "push" ayant des commits qui ne passent pas le linting de yamllint - même les avertissements empêcheront vos commits de se rendre à destination.

Le mieux dans ce cas c'est de corriger le problème souligné.

Pour quelques cas d'exceptions, il est possible de désactiver le check de certaines règles de lint directement dans les fichiers yaml.

Par exemple dans le fichier suivant, la valeur de la clef publique ssh contenue dans pubkey ne peut pas être rapetissée pour éviter d'avoir une ligne trop longue. On peut alors utiliser un commentaire sur la ligne au dessus avec une série de mots-clefs pour désactiver le test de longue ligne spécifiquement pour cette ligne là:

---
# example fictif
profile::local_users::users:
  # [...]
  # yamllint disable-line rule:line-length
  pubkey: 'AAAAzzz..................................................................................................'

Voir https://yamllint.readthedocs.io/en/stable/disable_with_comments.html pour plus d'information.

Piège commun: il y a des données dans hiera mais puppet ne les utilise pas

Un détail auquel il faut faire attention avec hiera c'est qu'il peut y avoir n'importe quoi dans les fichiers YAML sans affecter le code de puppet. Donc ça peut:

On n'a présentement pas de forme de validation du nom des clefs dans les fichiers YAML, et les problèmes plus haut ne provoqueront pas d'erreur dans la validation de syntaxe. Donc il faut se surveiller soi-même quand on modifie les fichiers hiera.

Exercices additionnels

  1. Modifier une donnée
    1. Provisionner la VM pm_buster. Connecter et faire un run puppet
    2. Modifier les données hiera de pm_buster.test pour que LetsEncrypt soit gérer à travers le profile basic_instance

    3. Rouler puppet
      • Quelles changements on été effectués?
  2. Modification d'une donnée complexe
    1. Modifier les données hiera de pm_buster.test afin de recevoir les courriels du fil roots en plus que de les envoyer à roots@rt.koumbit.net:

      profile::postfix::local_mta::root_alias:
       - 'roots@rt.koumbit.net',
       - 'example@koumbit.org'
      
    2. Rouler puppet.
    3. Indentifier les problèmes have la donnée proposée
    4. Où est-ce le valeur original de cette donnée configuré?
  3. Ajout d'un utilisateur et données provenant de trocla
    1. Ajouter la suivente dans les données du node pm-buster.test:

      profile::users::users:
        kim:
          ensure: present
          groups:
            - adm
          comment: "non-app user for administrative access"
          password: "%{hiera('trocla_lookup::plain::pc-buster.test_user_password_kim')}"
      
    2. Rouler puppet
    3. Identifier les problèmes avec les données proposées
  4. Changer l'environnement puppet utiliser par un node
    1. Vérifier quelle environnement est présentement utilisé sur pm-buster.test
    2. Mettre une branche différent en utilisant la donnée:

      puppet::environment: 'yourbranchname'
      
    3. Rouler puppet
      • Est-ce que la changement a fonctionné?
      • Où est la donnée spécifié normalement?
      • Si ça n'a pas marché, quelle autre donnée proposerais-tu utiliser pour ce cas?

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


CategoryFormation

FormationPuppetDonnéesHiera (last edited 2024-09-16 13:16:56 by mathieul)