Périmètre Link to heading
Cet article couvrira la mise en place du réseau de stockage ainsi que de l’installation de CEPH avec cephadm.
Configuration Réseau Link to heading
D’après la documentation officielle Network Configuration Reference, CEPH doit connaître deux réseaux : un réseau public qui permettra aux clients de communiquer avec le clusters et aux composants du cluster de communiquer entre eux et un réseau privé qui sera dédié à la réplication des OSD.

Réseau privé Link to heading
La configuration de ce réseau touche à cette partie du schéma présenté dans Mise à jour du lab :
Note : Merci à lyknode pour le tip sur l’utilisation des Jumbo Frames.
Routeur SFP+ Link to heading
J’ai découvert le langage de configuration des routeurs mikrotik lorsque j’ai voulu en configurer un pour le besoin de ce réseau. Je ne passerai pas par les différentes étapes qui permettent de modifier la configuration initiale. L’export final de la configuration est globalement le suivant :
Par défaut, les routeurs mikrotik sont accessibles à l’adresse 192.168.88.1/24 avec l’utilisateur admin et le mot de passe par défaut écrit sur l’appareil. Une fois connecté via http, l’utilisateur est prompté pour changer le mot de passe.
# Configuration des interfaces
/interface ethernet
set [ find default-name=ether1 ] comment="management interface"
set [ find default-name=sfp-sfpplus1 ] l2mtu=9092 mtu=9000 comment="gullintanni"
set [ find default-name=sfp-sfpplus2 ] l2mtu=9092 mtu=9000 comment="gulltoppr"
set [ find default-name=sfp-sfpplus3 ] l2mtu=9092 mtu=9000 comment="heimdallr"
set [ find default-name=sfp-sfpplus4 ] disabled=yes
# Création des listes dont peuvent faire partie les interfaces
# Les listes peuvent ensuite être utilisées dans le firewall
/interface list
add name=MGMT
add name=SAN
# Ajout des interfaces dans les listes
/interface list member
add interface=ether1 list=MGMT
add interface=sfp-sfpplus1 list=SAN
add interface=sfp-sfpplus2 list=SAN
add interface=sfp-sfpplus3 list=SAN
# Ajout d'une adresse du LAN pour l'interface de management
/ip address
add address=192.168.43.221/24 interface=ether1 network=192.168.43.0
# À ce stade, il est recommandé d'accéder à l'interface web/au terminal de
# configuration via cette nouvelle IP et de supprimer l'ip existante en
# 192.168.88.1 qui est configurée par défaut sur le bridge.
# Création du bridge
/interface bridge
add admin-mac=D0:EA:11:6B:14:65 auto-mac=no comment=san name=bridge
# Il y a déjà, par défaut, un bridge de créé sur l'appareil. Ce que j'ai dû
# faire plutôt que d'ajouter les interfaces dedans comme ce qui est fait
# ensuite, est de retirer les interfaces dont je ne voulais pas qu'elles
# fassent partie de ce bridge.
# Ici, j'ai donc dû retirer l'interface ether1 que je souhaitait dédier à
# l'administration du routeur ainsi que l'interface sfp-sfpplus4 qui n'est pas
# utilisée.
# Ajout des interfaces sfp+ dans le bridge
/interface bridge port
add bridge=bridge comment=san interface=sfp-sfpplus1
add bridge=bridge comment=san interface=sfp-sfpplus2
add bridge=bridge comment=san interface=sfp-sfpplus3
# Configuration du FW pour n'accepter les inputs qu'à travers ether1 pour
# l'administration
/ip firewall filter
add action=accept chain=input comment="Allow established" connection-state=established,related
add action=drop chain=input comment="Drop invalid" connection-state=invalid
add action=accept chain=input comment="Allow management from ether1" in-interface-list=MGMT
add action=drop chain=input comment="Drop all other input"
# La configuration qui suit est la configuration classique d'un hôte : TZ, DNS,
# hostname, ntp, etc.
/ip dns
set servers=192.168.43.254
/ip route
add disabled=no dst-address=0.0.0.0/0 gateway=192.168.43.254
/system clock
set time-zone-name=Europe/Paris
/system identity
set name=mikro-san
/system ntp client
set enabled=yes
/system ntp client servers
add address=192.168.43.254
Je configure ici une route par défaut pour que le routeur puisse aller télécharger au besoin ses mises à jour. Dans la pratique, mon FW WAN actuel bloque l’accès à internet à ce routeur depuis son IP sur mon LAN et les interfaces configurées en bridge n’ont pas accès un réseau avec internet, ce qui isole (suffisament à mon goût) le routeur d’internet.
Configuration de l’interface pour la réplication Link to heading
J’ai ici 3 hôtes. Si je souhaite qu’il puissent communiquer ensemble sans soucis, il me faudra donc un réseau au minimum en /29 pour que chacun puisse avoir une IP, soit 6 adresses maximum. J’ai décidé préalablement que tous les réseaux liés a mon homelab seraient derrière 10.43.0.0/16. Le premier /29 dans ce réseau pour le moment inutilisé est donc 10.43.0.0/29.
$ ipcalc 10.43.0.0/29
Address: 10.43.0.0 00001010.00101011.00000000.00000 000
Netmask: 255.255.255.248 = 29 11111111.11111111.11111111.11111 000
Wildcard: 0.0.0.7 00000000.00000000.00000000.00000 111
=>
Network: 10.43.0.0/29 00001010.00101011.00000000.00000 000
HostMin: 10.43.0.1 00001010.00101011.00000000.00000 001
HostMax: 10.43.0.6 00001010.00101011.00000000.00000 110
Broadcast: 10.43.0.7 00001010.00101011.00000000.00000 111
Hosts/Net: 6 Class A, Private Internet
Je considérerai aussi pour la suite que les hôtes seront toujours configurés dans l’ordre suivant : gullintanni > gulltoppr > heimdallr. Ainsi, ici gullintanni aura l’ip 10.43.0.1, gulltoppr 10.43.0.2 et heimdallr 10.43.0.3.
La configuration de l’interface réseau de ces machines est ici plutôt simple : il n’y a pas de vlan étant donné qu’un seul réseau est censé passer sur ces interfaces et que le routeur associé lui est dédié.
Nous avons donc sur chacun des hôtes la configuration suivante :
# /etc/systemd/network/10-san.network
[Match]
Name=enp2s0f0np0
[Link]
MTUBytes=9000
[Network]
Description=SAN interface
Address=<ip>/29
La configuration peut être appliquée via la commande networkctl reload puis consultée via
# networkctl list
IDX LINK TYPE OPERATIONAL SETUP
1 lo loopback carrier unmanaged
2 enp87s0 ether routable configured
3 enp90s0 ether off unmanaged
4 enp2s0f0np0 ether routable configured
5 enp2s0f1np1 ether off unmanaged
6 wlp91s0 wlan off unmanaged
6 links listed.
Réseau public Link to heading
La configuration de ce réseau touche à cette partie du schéma présenté dans Mise à jour du lab :
Ce réseau physique est le réseau qui portera tous les réseaux virtuels du cluster libvirt. Tous ces réseaux seront tagués et l’un de ces réseaux correspondra, plus tard, au réseau public de CEPH. Quand le cluster libvirt sera en place, ce réseau sera routé via le routeur virtualisé afin d’être rendu accessible au LAN et/ou aux autres réseaux qui pourraient en avoir besoin.
Ajout du vlan dans le routeur mikro-virt Link to heading
La configuration de ce routeur ressemblera fortement à celle du réseau privé. La seule différence notable est ici que le bridge n’acceptera que des réseaux tagués.
La configuration générale de ce routeur sera traitée dans l’article concernant la mise en place du cluster libvirt.
# Création du bridge avec le vlan filtering
/interface bridge
add admin-mac=D0:EA:11:6B:14:24 auto-mac=no comment=virt frame-types=admit-only-vlan-tagged name=bridge vlan-filtering=yes
Configuration de l’interface ceph public Link to heading
Par convention, les ips des hôtes sur le vlan 10 qui a été choisi pour CEPH auront des ips derrière 10.43.*10*.0/29. Ainsi nous aurons : gullintanni 10.43.10.1, gulltoppr 10.43.10.2 et heimdallr 10.43.10.3.
La configuration de cette interface sera plus verbeuse que la précédente. Il faudra tout d’abord créer le network device correspondant au VLAN puis configurer l’interface enp2s0f1np1 pour l’attacher à ce nouveau VLAN et enfin mettre une ip sur ce VLAN.
# /etc/systemd/network/20-trunk.ceph.netdev
[NetDev]
Name=trunk.ceph
Kind=vlan
[VLAN]
Id=10
# /etc/systemd/network/20-virt-trunk.network
[Match]
Name=enp2s0f1np1
[Network]
Description=mikro-virt trunk
LinkLocalAddressing=no
IPv6AcceptRA=no
VLAN=trunk.ceph
# /etc/systemd/network/21-trunk.ceph.network
[Match]
Name=trunk.ceph
[Network]
Address=<ip>/29
Installation de CEPH Link to heading
Si j’ai déjà utilisé CEPH au travers de rook par le passé, le mettre en place moi même hors d’un cluster kubernetes, avec cephadm est une complète nouveauté pour moi. J’ai donc passé un bon moment à lire la documentation officielle toutefois il est possible que les décisions que j’ai prises au moment de l’initialisation du cluster évoluent dans le futur. J’essaierai alors de mettre à jour cette page.
Préparation des nœuds Link to heading
Il s’agit tout d’abord de préparer les nœuds en installant les dépendances requises et cephadm. cephadm n’est pas présent dans les paquets de ma distribution, j’ai fait le choix de l’installer depuis le repository EL dans lequel il est publié, comme le suggère la documentation officielle.
# pacman -S python logrotate runc podman
# export CEPH_RELEASE=20.2.1
# curl --silent --remote-name --location https://download.ceph.com/rpm-${CEPH_RELEASE}/el9/noarch/cephadm
# chmod +x cephadm
Il me faut ensuite créer un utilisateur dédié, pour les connexions ssh entre les hôtes. CEPH utilise par défaut l’utilisateur root mais ma configuration sshd ne permet pas la connexion en tant que celui-ci.
# useradd --comment "CEPH cluster user" --home-dir "/var/lib/ceph" --create-home --system ceph
La documentation stipule que cet utilisateur doit pouvoir lancer des commandes sudo sans mot de passe.
# /etc/sudoers.d/ceph
ceph ALL=(ALL) NOPASSWD: ALL
Initialisation du cluster Link to heading
Lors du bootstrap du cluster, je précise bien l’ip du MON (dans le réseau 10.43.10.0/29) et j’indique à l’aide de --cluster-network que le réseau privé utilisé pour la réplication du stockage est le réseau 10.43.0.0/29.
# ./cephadm bootstrap --mon-ip 10.43.10.1 --cluster-network 10.43.0.0/29 --ssh-user ceph
Verifying ssh connectivity using standard pubkey authentication ...
Adding key to ceph@localhost authorized_keys...
Verifying podman|docker is present...
Verifying lvm2 is present...
Verifying time synchronization is in place...
Unit systemd-timesyncd.service is enabled and running
Repeating the final host check...
podman (/usr/bin/podman) version 5.8.2 is present
systemctl is present
lvcreate is present
Unit systemd-timesyncd.service is enabled and running
Host looks OK
Cluster fsid: 0d3c23e4-5089-11f1-ae88-380525379536
Verifying IP 10.43.10.1 port 3300 ...
Verifying IP 10.43.10.1 port 6789 ...
Mon IP `10.43.10.1` is in CIDR network `10.43.10.0/29`
Mon IP `10.43.10.1` is in CIDR network `10.43.10.0/29`
Pulling container image quay.io/ceph/ceph:v20...
Ceph version: ceph version 20.2.1 (6a49aff47758778a5f5951e731d437c317f72fb2) tentacle (stable)
Extracting ceph user uid/gid from container image...
Creating initial keys...
Creating initial monmap...
Creating mon...
Waiting for mon to start...
Waiting for mon...
mon is available
Assimilating anything we can from ceph.conf...
Generating new minimal ceph.conf...
Restarting the monitor...
Setting public_network to 10.43.10.0/29 in global config section
Setting cluster_network to 10.43.0.0/29
Wrote config to /etc/ceph/ceph.conf
Wrote keyring to /etc/ceph/ceph.client.admin.keyring
Creating mgr...
Verifying port 0.0.0.0:9283 ...
Verifying port 0.0.0.0:8765 ...
Verifying port 0.0.0.0:8443 ...
Waiting for mgr to start...
Waiting for mgr...
mgr not available, waiting (1/15)...
mgr not available, waiting (2/15)...
mgr is available
Enabling cephadm module...
Waiting for the mgr to restart...
Waiting for mgr epoch 5...
mgr epoch 5 is available
Verifying orchestrator module is enabled...
Setting orchestrator backend to cephadm...
Generating ssh key...
Wrote public SSH key to /etc/ceph/ceph.pub
Adding key to ceph@localhost authorized_keys...
Adding host gullintanni...
Deploying mon service with default placement...
Deploying mgr service with default placement...
Deploying crash service with default placement...
Deploying ceph-exporter service with default placement...
Deploying prometheus service with default placement...
Deploying grafana service with default placement...
Deploying node-exporter service with default placement...
Deploying alertmanager service with default placement...
Enabling the dashboard module...
Waiting for the mgr to restart...
Waiting for mgr epoch 9...
mgr epoch 9 is available
Using certmgr to generate dashboard self-signed certificate...
Creating initial admin user...
Fetching dashboard port number...
Ceph Dashboard is now available at:
URL: https://gullintanni:8443/
User: admin
Password: xxxxxxxxxx
Enabling client.admin keyring and conf on hosts with "admin" label
Saving cluster configuration to /var/lib/ceph/0d3c23e4-5089-11f1-ae88-380525379536/config directory
You can access the Ceph CLI as following in case of multi-cluster or non-default config:
sudo ./cephadm shell --fsid 0d3c23e4-5089-11f1-ae88-380525379536 -c /etc/ceph/ceph.conf -k /etc/ceph/ceph.client.admin.keyring
Or, if you are only running a single cluster on this host:
sudo ./cephadm shell
Please consider enabling telemetry to help improve Ceph:
ceph telemetry on
For more information see:
https://docs.ceph.com/en/latest/mgr/telemetry/
Bootstrap complete.
Enabling the logrotate.timer service to perform daily log rotation.
Je prépare ensuite les autres hôtes. Ici je me contenterai de gulltoppr, heimdallr étant encore utilisé et n’étant pas prêt à rentrer dans le cluster.
# ssh-copy-id -f -i /etc/ceph/ceph.pub ceph@gulltoppr
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/etc/ceph/ceph.pub"
ceph@gulltoppr's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh -i 'ceph@gulltoppr'"
and check to make sure that only the key(s) you wanted were added.
Il s’agit ensuite d’ajouter le nouveau membre du cluster.
# ceph orch host add gulltoppr 10.43.10.2 --labels _admin
Added host 'gulltoppr' with addr '10.43.10.2'
# ceph mon dump
epoch 2
fsid 0d3c23e4-5089-11f1-ae88-380525379536
last_changed 2026-05-15T18:14:26.029632+0000
created 2026-05-15T18:08:23.396309+0000
min_mon_release 20 (tentacle)
election_strategy: 1
0: [v2:10.43.10.1:3300/0,v1:10.43.10.1:6789/0] mon.gullintanni
1: [v2:10.43.10.2:3300/0,v1:10.43.10.2:6789/0] mon.gulltoppr
dumped monmap epoch 2
Le cluster contient deux membres. Ce n’est pas suffisant pour le quorum mais je m’en contenterai pour le moment, jusqu’à ce que heimdallr soit disponible pour rejoindre le cluster.
Ajout des OSDs Link to heading
À l’aide de ceph orch device ls, je peux lister tous les devices qui ne sont pas utilisés sur les différents membres du cluster. Les disques de gulltoppr ne sont pas considérés comme disponible car étant reconditionnés et contenant toujours des traces de leur ancien partitionnement ou de leur ancien FS.
# ceph orch device ls
HOST PATH TYPE DEVICE ID SIZE AVAILABLE REFRESHED REJECT REASONS
gullintanni /dev/nvme0n1 ssd CT2000P510SSD8_2546E9CDA94E 1863G Yes 16m ago
gullintanni /dev/nvme1n1 ssd CT2000P510SSD8_2546E9CDA946 1863G Yes 16m ago
gulltoppr /dev/nvme1n1 ssd CT2000P3PSSD8_2436E98ABF98 1863G No 3m ago Has GPT headers
gulltoppr /dev/nvme2n1 ssd CT2000P3PSSD8_2436E98ABF96 1863G No 3m ago Has a FileSystem, Insufficient space (<10 extents) on vgs, LVM detected
Il sera possible de les nettoyer à l’aide de sgdisk, wipefs, etc.
Une fois toutes les anciennes traces effacées, ceph orch device ls gulltoppr --refresh suivi peu de temps après par un nouveau ceph orch device ls permet d’afficher et de valider que tous les devices sont maintenant disponibles.
# ceph orch device ls gulltoppr
HOST PATH TYPE DEVICE ID SIZE AVAILABLE REFRESHED REJECT REASONS
gulltoppr /dev/nvme1n1 ssd CT2000P3PSSD8_2436E98ABF98 1863G Yes 17s ago
gulltoppr /dev/nvme2n1 ssd CT2000P3PSSD8_2436E98ABF96 1863G Yes 17s ago
Étant donné que je souhaite ajouter tous les disques disponibles comme OSD, je peux lancer la commande suivante :
ceph orch apply osd --all-available-devices
N’ayant pas correctement nettoyé l’un des disques, je me suis retrouvé avec un OSD down. Je l’ai nettoyé puis l’ai ré-ajouté, c’est la raison pour laquelle je n’ai pas d’osd.0.
# ceph osd tree
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
-1 7.27759 root default
-5 3.63879 host gullintanni
2 ssd 1.81940 osd.2 up 1.00000 1.00000
4 ssd 1.81940 osd.4 up 1.00000 1.00000
-3 3.63879 host gulltoppr
1 ssd 1.81940 osd.1 up 1.00000 1.00000
3 ssd 1.81940 osd.3 up 1.00000 1.00000
Done Link to heading
# ceph -s
cluster:
id: 0d3c23e4-5089-11f1-ae88-380525379536
health: HEALTH_OK
services:
mon: 2 daemons, quorum gullintanni,gulltoppr (age 42m) [leader: gullintanni]
mgr: gullintanni.bgykdr(active, since 116m), standbys: gulltoppr.uedsxd
osd: 4 osds: 4 up (since 41m), 4 in (since 48m); 1 remapped pgs
data:
pools: 1 pools, 1 pgs
objects: 2 objects, 577 KiB
usage: 112 MiB used, 7.3 TiB / 7.3 TiB avail
pgs: 2/6 objects misplaced (33.333%)
1 active+clean+remapped
Le cluster CEPH est maintenant en place. Sous peu heimdallr le rejoindra mais cela nécessitera que les VMs actuellement hébergées dessus soient migrées vers ce nouveau stockage et que le cluster libvirt soit en place sur les deux hôtes gullintanni et gulltoppr. Pour le moment il vivra donc en mode dégradé : la taille par défaut d’un pool est de 3 mais tant que heimdallr n’est pas dans le cluster, il ne sera pas possible de placer 3 replicas sur 3 hôtes différents.