Créer un nouveau service

Attention:

Prérequis : les articles de cette section.

Cette page donne quelques pistes pour lancer un nouveau service, versionné sur un nouveau dépôt à créer dans services (voir gestion des services).

L’idée de chaque dépôt est de rendre son service indépendant des machines virtuelles sur lesquelles il est lancé, c’est-à-dire qu’à partir de ce dépôt, on devrait pouvoir remonter sans aucun problème un service sur une machine quelconque (sauf les données, bien sûr).

Le dossier template est une bonne base pour commencer un nouveau service.

Attention:

Si on n’utilise pas d’image maison, il n’est pas nécessaire d’utiliser un Dockerfile.

A Savoir:

Pour le contenu des fichiers Dockerfile et docker-compose.yml, on se référera au guide des bonnes pratiques pour les Dockerfile et au guide des bonnes pratiques pour Compose en cas de doute.

Pour savoir si vous avez versionné tout les fichiers nécessaires et automatisé le démarrage du service, posez-vous la question suivante :

Question:

Si je fais un git clone sur n’importe quelle machine, cd puis un docker-compose up -d, est-ce-que mon service démarre correctement ?

Si non, voici quelques pistes.

La seule exception concerne les opérations nécessaires pour créer les secrets (voir plus bas).

Pour chaque service, on aura au moins :

  • Un README.md, qui explique de quoi il s’agit, comment lancer le service, comment le mettre à jour, etc. On pourra s’inspirer des services existants.
  • Un docker-compose.yml, qui permet de lancer le service sur les machines de Picasoft. Les images utilisées doivent toujours avoir un tag de version précis (voir bonnes pratiques).

Important:

S’il existe un Dockerfile sur un dépôt Git distant mais pas d’image poussée sur un registre Docker, mais que ce Dockerfile nous convient, il n’est pas nécessaire de le copier. On pourra utiliser un contexte de build avec une URL de dépôt (voir conseils généraux pour Compose).

Si on utilise un Dockerfile personnalisé, il faut rajouter :

  • Un ou plusieurs Dockerfile, qui permet(tent) de construire l’image.
  • Un CHANGELOG.md, qui indique les modifications effectuées au fil des versions.

Question:

Que faire s’il existe déjà une image Docker pour le service qu’on veut mettre en place, mais qu’on a besoin de le customiser ? Il y a deux solutions :

  • Soit on part de l’image officielle, avec un FROM, et on travaille dessus en rajoutant des fichiers, en enlevant des paquets… Cette solution a l’inconvénient de multiplier les layers inutiles, et d’augmenter la taille de l’image.
  • Soit on copie le Dockerfile de l’image officielle (c’est le cas pour Mattermost), et on fait nos modifications. Cette solution a pour inconvénient de devoir se synchroniser avec les modifications du Dockerfile officiel à chaque mise à jour, s’il contient des améliorations ou corrections importantes.

Le Dockerfile peut contenir des directives COPY pour ajouter des fichiers à l’image. S’il s’agit d’un ou deux fichiers de configuration, ou d’un peu de code pour personnaliser une page d’accueil, aucun souci pour les versionner directement sur le dépôt.

Important:

Si vous avez besoin de copier le code d’un service entier, il est préférable de créer un dépôt spécifique qui contiendra le code du service, et de faire un git pull dans le Dockerfile, ou de récupérer une release avec un wget. En effet, le dépôt d’un service ne contient en théorie que de la configuration pour Docker, pas le code du service.

Il est préférable de versionner la configuration du service sur ce dépôt, pour pouvoir relancer rapidement le service sur une machine quelconque sans devoir récupérer la configuration sur l’ancienne machine.

Attention:

Si la configuration est souvent modifiée via l’interface d’administration du service, il est préférable de ne pas la versionner. Par exemple, Mattermost utilise un fichier config.json, mais on le modifie essentiellement à travers la Console Administrateur (interface graphique). Versionner ce fichier obligerait à modifier la configuration “à la main”, puis à redémarrer Mattermost à chaque changement de paramètres.

Note:

Etherpad utilise un fichier config.json qui n’est pas modifiable via une interface graphique, et qui est pris en compte uniquement au démarrage. C’est donc un bon fichier à versionner.

La rule of thumb est donc la suivante : on versionnera tous les fichiers qui ne sont pas modifiés dynamiquement quand le service est lancé.

Attention:

Si le fichier de configuration est versionné et qu’on le modifie dans l’entrypoint (par exemple pour y injecter des secrets), on en fera une copie au démarrage du service, on remplacera les valeurs des secrets et on dira au service d’utiliser cette copie, afin de ne pas modifier la version versionnée.

Certaines images pré-construites demandent d’effectuer des opérations manuellement avant de les lancer pour la première fois (initialisation de base de données, etc). Toujours dans la logique de pouvoir monter un service avec un simple docker-compose up -d, on évitera de demander aux administrateurs de services de lancer des commandes supplémentaires.

Dans ce cas, on pourra créer un entrypoint qui effectue ces opérations si jamais le service est lancé pour la première fois, puis qui lance le service normalement.

Note:

Il ne faut pas hésiter à créer une image personnalisée basée sur l’image officielle “juste” pour ajouter un entrypoint personnalisé ! Ça ne coûte pas grand chose, ça fait gagner du temps, et ça évite les erreurs (exemple : une instruction d’initialisation de base de donnée sur une instance qui tourne déjà).

A Savoir:

On pourra marquer le fait qu’un service a déjà été initialisé en créant un fichier “marqueur” dans un volume. Voir Plume pour un exemple. D’autres techniques sont possibles :)

Un autre cas particulier est celui de la configuration du service. Si :

  • Les fichiers de configuration ne sont pas versionnables (car modifiés via l’interface graphique…),
  • Que les variables d’environnement ne permettent pas nativement de modifier la configuration,
  • Mais qu’on a besoin de modifier la configuration lors de l’initialisation,

Alors on créera nos propres variables d’environnement et un entrypoint personnalisé. C’est ce qu’on fait pour Mattermost : config.json n’est pas versionné, mais l’entrypoint récupère la configuration via l’environnement et l’injecte dans config.json.

Un service a souvent besoin de secrets pour démarrer. Par secrets, on entend souvent mot de passe, ou clé privée.

Important:

On utilise systématiquement des variables d’environnement dans des fichiers non-versionnés pour les secrets. On ne peut pas les mettre dans le fichier Compose ou dans le Dockerfile, car ces fichiers sont versionnés, et donc publics.

On créera un dossier secrets, puis des fichiers en <service>.secrets.example qui contiennent une variable d’environnement par ligne, ainsi qu’une valeur d’exemple. Ces fichiers sont versionnés. Ils seront ensuite copiés en .secrets sur la machine de production, les valeurs sont remplacées, et injectées dans le conteneur via la directive env_file de Compose. Tout ceci est expliqué dans les bonnes pratiques.

Note:

Il peut arriver qu’un service ne prenne pas en charge les variables d’environnement pour les secrets. Dans ce cas, on utilisera un entrypoint personnalisé pour injecter les variables d’environnement dans le fichier de configuration.

Picasoft est propriétaire du domaine picasoft.net, il est donc possible de créer des nom de domaine sur celui-ci. On veillera à choisir un nom clair et représentatif. De plus ce n’est pas une obligation mais nos noms sont souvent en anglais, il peut être pratique pour les utilisateurs de continuer ainsi pour plus de cohérence.

Note:

Quand on enregistre un nom de domaine pour un service on préférera utiliser un enregistrement de type CNAME plutôt que A ou AAAA, cela facilite le changement d’IP d’une machine par exemple.

Il existe actuellement deux systèmes de backup sur l’infrastructure de Picasoft.

Le premier système consiste en un backup régulier de la totalité des machines virtuelles, il n’y a rien à faire de particulier pour ces backups lors de la mise en place d’un service.

Le second système concerne les backups des bases de données, nous avons sur chaque machine virtuelle un service dédié dans un conteneur docker qui s’occupe de ces backups, il s’agit du service db-backup.

Note:

Cette section n’est pertinente que pour les services avec une base de données.

Modifier la configuration selon la documentation, puis redémarrer le service de backup sur la machine où tournera le nouveau service.

Pour que le backup soit faisable par ce service il faut qu’il soit en mesure de communiquer avec la base de donnés du nouveau service, pour cela on utilise les réseaux docker, il faut ajouter le service de backup dans le réseau dédié du nouveau service (dans la section networks du fichier docker-compose.yml).

Une fois que les backups sont exécutés il faut activer la rotation des backups afin qu’ils ne prennent pas trop de place. Encore une fois, nous avons un service dédié dans un conteneur dans le dossier db-backup-rotation.

Modifier la configuration selon la documentation, puis redémarrer le service de rotation sur la machine où tournera le nouveau service.

Note:

Cette partie concerne le monitoring du service, c’est-à-dire la collecte de métriques le concernant et l’assurance de sa bonne santé. Si vous n’y comprenez rien, demandez à un membre de l’équipe technique pour un petit résumé. :p

De plus en plus de services web proposent un exporter Prometheus qui sert des métriques sur /metrics. Parfois, l’exporter est intégré au service, parfois il se présente sous la forme d’un processus à part. Si aucun exporter n’existe, il est pertinent d’écrire votre propre exporter et peut-être même de le proposer au projet ! À titre d’exemple, Picadrop exporte ses métriques grâce à un exporter maison.

Dans tous les cas, la configuration pour exposer et récupérer les métriques d’un service est à peu près toujours la même.

Si les métriques s’y prêtent, on pourra rajouter une alerte.

Important:

Dans tous les cas, rajouter le service nouvellement créé dans la liste des services surveillés par Blackbox !

Pour ce faire, modifier la configuration du bot des mises à jour, qui publie un message sur Mattermost chaque fois qu’il y a une nouvelle mise à jour d’un service.

Une fois que tout est prêt, vous pouvez tester votre service.

  • technique/docker/picasoft/new.txt
  • de rdelaage