+++
title = "Migrer MinIO de service à plugin dans TrueNAS"
date = 2023-12-08
[taxonomies]
tags = [ "truenas", "minio", "s3", "sysadmin", "système" ]
+++

> La mauvaise doc, tu la lis… tu comprends rien ! La bonne doc, tu la lis… bon tu comprends rien non plus, mais c’est une bonne doc !

<!-- more -->

Parce que les emmerdes, ça vole souvent en escadrille, TrueNAS ne maintiendra plus le plugin S3 à partir de la version 13.1. Les utilisateurs sont priés de migrer vers le [plugin S3](https://www.truenas.com/docs/core/13.0/coretutorials/jailspluginsvms/plugins/minioplugin/).

Sauf que c’est bien gentil, mais ce n’est pas particulièrement bien documenté (que ce soit pour migrer ou même simplement pour installer et utiliser ledit plugin).

Guide non-officiel donc.

# Installation du plugin MinIO

Le service S3 de TrueNAS repose sur MinIO, c’est également le cas du plugin. Avant de faire quoique ce soit, on peut donc aller simplement activer le plugin en question. Pour cela, le plus simple est de se rendre sur l’interface Web (oui, je sais, c’est caca™), d’aller dans la section `Plugins`. On te propose alors d’indiquer sur quel volume il faut installer les `jails` (par défaut, ce sera dans un dossier `iocage`). Tu peux mettre le volume par défaut, ça ne gène en rien.

À la fin de l’installation, TrueNAS te donne quelques informations, notamment les informations de connexion, que tu pourras réafficher en cliquant sur la flèche au bout de la ligne correrpondant à MinIO puis dans les `Post install notes` (l’écran s’affiche, mais si t’as loupé un truc, c’est pas bien grave donc).

Une fois que cela est fait, je t’invite à stopper le plugin lui-même, parce qu’il va falloir aller faire pas mal de bricolage maintenant.

## Création d’un dataset dédié

Comme pour le service S3, il faut un dataset dédié (et malheureusement distinct du dataset d’origine) et avec les **bonnes ACLs**. Et c’est généralement là qu’on commence à bien rigoler…

Donc, rends-toi dans `Storage > Pools` pour créer le dataset dédié. Le nom a peu d’importance, ce qui est important en revanche, ce sont les ACLs.

Dans l’écran pour régler les permissions voici donc ce qu’il faut faire pour que ça marche correctement :
* pour le *preset*, tu peux sélectionner `Restricted` qui correspond plutôt pas mal au cas d’usage (on ne veut pas que quoique ce soit d’autres que MinIO vienne écrire dans ce dataset)
* au niveau utilisateur, **il faut** sélectionner `minio`
* puis **il faut appliquer récursivement** les changements (via la coche ` Apply permissions recursively `)

De cette manière, ton dataset appartient bien à l’utilisateur `minio` et à lui seul.

## Association du dataset au plugin

Une fois tout ceci fait, tu devrais avoir un plugin MinIO à l’arrêt et un dataset avec les bonnes permissions.

Le plugin lui-même va placer l’ensemble de ces données dans `<point de montage zfs>/iocage/jails/<nom de la jail>/root/var/db/minio`. Il faut donc idéalement aller monter le volume que l’on vient de créer là. **Sauf que** le dossier `/var/db/minio` dans la `jail` n’est pas vide (ce serait trop simple).

En fait, au premier démarrage MinIO peuple ce dossier avec quelques fichiers de configuration ce qui empêche complètement d’y associer le dataset.

On va donc bouger un dossier cacher, `.minio.sys/` de ce dossier vers la racine du dataset que l’on a créé :

```
mv <point de montage zfs>/iocage/jails/<nom de la jail>/root/var/db/minio/.minio.sys/ <point de montage zfs>/<dataset minio>/
```

À partir de là, dans l’interface des plugins, tu peux aller triturer les points de montage. Il suffit d’associer ton dataset avec le dossier `/var/db/minio` dans la `jail` et ça devrait cesser de gueuler.

## Ajouter la partie réseau

Une `jail`, ça fonctionne grosso merdo comme un conteneur Docker (en tout cas du point de vue de l’utilisateur). Il va donc falloir lui associer des ports sur l’hôte. Normalement, MinIO utilise deux ports :
* 9000, pour S3
* 9001, pour l’administration

Par défaut le plugin démarre sur le premier port libre, donc généralement le 9002. On peut aller changer cela dans le menu `Jails`. Il suffit de cliquer de nouveau sur la flèche de droite puis d’aller dans `Edit` pour changer les ports sous `Network Properties`.

Une fois tout ceci fait, on peut redémarrer une dernière fois la `jail`, elle devrait écouter sur le nouveau port.

# Recréation de la configuration

Parce que la nature est bien fait, il est impossible de migrer les métadonnées des buckets S3 de MinIO service vers MinIO plugin. Ça veut dire qu’il faut effectivement tout recréer (ou trouver une bricole avec l’API que je n’ai pas trop cherchée : avec un seul bucket et une seule clé, ça n’en valait pas la peine dans mon cas) des buckets aux clés en passant par les utilisateurs et les permissions.

Amuse-toi bien… Peut-être qu’il existe des scripts précuits ou des recettes de cuisine, peut-être même fournies par le projet MinIO, mais j’ai eu la flemme de chercher plus que ça.

# Migration des données

Comme je le disais auparavant, la façon dont MinIO stocke les données à changer entre la version service et la version plugin (essentiellement parce que la version service est relativement ancienne maintenant). Il est donc impossible de charger simplement les données, le seul moyen est de passer par un miroir via `mc` (*minio client* ou *mcli* dans certaines distributions).

Il va donc falloir passer par une machine tierce, de préférence sur le même réseau pour éviter latence et désaagrément, pour faire un miroir complement **pour chaque bucket**. Là encore, bon courage si tu en as plusieurs ou que tu as plusieurs dizaines de téraoctets de données sur MinIO.

Donc, il faut créer une clé ayant a minima les droits de lecture sur tous les buckets côté source et évidemment une clé ayant les droits d’écriture sur tous les buckets côté destination. Cela peut être créer dans l’interface d’admin de chaque MinIO, je ne détaille pas (c’est trop dépendant des versions et la doc de MinIO est éventuellement là pour aider).

Sur la machine tierce, une fois `mc` installé par la méthode de ton choix (il y a un paquet Debian qui semble fonctionner correctement cela dit, sous le nom `mcli`), il suffi d’enregistrer les deux alias qui vont bien :

```
mcli alias set service http://truenas:9000 cle_lecture_seule secret_lecture_seule
mcli alias set plugin http://truenas:10000 cle_lecture_écriture secret_lecture_écriture
```

Tant que tu ne t’es pas emmêlé les saucisses entre les ports/s3 source et destination et les clés, ça devrait bien se passer. `mc` indique en général tout de suite si quelque chose ne va pas, c’est déjà ça de pris.

Pour le transfert lui-même, il faut s’armer de patience (et de `tmux`) et se lancer :
```
mcli mirror --preserve service/<bucketA> plugin/<bucketB>
```

Une fois le transfert effectué, on peut simplement vérifier que l’on a le bon nombre d’objets. La taille devrait être « comparable » mais pas forcément similaire (la méthode de calcul peut différer entre les deux versions).

À ce moment, on peut simplement stopper la version service de MinIO, remplacer les ports de la version plugin, puis éventuellement effacer les données.

Bien entendu, il faudra quand même s’assurer que les données en question ont bien été transférées, bon courage là-dessus aussi.

# Conclusage

Un service qui s’arrête, ce sont des choses qui arrivent. Ça ne fait plaisir à personne, mais des fois, il n’y a simplement pas le choix (obsolescence, sécurité, maintenabilité, les raisons sont multiples).

Par contre, quand c’est le cas, le minimum c’est de prévenir bien à l’avance et de fournir le plus possible aux usagers de la solution la possibilité de migrer de la manière la plus simple et la plus efficace possible.

Là, je suis franchement déçu par TrueNAS sur ce point. Non seulement la documentation officielle est remplie de trous (d’où ce billet d’ailleurs), mais en plus elle est loin d’être efficace. Je n’avais qu’un seul téraoctet de données en S3 et heureusement suffisamment de place à côté. Je n’imagine même pas la galère les utilisateurs un peu justes en terme d’espace ou avec des volumétries bien plus importantes.
