Système de fichiers distribués

Chrtophe

Un système de fichiers distribué est un système où le poste client accède à un espace de stockage virtuel unique. Les données peuvent être réparties/dupliqués sur plusieurs machines de façon transparente pour celui-ci. C'est le moteur du système de fichiers distribué qui a la charge de répartir les données et de les dispatcher au client.

Commentez .

- Titre : Système de fichiers distribués

- Auteur : Chrtophe

- Parution : 15 novembre 2020

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2020 Chrtophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- 1. Systèmes de fichiers distribués

- 1-1. NFS

- 1-2. GlusterFS

- 1-2-1. Installation de GlusterFS

- 1-2-2. Installation mode répliqué

- 1-2-2-1. Montage d'un volume gluster

- 1-2-2-2. Ajout d'une machine supplémentaire au pool

- 1-2-2-2-1. Mise à jour de srv3

- 1-2-2-3. Retrait d'une brique

- 1-2-3. Test de mise en panne, simulation perte de srv1

- 1-2-3-1. Remplacement avec une nouvelle adresse IP

- 1-2-3-2. Remplacement en gardant la même adresse IP

- 1-2-4. Installation en mode distribué

- 1-2-5. Test du mode distribué-répliqué

- 1-2-5-1. Simulation de perte de srv2

- 1-2-6. Sauvegarder/restaurer

- 1-2-7. Sécurité

- 1-3. DRBD/OCFS2

- 1-3-1. DRBD

- 1-3-1-1. Qu'est-ce que DRBD ?

- 1-3-2. Installation de DRBD

- 1-3-2-1. Sécurité de DRBD

- 1-3-2-2. Surveillance des volumes DRBD

- 1-3-2-3. Tests

- 1-3-3. OCFS2

- 1-3-3-1. Qu'est-ce qu'OCFS2 ?

- 1-3-3-2. Installation et paramétrage d'OCFS2

- 1-3-4. Couplage DRBD/OCFS2 : Simulation de panne

- 1-3-5. Couplage DRBD/OCFS2 : redémarrage des deux serveurs

- 1-3-5-1. Ajout d’une troisième machine pour la sauvegarde

- 1-3-5-2. Perte de liaison entre deux machines : split-brain

- 1-3-6. DRBD 9

- 1-3-6-1. Installation du module noyau :

- 1-3-6-2. Installation des outils

- 1-3-6-3. Préparation du volume LVM

- 1-3-6-4. Intégration troisième poste

- 1-3-6-5. drbdmanage

- 1-3-6-6. Linstor

- 1-4. Ceph

- 1-4-1. Modules Ceph

- 1-4-2. Fonctionnement de Ceph

- 1-4-3. Installation de Ceph

- 1-4-3-1. Installation d'une première machine

- 1-4-3-1-1. Préparations

- 1-4-3-1-2. Installation de ceph-deploy

- 1-4-3-1-3. Configuration

- 1-4-3-1-4. Création d'un moniteur

- 1-4-3-1-5. Ajout d'OSD

- 1-4-3-1-6. Préparation des pools

- 1-4-3-1-7. Création d'un démon MDS

- 1-4-3-1-8. Création du système de fichiers CephFS

- 1-4-3-1-9. Montage du volume CephFS

- 1-4-3-2. Ajout d'une seconde machine

- 1-4-3-3. Test de panne : arrêt de srv1

- 1-4-3-4. Procédure de réparation d'un nœud

- 1-5. min.io

- 1-5-1. Les différents modes de fonctionnement

- 1-5-2. Installation de min.io

- 1-5-3. Test en mode simple instance

- 1-5-3-1. Accès via le web

- 1-5-3-2. Gestion de fichiers depuis l'interface web

- 1-5-3-2-1. Upload de fichier

- 1-5-3-2-2. Accès aux fichiers

- 1-5-3-2-3. Utilisation de https

- 1-5-4. Test en mode distribué

- 1-5-4-1. Tests

- 1-5-4-2. Passage en mode démon

- 1-5-5. Client min.io

- 1-5-6. Fonctionnement en mode S3

- 1-5-7. Sauvegarde

- 1-5-8. Test d’arrêt d’un des serveurs

- 1-5-8-1. Perte définitive d’un serveur

- 1-5-9. Ajout de serveur

- 1-6. Bilan

- 1-7. Quid de Windows ?

- 1-8. Quid de Mac OS X ?

- 2. Conclusion

- 3. Remerciements

1 - Systèmes de fichiers distribués

Cette version est une version allégée de mon livre sur le cloud computing. La version complète se trouve ici.

Un système de fichiers distribué est un système où le poste client accède à un espace de stockage virtuel unique. Les données peuvent être réparties/dupliqués sur plusieurs machines de façon transparente pour celui-ci. C'est le moteur du système de fichiers distribué qui a la charge de répartir les données et de les dispatcher au client.

Les systèmes de fichier distribués les plus répandus sont :

- Ceph ;

- GlusterFS ;

- Hadoop Distributed File System (HDFS) ;

- Lustre (utilisé par les super-calculateurs) ;

- NFS - Network File System.

Sur les tests effectués, il ressort deux approches :

- une approche en blocs (chunks) répartis sur plusieurs machines et pour lesquels les métadonnées peuvent être centralisées ou distribuées et permettent de reconstruire les fichiers ;

- une approche reposant sur la notion de fichiers et utilisant ou non des métadonnées. Certains nécessitent d'avoir une ou plusieurs machines dédiées aux métadonnées, d'autres permettant d'intégrer les métadonnées sur les machines stockant les données, ou éventuellement sur des machines autonomes.

Ceci a un impact sur le minimum de machines requis pour créer le système de fichiers distribués, sur la souplesse de retrait et d’ajout de machine, sur les performances, la maintenance et la sauvegarde.

Ce tutoriel couvre les systèmes de fichiers suivants :

- GlusterFS ;

- OCFS2 couplé à DRBD ;

- Ceph ;

- Minio.

En réalité, OCFS2 (Oracle Cluster File System) n'est pas un système de fichiers distribué, mais un système de fichiers gérant la concurrence d'accès aux fichiers entre plusieurs machines. Cela permet de gérer les accès concurrentiels, la répartition de charge sur plusieurs machines (deux dans notre cas) sera à gérer à part. C'est une approche intéressante pour un petit cloud.

Ceph, à son niveau le plus bas, va stocker des objets (des couples de clé/valeur). Un cache d'abstraction nommée RBD (Rados Block Device) fournira un accès en mode bloc. Par-dessus cela, CephFS fournira une abstraction permettant l'accès en mode fichier.

1-1 - NFS

NFS n'est pas en lui-même un système de fichiers répartis. Du point de vue utilisateur, vous pouvez le comparer à SMB : c'est un point d'exposition d'un système plus bas niveau pouvant lui être réparti. Pourquoi en parler ici alors ? Car certains systèmes de fichiers répartis comme GlusterFS – que nous allons voir dans le prochain chapitre – implémentent directement un accès NFS.

NFS (Network file System) est un protocole historique de partage réseau sous Unix. Les anciennes versions n'étaient pas sécurisées.

Sur les anciennes versions de NFS, avec un serveur NFS installé, pour partager un dossier, il suffisait d'ajouter une entrée dans le fichier /,etc/exports comme ceci :

/dossier_partage 192.168.1.0/24(rw)

pour permettre à toutes les machines du réseau 192.168.1.0 de se connecter au partage en lecture/écriture.

NFS fait un contrôle d'accès au niveau de l'hôte, pas du nom d'utilisateur.

L'accès client se fera soit par la commande mount, soit par une entrée dans le fichier /,etc/fstab comme ceci :

adresse_ip:/partage /point_de_montage nfs user,noauto 0 0

La version 4 a créé une réelle rupture permettant :

- la sécurisation et le chiffrement des communications (support de Kerberos) ;

- délégation de la gestion d'un document en local pour un client ;

- Migration possible d'une machine à l'autre du serveur de façon transparent pour le client.

Les systèmes Linux, Mac OS, Windows (seulement la version Pro, pour les versions home, il faut utiliser un logiciel externe) intègrent nativement un client NFS.

Mac OS, Linux, la plupart des NAS intègrent un serveur NFS (bien qu'en général on va plutôt utiliser un partage SMB). Windows Server intègre également un rôle serveur NFS.

VMWare permet de stocker ses machines virtuelles dans un partage NFS, ce sera par contre moins efficace qu'avec le filesystem VMFS natif, mais permettra par contre de facilement créer un stockage partagé.

Un volume GlusterFS, que nous verrons dans le prochain chapitre peut être monté en NFS.

1-2 - GlusterFS

GlusterFS est un système de fichiers distribué relativement souple. Il vient se greffer sur le système de fichiers local existant. Il permet de facilement « concaténer » plusieurs volumes locaux de plusieurs machines en un seul volume. Il possède plusieurs modes (distribués ou non) de fonctionnement. Certains d’entre eux permettent la redondance. C'est un système relativement simple à mettre en place et efficace. Voici une explication des modes de fonctionnement.

Mode répliqué

Ce mode de fonctionnement réplique les fichiers sur les différents nœuds du volume. Il s'agit là uniquement de l'aspect redondance, les fichiers ne sont pas répartis sur les différentes machines, ils sont répliqués.

Mode distribué

Dans ce mode, les fichiers sont répartis entre les différentes machines du volume. Il n'y a pas de redondance. Vous devez donc vous assurer de la sauvegarde des données.

Mode distribué-répliqué

Ce mode cumule la répartition et la redondance. Chaque nœud du volume distribué est redondé sur une autre machine. Il vous faut donc au minimum X machines multiplié par 2 pour un volume consistant, X représentant le nombre de nœuds répartis.

Autres modes possibles

Volumes strippés : les fichiers sont éclatés en plusieurs morceaux, ceux-ci étant répartis sur les machines membres du volume. Ce mode pourrait être comparé à du RAID 0 via le réseau.

Volumes strippés distribués : les fichiers sont éclatés en plusieurs morceaux comme pour les volumes strippés, mais sont répliqués sur plusieurs machines. Ce mode peut être comparé à du RAID 0+1 (encapsulation de RAID 0 dans un RAID 1) via le réseau.

Volumes dispersés : les fichiers sont morcelés sur plusieurs machines avec des fragments supplémentaires permettant la reconstruction de fichiers suite à une perte de fragments présents sur une machine en panne. Ce fonctionnement est comparable à du RAID 5 via le réseau.

Volumes dispersés distribués : il s'agit de volumes distribués répliqués utilisant des sous-volumes dispersés plutôt que répliqués.

GlusterFS utilise la nomenclature suivante :

- pool de machines : machines qui sont appairées pour gérer un ou plusieurs volumes en commun ;

- brique : une brique est un point de stockage sur une machine d'un pool. Plusieurs briques font un volume.

1-2-1 - Installation de GlusterFS

Pour créer un volume GlusterFS, il faut installer les paquets glusterfs-server et attr :

apt-get install glusterfs-server attr

Votre système de fichiers doit supporter les attributs étendus. C'est le cas pour ext4.

1-2-2 - Installation mode répliqué

Une fois les paquets GlusterFS installés sur srv1, nous créons un dossier à la racine que nous nommons srv1_data et qui accueillera le point de partage.

Nous créons ensuite le volume que nous nommerons VOL :

gluster volume create VOL srv1:/data_srv1 force

La commande retourne l’indication suivante :

volume create: VOL: success: please start the volume to access data

Option force : GlusterFS exige ce paramètre au cas où le point de montage utilisé pour le volume est dans la partition principale (ce que GlusterFS ne recommande pas).

La commande gluster volume list permet l'affichage des volumes visibles sur le système :

root@srv1:~# gluster volume list
VOL
root@srv1:~#

Nous pouvons voir l'état du volume avec la commande gluster volume info :

gluster volume info

Volume Name: VOL
Type: Distribute
Volume ID: 3fa199d1-7e7f-4ec5-985f-abf0f1f18ed4
Status: Created
Snapshot Count: 0
Number of Bricks: 1
Transport-type: tcp
Bricks:
Brick1: srv1:/data_srv1
Options Reconfigured:
transport.address-family: inet
performance.readdir-ahead: on
nfs.disable: on

Nous pouvons voir que le volume est en mode distribué (distribute), avec une seule brique.

Une fois le volume créé, il nous faut l'activer :

root@srv1:~# gluster volume start VOL
volume start: VOL: success.

À ce stade, le volume est montable, mais nous verrons cela dans le prochain chapitre.

Une fois les paquets installés sur srv2 et le dossier du point de montage créé, nous commençons par effectuer le jumelage GlusterFS de srv2 à srv1 depuis srv1 .

root@srv1:~# gluster peer probe srv2
peer probe :  success

La commande suivante permet de voir les machines membres du pool :

root@srv1:~# gluster pool list

Et qui donnera un résultat comme ceci :

root@srv1:~# gluster pool list
UUID                                    Hostname        State
bca2bdf3-ec7e-4e26-8d5e-01584b09d604    srv2            Connected
ffaa8716-0a58-4cea-b01d-70f49bcbe998    localhost       Connected

Les fichiers /,etc/hosts de chaque machine doivent contenir les noms des nœuds participant aux volumes GlusterFS.

La même commande exécutée sur la seconde machine donnera le même résultat, les deux lignes seront juste interverties.

Nous ajoutons ensuite la brique de srv2 au volume :

gluster volume add-brick VOL replica 2 srv2:/data_srv2 force
volume add-brick: success

Nous affichons les informations du volume :

gluster volume info

Volume Name: VOL
Type: Replicate
Volume ID: 3fa199d1-7e7f-4ec5-985f-abf0f1f18ed4
Status: Started
Snapshot Count: 0
Number of Bricks: 1 x 2 = 2
Transport-type: tcp
Bricks:
Brick1: srv1:/data_srv1
Brick2: srv2:/data_srv2
Options Reconfigured:
nfs.disable: on
performance.readdir-ahead: on
transport.address-family: inet

Nous pouvons voir les deux briques et pouvons voir que le type de réplication est maintenant « replicate ».

Nous aurions pu également créer le volume comme ceci à partir du moment où Gluster était installé sur les deux postes et les deux machines jumelées :

root@srv1:~# gluster create volume VOL replica 2 srv1:/data_srv1 srv2:/data_srv1 force
volume create: VOL;  success: please start volume to access data

Voici le détail des paramètres passés à la commande gluster create volume :

- VOL : nom du volume créé ;

- replica : nombre de machines nécessaires au volume répliqué (deux minimum) ;

- srv1:/data_srv1 : srv1 correspond au nom de la machine, /data_srv1 correspond au point de montage/dossier contenant les données du volume. Le nom de la machine et le chemin sont séparés par le caractère : ;

- srv2:/data_srv2: srv2 correspond au nom de la machine, /data_srv2 correspond au point de montage/dossier contenant les données du volume. Le nom de la machine et le chemin sont séparés par le caractère :.

Pour que la réplication fonctionne, il ne faut pas accéder au contenu directement depuis les dossiers /data_srv1 ou /data_srv2 dans notre exemple, mais depuis un point de montage GlusterFS.

1-2-2-1 - Montage d'un volume gluster

Pour monter un volume gluster, vous aurez besoin du paquet glusterfs-client. Si vous souhaitez monter un volume gluster sur une machine faisant office de serveur gluster, vous n'en aurez pas besoin, le paquet glusterfs-client étant installé en même temps que glusterfs-server.

Le montage s’effectue de la même façon que pour tout autre type de volume :

# mount -t glusterfs [nom d'hôte ou adresse IP]:/[nom du volume] [point de montage]

Ou dans le /etc/fstab sur srv1 par exemple :

srv1:/VOL /mnt glusterfs defaults,_netdev 0 0

Il est possible de monter un volume gluster via NFS. Cela n'est pas recommandé, car la sécurité de NFS, notamment en troisième version est rudimentaire.

1-2-2-2 - Ajout d'une machine supplémentaire au pool

Dans notre exemple, le serveur supplémentaire sera nommé srv3.

Lors de l’ajout d’une machine au pool, il ne faut pas oublier d’ajouter la nouvelle machine au fichier /,etc/hosts des machines déjà existantes ou s'assurer que l'entrée soit présente dans les DNS utilisés.

La commande suivante ajoute srv3 au pool :

root@srv1:~#gluster peer probe srv3

Nous ajoutons ensuite la nouvelle machine :

gluster volume add-brick VOL replica 3 srv3:/data_srv3 force

Il faut passer le bon nombre de machines à l'option replica.

Si nous appelons la commande gluster volume info, nous pouvons constater que le nombre de briques est passé de 1 x 2 = 2 à 1 x 3 = 3.

1-2-2-2-1 - Mise à jour de srv3

Une fois la brique intégrée, aucune donnée n'est automatiquement répliquée dessus. À ce stade, si nous ajoutons un nouveau fichier au volume, une copie sera bien présente dans srv3, mais les anciens fichiers ne le seront pas. Pour pallier ceci, il faut lancer la commande suivante :

gluster volume heal VOL full

1-2-2-3 - Retrait d'une brique

Dans notre cas, nous allons retirer srv2 avec la commande suivante :

gluster volume remove-brick VOL replica 2 srv2:/data_srv2 force

La commande demande confirmation avant de procéder au retrait.

replica doit être égal au nombre final de briques après opération.

Dans notre cas où les volumes sont répliqués, il est possible de diminuer le nombre de volumes jusqu’à n’en garder plus qu’un. Le volume dans ce cas passera en mode distribué.

Le retrait de la brique du volume ne supprime pas les données de celle-ci, mais il n'y a plus aucun lien entre celles-ci et le volume. Il ne sera pas possible de réintégrer la brique telle quelle.

Si vous souhaitez retirer la machine du pool :

gluster peer detach srv2

1-2-3 - Test de mise en panne, simulation perte de srv1

L'arrêt de srv1 ne provoque aucune erreur. Comme nous avons appairé srv2 à srv1, nous pouvons voir l'état de la connexion (et donc sa perte) avec la commande :

root@srv1:~# gluster peer status
Number of Peers: 1

Hostname: srv1
Uuid: c0c487b3-1135-41c7-b160-b8a061c10e9d
State: Peer in Cluster (Disconnected)

Si vous souhaitez garder l'adresse IP de la machine perdue, la reconnexion est plus complexe.

1-2-3-1 - Remplacement avec une nouvelle adresse IP

Nous appairons le nouveau serveur :

root@srv2:~# gluster peer probe srv1

Nous remplaçons ensuite la brique :

root@srv2:~# gluster volume replace-brick VOL srv1:/data_srv1 [nouvelle ip/hote]/data  commit force

Pour que les machines se synchronisent, il faut ensuite lancer la commande :

gluster volume heal VOL full

1-2-3-2 - Remplacement en gardant la même adresse IP

Il faut d'abord retirer la brique défectueuse :

root@srv2:~# gluster volume remove-brick VOL srv1:/data_srv1 force
Removing brick(s) can result in data loss. Do you want to continue ? (y/n) y
volume remove brick commit force:success

Puis :

root@srv2:~# gluster peer detach srv1
peer detach: success

À ce stade, et comme déjà vu, le volume ne contenant plus qu'une seule brique, passe en mode distribué.

Une fois le nouveau serveur préparé, nous le réappairons :

root@srv2:~# gluster peer probe srv1

Nous ajoutons la nouvelle brique :

root@srv2:~# gluster volume add-brick VOL replica2 srv1:/data_srv1 force

Nous resynchronisons le volume :

gluster volume heal VOL full
Launching heal operation to perform full self heal on volume VOL has been successful
Use heal info commands to check status

Comme indiqué, nous pouvons voir le résultat avec la commande :

gluster volume heal info

Si vous rencontrez des difficultés, consultez le chapitre 1.3.5.1.

1-2-4 - Installation en mode distribué

Certaines notions sont identiques ou de simples variantes du mode répliqué. Il est important pour la suite d'avoir lu le chapitre précédent.

Nous préparons une machine srv1 qui contiendra le fichier fichier1.txt dans /data_srv1.

Nous y créons un volume avec une brique unique.

gluster volume create VOL srv1:/data_srv1 force
volume create: VOL:  success: please start volume to access data

Nous pouvons voir l'état du volume avec la commande gluster volume info :

root@srv1:~# gluster volume info

Volume Name: VOL
Type: Distribute
Volume ID: 3f0a379a-921a-4c63-a5cc-7a62c3c39d19
Status: Created
Number of Bricks: 1
Transport-type: tcp
Bricks:
Brick1: srv1:/data_srv1

Nous pouvons constater que le volume est en mode distribué (distribute)

Démarrons ensuite le volume :

root@srv1:~# gluster volume start  VOL

Nous préparons ensuite un serveur srv2 avec le fichier /data_srv2/fichier2.txt. Il nous faut appairer la nouvelle machine :

root@srv1:~# gluster peer probe srv2

Puis ajouter la nouvelle brique :

root@srv1:~# gluster volume add-brick VOL srv2:/data_srv2
volume add-brick: success

Nous pouvons voir le nouvel état du volume :

root@srv1:~# gluster volume info

Volume Name: VOL
Type: Distribute
Volume ID: 3f0a379a-921a-4c63-a5cc-7a62c3c39d19
Status: Started
Number of Bricks: 2
Transport-type: tcp
Bricks:
Brick1: srv1:/data_srv1
Brick2: srv2:/data_srv2

Si nous montons le volume, nous pourrons voir les deux fichiers fichier1.txt et fichier2.txt. L'arrêt d'une des deux machines fera disparaître les fichiers présents dans le nœud coupé. Le premier accès sera lent, gluster cherchant la machine manquante. Le volume continue de fonctionner, il reste possible d'ajouter des fichiers. Le redémarrage de la machine manquante fera instantanément réapparaître les fichiers inaccessibles.

Créez quelques fichiers pour tester le comportement. J'ai créé plusieurs fichiers nommés fichier3.txt, fichier4.txt, etc. Tous restant dans /data-srv1.

Gluster gère cela lui-même et du point de vue extérieur, cela n'a pas d'importance pour l'accès. Lisez cette partie de la documentation pour plus d'informations.

Il est possible de changer la répartition avec la commande rebalance :

gluster volume rebalance VOL start

Selon le volume de données à traiter, la répartition peut prendre du temps. Il est possible de voir l'état de celle-ci via la commande :

gluster volume rebalance VOL status

J'ai pu constater que certains fichiers apparaissent en doublon dans les dossiers contenant les briques, ceux-ci restant uniques dans le point de montage GlusterFS. Je présume que gluster est suffisamment intelligent pour les conserver tant qu'il y a de la place.

Rappel : si vous insérez un fichier dans un dossier faisant partie d'un volume gluster sans passer par le point de montage gluster, celui-ci n’apparaîtra pas dans le volume et ne sera ni répliqué, ni distribué.

1-2-5 - Test du mode distribué-répliqué

Pour ce mode, je vais repartir sur la configuration précédente : deux machines en mode distribué que je vais passer en mode distribué-répliqué.

Je vais rajouter deux machines supplémentaires aux deux machines déjà présentes de façon à ce que chacune soit répliquée.

Une fois les deux serveurs supplémentaires préparés et appairés, je les intègre au volume :

gluster peer probe srv3
gluster peer probe srv4

gluster volume add-brick VOL replica 2 srv3:/data_srv3 srv4:/data_srv4 force

Nous obtenons le résultat suivant :

Volume Name: VOL
Type: Distributed-Replicate
Volume ID: 8f4d1305-7f28-41eb-bc76-85132c009c51
Status: Started
Number of Bricks: 2 x 2 = 4
Transport-type: tcp
Bricks:
Brick1: srv1:/data_srv1
Brick2: srv3:/data_srv3
Brick3: srv2:/data_srv2
Brick4: srv4:/data_srv4

L'ajout d'un fichier dans le point de montage du volume GlusterFS, point de montage depuis srv1 et donc création du fichier depuis srv1 va générer l'ajout de celui-ci dans /data_srv2 et /data_srv4. Nous avons donc bien la réplication ainsi que la distribution répartie.

Seuls les nouveaux fichiers ou fichiers modifiés après l'ajout des briques bénéficieront de la réplication.

Pour que tous les fichiers soient répliqués, il faudra exécuter la commande rebalance comme vu précédemment.

gluster volume rebalance VOL start

La répartition devient donc :

- srv1 : fichier1.txt, fichier2.txt ;

- srv2 : fichier2.txt, fichier3.txt ;

- srv3 : fichier2.txt ;

- srv4 : fichier2.txt, fichier3.txt ;

Chaque fichier est donc bien répliqué.

1-2-5-1 - Simulation de perte de srv2

La manipulation la plus simple est de préparer une nouvelle machine, de lui affecter une nouvelle adresse IP, de l'appairer et d'utiliser replace-brick comme vu précédemment.

Si vous souhaitez garder la même IP, il va falloir effectuer plusieurs opérations.

La difficulté ici est qu'un nouveau serveur n'aura pas le même UUID. Il y aura donc des manipulations supplémentaires à effectuer une fois le serveur préparé.

Il va nous falloir récupérer l'ancien UUID de srv2 :

root@srv1:~# grep -r uuid= /var/lib/glusterd/peers/* >fichier.txt

Uniquement valable si votre dossier ne contient qu'un seul fichier /var/lib/glusterd/peers/. Si ce n'est pas le cas, il faut identifier celui-ci et exécuter :

grep uuid= /var/lib/glusterd/peers/[nom du fichier contenant hostname=srv1] >fichier.txt

Nous transférerons ensuite cet UUID sur le nouvel srv2. Nous insérons ensuite cet UUID dans /var/lib/glusterd/glustered :

cat fichier.txt >>/var/lib/glusterd/glusterd.info

Nous éditons le fichier afin de fixer l'UUID, puis redémarrons le service :

/etc/init.d/glusterfs-server restart

Nous appairons ensuite le serveur :

root@srv2:~# gluster peer probe srv1

Nous redémarrons le service en appelant la commande gluster pool list, vous verrez les deux machines connectées.

Il faut ensuite synchroniser les volumes.

Depuis srv2, la commande gluster volume status vous retournera :

No volumes present

Nous synchronisons les volumes avec la commande ;

root@srv1:~# gluster volume sync srv2 all
sync volume may data inaccessible while the sync is in progress. Do you want to continue ? (y/n)
volume sync success.

À ce stade, les données ne sont pas encore synchronisées.

Mises à jour des métadonnées

Il va nous falloir mettre à jour les métadonnées sur le nouveau serveur depuis un serveur actif.

root@srv1:~# getfattr -n trusted.glusterfs.volume-id /data_srv1

getfattr:suppression des « / »en tête des chemins absolus
# file: data_srv2/
trusted.glusterfs.volume-id=0s8VVsv3xRTa6G41mE+5E1dA==

Il va falloir appliquer le volume id sur srv2 avec la commande :

setfattr -n trusted.glusterfs.volume-id -v '0s8VVsv3xRTa6G41mE+5E1dA==' /data_srv2

Nous redémarrons ensuite le service et depuis srv1, nous exécutons :

gluster volume heal VOL full

1-2-6 - Sauvegarder/restaurer

Il me parait indispensable d'avoir une sauvegarde hors ligne même en cas de système répliqué, ceci afin de se protéger de cryptolocker ou d’un effacement involontaire de fichiers. L'idéal sera une sauvegarde en ligne sur la même infrastructure, afin d'avoir une sauvegarde/restauration régulière rapide, doublé par une sauvegarde hors ligne moins fréquente.

1-2-7 - Sécurité

Les serveurs faisant partie d'un pool gluster, ils se reconnaissent via leur UUID. Pour qu'un serveur fasse partie d'un pool, il doit être intégré par un serveur du pool (c'est la commande gluster peer probe que nous avons déjà vue).

Par défaut, n'importe quel client peut se connecter à un volume gluster. Il est possible de restreindre l'accès à certaines IP via la commande :

gluster volume set VOL auth.allow [adresse IP 1],[adresse IP 2]

Par défaut, le dialogue s'effectue en clair. Il est possible d'établir un dialogue SSL/TLS (documentation ici), celui-ci gérant l'authentification et le cryptage, mais pas l'autorisation. La sécurisation peut bien sûr se faire via un tunnel VPN, l'authentification et le cryptage étant alors délégué au tunnel VPN.

Comme il n'y a pas de login/mot de passe, il ne faut pas exposer directement un point de montage gluster aux utilisateurs. Par exemple, ce point de montage peut-être partagé en SMB. C'est le serveur SMB (point d'entrée exposé) qui s’occupera alors des autorisations d'accès.

1-3 - DRBD/OCFS2

Nous allons ici cumuler l'utilisation de DRBD avec OCFS, DRBD s'occupant de la réplication, OCFS de l'accès concurrentiel.

1-3-1 - DRBD

1-3-1-1 - Qu'est-ce que DRBD ?

DRBD : Distributed Replicated Block Device permet la réplication de périphériques bloc entre serveurs via le réseau. Il peut être assimilé à du RAID 1 over IP.

Par défaut, DRBD utilise la notion de primaire/secondaire. Un système de fichiers ne peut être monté que depuis une machine primaire. La machine primaire transmet les modifications à la machine secondaire. Une machine en mode secondaire ne peut pas être utilisée de façon à garder la cohérence du cache.

Nous utiliserons un mode permettant d'avoir deux machines primaires et donc pouvoir faire des lectures/écritures depuis les deux nœuds.

1-3-2 - Installation de DRBD

La version utilisée ici sera la version 8.

L'installation se fait simplement par :

apt-get install drbd-utils

Il va falloir effectuer la configuration du nœud primaire et du nœud secondaire. Nous devons donc préparer un fichier de configuration en conséquence.

DRBD va utiliser une partition en tant que périphérique bloc sur chaque nœud.

Une partition doit être mise à disposition. Utiliser une partition avec DRBD va écraser son contenu.

Le fichier de configuration suivant, nommé r0.res et placé dans /,etc/drbd.d permet d’utiliser les nœuds accessibles en 192.168.8.1 et 192.168.8.2. Sur chacun d'eux, nous utiliserons la partition /dev/sdb1. Ce fichier sera à adapter à votre cas.

resource r0 {
syncer {
rate 100M;
}
on srv1 {
device /dev/drbd0;
disk /dev/sdb1;
address 192.168.8.1:7789;
meta-disk internal;
}

on srv2 {
device /dev/drbd0;
disk /dev/sdb1;
address 192.168.8.2:7789;
meta-disk internal;
}
}

Un fichier de définition de ressource DRBD doit avoir l'extension .res

Les noms de machines utilisés avec la directive « on »

doivent correspondre aux noms des machines retournés par la commande hostname.

Ce fichier devra être recopié sur le second nœud.

Le fichier est relativement simple à comprendre. Nous créons un volume DRBD accessible depuis /dev/drbd0 sur chaque nœud.

Nous créons ensuite le volume sur le nœud primaire :

# drbdadm create-md r0

initialising activiy log
NOT initialializing bitrmap
Writing meta data …
New dbrd meta data block successfully created.

Nous activons ensuite celui-ci :

# drbdadm up r0

Nous pouvons observer le résultat avec la commande drbd-overview :

# drbd-overview
0:r0/0 WFConnexion Secondary/Unknown Inconsistent/DUnknown

Il faut effectuer ces commandes sur les deux nœuds. Pour le second nœud, la commande drbd-overview donne :

0:r0/0 Connected Secondary/Primary Inconsistent/ Inconsistent

Nous voyons que la connexion est effectuée, mais que le « RAID » DRBD est inconsistant.

Nous lançons ensuite la synchronisation uniquement depuis le poste maitre (192.168.8.1 ou srv1), nous passons également le nœud en primaire :

drbdadm -- --overwrite-data-of-peer primary r0

Nous pouvons voir l'évolution de la synchronisation depuis le fichier /proc/drbd ou depuis la commande drbd-overview :

version: 8.4.3 (api:1/proto:86-101)
srcversion: 6681A7B41C129CD2CE0624F
0: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r-----
ns:417288 nr:0 dw:0 dr:418200 al:0 bm:25 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:7970004
[>...................] sync'ed:  5.1% (7780/8188)Mfinish: 0:05:05 speed: 26,080 (26,080) K/sec

Une fois la synchronisation terminée, nous allons passer le second nœud en primaire. Pour cela, nous ajoutons les lignes suivantes dans le bloc ressources du fichier de configuration r0 :

net {
allow-two-primaries;
after-sb-0pri discard-zero-changes;
after-sb-1pri discard-secondary;

}
startup {
become-primary-on both;
}

Le fichier devient :

resource r0 {
syncer {
rate 100M;
}
net {
allow-two-primaries yes;
after-sb-0pri discard-zero-changes;
after-sb-1pri discard-secondary;

}
startup {
become-primary-on both;
}
on srv1 {
device /dev/drbd0;
disk /dev/sdb1;
address 192.168.8.1:7789:
meta-disk internal;
}

on srv2 {
device /dev/drbd0;
disk /dev/sdb1;
address 192.168.8.2:7789:
meta-disk internal;
}
}

En détails, voici les nouvelles fonctions utilisées :

- allow-two-primaries : permet d'utiliser deux nœuds en mode primaire ;

- after-sb-0pri discard-zero-changes : en cas de split-brain, et que les deux nœuds sont considérés comme primaires, DRBD va prendre les modifications les plus récentes et les appliquer à l'autre nœud ;

- after-sb-1pri discard-secondary : en cas de split-brain avec un nœud primaire et un secondaire, le primaire écrasera les modifications sur le secondaire ;

- after-sb-2pri disconnect (non utilisé) : en cas de split-brain, DRBD déconnecte les volumes et le réglage du problème (et la décision du nœud où il faut sacrifier les différences) doit être fait manuellement.

Pensez à faire une copie du fichier de configuration avant modification pour pouvoir revenir à la situation initiale en cas de problème.

Nous recopions le fichier sur le second nœud et redémarrons le service DRBD sur les deux machines.

Nous pouvons vérifier l'état sur les deux serveurs avec :

# cat /proc/drbd

version: 8.4.3 (api:1/proto:86-101)
srcversion: 1A9F77B1CA5FF92235C2213
0: cs:Connected ro:Primary/Primary ds:UpToDate/Diskless C r-----
ns:912 nr:0 dw:0 dr:1824 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:8387292

Rappel : Il n'est pas possible de monter un système de fichiers dans un volume DRBD en mode secondaire.

1-3-2-1 - Sécurité de DRBD

Il est possible de sécuriser les dialogues DRBD en ajoutant les éléments suivant dans le fichier de configuration :

net {
cram-hmac-alg "sha1";
secret "le mot de passe";
}

Un transfert via une connexion sécurisée entre les nœuds hors DRBD peut aussi être utilisé. (interconnexion via cartes réseau dédiées hors réseau normal, VPN).

1-3-2-2 - Surveillance des volumes DRBD

DRBD est fourni avec un système de handlers et des scripts pour gérer les problèmes. Par exemple, la mise en place d’une notification par mail lors d’un split-brain s’effectue en ajoutant ce qui suit dans la section resources :

handlers {
split-brain "/usr/lib/drbd/notify-split-brain.sh <adresse>";
...
}

Je vous invite à regarder les différents scripts à disposition dans /usr/lib/drbd.

1-3-2-3 - Tests

Une fois la synchronisation effectuée, nous créons ensuite un système de fichiers sur /dev/drbd0 :

mkfs.ext4 /dev/drbd0

Quelle que soit la machine, le système de fichiers sera présent sur l'autre, le volume DRBD étant répliqué.

Nous y créons un fichier de test fichier1.txt après montage du volume DRBD dans un point de montage.

Nous montons ensuite /dev/drbd0 sur la seconde machine (srv2), nous voyons bien le fichier fichier1.txt.

Nous ajoutons un fichier fichier2.txt depuis srv2, celui-ci n’apparaît pas sur srv1.

Nous démontons et remontons le volume sur srv1, Après remontage, nous voyons bien le second fichier.

Explications

DRBD travaille au niveau bloc et non au niveau du système de fichiers. Nous pouvons l'utiliser tel quel en tant que sauvegarde, mais pas pour un double montage. Le monter simultanément risque de provoquer une inconsistance au niveau du système de fichiers.

Pour pallier ceci, nous allons utiliser OCFS2, un système de fichiers permettant les accès concurrents.

1-3-3 - OCFS2

1-3-3-1 - Qu'est-ce qu'OCFS2 ?

OCFS2 (Oracle Cluster File System) est un système de fichiers sous licence GPL qui permet l'accès concurrent à des fichiers, c'est-à-dire un accès simultané possible en lecture/écriture à un fichier sans risque d’inconsistance. Ceci nous permettra de résoudre le problème vu dans le chapitre précédent.

1-3-3-2 - Installation et paramétrage d'OCFS2

Pour installer OCFS2, il faut installer le paquet comme ci-dessous :

apt-get install ocfs2-tools

Nous créons le système de fichiers ocfs sur le volume DRBD :

mkfs -t ocfs2  -L MYCLOUD /dev/drbd0

Avec en options :

- -L : le nom du volume OCFS2.

La configuration s'effectue via les commandes suivantes.

Création du cluster que nous nommerons « MYCLOUD » :

o2cb add-cluster MYCLOUD

Ajout des nœuds :

o2cb add-node MYCLOUD --ip 192.168.8.1 --port 7777 --number 0 srv1

o2cb add-node MYCLOUD --ip 192.168.8.2 --port 7777 --number 1 srv2

Ce qui nous donnera La configuration suivante dans le fichier /etc/ocfs2/cluster.conf :

cluster:
heartbeat_mode = local
node_count = 2
name = MYCLOUD

node:
number = 0
cluster = MYCLOUD
ip_port = 7777
ip_address = 192.168.8.1
name = srv1

node:
number = 1
cluster = MYCLOUD
ip_port = 7777
ip_address = 192.168.8.2
name = srv2

Afin de modifier la configuration au démarrage, nous lançons :

dpkg-reconfigure ocfs2-tools

Après un redémarrage de la machine, ou plus simplement des services o2cb et ocfs2, il suffit de monter le volume :

mount -t ocfs2 /dev/drbd0 /data

ou grâce au fichier fstab :

/dev/drbd0 /data ocfs2 _netdev 0 0

Pour avoir accès aux données sur la seconde machine, il faudra effectuer les mêmes opérations après voir copié le fichier de configuration /etc/ocfs2/cluster.conf.

Les tests depuis les deux postes sont fonctionnels. Le fichier fichier1.txt créé depuis srv1 est visible sur srv2, et le fichier fichier2.txt créé depuis srv2 est visible dans le dossier /data de srv1.

Le montage automatique au redémarrage ne semble pas fonctionnel. Peut-être un problème de configuration.

1-3-4 - Couplage DRBD/OCFS2 : Simulation de panne

Pour simuler notre panne, nous allons arrêter srv2. Après quelques secondes, l’erreur suivante apparaît sur la console de srv1 :

drbd r0: PingAck did not arrive in time

De plus, la commande drbd-overview retournera un message similaire à :

0:r0/0  WFConnection Primary/Unknown UpToDate/DUnknown /data ocfs2 8.0G 151M 7.9G 2%

Le premier accès à la commande drbd-overview va être long.

L'arrêt de srv2 ne perturbe pas le volume /data dans srv1, sauf si celui-ci est redémarré.

Au redémarrage de srv2, j'ai le message suivant dans la console :

A start job is running for dev-drbd0.device (36s/1mn 30s)

Comme nous l'avons déjà vu, nous ne pouvons pas monter un volume DRBD en mode Secondary. Le volume OCFS2 n'est pas montable. Une tentative de montage avec mount -a donnera le message suivant :

mount.ocfs2: Device name specified was not found while opening device /dev/drbd0

Une fois le système démarré, le volume n'est pas disponible. En exécutant la commande drbd-overview, nous pouvons voir :

0:r0/0  Unconfigured . .

La commande :

drbdadm up r0

Nous retournera :

Marked additional 12 MB as out-of-sync based on AL.

Et le rappel de drbd-overview nous donnera :

0:r0/0  Connected Secondary/Primary UpToDate/UpToDate

Je redémarre DRBD sur les deux postes avec la commande service drbd restart.

Les deux postes repassent en mode Primary.

Il est alors possible de remonter le volume OCFS2 sur srv2 avec la commande mount -a (et sur srv1).

Nous avons donc une méthode pour redémarrer en mode dégradé.

1-3-5 - Couplage DRBD/OCFS2 : redémarrage des deux serveurs

Le redémarrage des deux serveurs simultanément nous donnera une situation de split-brain. La commande drbd-overview nous donnera « Unconfigured » sur les deux postes.

Pour avoir accès au volume sur un des postes, il faudra lancer les commandes suivantes :

- drbdadm up r0 ;

- drbdadm primary r0 ;

- mount -a.

Sur le second poste :

- drbdadm up r0.

À ce stade, le volume DRBD sera consistant avec le mode Primary sur le premier poste, et le mode Secondary sur le second. Un mount -a sur le second nœud réactivera le volume OCFS2.

En cas de perte complète d'un nœud (et non plus un simple arrêt), le volume sera indisponible sur le second nœud tant que la synchronisation n'a pas été refaite. Une fois celle-ci refaite, il sera possible de passer le nœud en Primary et ensuite de monter le volume OCFS2.

1-3-5-1 - Ajout d’une troisième machine pour la sauvegarde

La version 9 de DRBD permet d’avoir jusqu'à 16 machines. Ce chapitre repose sur la version 8.4 et permet d'empiler deux volumes DRBD. Ce système est appelé stacked et correspond à cette architecture :

Nous allons donc mettre en place un serveur srv3 comme serveur de sauvegarde.

Nous ajoutons la nouvelle ressource imbriquée dans /etc/drbd.d/r0.res à la suite de r0 :

resource r1 {

stacked-on-top-of r0 {
device     /dev/drbd10;
address    192.168.8.4:7788;
}

on srv3 {
device     /dev/drbd10;
disk       /dev/sdb1;
address    192.168.1.3:7788;
meta-disk  internal;
}
}

Vous remarquerez que nous utilisons un port différent, chaque ressource dialoguant sur son propre port.

Nous démontons ensuite le volume sur les deux machines. La commande drbd-overview vous permet de voir si le volume est monté :

0:0/r0    Connected    Primary/Primary    UpToDate/ UpToDate    /data    ocfs2    63M    13m    51m    20%
10:r1/0 ^^0 Unconfigured .

Voici le retour lorsque le volume est démonté :

0:0/r0    Connected    Primary/Primary    UpToDate/ UpToDate    11-dev of: 10 r1/0
10:r1/0 ^^0 Unconfigured .

Nous pouvons voir que le volume r1 n'est pas configuré.

Pour cela il nous faut exécuter les commandes :

drbdadm --stacked create-md r1
md_offset 66015232
al_offset 65982464
bm_offset 65978368

Found some data
==> This might destroy existing data! <==
Do you want to proceeed?
[need to type 'yes' to confirm]

Il faudra confirmer en tapant « yes », puis vous aurez un message de ce type en retour :

Initializing activity log
NOT initializing bitmap
Writing meta data...
New drbd meta data block successfull created.

Nous tapons ensuite la commande :

drbdadm --stacked up r1

À ce stade, il n'est pas possible de monter le volume.

Comme précisé par le message lors de la commande, effectuer ceci sur un volume existant peut provoquer une perte de données.

Nous copions ensuite la configuration sur srv3, puis créons le volume DRBD dessus :

root@srv3:~# drbdadm create-md r1

initializing activity log
NOT initializing bitmap
Writing meta data...
New drbd meta data block successfully created.

Puis :

drbdadm up r1

Nous invalidons ensuite le contenu de la machine par :

drbdadm invalidate r1

La synchronisation de srv3 se déclenche immédiatement.

Nous activons le mode primaire sur srv1 :

root@srv3:~# drbdadm –stacked primary r1

il faut ensuite monter le volume avec /dev/drbd10 au lieu de /dev/drbd0.

/dev/drbd10 sera le nom de device utilisé pour un volume stacked.

En cas de perte d'une des machines, il faudra appliquer la méthode vue au chapitre 1.3.5.1.

1-3-5-2 - Perte de liaison entre deux machines : split-brain

Si les deux machines croient que l'autre ne fonctionne plus, vous vous trouverez dans une situation nommée split brain. Dans cette situation, les deux machines passeront en mode standalone avec le statut inconnu :

0:r0/0 StandAlone Primary/Unknown /data ocfs2 127M 17M 1111M 14%

Pour régler ce problème, vous devrez en considérer une comme « sacrifiable » et la resynchroniser entièrement à partir de l'autre. Si la situation a perduré un moment, et qu'il y a des différences entre les deux, les différences de la machine sacrifiée seront perdues.

Nous commençons par effectuer un redémarrage des deux machines. À ce stade aucune des deux ne devrait être connectée au volume OCFS2.

Vous pouvez voir un peu plus haut que la commande drbd-overview indique des informations sur le volume monté.

Nous pouvons voir que le volume est monté dans /data. Si aucun volume n'est monté, vous ne verrez que l'information Primary/Unknown (ou Secundary/Unknown).

Nous allons basculer la machine « victime » en secondaire si nécessaire.

Avant ce redémarrage, nous commentons dans le fichier /etc/drbd.d/r0 les lignes concernant la gestion du double primaire.

Après redémarrage. Avec drbd-overview, vous devriez avoir quelque chose comme :

0:r0/0 WFConnection Secondary/Unknown UpToDate/Unknown

Nous allons ensuite déclarer une des machines comme obsolète, commande à effectuer sur la machine concernée :

drbdadm – --discard-my-data connect r0

La resynchronisation se déclenche. Pendant celle-ci, vous pouvez basculer la machine servant de source en primaire et remonter le volume OCFS.

Une fois la synchronisation terminée, nous décommentons les lignes concernant l'utilisation de deux machines primaires et redémarrons le service sur les machines une à une.

1-3-6 - DRBD 9

DRBD 9 permet d'utiliser LVM comme conteneur de volume. Il permet aussi d'avoir jusqu'à 16 nœuds par ressource sans devoir recourir à l'empilement comme vu avec la version 8.4. La version fournie avec Debian 9 étant la 8,4, il va falloir compiler :

- le module noyau ;

- les outils drbd (drbd-utils).

Avant de commencer, nous installerons LVM (apt-get install lvm2).

1-3-6-1 - Installation du module noyau :

Commençons par télécharger les sources du module :

wget https://www.linbit.com/downloads/drbd/9.0/drbd-9.0.19-1.tar.gz

Je n'ai pas pris la dernière version pour des questions de soucis de compilation sur Debian 9 utilisé (Debian 9 étant une ancienne version maintenant).

Les liens de téléchargements peuvent changer avec le temps et devront donc être adaptés

Décompression :

gunzip drbd-9.0.19-1.tar.gz

Désarchivage :

tar -xvf drbd-9.0.19-1.tar

La compilation se fera avec la commande make dans le dossier décompressé. Les prérequis sont make bien sûr, et les en-têtes de votre noyau (installable avec la commande apt-get install linux-headers-$(uname -r)).

Une fois la compilation effectuée, l'installation se fera par :

make install

1-3-6-2 - Installation des outils

wget https://www.linbit.com/downloads/drbd/utils/drbd-utils-9.13.1.tar.gz
gunzip drbd-utils-9.13.1.tar.gz
tar -xvf drbd-utils-9.13.1.tar

Les prérequis avant compilation seront gcc, flex, xlstproc (pour la documentation). La compilation se fera ensuite par :

./configure
make

À la fin de la compilation, j'ai eu le message d'erreur suivant :

Makefile:108 : la recette pour la cible « doc » a échoué

Cela n’empêche pas le make install.

Nous faisons ensuite l'installation :

make install

1-3-6-3 - Préparation du volume LVM

Nous commençons par préparer la partition à l'usage de LVM (dans notre cas sdb1) :

pvcreate /dev/sdb1

Nous créons ensuite un volume Group que nous appellerons vg01 :

vgcreate vg01 /dev/sdb1

Et créons enfin le volume logique lv01 (volume de 1900 Mo sur un disque de 2 Go pour l'essai) :

lvcreate -L 1900 -n lv01 vg01

Nous créons ensuite un fichier de configuration dans un premier temps avec une machine unique :

resource r0 {
protocol C;

on srv1 {
disk /dev/vg01/lv01;
device /dev/drbd0;
address 192.168.1.201:7789;
meta-disk internal;
node-id 0;
}
}

Comme nous utilisons une version compilée de DRBD, les fichiers de configuration devront être placés dans /usr/local/,etc/drbd.d au lieu de /,etc/drbd.d.

Remarquez la présence de l'option node-id 0;. Cette option, apparue avec DRBD 9 permet de numéroter chaque nœud participant au cluster.

La procédure sera ensuite la même que pour la version 8.4.

Création des métadonnées sur le volume :

drbdadm create-md r0

Activation du volume :

drbdadm up r0

À ce stade, nous pouvons voir l'état du volume avec la commande drbdadm status, qui remplace drbd-overview :

~# drbdadm status
r0 role:Secondary
disk:Inconsistent

Nous allons ensuite passer celui-ci en primaire. La syntaxe a été simplifiée par rapport aux versions précédentes :

drbdadm primary r0 --force

Résultat de drbdadm status :

# drbdadm status
r0 role:Primary
disk:UpToDate

Nous modifions le fichier de configuration pour intégrer la seconde machine :

resource r0 {
protocol C;

on srv1 {
disk /dev/vg01/lv01;
device /dev/drbd0;
address 192.168.1.201:7789;
meta-disk internal;
node-id 0;
}
on srv2 {
disk /dev/vg01/lv01;
device /dev/drbd0;
address 192.168.1.202:7789;
meta-disk internal;
node-id 1;
}
}

Rappel : la valeur node-id doit être unique à chaque nœud.

Une fois le fichier mis à jour, la commande suivante permet de prendre en compte les changements :

drbdadm adjust r0

La commande drbdadm status nous montre l'attente de connexion pour srv2 non encore préparé.

~# drbdadm status
r0 role:Primary
disk:UpToDate
srv2 connection:Connecting

Reste à préparer srv2. La copie des dossiers source depuis srv1 permettra d'installer le module noyau DRBD avec make install sans devoir recompiler (le module .ko compilé sur srv1 étant dans le dossier des sources copié). Pour les outils, il faudra réexecuter ./configure, puis make et make install. Restera à copier le fichier de configuration.

Une fois le volume LVM créé, les métadonnées DRBD créées (avec drbdadm create-md r0), le lancement de la commande drbdadm up r0 déclenchera la synchronisation. Ci-dessous la synchronisation en cours :

~# drbdadm status
r0 role:Primary
disk:UpToDate
srv2 role:Secondary
replication:SyncSource peer-disk:Inconsistent done:43.03

Une fois les volumes synchronisés, passer srv2 en primaire ne posera pas de difficultés.

1-3-6-4 - Intégration troisième poste

Bien que cela soit possible, je n'ai pas réussi à intégrer un troisième poste sans erreur. La documentation manque de précision.

1-3-6-5 - drbdmanage

drbdmanage est un utilitaire simplifiant la gestion de DRBD. drbdmanage est déprécié et remplacé par linstor. Celui-ci étant toujours disponible sur github, j'ai décidé d'en faire une présentation.

Nous commençons par récupérer les sources :

git clone https://github.com/LINBIT/drbdmanage.git

Prérequis : python-dbus, python-gobject.

Une fois entre dans le dossier, l'installation se fera par :

./setup.py install

La commande drbdmanage sera alors disponible.

drbdmanage attend par défaut la présence d'un volume group LVM nommé drbdpool. Si vous souhaitez définir un nom différent décommentez la ligne drbdctrl-vg dans le fichier /etc/drbdmanage.cfg et mettez-y la valeur de notre choix, dans l'exemple suivant le volume group utilisé s’appellera « drbd », créée dans la partition /dev/sdb1 comme ceci :

~# pvcreate /dev/sdb1
Physical volume "/dev/sdb1" successfully created.
~# vgcreate drbd /dev/sdb1
Volume group "/dev/sdb1" successfully created.

Avant de créer le cluster, comme drbdmanage a été installé par les sources, pour éviter un message d'erreur dbus, il faut créer le lien symbolique suivant :

ln -s /usr/local/bin/dbus-drbdmanage-service /usr/bin

Ces opérations préliminaires seront à effectuer sur les deux machines minimales qui seront mises en place.

Nous créons une liaison SSH par clé entre les deux serveurs :

root@srv1 ~#  ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/cloud/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/cloud/.ssh/id_rsa.
Your public key has been saved in /home/cloud/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:RgvrHWfPnz6PiniTRaTL0AFHFoR6xWp/cRZb6Q1RJc8 cloud@Debian
The key's randomart image is:
+---[RSA 2048]----+
|        .**.  oo=|
|        .o+ . o=.|
|      ...+ +  .=E|
|      .+=.o o +..|
|      .oS+oo +   |
|     . o ++oo    |
|      . .  +o    |
|         .+. ..o |
|        .....o=o.|
+----[SHA256]-----+

root@srv1 ~# ssh-copy-id root@192.168.1.202
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/cloud/.ssh/id_rsa.pub"
The authenticity of host 'srv1 (192.168.1.201)' can't be established.
ECDSA key fingerprint is SHA256:LLALxAyQlZLXlVtPSyTrOkUaTKKC+C0UCDAQKrWTuMI.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@srv1's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'cloud@srv1.local'"
and check to make sure that only the key(s) you wanted were added.

Nous initialisons ensuite le cluster :

drbdmanage init 192.168.1.201

Qui nous retournera :

You are going to initialize a new drbdmanage cluster.
CAUTION! Note that:
* Any previous drbdmanage cluster information may be removed
* Any remaining resources managed by a previous drbdmanage installation
that still exist on this system will no longer be managed by drbdmanage

Confirm:

yes/no: yes
Empty drbdmanage control volume initialized on '/dev/drbd0'.
Empty drbdmanage control volume initialized on '/dev/drbd1'.
Waiting for server: .
Operation completed successfully

Nous pouvons voir la liste des nœuds (un seul pour le moment) avec la commande :

drbdmanage list-nodes

Qui nous retournera :

+------------------------------------------------------------------------------+
| Name | Pool Size | Pool Free |                                       | State |
|------------------------------------------------------------------------------|
| srv1 |      2044 |      2036 |                                       |    ok |
+------------------------------------------------------------------------------+

Nous ajoutons ensuite le second nœud :

drbdmanage add-node srv2 192.168.1.202
Operation completed successfully
Operation completed successfully

Executing join command using ssh.
IMPORTANT: The output you see comes from srv2
IMPORTANT: Your input is executed on srv2
You are going to join an existing drbdmanage cluster.
CAUTION! Note that:
* Any previous drbdmanage cluster information may be removed
* Any remaining resources managed by a previous drbdmanage installation
that still exist on this system will no longer be managed by drbdmanage

Confirm:

yes/no: yes
Waiting for server to start up (can take up to 1 min)

Waiting for server: ........
Operation completed successfully
Give leader time to contact the new node
Operation completed successfully
Operation completed successfully

La commande drbdmanage list-nodes nous retournera ceci :

drbdmanage list-nodes
+------------------------------------------------------------------------------+
| Name | Pool Size | Pool Free |                 |                       State |
|------------------------------------------------------------------------------|
| srv1 |      2044 |      2036 |                 |  online/quorum vote ignored |
| srv2 |      2044 |      2036 |                 | offline/quorum vote ignored |
+------------------------------------------------------------------------------+

Nous créons ensuite une ressource :

:~/drbdmanage# drbdmanage add-resource r0
Operation completed successfully

Puis un volume dans la ressource :

:~/drbdmanage# drbdmanage add-volume r0 1500MB
Operation completed successfully

Nous pouvons ensuite voir la liste des volumes avec la commande drbdmanage list-volumes :

~# drbdmanage list-volumes
+------------------------------------------------------------------------------+
| Name | Vol ID |     Size | Minor |                                   | State |
|------------------------------------------------------------------------------|
| r0   |      0 | 1,40 GiB |   100 |                                   |    ok |
+------------------------------------------------------------------------------+

Nous pouvons voir la valeur 100 au niveau du minor, ce qui signifie que le nom du device à utiliser sera /dev/drbd100.

Nous le formatons en OCFS2 comme vu au chapitre précédent :

~# mkfs -t ocfs2 -L MYCLOUD /dev/drbd100
mkfs.ocfs2 1.8.4
Cluster stack: classic o2cb
Label: MYCLOUD
Features: sparse extended-slotmap backup-super unwritten inline-data strict-journal-super xattr indexed-dirs refcount discontig-bg
Block size: 4096 (12 bits)
Cluster size: 4096 (12 bits)
Volume size: 1500000256 (366211 clusters) (366211 blocks)
Cluster groups: 12 (tail covers 11395 clusters, rest cover 32256 clusters)
Extent allocator size: 4194304 (1 groups)
Journal size: 67108864
Node slots: 2
Creating bitmaps: done
Initializing superblock: done
Writing system files: done
Writing superblock: done
Writing backup superblock: 1 block(s)
Formatting Journals: done
Growing extent allocator: done
Formatting slot map: done
Formatting quota files: done
Writing lost+found: done
mkfs.ocfs2 successful

1-3-6-6 - Linstor

Linstor est le successeur de DRBD. Il est utilisé dans les solutions comme OpenNebula et Proxmox. Celui-ci est libre.

N'ayant pas réussi à l'installer, je n'ai pu le tester.

1-4 - Ceph

Ceph est une plateforme libre de stockage distribué. Ceph est conçu pour être automatiquement distribué et réparable et sans point unique de défaillance.

Ceph est utilisable en mode bloc ou en mode objet (comme Amazon S3 en mode HTTP REST).

Ceph pourrait à lui tout seul faire l'objet d'un tutoriel, nous allons ici le survoler. Vous pourrez avoir une installation fonctionnelle au moins à minima en suivant ce chapitre.

1-4-1 - Modules Ceph

Ceph est composé de plusieurs démons, répartis sur plusieurs machines. Il est possible d'avoir plusieurs types de démons sur la même machine, mais cela n'a pas d’intérêt et est même contre-productif sur un important cluster.

- Monitor (Mon) : ce sont les chefs d’orchestre du cluster Ceph. S'il n'y a pas de moniteur disponible, il n'y a pas d’accès au cluster Ceph. Pour assurer la pérennité du cluster, les moniteurs doivent être sur des machines indépendantes et en nombre impair. Un minimum de trois moniteurs est recommandé.

- OSD (Object Storage Device ou OSD) : il y a un démon OSD par device OSD. Ce démon est en charge du stockage, de la réplication et de la redistribution des données en cas de défaillance. Il fournit les informations de monitoring aux monitors. Un device OSD est l'unité bas niveau de stockage des données. Un cluster Ceph va être composé d'un ensemble d'OSD.

- Meta Data Service (MDS) : nécessaire à l’utilisation de CephFS, va stocker les métadonnées de tous les fichiers et permettre le support de POSIX.

- CephFS : système de fichiers POSIX fourni avec Ceph et s’appuyant sur le stockage Ceph (objet ou bloc). C’est la couche de plus haut niveau.

Les démons MDS et CephFS ne sont nécessaires que si vous utilisez Ceph avec son système de fichiers intégré.

Éléments un peu plus avancés

- pool : regroupement logique de stockage d’objets. Des pools par défaut suffisent à la gestion d’un petit cluster Ceph, mais pour des clusters intersites, il est important d’affiner ce type de réglage. Exemple : nombre de copies/répliquas des objets, répartition des données de type RAID5, etc.

- Placement Group (PG) : peut être vu comme des unités d’allocation et/ou index internes, ils servent à la répartition dans le cluster. Plus il y a de PG, plus on consomme de ressources (CPU/RAM).

Il est possible d’augmenter le nombre de PG d’un pool, mais pas de le réduire.

1-4-2 - Fonctionnement de Ceph

CRUSH

CRUSH est l’algorithme de répartition des données dans le cluster. La crush map est la cartographie de la répartition des données. Les crush rules sont les règles de répartition des données.

Quand vous créez un cluster Ceph, il y a une crush map par défaut qui peut fonctionner automatiquement. Mais pour un gros cluster, il est important de la gérer. Cela permet d’affiner la répartition des données (entre deux centres de données par exemple), et de repérer facilement un OSD tombé (dans quel centre de données, quelle baie, quelle machine, etc.).

Voici les différents niveaux utilisés par les crush map :

- OSD (peut être vu comme le « device ») ;

- host ;

- chassis ;

- rack ;

- row ;

- pdu ;

- pod ;

- room ;

- datacenter ;

- region ;

- root.

Schéma tiré de la documentation officielle :

Voici le processus de lecture/écriture sur un cluster Ceph :

1. Le client Ceph contacte un moniteur pour obtenir la cartographie du cluster ;

2. Les données sont converties en objets (contenant un identifiant d’objet et de pool) ;

3. L’algorithme CRUSH détermine le groupe où placer les données et l’OSD primaire ;

4. Le client contacte l’OSD primaire pour stocker/récupérer les données ;

5. L’OSD primaire effectue une recherche CRUSH pour déterminer le groupe de placement et l’OSD secondaire.

1. Dans un pool répliqué, l’OSD primaire copie l’objet vers l’OSD secondaire,

2. Dans un pool avec erasure coding, l’OSD primaire découpe l’objet en segments, génère les segments contenant les calculs de parité et distribue l’ensemble de ces segments vers les OSD secondaires tout en écrivant un segment en local.

1-4-3 - Installation de Ceph

Nous utiliserons la version Ceph Luminous (v,12).

1-4-3-1 - Installation d'une première machine

1-4-3-1-1 - Préparations

Nous allons commencer par les prérequis.

Nous fixons le nom de notre hôte dans le fichier /,etc/hosts :

192.168.1.200 srv1

Nous spécifions le hostname dans le fichier /,etc/hostname en y mettant le nom « srv1 ».

Nous lançons la commande hostname :

hostname srv1

Nous fermons et rouvrons la session pour prendre en compte le nouveau nom.

Nous installons ensuite le serveur de temps, indispensable à la synchronisation correcte entre différentes machines :

apt-get install ntp ntpdate

Ensuite, nous configurons SSH afin de permettre une connexion par clé. D’abord, nous générons une clé avec la commande ssh-keygen :

root@srv1:~# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
/root/.ssh/id_rsa already exists.
Overwrite (y/n)? ^C
root@srv1:~# rm .ssh/* -rf
root@srv1:~# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
3c:38:bc:0d:54:45:13:2c:dc:bd:61:8c:24:d9:58:06 root@srv1
The key's randomart image is:
+---[RSA 2048]----+
|       .E%O=     |
|       .=o=.=    |
|      .  . . o   |
|     o o    .    |
|      = S        |
|       = .       |
|      . .        |
|                 |
|                 |
+-----------------+
root@srv1:~#

Ensuite, nous copions la clé avec ssh-copy-id :

ssh-copy-id root@srv1

The authenticity of host 'srv1 (192.168.1.200)' can't be established.
ECDSA key fingerprint is 92:27:9f:61:14:19:63:85:28:d2:1b:88:4e:86:d6:08.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@srv1's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@srv1'"
and check to make sure that only the key(s) you wanted were added.

Toutes les commandes Ceph passent par SSH et le nom d'hôte, il faut donc créer une clé SSH même pour une communication locale.

Grâce à cela, la commande ssh root@srv1 devrait ouvrir un Shell, sans nécessité de mot de passe, ce qui nous sera nécessaire pour les commandes suivantes.

1-4-3-1-2 - Installation de ceph-deploy

Une fois les prérequis effectués, nous allons installer et utiliser la commande ceph-deploy qui nous permettra de préparer et déployer notre cluster.

Nous commençons par télécharger le fichier de signature de dépôt :

wget download.ceph.com/keys/release.asc

Nous installons celui-ci :

apt-key add release.asc

Nous ajoutons le dépôt dans /etc/apt/sources.list :

deb https://download.ceph.com/debian-luminous/ stretch main

Puis effectuons l'installation :

apt-get update
apt-get install ceph-deploy

1-4-3-1-3 - Configuration

Nous créons un dossier qui contiendra les fichiers de configuration du cluster :

mkdir cephdeploy
cd cephdeploy

Nous créons notre cluster :

ceph-deploy new srv1

La console nous retournera les informations suivantes :

[ceph_deploy.conf][DEBUG ] found configuration file at: /root/.cephdeploy.conf
[ceph_deploy.cli][INFO  ] Invoked (1.5.39): /usr/bin/ceph-deploy new srv1
[ceph_deploy.cli][INFO  ] ceph-deploy options:
[ceph_deploy.cli][INFO  ]  username                      : None
[ceph_deploy.cli][INFO  ]  verbose                       : False
[ceph_deploy.cli][INFO  ]  overwrite_conf                : False
[ceph_deploy.cli][INFO  ]  quiet                         : False
[ceph_deploy.cli][INFO  ]  cd_conf                       : <ceph_deploy.conf.cephdeploy.Conf instance at 0x7f2db686dc68>
[ceph_deploy.cli][INFO  ]  cluster                       : ceph
[ceph_deploy.cli][INFO  ]  ssh_copykey                   : True
[ceph_deploy.cli][INFO  ]  mon                           : ['srv1']
[ceph_deploy.cli][INFO  ]  func                          : <function new at 0x7f2db6843cf8>
[ceph_deploy.cli][INFO  ]  public_network                : None
[ceph_deploy.cli][INFO  ]  ceph_conf                     : None
[ceph_deploy.cli][INFO  ]  cluster_network               : None
[ceph_deploy.cli][INFO  ]  default_release               : False
[ceph_deploy.cli][INFO  ]  fsid                          : None
[ceph_deploy.new][DEBUG ] Creating new cluster named ceph
[ceph_deploy.new][INFO  ] making sure passwordless SSH succeeds
[srv1][DEBUG ] connected to host: srv1
[srv1][DEBUG ] detect platform information from remote host
[srv1][DEBUG ] detect machine type
[srv1][DEBUG ] find the location of an executable
[srv1][INFO  ] Running command: /bin/ip link show
[srv1][INFO  ] Running command: /bin/ip addr show
[srv1][DEBUG ] IP addresses found: [u'192.168.1.200']
[ceph_deploy.new][DEBUG ] Resolving host srv1
[ceph_deploy.new][DEBUG ] Monitor srv1 at 192.168.1.200
[ceph_deploy.new][DEBUG ] Monitor initial members are ['srv1']
[ceph_deploy.new][DEBUG ] Monitor addrs are ['192.168.1.200']
[ceph_deploy.new][DEBUG ] Creating a random mon key...
[ceph_deploy.new][DEBUG ] Writing monitor keyring to ceph.mon.keyring...
[ceph_deploy.new][DEBUG ] Writing initial config to ceph.conf...
root@srv1:~/cephdeploy#

Ceci va créer les fichiers :

- ceph.conf ;

- ceph-deploy-ceph.log ;

- ceph.mon.keyring.

le fichier ceph.conf contient :

[global]
fsid = 85967fe2-3f08-4e0b-9f3c-ca6647776383
mon_initial_members = srv1
mon_host = 192.168.1.200
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx

Dans lequel on ajoute :

osd pool default size = 2
osd pool default min size = 1
public_network = 192.168.1.0/24
cluster_network = 192.168.1.0/24

C'est ce fichier qui contiendra la configuration complète du cluster. À ce stade, il n'y a qu'une machine avec les réglages minimums nécessaires au démarrage. Ce fichier sera complété au fur et à mesure de l'avancée dans le chapitre et de l'ajout des modules/machines.

Ceci va nous permettre de créer un pool OSD à deux disques et permettre l'utilisation avec un seul nœud (en mode dégradé).

Les lignes public_network/cluster_network permettent de gérer les réseaux autorisés pour le dialogue entre les entités Ceph. Dans notre cas, il n'y a aucune séparation ce qui n'est pas recommandé en production.

Nous installons ceph-deploy sur notre premier nœud :

ceph-deploy install srv1

Lire les logs peut permettre de comprendre les opérations déclenchées. Cela pourra vous être utile si vous comptez utiliser le service. Si vous ne lisez ce chapitre qu'à titre de découverte ou de veille technologique, vous pouvez passer directement à la suite.

Voici un exemple des logs affichés :

Debian GNU/Linux 8
srv1 login: root
Password:
Last login: Fri Nov 16 18:45:59 CET 2018 from srv1 on pts/1
Linux srv1 3.16.0-4-amd64 #1 SMP Debian 3.16.51-3 (2017-12-13) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@srv1:~# apt-get install ca-certificates apt-transport-https
Lecture des listes de paquets... Fait
Construction de l'arbre des dépendances
Lecture des informations d'état... Fait
apt-transport-https est déjà la plus récente version disponible.
ca-certificates est déjà la plus récente version disponible.
0 mis à jour, 0 nouvellement installés, 0 à enlever et 24 non mis à jour.
root@srv1:~# ceph-deploy install srv1
[ceph_deploy.conf][DEBUG ] found configuration file at: /root/.cephdeploy.conf
[ceph_deploy.cli][INFO  ] Invoked (1.5.39): /usr/bin/ceph-deploy install srv1
[ceph_deploy.cli][INFO  ] ceph-deploy options:
[ceph_deploy.cli][INFO  ]  verbose                       : False
[ceph_deploy.cli][INFO  ]  testing                       : None
[ceph_deploy.cli][INFO  ]  cd_conf                       : <ceph_deploy.conf.cephdeploy.Conf instance at 0x7fd903c207a0>
[ceph_deploy.cli][INFO  ]  cluster                       : ceph
[ceph_deploy.cli][INFO  ]  dev_commit                    : None
[ceph_deploy.cli][INFO  ]  install_mds                   : False
[ceph_deploy.cli][INFO  ]  stable                        : None
[ceph_deploy.cli][INFO  ]  default_release               : False
[ceph_deploy.cli][INFO  ]  username                      : None
[ceph_deploy.cli][INFO  ]  adjust_repos                  : True
[ceph_deploy.cli][INFO  ]  func                          : <function install at 0x7fd904063410>
[ceph_deploy.cli][INFO  ]  install_mgr                   : False
[ceph_deploy.cli][INFO  ]  install_all                   : False
[ceph_deploy.cli][INFO  ]  repo                          : False
[ceph_deploy.cli][INFO  ]  host                          : ['srv1']
[ceph_deploy.cli][INFO  ]  install_rgw                   : False
[ceph_deploy.cli][INFO  ]  install_tests                 : False
[ceph_deploy.cli][INFO  ]  repo_url                      : None
[ceph_deploy.cli][INFO  ]  ceph_conf                     : None
[ceph_deploy.cli][INFO  ]  install_osd                   : False
[ceph_deploy.cli][INFO  ]  version_kind                  : stable
[ceph_deploy.cli][INFO  ]  install_common                : False
[ceph_deploy.cli][INFO  ]  overwrite_conf                : False
[ceph_deploy.cli][INFO  ]  quiet                         : False
[ceph_deploy.cli][INFO  ]  dev                           : master
[ceph_deploy.cli][INFO  ]  nogpgcheck                    : False
[ceph_deploy.cli][INFO  ]  local_mirror                  : None
[ceph_deploy.cli][INFO  ]  release                       : None
[ceph_deploy.cli][INFO  ]  install_mon                   : False
[ceph_deploy.cli][INFO  ]  gpg_url                       : None
[ceph_deploy.install][DEBUG ] Installing stable version jewel on cluster ceph hosts srv1
[ceph_deploy.install][DEBUG ] Detecting platform for host srv1 ...
[srv1][DEBUG ] connected to host: srv1
[srv1][DEBUG ] detect platform information from remote host
[srv1][DEBUG ] detect machine type
[ceph_deploy.install][INFO  ] Distro info: debian 8.10 jessie
[srv1][INFO  ] installing Ceph on srv1
[srv1][INFO  ] Running command: env DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=critical apt-get --assume-yes -q --no-install-recommends install ca-certificates apt-transport-https
[srv1][DEBUG ] Lecture des listes de paquets…
[srv1][DEBUG ] Construction de l'arbre des dépendances…
[srv1][DEBUG ] Lecture des informations d'état…
[srv1][DEBUG ] apt-transport-https est déjà la plus récente version disponible.
[srv1][DEBUG ] ca-certificates est déjà la plus récente version disponible.
[srv1][DEBUG ] 0 mis à jour, 0 nouvellement installés, 0 à enlever et 24 non mis à jour.
[srv1][INFO  ] Running command: wget -O release.asc https://download.ceph.com/keys/release.asc
[srv1][WARNIN] --2018-11-16 19:30:22--  https://download.ceph.com/keys/release.asc
[srv1][WARNIN] Résolution de download.ceph.com (download.ceph.com)… 158.69.68.124, 2607:5300:201:2000::3:58a1
[srv1][WARNIN] Connexion à download.ceph.com (download.ceph.com)|158.69.68.124|:443… connecté.
[srv1][WARNIN] requête HTTP transmise, en attente de la réponse… 200 OK
[srv1][WARNIN] Taille : 1645 (1,6K) [application/octet-stream]
[srv1][WARNIN] Sauvegarde en : « release.asc »
[srv1][WARNIN]
[srv1][WARNIN]      0K .                                                     100% 27,7M=0s
[srv1][WARNIN]
[srv1][WARNIN] 2018-11-16 19:30:23 (27,7 MB/s) — « release.asc » sauvegardé [1645/1645]
[srv1][WARNIN]
[srv1][INFO  ] Running command: apt-key add release.asc
[srv1][DEBUG ] OK
[srv1][DEBUG ] add deb repo to /etc/apt/sources.list.d/
[srv1][INFO  ] Running command: env DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=critical apt-get --assume-yes -q update
[srv1][DEBUG ] Ign http://ftp.fr.debian.org jessie InRelease
[srv1][DEBUG ] Atteint http://ftp.fr.debian.org jessie-updates InRelease
[srv1][DEBUG ] Atteint http://ftp.fr.debian.org jessie/updates InRelease
[srv1][DEBUG ] Atteint http://ftp.fr.debian.org jessie Release.gpg
[srv1][DEBUG ] Atteint http://ftp.fr.debian.org jessie Release
[srv1][DEBUG ] Réception de : 1 http://ftp.fr.debian.org jessie-updates/main amd64 Packages/DiffIndex [11,8 kB]
[srv1][DEBUG ] Réception de : 2 http://ftp.fr.debian.org jessie-updates/main Translation-en/DiffIndex [3 688 B]
[srv1][DEBUG ] Atteint https://download.ceph.com jessie InRelease
[srv1][DEBUG ] Atteint http://ftp.fr.debian.org jessie/updates/main amd64 Packages
[srv1][DEBUG ] Atteint http://ftp.fr.debian.org jessie/updates/main Translation-en
[srv1][DEBUG ] Atteint http://ftp.fr.debian.org jessie/main amd64 Packages
[srv1][DEBUG ] Atteint http://ftp.fr.debian.org jessie/main Translation-fr
[srv1][DEBUG ] Réception de : 3 https://download.ceph.com jessie/main Translation-fr_FR [178 B]
[srv1][DEBUG ] Atteint http://ftp.fr.debian.org jessie/main Translation-en
[srv1][DEBUG ] Réception de : 4 https://download.ceph.com jessie/main Translation-fr [178 B]
[srv1][DEBUG ] Réception de : 5 https://download.ceph.com jessie/main Translation-en [178 B]
[srv1][DEBUG ] Atteint https://download.ceph.com jessie/main amd64 Packages
[srv1][DEBUG ] Réception de : 6 https://download.ceph.com jessie/main Translation-fr_FR [178 B]
[srv1][DEBUG ] Réception de : 7 https://download.ceph.com jessie/main Translation-fr [178 B]
[srv1][DEBUG ] Réception de : 8 https://download.ceph.com jessie/main Translation-en [178 B]
[srv1][DEBUG ] Réception de : 9 https://download.ceph.com jessie/main Translation-fr_FR [178 B]
[srv1][DEBUG ] Réception de : 10 https://download.ceph.com jessie/main Translation-fr [178 B]
[srv1][DEBUG ] Réception de : 11 https://download.ceph.com jessie/main Translation-en [178 B]
[srv1][DEBUG ] Réception de : 12 https://download.ceph.com jessie/main Translation-fr_FR [178 B]
[srv1][DEBUG ] Réception de : 13 https://download.ceph.com jessie/main Translation-fr [178 B]
[srv1][DEBUG ] Réception de : 14 https://download.ceph.com jessie/main Translation-en [178 B]
[srv1][DEBUG ] Réception de : 15 https://download.ceph.com jessie/main Translation-fr_FR [178 B]
[srv1][DEBUG ] Ign https://download.ceph.com jessie/main Translation-fr_FR
[srv1][DEBUG ] Réception de : 16 https://download.ceph.com jessie/main Translation-fr [178 B]
[srv1][DEBUG ] Ign https://download.ceph.com jessie/main Translation-fr
[srv1][DEBUG ] Réception de : 17 https://download.ceph.com jessie/main Translation-en [178 B]
[srv1][DEBUG ] Ign https://download.ceph.com jessie/main Translation-en
[srv1][DEBUG ] 15,5 ko réceptionnés en 5s (3 032 o/s)
[srv1][DEBUG ] Lecture des listes de paquets…
[srv1][WARNIN] W: Duplicate sources.list entry https://download.ceph.com/debian-jewel/ jessie/main amd64 Packages (/var/lib/apt/lists/download.ceph.com_debian-jewel_dists_jessie_main_binary-amd64_Packages)
[srv1][WARNIN] W: Vous pouvez lancer « apt-get update » pour corriger ces problèmes.
[srv1][INFO  ] Running command: env DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=critical apt-get --assume-yes -q --no-install-recommends install -o Dpkg::Options::=--force-confnew ceph ceph-osd ceph-mds ceph-mon radosgw
[srv1][DEBUG ] Lecture des listes de paquets…
[srv1][DEBUG ] Construction de l'arbre des dépendances…
[srv1][DEBUG ] Lecture des informations d'état…
[srv1][DEBUG ] ceph est déjà la plus récente version disponible.
[srv1][DEBUG ] ceph-mds est déjà la plus récente version disponible.
[srv1][DEBUG ] ceph-mon est déjà la plus récente version disponible.
[srv1][DEBUG ] ceph-osd est déjà la plus récente version disponible.
[srv1][DEBUG ] radosgw est déjà la plus récente version disponible.
[srv1][DEBUG ] 0 mis à jour, 0 nouvellement installés, 0 à enlever et 24 non mis à jour.
[srv1][INFO  ] Running command: ceph --version
[srv1][DEBUG ] ceph version 10.2.11 (e4b061b47f07f583c92a050d9e84b1813a35671e)
root@srv1:~#

Dans les logs, nous pouvons voir ce qu'il se passe :

- connexion SSH sur srv1 ;

- téléchargement de la clé de dépôt Ceph (nous l'avons déjà fait pour l'installation de ceph-deploy, inutile ici, mais nécessaire pour le déploiement de Ceph sur une autre machine) ;

- ajout de la clé avec apt-key (déjà fait) ;

- ajout du dépôt dans /etc/apt/sources.list.d (en doublon avec ce qui a déjà été fait pour installer ceph-deploy, nous voyons un avertissement à ce sujet) ;

- installation des paquets nécessaires.

La commande se termine par l'appel de ceph –version.

La commande est prévue pour installer tout ce qu'il faut sur n'importe quelle machine via SSH.

1-4-3-1-4 - Création d'un moniteur

Pour gérer notre cluster, nous avons besoin d’un moniteur. La création s’effectue avec la commande :

ceph-deploy mon create-initial

Qui retourne :

[ceph_deploy.conf][DEBUG ] found configuration file at: /root/.cephdeploy.conf
[ceph_deploy.cli][INFO  ] Invoked (1.5.39): /usr/bin/ceph-deploy mon create-initial
[ceph_deploy.cli][INFO  ] ceph-deploy options:
[ceph_deploy.cli][INFO  ]  username                      : None
[ceph_deploy.cli][INFO  ]  verbose                       : False
[ceph_deploy.cli][INFO  ]  overwrite_conf                : False
[ceph_deploy.cli][INFO  ]  subcommand                    : create-initial
[ceph_deploy.cli][INFO  ]  quiet                         : False
[ceph_deploy.cli][INFO  ]  cd_conf                       : <ceph_deploy.conf.cephdeploy.Conf instance at 0x7faf0fb69fc8>
[ceph_deploy.cli][INFO  ]  cluster                       : ceph
[ceph_deploy.cli][INFO  ]  func                          : <function mon at 0x7faf0ffd4500>
[ceph_deploy.cli][INFO  ]  ceph_conf                     : None
[ceph_deploy.cli][INFO  ]  keyrings                      : None
[ceph_deploy.cli][INFO  ]  default_release               : False
[ceph_deploy.mon][DEBUG ] Deploying mon, cluster ceph hosts srv1
[ceph_deploy.mon][DEBUG ] detecting platform for host srv1 ...
[srv1][DEBUG ] connected to host: srv1
[srv1][DEBUG ] detect platform information from remote host
[srv1][DEBUG ] detect machine type
[srv1][DEBUG ] find the location of an executable
[ceph_deploy.mon][INFO  ] distro info: debian 8.10 jessie
[srv1][DEBUG ] determining if provided host has same hostname in remote
[srv1][DEBUG ] get remote short hostname
[srv1][DEBUG ] deploying mon to srv1
[srv1][DEBUG ] get remote short hostname
[srv1][DEBUG ] remote hostname: srv1
[srv1][DEBUG ] write cluster configuration to /etc/ceph/{cluster}.conf
[srv1][DEBUG ] create the mon path if it does not exist
[srv1][DEBUG ] checking for done path: /var/lib/ceph/mon/ceph-srv1/done
[srv1][DEBUG ] done path does not exist: /var/lib/ceph/mon/ceph-srv1/done
[srv1][INFO  ] creating keyring file: /var/lib/ceph/tmp/ceph-srv1.mon.keyring
[srv1][DEBUG ] create the monitor keyring file
[srv1][INFO  ] Running command: ceph-mon --cluster ceph --mkfs -i srv1 --keyring /var/lib/ceph/tmp/ceph-srv1.mon.keyring --setuser 64045 --setgroup 64045
[srv1][DEBUG ] ceph-mon: renaming mon.noname-a 192.168.1.200:6789/0 to mon.srv1
[srv1][DEBUG ] ceph-mon: set fsid to 85967fe2-3f08-4e0b-9f3c-ca6647776383
[srv1][DEBUG ] ceph-mon: created monfs at /var/lib/ceph/mon/ceph-srv1 for mon.srv1
[srv1][INFO  ] unlinking keyring file /var/lib/ceph/tmp/ceph-srv1.mon.keyring
[srv1][DEBUG ] create a done file to avoid re-doing the mon deployment
[srv1][DEBUG ] create the init path if it does not exist
[srv1][INFO  ] Running command: systemctl enable ceph.target
[srv1][INFO  ] Running command: systemctl enable ceph-mon@srv1
[srv1][WARNIN] Created symlink from /etc/systemd/system/ceph-mon.target.wants/ceph-mon@srv1.service to /lib/systemd/system/ceph-mon@.service.
[srv1][INFO  ] Running command: systemctl start ceph-mon@srv1
[srv1][INFO  ] Running command: ceph --cluster=ceph --admin-daemon /var/run/ceph/ceph-mon.srv1.asok mon_status
[srv1][DEBUG ] ********************************************************************************
[srv1][DEBUG ] status for monitor: mon.srv1
[srv1][DEBUG ] {
[srv1][DEBUG ]   "election_epoch": 3,
[srv1][DEBUG ]   "extra_probe_peers": [],
[srv1][DEBUG ]   "monmap": {
[srv1][DEBUG ]     "created": "2018-11-16 19:53:16.240703",
[srv1][DEBUG ]     "epoch": 1,
[srv1][DEBUG ]     "fsid": "85967fe2-3f08-4e0b-9f3c-ca6647776383",
[srv1][DEBUG ]     "modified": "2018-11-16 19:53:16.240703",
[srv1][DEBUG ]     "mons": [
[srv1][DEBUG ]       {
[srv1][DEBUG ]         "addr": "192.168.1.200:6789/0",
[srv1][DEBUG ]         "name": "srv1",
[srv1][DEBUG ]         "rank": 0
[srv1][DEBUG ]       }
[srv1][DEBUG ]     ]
[srv1][DEBUG ]   },
[srv1][DEBUG ]   "name": "srv1",
[srv1][DEBUG ]   "outside_quorum": [],
[srv1][DEBUG ]   "quorum": [
[srv1][DEBUG ]     0
[srv1][DEBUG ]   ],
[srv1][DEBUG ]   "rank": 0,
[srv1][DEBUG ]   "state": "leader",
[srv1][DEBUG ]   "sync_provider": []
[srv1][DEBUG ] }
[srv1][DEBUG ] ********************************************************************************
[srv1][INFO  ] monitor: mon.srv1 is running
[srv1][INFO  ] Running command: ceph --cluster=ceph --admin-daemon /var/run/ceph/ceph-mon.srv1.asok mon_status
[ceph_deploy.mon][INFO  ] processing monitor mon.srv1
[srv1][DEBUG ] connected to host: srv1
[srv1][DEBUG ] detect platform information from remote host
[srv1][DEBUG ] detect machine type
[srv1][DEBUG ] find the location of an executable
[srv1][INFO  ] Running command: ceph --cluster=ceph --admin-daemon /var/run/ceph/ceph-mon.srv1.asok mon_status
[ceph_deploy.mon][INFO  ] mon.srv1 monitor has reached quorum!
[ceph_deploy.mon][INFO  ] all initial monitors are running and have formed quorum
[ceph_deploy.mon][INFO  ] Running gatherkeys...
[ceph_deploy.gatherkeys][INFO  ] Storing keys in temp directory /tmp/tmpyWJn4J
[srv1][DEBUG ] connected to host: srv1
[srv1][DEBUG ] detect platform information from remote host
[srv1][DEBUG ] detect machine type
[srv1][DEBUG ] get remote short hostname
[srv1][DEBUG ] fetch remote file
[srv1][INFO  ] Running command: /usr/bin/ceph --connect-timeout=25 --cluster=ceph --admin-daemon=/var/run/ceph/ceph-mon.srv1.asok mon_status
[srv1][INFO  ] Running command: /usr/bin/ceph --connect-timeout=25 --cluster=ceph --name mon. --keyring=/var/lib/ceph/mon/ceph-srv1/keyring auth get client.admin
[srv1][INFO  ] Running command: /usr/bin/ceph --connect-timeout=25 --cluster=ceph --name mon. --keyring=/var/lib/ceph/mon/ceph-srv1/keyring auth get client.bootstrap-mds
[srv1][INFO  ] Running command: /usr/bin/ceph --connect-timeout=25 --cluster=ceph --name mon. --keyring=/var/lib/ceph/mon/ceph-srv1/keyring auth get-or-create client.bootstrap-mds mon allow profile bootstrap-mds
[srv1][INFO  ] Running command: /usr/bin/ceph --connect-timeout=25 --cluster=ceph --name mon. --keyring=/var/lib/ceph/mon/ceph-srv1/keyring auth get client.bootstrap-mgr
[srv1][INFO  ] Running command: /usr/bin/ceph --connect-timeout=25 --cluster=ceph --name mon. --keyring=/var/lib/ceph/mon/ceph-srv1/keyring auth get-or-create client.bootstrap-mgr mon allow profile bootstrap-mgr
[srv1][INFO  ] Running command: /usr/bin/ceph --connect-timeout=25 --cluster=ceph --name mon. --keyring=/var/lib/ceph/mon/ceph-srv1/keyring auth get client.bootstrap-osd
[srv1][INFO  ] Running command: /usr/bin/ceph --connect-timeout=25 --cluster=ceph --name mon. --keyring=/var/lib/ceph/mon/ceph-srv1/keyring auth get client.bootstrap-rgw
[ceph_deploy.gatherkeys][INFO  ] Storing ceph.client.admin.keyring
[ceph_deploy.gatherkeys][INFO  ] Storing ceph.bootstrap-mds.keyring
[ceph_deploy.gatherkeys][INFO  ] Storing ceph.bootstrap-mgr.keyring
[ceph_deploy.gatherkeys][INFO  ] keyring 'ceph.mon.keyring' already exists
[ceph_deploy.gatherkeys][INFO  ] Storing ceph.bootstrap-osd.keyring
[ceph_deploy.gatherkeys][INFO  ] Storing ceph.bootstrap-rgw.keyring
[ceph_deploy.gatherkeys][INFO  ] Destroy temp directory /tmp/tmpyWJn4J
root@srv1:~/cephdeploy#

1-4-3-1-5 - Ajout d'OSD

Nous pouvons commencer par lister les disques d'un hôte Ceph avec la commande suivante :

ceph-deploy disk list srv1

Qui affichera dans mon exemple :

…
[srv1][INFO  ] Running command: /usr/sbin/ceph-disk list
[srv1][DEBUG ] /dev/sda :
[srv1][DEBUG ]  /dev/sda2 swap, swap
[srv1][DEBUG ]  /dev/sda1 other, ext4, mounted on /
[srv1][DEBUG ] /dev/sdb other, unknown
[srv1][DEBUG ] /dev/sr0 other, unknown
root@srv1:~/cephdeploy#

Nous allons procéder à la préparation de l'OSD sur le disque /dev/sdb.

Ceci effacera l'éventuel contenu sur le disque.

Voici la commande :

ceph-deploy osd prepare srv1:/dev/sdb

Qui retournera :

[ceph_deploy.conf][DEBUG ] found configuration file at: /root/.cephdeploy.conf
[ceph_deploy.cli][INFO  ] Invoked (1.5.39): /usr/bin/ceph-deploy osd prepare srv1:/dev/sdb
[ceph_deploy.cli][INFO  ] ceph-deploy options:
[ceph_deploy.cli][INFO  ]  username                      : None
[ceph_deploy.cli][INFO  ]  block_db                      : None
[ceph_deploy.cli][INFO  ]  disk                          : [('srv1', '/dev/sdb', None)]
[ceph_deploy.cli][INFO  ]  dmcrypt                       : False
[ceph_deploy.cli][INFO  ]  verbose                       : False
[ceph_deploy.cli][INFO  ]  bluestore                     : None
[ceph_deploy.cli][INFO  ]  block_wal                     : None
[ceph_deploy.cli][INFO  ]  overwrite_conf                : False
[ceph_deploy.cli][INFO  ]  subcommand                    : prepare
[ceph_deploy.cli][INFO  ]  dmcrypt_key_dir               : /,etc/ceph/dmcrypt-keys
[ceph_deploy.cli][INFO  ]  quiet                         : False
[ceph_deploy.cli][INFO  ]  cd_conf                       : <ceph_deploy.conf.cephdeploy.Conf instance at 0x7fc9a8963ef0>
[ceph_deploy.cli][INFO  ]  cluster                       : ceph
[ceph_deploy.cli][INFO  ]  fs_type                       : xfs
[ceph_deploy.cli][INFO  ]  filestore                     : None
[ceph_deploy.cli][INFO  ]  func                          : <function osd at 0x7fc9a8dc6488>
[ceph_deploy.cli][INFO  ]  ceph_conf                     : None
[ceph_deploy.cli][INFO  ]  default_release               : False
[ceph_deploy.cli][INFO  ]  zap_disk                      : False
[ceph_deploy.osd][DEBUG ] Preparing cluster ceph disks srv1:/dev/sdb:
[srv1][DEBUG ] connected to host: srv1
[srv1][DEBUG ] detect platform information from remote host
[srv1][DEBUG ] detect machine type
[srv1][DEBUG ] find the location of an executable
[ceph_deploy.osd][INFO  ] Distro info: debian 8.10 jessie
[ceph_deploy.osd][DEBUG ] Deploying osd to srv1
[srv1][DEBUG ] write cluster configuration to /etc/ceph/{cluster}.conf
[ceph_deploy.osd][DEBUG ] Preparing host srv1 disk /dev/sdb journal None activate False
[srv1][DEBUG ] find the location of an executable
[srv1][INFO  ] Running command: /usr/sbin/ceph-disk -v prepare --cluster ceph --fs-type xfs -- /dev/sdb
[srv1][WARNIN] command: Running command: /usr/bin/ceph-osd --cluster=ceph --show-config-value=fsid
[srv1][WARNIN] command: Running command: /usr/bin/ceph-osd --check-allows-journal -i 0 --log-file $run_dir/$cluster-osd-check.log --cluster ceph --setuser ceph --setgroup ceph
[srv1][WARNIN] command: Running command: /usr/bin/ceph-osd --check-wants-journal -i 0 --log-file $run_dir/$cluster-osd-check.log --cluster ceph --setuser ceph --setgroup ceph
[srv1][WARNIN] command: Running command: /usr/bin/ceph-osd --check-needs-journal -i 0 --log-file $run_dir/$cluster-osd-check.log --cluster ceph --setuser ceph --setgroup ceph
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb uuid path is /sys/dev/block/8:16/dm/uuid
[srv1][WARNIN] set_type: Will colocate journal with data on /dev/sdb
[srv1][WARNIN] command: Running command: /usr/bin/ceph-osd --cluster=ceph --show-config-value=osd_journal_size
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb uuid path is /sys/dev/block/8:16/dm/uuid
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb uuid path is /sys/dev/block/8:16/dm/uuid
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb uuid path is /sys/dev/block/8:16/dm/uuid
[srv1][WARNIN] command: Running command: /usr/bin/ceph-conf --cluster=ceph --name=osd. --lookup osd_mkfs_options_xfs
[srv1][WARNIN] command: Running command: /usr/bin/ceph-conf --cluster=ceph --name=osd. --lookup osd_fs_mkfs_options_xfs
[srv1][WARNIN] command: Running command: /usr/bin/ceph-conf --cluster=ceph --name=osd. --lookup osd_mount_options_xfs
[srv1][WARNIN] command: Running command: /usr/bin/ceph-conf --cluster=ceph --name=osd. --lookup osd_fs_mount_options_xfs
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb uuid path is /sys/dev/block/8:16/dm/uuid
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb uuid path is /sys/dev/block/8:16/dm/uuid
[srv1][WARNIN] ptype_tobe_for_name: name = journal
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb uuid path is /sys/dev/block/8:16/dm/uuid
[srv1][WARNIN] create_partition: Creating journal partition num 2 size 5120 on /dev/sdb
[srv1][WARNIN] command_check_call: Running command: /sbin/sgdisk --new=2:0:+5120M --change-name=2:ceph journal --partition-guid=2:74a9b3f0-08b8-48db-a3ec-e6e36451d0d9 --typecode=2:45b0969e-9b03-4f30-b4c6-b4b80ceff106 --mbrtogpt -- /dev/sdb
[srv1][DEBUG ] Creating new GPT entries.
[srv1][DEBUG ] Setting name!
[srv1][DEBUG ] partNum is 1
[srv1][DEBUG ] REALLY setting name!
[srv1][DEBUG ] The operation has completed successfully.
[srv1][WARNIN] update_partition: Calling partprobe on created device /dev/sdb
[srv1][WARNIN] command_check_call: Running command: /sbin/udevadm settle --timeout=600
[srv1][WARNIN] command: Running command: /usr/bin/flock -s /dev/sdb /sbin/partprobe /dev/sdb
[srv1][WARNIN] command_check_call: Running command: /sbin/udevadm settle --timeout=600
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb uuid path is /sys/dev/block/8:16/dm/uuid
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb uuid path is /sys/dev/block/8:16/dm/uuid
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb2 uuid path is /sys/dev/block/8:18/dm/uuid
[srv1][WARNIN] prepare_device: Journal is GPT partition /dev/disk/by-partuuid/74a9b3f0-08b8-48db-a3ec-e6e36451d0d9
[srv1][WARNIN] prepare_device: Journal is GPT partition /dev/disk/by-partuuid/74a9b3f0-08b8-48db-a3ec-e6e36451d0d9
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb uuid path is /sys/dev/block/8:16/dm/uuid
[srv1][WARNIN] set_data_partition: Creating osd partition on /dev/sdb
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb uuid path is /sys/dev/block/8:16/dm/uuid
[srv1][WARNIN] ptype_tobe_for_name: name = data
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb uuid path is /sys/dev/block/8:16/dm/uuid
[srv1][WARNIN] create_partition: Creating data partition num 1 size 0 on /dev/sdb
[srv1][WARNIN] command_check_call: Running command: /sbin/sgdisk --largest-new=1 --change-name=1:ceph data --partition-guid=1:720e149a-ebb7-4d44-9b89-d1c017481c18 --typecode=1:89c57f98-2fe5-4dc0-89c1-f3ad0ceff2be --mbrtogpt -- /dev/sdb
[srv1][DEBUG ] Setting name!
[srv1][DEBUG ] partNum is 0
[srv1][DEBUG ] REALLY setting name!
[srv1][DEBUG ] The operation has completed successfully.
[srv1][WARNIN] update_partition: Calling partprobe on created device /dev/sdb
[srv1][WARNIN] command_check_call: Running command: /sbin/udevadm settle --timeout=600
[srv1][WARNIN] command: Running command: /usr/bin/flock -s /dev/sdb /sbin/partprobe /dev/sdb
[srv1][WARNIN] command_check_call: Running command: /sbin/udevadm settle --timeout=600
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb uuid path is /sys/dev/block/8:16/dm/uuid
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb uuid path is /sys/dev/block/8:16/dm/uuid
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb1 uuid path is /sys/dev/block/8:17/dm/uuid
[srv1][WARNIN] populate_data_path_device: Creating xfs fs on /dev/sdb1
[srv1][WARNIN] command_check_call: Running command: /sbin/mkfs -t xfs -f -i size=2048 -- /dev/sdb1
[srv1][DEBUG ] meta-data=/dev/sdb1              isize=2048   agcount=4, agsize=196543 blks
[srv1][DEBUG ]          =                       sectsz=512   attr=2, projid32bit=1
[srv1][DEBUG ]          =                       crc=0        finobt=0
[srv1][DEBUG ] data     =                       bsize=4096   blocks=786171, imaxpct=25
[srv1][DEBUG ]          =                       sunit=0      swidth=0 blks
[srv1][DEBUG ] naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
[srv1][DEBUG ] log      =internal log           bsize=4096   blocks=2560, version=2
[srv1][DEBUG ]          =                       sectsz=512   sunit=0 blks, lazy-count=1
[srv1][DEBUG ] realtime =none                   extsz=4096   blocks=0, rtextents=0
[srv1][WARNIN] mount: Mounting /dev/sdb1 on /var/lib/ceph/tmp/mnt.zWKFv6 with options noatime,inode64
[srv1][WARNIN] command_check_call: Running command: /bin/mount -t xfs -o noatime,inode64 -- /dev/sdb1 /var/lib/ceph/tmp/mnt.zWKFv6
[srv1][WARNIN] populate_data_path: Preparing osd data dir /var/lib/ceph/tmp/mnt.zWKFv6
[srv1][WARNIN] command: Running command: /bin/chown -R ceph:ceph /var/lib/ceph/tmp/mnt.zWKFv6/ceph_fsid.4952.tmp
[srv1][WARNIN] command: Running command: /bin/chown -R ceph:ceph /var/lib/ceph/tmp/mnt.zWKFv6/fsid.4952.tmp
[srv1][WARNIN] command: Running command: /bin/chown -R ceph:ceph /var/lib/ceph/tmp/mnt.zWKFv6/magic.4952.tmp
[srv1][WARNIN] command: Running command: /bin/chown -R ceph:ceph /var/lib/ceph/tmp/mnt.zWKFv6/journal_uuid.4952.tmp
[srv1][WARNIN] adjust_symlink: Creating symlink /var/lib/ceph/tmp/mnt.zWKFv6/journal -> /dev/disk/by-partuuid/74a9b3f0-08b8-48db-a3ec-e6e36451d0d9
[srv1][WARNIN] command: Running command: /bin/chown -R ceph:ceph /var/lib/ceph/tmp/mnt.zWKFv6
[srv1][WARNIN] unmount: Unmounting /var/lib/ceph/tmp/mnt.zWKFv6
[srv1][WARNIN] command_check_call: Running command: /bin/umount -- /var/lib/ceph/tmp/mnt.zWKFv6
[srv1][WARNIN] get_dm_uuid: get_dm_uuid /dev/sdb uuid path is /sys/dev/block/8:16/dm/uuid
[srv1][WARNIN] command_check_call: Running command: /sbin/sgdisk --typecode=1:4fbd7e29-9d25-41b8-afd0-062c0ceff05d -- /dev/sdb
[srv1][DEBUG ] The operation has completed successfully.
[srv1][WARNIN] update_partition: Calling partprobe on prepared device /dev/sdb
[srv1][WARNIN] command_check_call: Running command: /sbin/udevadm settle --timeout=600
[srv1][WARNIN] command: Running command: /usr/bin/flock -s /dev/sdb /sbin/partprobe /dev/sdb
[srv1][WARNIN] command_check_call: Running command: /sbin/udevadm settle --timeout=600
[srv1][WARNIN] command_check_call: Running command: /sbin/udevadm trigger --action=add --sysname-match sdb1
[srv1][INFO  ] checking OSD status...
[srv1][DEBUG ] find the location of an executable
[srv1][INFO  ] Running command: /usr/bin/ceph --cluster=ceph osd stat --format=json
[srv1][WARNIN] there is 1 OSD down
[srv1][WARNIN] there is 1 OSD out
[ceph_deploy.osd][DEBUG ] Host srv1 is now ready for osd use.
root@srv1:~/cephdeploy#

Nous pouvons voir la création d'une table de partitions GPT et la création de partitions XFS.

Rappelons la commande ceph-deploy disk list srv1 :

…
[srv1][INFO  ] Running command: /usr/sbin/ceph-disk list
[srv1][DEBUG ] /dev/sda :
[srv1][DEBUG ]  /dev/sda2 swap, swap
[srv1][DEBUG ]  /dev/sda1 other, ext4, mounted on /
[srv1][DEBUG ] /dev/sdb :
[srv1][DEBUG ]  /dev/sdb2 ceph journal, for /dev/sdb1
[srv1][DEBUG ]  /dev/sdb1 ceph data, active, cluster ceph, osd.0, journal /dev/sdb2
[srv1][DEBUG ] /dev/sr0 other, unknown
root@srv1:~/cephdeploy#

Nous pouvons voir qu'il y a en fait deux partitions : une partition pour les données de Ceph (ceph data) en /dev/sdb1 et une partition pour les journaux Ceph (ceph journal) en /dev/sdb2.

Pour des questions de performance, il est conseillé de mettre les journaux sur disques SSD).

Nous activons ensuite l'OSD :

ceph-deploy osd activate srv1:/dev/sdb1

Pour lister les OSD d'un cluster Ceph, vous pouvez utiliser la commande suivante :

ceph osd tree

Qui retournera dans mon exemple :

ID WEIGHT  TYPE NAME     UP/DOWN REWEIGHT PRIMARY-AFFINITY
-1 0.00580 root default
-2 0.00290     host srv1
0 0.00290         osd.0      up  1.00000          1.00000

root@srv1:~#

Nous pouvons voir que notre cluster ne contient qu'un seul OSD : osd.0 sur l'hôte srv1.

1-4-3-1-6 - Préparation des pools

Nous préparation ensuite le pool pour le système de fichiers CephFS :

ceph osd pool create cephfs_metadata 128
ceph osd pool create cephfs_data 128

La valeur de paramètre 128 correspond à la valeur de « placement group » appelé aussi PG.

Voici ce qui est préconisé par Ceph :

- moins de 5 OSD : 128 ;

- entre 5 et 10 OSD : 512 ;

- entre 10 et 50 OSD : 1024.

Au-delà de 50 OSD, il est recommandé d’utiliser la formule conseillée par les développeurs. Vous pouvez la retrouver avec l’outil en ligne pgcal.

Les « placement group » permettent d'agréger les objets en pools, permettant le suivi de ceux-ci de façon plus efficace, surtout dans des infrastructures importantes.

Listage des pool

Pour lister les pool d'un cluster Ceph, on utilisera la commande :

ceph osd lspools

Qui nous retournera :

0 rbd,1 cephfs_metadata,2 cephfs_data,
root@srv1:~#

Le pool rbd est un pool de base, qui ne nous servira pas, nous pouvons le supprimer avec la commande :

ceph osd pool delete rbd

Vous aurez un message vous expliquant qu'il faut saisir deux fois le nom du rbd suivi de –yes-i-really-really-mean-it.

1-4-3-1-7 - Création d'un démon MDS

La création d’un démon MDS s’effectue avec la commande suivante :

ceph-deploy mds create srv1

Celui-ci sera nécessaire pour gérer les métadonnées du système de fichier CephFS.

1-4-3-1-8 - Création du système de fichiers CephFS

La création de notre système de fichiers se fait via la commande :

root@srv1:~/cephdeploy# ceph fs new mon_fs cephfs_metadata cephfs_data
new fs with metadata pool 1 and data pool 2
root@srv1:~/cephdeploy#

mon_fs étant le nom donné au système de fichiers.

État du cluster

Nous pouvons voir l'état du cluster Ceph avec la commande :

ceph -s

Résultat :

cluster fba9a869-5b18-4feb-bd9c-5374808af689
health HEALTH_WARN
192 pgs degraded
64 pgs stuck unclean
192 pgs undersized
recovery 20/40 objects degraded (50.000%)
monmap e1: 1 mons at {srv1=192.168.1.200:6789/0}
election epoch 3, quorum 0 srv1
fsmap e5: 1/1/1 up {0=srv1=up:active}
osdmap e10: 1 osds: 1 up, 1 in
flags sortbitwise,require_jewel_osds
pgmap v22: 192 pgs, 3 pools, 2068 bytes data, 20 objects
108 MB used, 2952 MB / 3060 MB avail
20/40 objects degraded (50.000%)
192 active+undersized+degraded
root@srv1:~#

1-4-3-1-9 - Montage du volume CephFS

Nous commençons par déployer les fichiers de configuration avec la commande :

ceph-deploy admin srv1

Ceci va copier les fichiers suivants dans /,etc/ceph :

- ceph.client.admin.keyring ;

- ceph.conf ;

- rbdmap.

Il nous faut créer un fichier ceph.client.admin.keyring contenant la clé codée en Base64.

Le fichier a le format suivant :

[client.test]
key = AQDR1O9bDuaFMBAAwlLxUpWYzVTtNaAAawYygA==

Nous dupliquons le fichier client.ceph.admin.keyring dans le dossier /,etc/ceph. Nous nommons la copie client.admin.

Le fichier ne devra contenir que la clé Base64 :

AQDR1O9bDuaFMBAAwlLxUpWYzVTtNaAAawYygA==

Exemple de commande de génération d'une clé pour un utilisateur précis :

root@srv1:~/cephdeploy# ceph auth get-or-create client.test mds 'allow' osd 'allow *' mon 'allow *' > fichier_de_keyring

Nous aurons besoin du paquet ceph-fs-common que ceph-deploy n'a pas installé :

apt-get install ceph-fs-common

Nous pourrons ensuite monter le volume avec la commande mount à laquelle nous lui aurons donné en option le nom d'utilisateur ainsi que le fichier de clé :

mount.ceph srv1:/ /mnt -o name=admin,secretfile=/etc/ceph/client.admin

Voici la ligne à ajouter dans /,etc/fstab pour un montage automatique lors du démarrage de la machine :

srv1:/    /mnt    ceph    name=admin,secretfile=/etc/ceph/admin.client

Il faudra garder les fichiers du dossier de configuration ceph-deploy et s'assurer d'en avoir une sauvegarde.

1-4-3-2 - Ajout d'une seconde machine

Il faudra qu’OpenSSH, un serveur de temps et Python soit installé sur l’hôte.

Il faudra procéder à la configuration de SSH de façon à ce que srv1 puisse le contacter sans authentification. Tout cela comme pour la préparation du premier serveur.

Nous installons ensuite Ceph sur le nouveau serveur srv2 depuis srv1 :

ceph-deploy install srv2

Nous créons ensuite un OSD sur la machine srv2 de la même façon que pour srv1 :

ceph-deploy osd prepare srv2:/dev/sdb
ceph-deploy osd activate srv2:/dev/sdb1

Nous pourrons voir les deux OSD sur les deux hôtes avec la commande ceph osd tree :

root@srv1:~# ceph osd tree
ID WEIGHT  TYPE NAME     UP/DOWN REWEIGHT PRIMARY-AFFINITY
-1 0.00580 root default
-2 0.00290     host srv1
0 0.00290         osd.0      up  1.00000          1.00000
-3 0.00290     host srv2
1 0.00290         osd.1      up  1.00000          1.00000

Nous pouvons voir l'état du cluster avec la commande ceph -s. Vous pourrez voir son état de reconstruction. Une fois la mise à jour des blocs sur le nouvel OSD, nous pourrons voir le cluster en mode HEALTH_OK :

root@srv1:~# ceph -s
cluster fba9a869-5b18-4feb-bd9c-5374808af689
health HEALTH_OK
monmap e1: 1 mons at {srv1=192.168.1.200:6789/0}
election epoch 4, quorum 0 srv1
fsmap e11: 1/1/1 up {0=srv1=up:active}
osdmap e21: 2 osds: 2 up, 2 in
flags sortbitwise,require_jewel_osds
pgmap v140: 192 pgs, 3 pools, 6186 kB data, 34 objects
231 MB used, 5890 MB / 6121 MB avail
192 active+clean
root@srv1:~#

Nous pouvons ensuite ajouter srv2 en tant que moniteur :

ceph-deploy mon add srv2

Résultat :

…
[srv2][INFO  ] monitor: mon.srv2 is currently at the state of probing

Pour rappel, le nombre de moniteurs doit être impair, et il est recommandé de mettre un moniteur sur une machine autonome hors OSD.

Sur le même principe, nous pouvons ajouter un serveur de métadonnées sur srv2 :

ceph-deploy mds create srv2

Nous modifions le fichier ceph.conf en y ajoutant l'adresse IP du second moniteur dans la ligne mon_host, puis nous mettons ensuite à jour les configurations :

ceph-deploy --overwrite-conf admin srv1 srv2

L'option -–overwite-conf étant nécessaire pour écraser une ancienne configuration (celle de srv1 dans notre cas, la commande ayant déjà été lancée dessus).

1-4-3-3 - Test de panne : arrêt de srv1

La perte de srv1 (ou de srv2) ne provoque pas l’indisponibilité du cluster en cas de présence d'un troisième serveur hébergeant un moniteur. Dans le cas contraire, le point de montage est indisponible après quelques secondes et la commande ceph -s bloque la console.

Le redémarrage de la machine arrêtée permettra de récupérer le cluster après réparation automatique.

1-4-3-4 - Procédure de réparation d'un nœud

Nous commençons par voir l'état de Ceph :

~# ceph -s

Qui nous affichera :

cluster 6e3c0267-1480-4671-9382-9686be7e2663
health HEALTH_WARN
200 pgs degraded
200 pgs stuck degraded
200 pgs stuck unclean
200 pgs stuck undersized
200 pgs undersized
recovery 21/63 objects degraded (33.333%)
1 mons down, quorum 0,2 srv1,srv3
monmap e3: 3 mons at {srv1=192.168.1.200:6789/0,srv2=192.168.1.201:6789/0,srv3=192.168.1.202:6789/0}
election epoch 16, quorum 0,2 srv1,srv3
fsmap e9: 1/1/1 up {0=srv1=up:active}
osdmap e45: 3 osds: 2 up, 2 in; 200 remapped pgs
flags sortbitwise,require_jewel_osds
pgmap v189: 200 pgs, 2 pools, 23070 bytes data, 21 objects
218 MB used, 5903 MB / 6121 MB avail
21/63 objects degraded (33.333%)
200 active+undersized+degraded

Pour voir ce qu’il en est des OSD :

~# ceph osd tree

Qui nous retournera :

ID WEIGHT  TYPE NAME     UP/DOWN REWEIGHT PRIMARY-AFFINITY
-1 0.00870 root default
-2 0.00290     host srv1
0 0.00290         osd.0      up  1.00000          1.00000
-3 0.00290     host srv2
1 0.00290         osd.1    down        0          1.00000
-4 0.00290     host srv3
2 0.00290         osd.2      up  1.00000          1.00000

Nous voyons que l’OSD.1 sur l'hôte srv2 est « down ». Nous le supprimons :

~# ceph osd rm osd.1
removed osd.1

Nous rappelons la commande ceph osd tree :

~# ceph osd tree
ID WEIGHT TYPE NAME UP/DOWN REWEIGHT PRIMARY-AFFINITY
-1 0.00870 root default
-2 0.00290 host srv1
0 0.00290 osd.0 up 1.00000 1.00000
-3 0.00290 host srv2
1 0.00290 osd.1 DNE 0
-4 0.00290 host srv3
2 0.00290 osd.2 up 1.00000 1.00000

Nous voyons l’OSD 1 toujours présent en mode DNE (pour Do Not Exist).

Nous supprimons celui-ci définitivement avec la commande suivante :

~# ceph osd crush rm osd.1
removed item id 1 name 'osd.1' from crush map

Nous supprimons ensuite les autorisations :

~# ceph auth del osd.1
updated

Si nous rappelons la commande ceph osd tree, l'OSD n'est plus présent, mais nous voyons toujours le nœud (sans OSD) :

ID WEIGHT  TYPE NAME     UP/DOWN REWEIGHT PRIMARY-AFFINITY
-1 0.00580 root default
-2 0.00290     host srv1
0 0.00290         osd.0      up  1.00000          1.00000
-3       0     host srv2
-4 0.00290     host srv3
2 0.00290         osd.2      up  1.00000          1.00000

Pour supprimer celui-ci, nous allons l'enlever de la crush map.

Nous commençons par exporter celle-ci avec la commande getcrushmap.

~# ceph osd getcrushmap -o crush_map
got crush map from osdmap epoch 79

Il va falloir convertir ce fichier en mode texte :

~# crushtool -d crush_map -o crush_map.txt

Voici un exemple du contenu de ce fichier texte :

# begin crush map
tunable choose_local_tries 0
tunable choose_local_fallback_tries 0
tunable choose_total_tries 50
tunable chooseleaf_descend_once 1
tunable chooseleaf_vary_r 1
tunable straw_calc_version 1

# devices
device 0 osd.0
device 1 device1
device 2 osd.2

# types
type 0 osd
type 1 host
type 2 chassis
type 3 rack
type 4 row
type 5 pdu
type 6 pod
type 7 room
type 8 datacenter
type 9 region
type 10 root

# buckets
host srv1 {
id -2           # do not change unnecessarily
# weight 0.003
alg straw
hash 0  # rjenkins1
item osd.0 weight 0.003
}
host srv3 {
id -4           # do not change unnecessarily
# weight 0.003
alg straw
hash 0  # rjenkins1
item osd.2 weight 0.003
}
host srv2 {
id -3           # do not change unnecessarily
# weight 0.000
alg straw
hash 0  # rjenkins1
}
root default {
id -1           # do not change unnecessarily
# weight 0.006
alg straw
hash 0  # rjenkins1
item srv1 weight 0.003
item srv3 weight 0.003
item srv2 weight 0.000
}

# rules
rule replicated_ruleset {
ruleset 0
type replicated
min_size 1
max_size 10
step take default
step chooseleaf firstn 0 type host
step emit
}

# end crush map

Modifier la crush map va permettre d'optimiser la gestion du cluster Ceph notamment dans le cas de nœuds importants (gestion de régions, rack, pds, etc.)

Je retire les références à srv2 (le bloc srv2 entre crochets, et la ligne item srv2...)

Pour appliquer les modifications, je recompile le fichier texte :

~# crushtool -c crush_map.txt -o crush_map

Puis applique celui-ci :

~# ceph osd setcrushmap -i crush_map
set crush map

Toute trace de srv2 dans les OSD est alors supprimée.

Nous préparons ensuite un serveur de base avec les prérequis (adresse IP de srv2, nom de machine srv2, fichier hosts renseigné avec les autres serveurs, paquets ntp, openssh-server, et python installé).

Nous recopions ensuite la clé SSH de srv1 vers srv2 :

~# ssh-copy-id root@srv2

Nous allons avoir un message d'erreur :

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed

/usr/bin/ssh-copy-id: ERROR: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ERROR: @    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
ERROR: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ERROR: IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
ERROR: Someone could be eavesdropping on you right now (man-in-the-middle attack)!
ERROR: It is also possible that a host key has just been changed.
ERROR: The fingerprint for the ECDSA key sent by the remote host is
ERROR: SHA256:GXC4wVDCLG3a+KXA3Tb95ULTZGm2REM0pmOBBCZ371A.
ERROR: Please contact your system administrator.
ERROR: Add correct host key in /root/.ssh/known_hosts to get rid of this message.
ERROR: Offending ECDSA key in /root/.ssh/known_hosts:5
ERROR:   remove with:
ERROR:   ssh-keygen -f "/root/.ssh/known_hosts" -R srv2
ERROR: ECDSA host key for srv2 has changed and you have requested strict checking.
ERROR: Host key verification failed.

Nous utilisons la commande ssh-keygen :

~# ssh-keygen -f "/root/.ssh/known_hosts" -R srv2
# Host srv2 found: line 5
/root/.ssh/known_hosts updated.
Original contents retained as /root/.ssh/known_hosts.old

Nous refaisons une tentative de connexion :

ssh root@srv2
The authenticity of host 'srv2 (192.168.1.201)' can't be established.
ECDSA key fingerprint is SHA256:GXC4wVDCLG3a+KXA3Tb95ULTZGm2REM0pmOBBCZ371A.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'srv2' (ECDSA) to the list of known hosts.
Warning: the ECDSA host key for 'srv2' differs from the key for the IP address '192.168.1.201'
Offending key for IP in /root/.ssh/known_hosts:5
Are you sure you want to continue connecting (yes/no)? yes
root@srv2's password:

Nous entrons le mot de passe. La prochaine connexion donnera :

Offending key for IP in /root/.ssh/known_hosts:5
Matching host key in /root/.ssh/known_hosts:6
Are you sure you want to continue connecting (yes/no)? yes

Nous supprimons la ligne concernée :

~# sed -i '5d' ~/.ssh/known_hosts

La commande ssd-copy-id pourra ensuite s’exécuter sans erreur, et une connexion via ssh root@srv2 sans demande de mot de passe sera possible.

Nous réinstallons ensuite Ceph :

~# ceph-deploy install srv2

Nous recréons ensuite les OSD comme vu précédemment.

Nous réinstallons le moniteur sur srv2 :

ceph mon add srv2

Nous lançons la commande ceph health. Une fois la réparation terminée, la commande ceph -s nous donnera un statut de HEALTH_OK.

1-5 - min.io

min.io est un système de stockage cloud open source, crée par un ancien de l’équipe Gluster. Il peut être utilisé avec une configuration de 2 à 32 serveurs et stocker des objets jusqu’à 5 To. Il ne possède pas de limite sur le nombre de buckets (notion que nous verrons plus tard) ou d’objets par bucket.

Il peut se comporter comme le service S3 d’Amazon ou faire passerelle avec le service S3 Amazon. Il peut également faire passerelle NFS .

Il est prévu d’origine pour fonctionner dans Docker.

1-5-1 - Les différents modes de fonctionnement

Default mode : c'est le mode par défaut de fonctionnement de min.io quand utilisé avec une seule machine et un seul disque.

Erasure coded mode : mode permettant la reconstruction des données en cas de perte de ressource. Cet algorithme est basé sur l'algorithme Reed-Solomon. Ce mode nécessite un minimum de quatre disques.

Distributed mode : le serveur min.io en mode distribué vous permet de mettre en pool plusieurs lecteurs (même sur différentes machines) sur un serveur de stockage d'objet unique. Les disques étant répartis sur plusieurs nœuds, min.io distribué peut supporter plusieurs défaillances tout en assurant une protection complète des données.

1-5-2 - Installation de min.io

min.io est un simple exécutable. Il est récupérable sur le site officiel à l'adresse https://min.io/download ou comme ceci :

wget https://dl.min.io/server/minio/release/linux-amd64/minio

il faudra ensuite mettre les droits d’exécution :

chmod +x minio

Nous déplacerons ensuite le fichier dans /usr/local/bin.

Il est également possible d’installer min.io au travers de brew pour Mac OS X.

Il suffira ensuite de taper la commande minio pour obtenir de l’aide.

1-5-3 - Test en mode simple instance

Nous allons lancer min.io en fournissant le dossier /data1/minio1 en paramètre :

minio server /data1/minio1

Ce qui donne :

Endpoint:  http://192.168.1.200:9000  http://127.0.0.1:9000
AccessKey: minioadmin
SecretKey: minioadmin

Browser Access:
http://192.168.1.200:9000  http://127.0.0.1:9000

Command-line Access: https://docs.min.io/docs/minio-client-quickstart-guide
$ mc config host add myminio http://192.168.1.200:9000 minioadmin minioadmin

Object API (Amazon S3 compatible):
Go:         https://docs.min.io/docs/golang-client-quickstart-guide
Java:       https://docs.min.io/docs/java-client-quickstart-guide
Python:     https://docs.min.io/docs/python-client-quickstart-guide
JavaScript: https://docs.min.io/docs/javascript-client-quickstart-guide
.NET:       https://docs.min.io/docs/dotnet-client-quickstart-guide
Detected default credentials 'minioadmin:minioadmin', please change the credentals immediately using 'MINIO_ACCESS_KEY' and 'MINIO_SECRET_KEY'

Le retour de la commande nous donne toutes les méthodes d'accès possibles.

Nous pouvons notamment voir que l’accès peut se faire depuis le web via le port 9000. Il est possible de changer le port par défaut en le précisant dans la ligne d'appel sous la forme http://192.168.1.200:9000.

Il est également précisé que l’identifiant et mot de passe par défaut est « minioadmin ». Il faudra bien sûr le changer.

Pour cela il suffit d'exporter les variables MINIO_ACCESS_KEY et MINIO_SECRET_KEY.

MINIO_SECRET_KEY doit faire minium huit caractères.

~# export MINIO_ACCESS_KEY=admin
~# export MINIO_SECRET_KEY=rootroot
~# ./minio server /data1
Attempting encryption of all config, IAM users and policies on MinIO backend
Endpoint:  http://192.168.1.200:9000  http://127.0.0.1:9000
AccessKey: admin
SecretKey: rootroot

Browser Access:
http://192.168.1.200:9000  http://127.0.0.1:9000

Command-line Access: https://docs.min.io/docs/minio-client-quickstart-guide
$ mc config host add myminio http://192.168.1.200:9000 admin rootroot

Object API (Amazon S3 compatible):
Go:         https://docs.min.io/docs/golang-client-quickstart-guide
Java:       https://docs.min.io/docs/java-client-quickstart-guide
Python:     https://docs.min.io/docs/python-client-quickstart-guide
JavaScript: https://docs.min.io/docs/javascript-client-quickstart-guide
.NET:       https://docs.min.io/docs/dotnet-client-quickstart-guide

1-5-3-1 - Accès via le web

Le login et le mot de passe correspondent à l’accessKey et la SecretKey retourné par l’appel de min.io .

1-5-3-2 - Gestion de fichiers depuis l'interface web

Une fois logué, vous obtiendrez l’écran suivant :

Il va nous falloir créer au moins un Bucket, entité de stockage de min.io, qui peut être considéré comme un dossier, ceci en cliquant sur le , puis « create Bucket » :

Après création, les Buckets apparaîtront sur la gauche (dans notre cas bucket1, puis bucket2) :

Lors de la création des Buckets, ceux-ci ne sont affichés dans l’ordre alphabétique qu’après rafraîchissement par clic sur l’adresse en bas à gauche.

La création d'un Bucket va créer un dossier du même nom dans le système de fichiers (dans le dossier /data1 dans notre cas). La création d'un dossier hors de l'interface va être vue comme un Bucket dans l'interface web.

Un sous-dossier créé en ligne de commande sera exploitable depuis l'interface web :

Il sera possible d'entrer dans le dossier, d'y uploader des fichiers. Par contre, il n’y a pas d'option dans l'interface web pour créer un sous-dossier.

La suppression d'un Bucket (un dossier) se fera en se mettant sur celui-ci et en cliquant sur les traits :

La suppression d'un Bucket va supprimer son contenu.

1-5-3-2-1 - Upload de fichier

Pour uploader un fichier, il faut cliquer sur le , puis sur l’icône upload file

Les fichiers apparaîtront sur le disque tels quels. Si vous ajoutez un fichier manuellement dans le dossier/Bucket, celui-ci sera disponible dans l'interface.

1-5-3-2-2 - Accès aux fichiers

L’icône en 1 permet de créer un lien de partage dont la validité peut s’étendre jusqu’à sept jours. Il n’y a pas de possibilité de créer un lien permanent. L’icône 2 permet la suppression du document. Il n’y a pas de système de versionnage. Même si on peut utiliser un accès web, il s’agit d’un espace de stockage, pas d’un service de synchronisation de fichiers comme ceux déjà vus.

Il ne semble pas possible de renommer un fichier.

Il est possible de télécharger le fichier en cliquant sur le rond à gauche du nom. Une barre apparaîtra en haut de l’écran permettant le téléchargement (ainsi que la suppression comme avec l’icône vue sur l’écran précédent) :

1-5-3-2-3 - Utilisation de https

La clé privée (qui doit se nommer private.key) et la clé publique (qui doit se nommer public.crt) doivent être placées dans le dossier de configuration par défaut : .minio/certs (créé dans le dossier à partir duquel vous avez lancé min.io). Il est possible de préciser le chemin d'emplacement des clés avec l'option --cert.

La sécurisation de la connexion au serveur web de min.io est détaillée dans cette page de documentation : https://docs.min.io/docs/how-to-secure-access-to-minio-server-with-tls.html.

1-5-4 - Test en mode distribué

Le mode distribué nécessite la déclaration d’au minimum quatre sources dont au moins deux accessibles. Il est possible de déclarer plusieurs sources sur le même nœud. Cela n'aura un sens qu'en cas de sources sur différents disques (un peu comme du RAID).

L’erasure code est un mécanisme permettant la redondance des données. Celui-ci utilise l’algorithme de Reed Salomon et permet de gérer l’espace utilisé pour la redondance. Par exemple : avec douze disques, vous pourrez utiliser six disques de données et six de parité ; ou bien dix disques de données et deux de parité. Plus vous avez de disques de parité, plus vous pourrez supporter de pertes de disques simultanés.

Pour créer un cluster distribué, nous préparons deux volumes data1 et data2 (sur deux disques différents) sur un même nœud.

Minio refusera de démarrer si les volumes déclarés sont sur le disque de démarrage.

Nous stockons l’AccessKey et la SecretKey dans les variables d’environnement (reprise des clés précédemment utilisées) :

export MINIO_ACCESS_KEY=XLI1NFFBHMAR5LFTTXD8
export MINIO_SECRET_KEY=+4tHexZ4EUU0Ltbo1gQVfTJ6bFcGTZGtRqYNHpmz

Puis appelons la commande :

./minio server http://192.168.1.200/data1 http://192.168.1.200/data2 http://192.168.1.201/data3 http://192.168.1.201/data4

Qui retourne :

root@ubuntu:~# ./minio server http://192.168.1.200/data1 http://192.168.1.200/data2 http://192.168.1.201/data3 http://192.168.1.201/data4
Waiting for a minimum of 2 disks to come online (elapsed 3s)

Waiting for a minimum of 2 disks to come online (elapsed 6s)

Waiting for a minimum of 2 disks to come online (elapsed 9s)

Il n'est pas possible de passer un volume précédemment démarré en mode unique sans effacer les métadonnées contenues dans le dossier .minio.sys présent dans le volume précédemment créé.

En mode distribué, l'utilisation de clés d'accès est obligatoire.

Nous voyons que le cluster attend la disponibilité d’au minimum deux disques pour démarrer.

Installons un second hôte.

Le second serveur devra être accessible en SSH sans demande de mot de passe.

Une fois l’exécutable minio copié, les volumes data1 et data2 préparés, puis les variables MINIO_ACCESS_KEY et MINIO_SECRET_KEY positionnées, au 1er lancement sur le second hôte, nous verrons :

root@ubuntu:~# ./minio server http://192.168.1.200/data1 http://192.168.1.200/data2 http://192.168.1.201/data3 http://192.168.1.201/data4
Waiting for the first server to format the disks.
Waiting for the first server to format the disks.
Waiting for the first server to format the disks.
Waiting for the first server to format the disks.
Status:         4 Online, 0 Offline.
Endpoint:  http://192.168.1.201:9000  http://127.0.0.1:9000
AccessKey: XLI1NFFBHMAR5LFTTXD8
SecretKey: +4tHexZ4EUU0Ltbo1gQVfTJ6bFcGTZGtRqYNHpmz

Browser Access:
http://192.168.1.201:9000  http://127.0.0.1:9000

Command-line Access: https://docs.minio.io/docs/minio-client-quickstart-guide
$ mc config host add myminio http://192.168.1.201:9000 XLI1NFFBHMAR5LFTTXD8 +4tHexZ4EUU0Ltbo1gQVfTJ6bFcGTZGtRqYNHpmz

Object API (Amazon S3 compatible):
Go:         https://docs.minio.io/docs/golang-client-quickstart-guide
Java:       https://docs.minio.io/docs/java-client-quickstart-guide
Python:     https://docs.minio.io/docs/python-client-quickstart-guide
JavaScript: https://docs.minio.io/docs/javascript-client-quickstart-guide
.NET:       https://docs.minio.io/docs/dotnet-client-quickstart-guide

La commande minio doit donc être lancée sur les deux machines.

1-5-4-1 - Tests

Depuis l’interface web, nous créons ensuite deux buckets et uploadons quelques fichiers dans chaque bucket.

Nous pouvons ensuite observer la présence d’un dossier par bucket dans /data1 et dans /data2, sur les deux hôtes. La réplication s’effectue entre les deux disques locaux et sur les deux hôtes. Nous avons donc quatre exemplaires visibles, répartis sur deux hôtes.

Nous pouvons également observer que chaque fichier uploadé se présente sous forme d'un dossier portant le nom du fichier et contenant un fichier part.1 (ou, selon la taille, plusieurs fichiers part.x) dans un dossier avec un nom représentant un UUID, et un fichier xl.meta. Le fichier part.1 n’est pas exploitable. L’accès aux fichiers n’est donc pas possible sans passer par l’interface web.

1-5-4-2 - Passage en mode démon

Nous allons installer minio en mode démon. Nous commençons par fixer les variables dans le fichier /,etc/default/minio :

MINIO_VOLUMES=https://192.168.1.200/data1 https://192.168.1.201/data1 https://192.168.1.202/data1 https://192.168.1.203/data1
MINIO_ACCESS_KEY=XLI1NFFBHMAR5LFTTXD8
MINIO_SECRET_KEY=+4tHexZ4EUU0Ltbo1gQVfTJ6bFcGTZGtRqYNHpmz

Nous allons ensuite utiliser le script de laudukang :

[Unit]
Description=Minio
Documentation=https://docs.minio.io
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/bin/minio

[Service]
WorkingDirectory=/usr/local

User=root
Group=root

PermissionsStartOnly=true

EnvironmentFile=-/etc/default/minio
ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo \"Variable MINIO_VOLUMES not set in /etc/default/minio\"; exit 1; fi"
ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_ACCESS_KEY}\" ]; then echo \"Variable MINIO_ACCESS_KEY not set in /etc/default/minio\"; exit 1; fi"
ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_SECRET_KEY}\" ]; then echo \"Variable MINIO_SECRET_KEY not set in /etc/default/minio\"; exit 1; fi"

ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES

# Let systemd restart this service only if it has ended with the clean exit code or signal.
Restart=on-success

StandardOutput=journal
StandardError=inherit

# Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE=65536

# Disable timeout logic and wait until process is stopped
TimeoutStopSec=0

# SIGTERM signal is used to stop Minio
KillSignal=SIGTERM

SendSIGKILL=no

SuccessExitStatus=0

[Install]
WantedBy=multi-user.target

# Built for ${project.name}-${project.version} (${project.name})

Nous pouvons voir que le démon attend la commande minio dans /usr/local/bin et en utilisateur root, ce que vous pouvez changer si vous le souhaitez. Nous pouvons également voir que le script récupère les variables dans /,etc/default/minio.

Nous plaçons donc le script dans le fichier /etc/systemd/system/minio.service avec les droits 755.

Nous enregistrons ensuite le service :

systemctl daemon-reload
systemctl enable minio

Ce qui renvoie :

Created symlink from /etc/systemd/system/multi-user.target.wants/minio.service to /etc/systemd/system/minio.service.
root@ubuntu:~#

Nous arrêtons ensuite min.io sur les deux machines et lançons le service sur les deux hôtes, après avoir effectué la copie des fichiers de configuration d'une machine à l'autre.

Pour utiliser le mode https, il faudra ajouter la ligne suivante :

MINIO_OPTS= "-C /,etc/minio"

puis copier les clés .key et .crt dans le dossier /,etc/minio/certs.

1-5-5 - Client min.io

Pour accéder aux buckets min.io depuis la ligne de commande, nous pouvons utiliser le client min.io nommé mc (ne pas confondre avec Midnight Commander) téléchargeable à l’adresse :

https://dl.min.io/client/mc/release/linux-amd64/mc

Un simple appel sans paramètres donnera la liste des options :

~# ./mc
mc: Configuration written to `/root/.mc/config.json`. Please update your access credentials.
mc: Successfully created `/root/.mc/share`.
mc: Initialized share uploads `/root/.mc/share/uploads.json` file.
mc: Initialized share downloads `/root/.mc/share/downloads.json` file.
NAME:
mc - Minio Client for cloud storage and filesystems.

USAGE:
mc [FLAGS] COMMAND [COMMAND FLAGS | -h] [ARGUMENTS...]

COMMANDS:
ls       list buckets and objects
mb       make a bucket
cat      display object contents
pipe     stream STDIN to an object
share    generate URL for temporary access to an object
cp       copy objects
mirror   synchronize object(s) to a remote site
find     search for objects
sql      run sql queries on objects
stat     show object metadata
diff     list differences in object name, size, and date between two buckets
rm       remove objects
event    configure object notifications
watch    listen for object notification events
policy   manage anonymous access to buckets and objects
admin    manage minio servers
session  resume interrupted operations
config   configure minio client
update   update mc to latest release
version  show version info

GLOBAL FLAGS:
--config-dir value, -C value  path to configuration folder (default: "/root/.mc")
--quiet, -q                   disable progress bar display
--no-color                    disable color theme
--json                        enable JSON formatted output
--debug                       enable debug output
--insecure                    disable SSL certificate verification
--help, -h                    show help
--version, -v                 print the version

VERSION:
RELEASE.2018-12-27T00-37-49Z

Nous reconnaissons les commandes classiques du shell.

Nous commençons par créer un alias pour faciliter l’accès, et comme indiqué lors de l’appel à la commande minio server :

mc config host add minioalias http://192.168.1.200:9000 XLI1NFFBHMAR5LFTTXD8 +4tHexZ4EUU0Ltbo1gQVfTJ6bFcGTZGtRqYNHpmz

Ce qui retourne :

mc: Configuration written to `/root/.mc/config.json`. Please update your access credentials.
mc: Successfully created `/root/.mc/share`.
mc: Initialized share uploads `/root/.mc/share/uploads.json` file.
mc: Initialized share downloads `/root/.mc/share/downloads.json` file.
Added `minioalias` successfully.

Nous pouvons consulter le contenu de l’hôte via la commande mc ls suivi du nom de l’alias :

~# ./mc ls minioalias
[2018-12-27 13:49:34 CET]     0B dossier1/
[2018-12-27 13:49:51 CET]     0B dossier2/
~#

La commande cp permettra de copier des fichiers dans le cluster ou d’en récupérer depuis celui-ci.

Il n’y a pas de notion de sous-dossier avec min.io. Par contre, si vous copiez le fichier fichier.txt avec la commande suivante :

./mc cp fichier.txt minioalias/dossier1/textes/fichier.txt

vous pourrez voir l’arborescence texte.

Si vous copiez plusieurs fichiers dans le chemin minioalias/dossier1/textes, vous pourrez les voir avec la commande ./mc ls minioalias/dossier1/textes.

1-5-6 - Fonctionnement en mode S3

Pour cet usage, j’ai testé s3fs qui permet de monter un volume S3 avec FUSE.

Il va nous falloir créer un fichier /etc/passwd-s3fs pour la connexion de la forme identifiant:clé

Dans notre cas, ce sera :

XLI1NFFBHMAR5LFTTXD8:+4tHexZ4EUU0Ltbo1gQVfTJ6bFcGTZGtRqYNHpmz

Ensuite, le volume peut être monté avec s3fs :

s3fs <nom du bucket> /mnt -o use_path_request_style,url=http://192.168.1.200:9000

À partir de ce point de montage, le Bucket est accessible comme n’importe quel autre point de montage.

1-5-7 - Sauvegarde

Pour les sauvegardes, le plus simple est de sauvegarder depuis un point de montage s3fs.

1-5-8 - Test d’arrêt d’un des serveurs

Lors de l’arrêt d’un des serveurs, les données restent accessibles, mais en lecture seule. Après redémarrage du serveur, la situation se débloque.

1-5-8-1 - Perte définitive d’un serveur

La situation ne revient pas à la normale même si vous préparez un nouveau serveur en copiant les fichiers /usr/local/bin/minio, /,etc/default/minio, recréant les points de montages data1 et data2.

Je commence par créer un alias pour la commande mc pointant sur le serveur fonctionnel :

~# ./mc config host add minioalias http://192.168.1.200:9000 XLI1NFFBHMAR5LFTTXD8 +4tHexZ4EUU0Ltbo1gQVfTJ6bFcGTZGtRqYNHpmz
Added `minioalias` successfully.

Je lance la réparation avec la commande ./mc admin heal minioalias :

~# ./mc admin heal minioalias
◓  dossier2
0/0 objects; 0 B in 3s
┌────────┬───┬─────────────────────┐
│ Green  │ 4 │ 100.0% ████████████ │
│ Yellow │ 0 │   0.0%              │
│ Red    │ 0 │   0.0%              │
│ Grey   │ 0 │   0.0%              │
└────────┴───┴─────────────────────┘

Ceci va recréer l’arborescence, mais ne suffira pas pour les fichiers

Il faudra ajouter la commande ./mc admin heal minioalias --recursive.

Vous verrez défiler le nom des fichiers, la console restant sur le dernier fichier synchronisé.

~# ./mc admin heal minioalias --recursive
◐  dossier2/pydio.pdf
7/7 objects; 2 MiB in 6s
┌────────┬────┬─────────────────────┐
│ Green  │ 11 │ 100.0% ████████████ │
│ Yellow │  0 │   0.0%              │
│ Red    │  0 │   0.0%              │
│ Grey   │  0 │   0.0%              │
└────────┴────┴─────────────────────┘

1-5-9 - Ajout de serveur

Pour ajouter un serveur supplémentaire, il faudra modifier le fichier /,etc/default/minio sur les deux serveurs existants (ajout dans la ligne MINIO_VOLUMES= du fichier /,etc/default/minio).

1-6 - Bilan

GlusterFS est une solution souple et relativement simple. Je n'utiliserais pas la méthode DRBD/OCFS, car la désynchronisation est trop facile, et la nouvelle version, paraissant plus souple, m'a posé des difficultés (mais il s'agit ici d'un point de vue personnel).

La solution Ceph est complexe, mais offre l’avantage de s'autoréparer en cas de problème. Ceph est adapté aux solutions à grande échelle et est utilisé par OpenStack, OpenNebula. Elle reste complexe à mettre en place, mais fait référence.

1-7 - Quid de Windows ?

Il est possible de gérer un système de fichiers distribués avec Windows via un Active Directory en utilisant DFSR (Distributed FileSystem Replication).

DFS permet de faire de la répartition de données (une partie sur chaque serveur, vue à partir d’un seul point d'accès) ou de la redondance en répliquant les données d'un serveur à un autre.

Il faudra sur un Windows Server avec Active Directory fonctionnel installer le rôle « Réplication DFS », puis depuis le menu outil du gestionnaire de serveurs aller dans « Gestion du système de fichiers distribués DFS ».

Dans le gestionnaire DFS qui va s'ouvrir, il va falloir faire un clic droit sur Espace de noms→ Nouvel espace de noms.

Une fois l'espace de nom créé, il faudra ajouter les dossiers cibles de chaque serveur.

Vous pourrez sélectionner une réplication en temps réel ou planifier la fréquence.

1-8 - Quid de Mac OS X ?

Mac OS X ou mac OS Server ne proposent aucun système de fichiers distribués. Il pourra se connecter à un DFS Active Directory.

Pour se référer à ce qui a été vu dans ce tutoriel, GlusterFS n'est actuellement pas compatible Mac OS.

Il est possible de compiler Ceph via Homebrew, mais cela me parait trop expérimental pour une utilisation en production.

2 - Conclusion

J'espère que ce tutoriel vous a éclairé sur les systèmes de fichier distribués.

3 - Remerciements

Je remercie Mickael Baron, khayyam90, LittleWhite, et Louis-Guillaume Morland pour leur relecture technique.

Je remercie Claude Leloup pour sa relecture orthographique.