<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Proxmox on Mook’s Lab Chronicles</title><link>https://blog.homeblack.fr/tags/proxmox/</link><description>Recent content in Proxmox on Mook’s Lab Chronicles</description><generator>Hugo -- gohugo.io</generator><language>fr-FR</language><lastBuildDate>Mon, 24 Aug 2026 15:20:00 +0200</lastBuildDate><atom:link href="https://blog.homeblack.fr/tags/proxmox/index.xml" rel="self" type="application/rss+xml"/><item><title>J’ai enfin activé Hyperscan sur mes deux OPNsense</title><link>https://blog.homeblack.fr/p/hyperscan-suricata-opnsense/</link><pubDate>Mon, 24 Aug 2026 15:20:00 +0200</pubDate><guid>https://blog.homeblack.fr/p/hyperscan-suricata-opnsense/</guid><description>&lt;img src="https://blog.homeblack.fr/p/hyperscan-suricata-opnsense/cover.png" alt="Featured image of post J’ai enfin activé Hyperscan sur mes deux OPNsense" /&gt;&lt;p&gt;Tout est parti d’un article publié sur le blog de Suricata : &lt;a class="link" href="https://suricata.io/2025/10/07/faster-suricata-startups-with-hyperscan-caching/" target="_blank" rel="noopener"
&gt;&lt;em&gt;Faster Suricata startups with Hyperscan caching&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Le sujet était le cache MPM (&lt;em&gt;Multi-Pattern Matching&lt;/em&gt;) introduit avec Suricata 8. Au lieu de recompiler toutes les bases de motifs Hyperscan à chaque démarrage ou rechargement des règles, Suricata peut les conserver sur disque et les réutiliser. L’article annonçait un temps de démarrage réduit jusqu’à 50 %.&lt;/p&gt;
&lt;p&gt;En le lisant, je me suis surtout posé une question beaucoup plus basique : est-ce qu’Hyperscan tournait réellement sur mes firewalls ?&lt;/p&gt;
&lt;p&gt;La réponse était non.&lt;/p&gt;
&lt;p&gt;Suricata fonctionnait déjà sur mes deux OPNsense, les événements remontaient bien dans VictoriaLogs et mon cluster HA faisait son travail. Mais le moteur de recherche de motifs capable de profiter des instructions vectorielles du processeur n’était pas actif.&lt;/p&gt;
&lt;p&gt;Le verrou ne se trouvait pas vraiment dans Suricata. Mes deux VM utilisaient encore le modèle de CPU générique &lt;code&gt;kvm64&lt;/code&gt;, pratique pour la compatibilité, mais trop conservateur pour exposer les instructions que je voulais utiliser. Avant de jouer avec le cache, il fallait donc commencer par activer le moteur lui-même.&lt;/p&gt;
&lt;h2 id="donner-le-bon-cpu-virtuel-à-suricata"&gt;Donner le bon CPU virtuel à Suricata
&lt;/h2&gt;&lt;p&gt;J’ai passé &lt;code&gt;fw-core-p1&lt;/code&gt; et &lt;code&gt;fw-core-p2&lt;/code&gt; en &lt;code&gt;x86-64-v3&lt;/code&gt;. FreeBSD voyait alors correctement AVX2, AES et FMA, et je pouvais enfin demander explicitement Hyperscan à Suricata :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-hcl" data-lang="hcl"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;cpu&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;x86-64-v3&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;opnsense_ids_mpm_algo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;hs&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Le &lt;code&gt;hs&lt;/code&gt; sélectionne Hyperscan comme moteur MPM. C’est la partie de Suricata qui cherche plusieurs motifs à la fois dans le trafic et écarte rapidement les signatures qui ne peuvent pas correspondre. La &lt;a class="link" href="https://docs.opnsense.org/manual/ips.html" target="_blank" rel="noopener"
&gt;documentation OPNsense&lt;/a&gt; le présente d’ailleurs comme le meilleur choix sur les plateformes compatibles.&lt;/p&gt;
&lt;p&gt;Le changement posait tout de même une question importante : mes hôtes Proxmox mélangent des processeurs Intel et AMD. J’ai donc fait migrer une VM de test d’Intel vers AMD, puis de nouveau vers Intel, avant de considérer &lt;code&gt;x86-64-v3&lt;/code&gt; comme un socle suffisamment portable chez moi.&lt;/p&gt;
&lt;p&gt;Je n’ai pas touché aux règles de placement HA. Les deux firewalls restent volontairement séparés sur deux hôtes différents.&lt;/p&gt;
&lt;h2 id="le-test-qui-comptait-vraiment"&gt;Le test qui comptait vraiment
&lt;/h2&gt;&lt;p&gt;Voir &lt;code&gt;mpm-algo = hs&lt;/code&gt; sur les deux nœuds était une bonne nouvelle, mais cela ne disait encore rien sur le comportement du cluster pendant une vraie bascule.&lt;/p&gt;
&lt;p&gt;J’ai donc laissé &lt;code&gt;p2&lt;/code&gt; reprendre les neuf VIP CARP. Pendant qu’il était MASTER avec Hyperscan actif, la sortie Internet continuait de fonctionner. Je n’ai observé aucune perte de paquets pendant le failover, avec une latence maximale de 13 ms.&lt;/p&gt;
&lt;p&gt;Après le test, la situation normale était revenue : &lt;code&gt;p1&lt;/code&gt; MASTER, &lt;code&gt;p2&lt;/code&gt; BACKUP et neuf VIP au bon endroit. Le moteur de détection avait changé sans perturber le cluster.&lt;/p&gt;
&lt;h2 id="seize-heures-plus-tard"&gt;Seize heures plus tard
&lt;/h2&gt;&lt;p&gt;Le premier contrôle montrait déjà Suricata autour de 356 à 359 Mio de mémoire, contre environ 548 Mio auparavant. J’ai laissé tourner avant de regarder de nouveau les compteurs.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mesure&lt;/th&gt;
&lt;th&gt;Après environ 16 heures&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CPU Suricata&lt;/td&gt;
&lt;td&gt;0 à 0,1 % sur les deux nœuds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mémoire sur P1&lt;/td&gt;
&lt;td&gt;233 Mio, soit −57,5 % par rapport au repère de 548 Mio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mémoire sur P2&lt;/td&gt;
&lt;td&gt;356 Mio, stable depuis le premier contrôle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Capture sur P1&lt;/td&gt;
&lt;td&gt;51 044 239 paquets, 4 669 drops, soit 0,0091 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Capture sur P2&lt;/td&gt;
&lt;td&gt;1 078 301 paquets, aucun drop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Événements TLS&lt;/td&gt;
&lt;td&gt;22 056 événements centralisés dans VictoriaLogs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Les 4 669 drops de capture observés sur &lt;code&gt;p1&lt;/code&gt; n’avaient pas augmenté depuis plus de deux heures lors du dernier relevé. Aucun drop Suricata n’apparaissait dans les échantillons contrôlés et la qualité de capture restait supérieure à 99,99 %.&lt;/p&gt;
&lt;p&gt;Surtout, l’enrichissement n’avait pas disparu au passage : 926 SNI, 370 empreintes JA4, 55 empreintes de certificats et 23 émetteurs distincts remontaient toujours dans VictoriaLogs.&lt;/p&gt;
&lt;p&gt;Ce n’est pas un benchmark. &lt;code&gt;p1&lt;/code&gt; et &lt;code&gt;p2&lt;/code&gt; n’ont ni le même rôle ni le même volume de trafic, et je ne vais pas attribuer toute la baisse à une seule option. La tendance observée reste néanmoins assez nette : CPU négligeable, mémoire en baisse et aucune dégradation visible de la détection ou du failover.&lt;/p&gt;
&lt;p&gt;La configuration est maintenant décrite dans Terraform et Ansible. Le plan Terraform ne montrait aucun drift, le second passage Ansible terminait avec &lt;code&gt;changed=0&lt;/code&gt;, et les sept tests du rôle passaient avec le &lt;em&gt;syntax-check&lt;/em&gt; et &lt;code&gt;ansible-lint&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Assez ironiquement, un article consacré au cache m’aura d’abord fait découvrir que je n’utilisais même pas le moteur. Le cache pourra venir ensuite. Pour l’instant, Hyperscan tourne enfin sur mes deux firewalls — et c’était déjà le vrai chantier.&lt;/p&gt;</description></item><item><title>J’allais ajouter un nœud Ceph. Mes backups partaient en même temps</title><link>https://blog.homeblack.fr/p/ceph-backups-pbs/</link><pubDate>Fri, 14 Aug 2026 12:40:31 +0200</pubDate><guid>https://blog.homeblack.fr/p/ceph-backups-pbs/</guid><description>&lt;img src="https://blog.homeblack.fr/p/ceph-backups-pbs/cover.png" alt="Featured image of post J’allais ajouter un nœud Ceph. Mes backups partaient en même temps" /&gt;&lt;p&gt;Toutes les deux heures, mon cluster Ceph avait un petit passage à vide. Les VM devenaient moins réactives, les latences grimpaient et BlueStore finissait parfois par signaler des opérations lentes.&lt;/p&gt;
&lt;p&gt;Ma première question a été assez classique : est-ce que le scheduler mClock était mal adapté à mon petit cluster ? Un retour à WPQ pouvait-il arranger les choses ? Et si le problème venait simplement du fait que trois nœuds et trois OSD ne suffisaient plus, fallait-il ajouter un quatrième PVE ?&lt;/p&gt;
&lt;p&gt;Cette dernière option ne m’enchantait pas. Un nœud supplémentaire aurait apporté de la capacité et réparti la charge, mais aussi un nouveau coût pour corriger un problème que je ne comprenais pas encore.&lt;/p&gt;
&lt;p&gt;J’ai donc commencé par regarder ce qui se passait réellement au moment des ralentissements. Le coupable n’était pas caché dans un obscur réglage Ceph : mes trois sauvegardes Proxmox Backup Server partaient exactement en même temps.&lt;/p&gt;
&lt;h2 id="avec-trois-osd-le-plus-lent-donne-le-tempo"&gt;Avec trois OSD, le plus lent donne le tempo
&lt;/h2&gt;&lt;p&gt;Mon cluster repose sur trois nœuds Proxmox et un OSD NVMe par nœud :&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nœud&lt;/th&gt;
&lt;th&gt;OSD&lt;/th&gt;
&lt;th&gt;SSD&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pve-forum&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;osd.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;WD Black SN770 2 To&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pve-dell&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;osd.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Crucial P310 2 To&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pve-fuji&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;osd.2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Crucial P3 Plus 2 To&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Le pool des VM utilise une réplication par trois. Chaque écriture doit donc être confirmée par les trois OSD. Ce choix me donne la tolérance aux pannes que je veux, mais il transforme naturellement le disque le plus lent en limite commune.&lt;/p&gt;
&lt;p&gt;Le cluster n’était pourtant ni plein ni déséquilibré. Au moment du diagnostic, il était occupé à environ 33 %, ses 129 groupes de placement étaient &lt;code&gt;active+clean&lt;/code&gt; et aucun recovery n’avait eu lieu durant les trente jours observés. Le réseau Ceph en 2,5 Gb/s ne montrait pas non plus d’erreurs ni de pertes.&lt;/p&gt;
&lt;p&gt;En revanche, les latences maximales des OSD racontaient une tout autre histoire :&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;OSD&lt;/th&gt;
&lt;th style="text-align: right"&gt;Latence commit maximale sur 30 jours&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;osd.0&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: right"&gt;3,2 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;osd.1&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: right"&gt;567 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;osd.2&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: right"&gt;9,5 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Le Crucial P3 Plus de &lt;code&gt;pve-fuji&lt;/code&gt; était le plus préoccupant sur la durée, tandis que l’alerte active pouvait très bien pointer ponctuellement vers le WD de &lt;code&gt;pve-forum&lt;/code&gt;. Ce n’était pas un OSD isolé qui souffrait en permanence : les trois SSD grand public encaissaient mal certaines rafales de petites écritures synchrones.&lt;/p&gt;
&lt;h2 id="wpq-était-une-piste-séduisante-mais-pas-la-bonne"&gt;WPQ était une piste séduisante, mais pas la bonne
&lt;/h2&gt;&lt;p&gt;Le cluster utilisait déjà mClock avec son profil &lt;code&gt;balanced&lt;/code&gt;. J’ai envisagé de repasser à la &lt;em&gt;Weighted Priority Queue&lt;/em&gt; (WPQ), l’ancien scheduler, parce que le changement est souvent cité lorsque l’on cherche à réduire des latences Ceph.&lt;/p&gt;
&lt;p&gt;Le souci, c’est que mon cluster n’était pas en train de faire du recovery ou du backfill. Les profils mClock savent répartir les ressources entre les opérations clientes, la récupération et les travaux de fond. Ici, les écritures des VM et celles provoquées par leurs sauvegardes appartenaient toutes à la même famille : des opérations clientes.&lt;/p&gt;
&lt;p&gt;Passer à &lt;code&gt;high_client_ops&lt;/code&gt; n’aurait donc pas appris à Ceph à préférer une VM interactive à sa propre sauvegarde. Revenir à WPQ aurait surtout changé la façon d’ordonner une saturation que je continuais à provoquer moi-même.&lt;/p&gt;
&lt;p&gt;La &lt;a class="link" href="https://docs.ceph.com/en/squid/rados/configuration/mclock-config-ref/" target="_blank" rel="noopener"
&gt;documentation mClock de Ceph&lt;/a&gt; recommande d’ailleurs de rester prudent avec les réglages de bas niveau. Avant d’ajuster le scheduler, il fallait d’abord vérifier ce que je lui demandais d’absorber.&lt;/p&gt;
&lt;h2 id="le-graphique-qui-revenait-toutes-les-deux-heures"&gt;Le graphique qui revenait toutes les deux heures
&lt;/h2&gt;&lt;p&gt;Mon job PBS global était configuré toutes les deux heures, sans limite de bande passante. À chaque déclenchement, les sauvegardes des VM hébergées sur les trois nœuds partaient en parallèle : lecture des disques Ceph, création des snapshots et envoi vers PBS.&lt;/p&gt;
&lt;p&gt;La corrélation avec les lenteurs était difficile à ignorer. Sur les 48 heures examinées :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;les 563 événements &lt;code&gt;aio_submit retries&lt;/code&gt; étaient tous apparus dans les trente minutes suivant le départ d’un backup ;&lt;/li&gt;
&lt;li&gt;800 des 1 138 avertissements BlueStore étaient concentrés dans cette même fenêtre ;&lt;/li&gt;
&lt;li&gt;les files NVMe avaient atteint une profondeur de 47 sur &lt;code&gt;pve-forum&lt;/code&gt; et de 20 sur &lt;code&gt;pve-fuji&lt;/code&gt; pendant un incident.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ceph ne manquait pas de capacité. Il recevait simplement, à intervalles réguliers, trois grosses tapes sur l’épaule au même moment 😂.&lt;/p&gt;
&lt;p&gt;Un quatrième PVE aurait probablement réduit la charge moyenne de chaque OSD. Il aurait aussi augmenté la capacité brute et les performances agrégées. Mais il n’aurait pas rendu raisonnables trois sauvegardes illimitées lancées ensemble. J’aurais payé du matériel pour mieux encaisser une mauvaise planification.&lt;/p&gt;
&lt;h2 id="quarante-minutes-entre-chaque-sauvegarde"&gt;Quarante minutes entre chaque sauvegarde
&lt;/h2&gt;&lt;p&gt;J’ai remplacé le job global par trois jobs liés chacun à un nœud. Ils restent exécutés toutes les deux heures, mais avec quarante minutes d’écart :&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nœud&lt;/th&gt;
&lt;th&gt;Horaire&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pve-forum&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;heures paires à &lt;code&gt;:00&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pve-dell&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;heures paires à &lt;code&gt;:40&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pve-fuji&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;heures impaires à &lt;code&gt;:20&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Dans la syntaxe du planificateur Proxmox, cela donne :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pve-forum */2:00
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pve-dell */2:40
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pve-fuji 1/2:20
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;J’ai ajouté la même limite à chaque job :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bwlimit: 102400
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;La valeur est exprimée en Kio/s, soit 100 Mio/s. Le but n’était pas de rendre les sauvegardes artificiellement lentes, mais de leur laisser assez de débit sans leur permettre de prendre tout ce que les OSD pouvaient fournir pendant une pointe.&lt;/p&gt;
&lt;p&gt;Je n’ai modifié ni la destination PBS, ni le mode snapshot, ni les exclusions existantes. Ce petit périmètre était important : une seule hypothèse changeait à la fois, donc le résultat restait lisible.&lt;/p&gt;
&lt;h2 id="le-poc-a-calmé-la-pointe-pas-effacé-le-problème"&gt;Le PoC a calmé la pointe, pas effacé le problème
&lt;/h2&gt;&lt;p&gt;Après avoir vérifié qu’aucun backup n’était encore actif, j’ai lancé manuellement le nouveau job de &lt;code&gt;pve-dell&lt;/code&gt;. La sauvegarde complète s’est terminée en 43 secondes, avec des transferts ramenés autour de 80 à 104 Mio/s.&lt;/p&gt;
&lt;p&gt;Sur ce passage, les logs ont compté cinq retries AIO, contre 22 pendant la fenêtre globale précédente. La latence commit Ceph a culminé à 47 ms, puis les 129 groupes de placement sont restés &lt;code&gt;active+clean&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Cette comparaison reste indicative. Le PoC était fortement dédupliqué et un seul passage ne remplace pas plusieurs jours de métriques. Il a toutefois validé deux points utiles : le plafond était réellement appliqué et l’étalement réduisait déjà la violence de la pointe.&lt;/p&gt;
&lt;p&gt;Le cluster n’est pas devenu parfait pour autant. Ceph continue ponctuellement de remonter un &lt;code&gt;HEALTH_WARN&lt;/code&gt; pour des opérations BlueStore lentes. Les trois OSD sont toujours des SSD grand public sans protection contre les coupures de courant, et le P3 Plus en QLC reste le maillon qui m’inspire le moins confiance sous charge soutenue. La &lt;a class="link" href="https://docs.ceph.com/en/squid/start/hardware-recommendations/" target="_blank" rel="noopener"
&gt;documentation matérielle de Ceph&lt;/a&gt; rappelle justement que les SSD clients peuvent voir leurs performances s’effondrer une fois leur cache épuisé, là où les modèles entreprise apportent notamment la protection contre les pertes d’alimentation.&lt;/p&gt;
&lt;p&gt;Au moment où j’écris ces lignes, je prévois donc encore de remplacer progressivement les deux SSD les plus irréguliers, en commençant par celui de &lt;code&gt;pve-fuji&lt;/code&gt;. Mais ce sera une amélioration matérielle posée sur une charge déjà mieux organisée, pas un achat destiné à masquer le symptôme.&lt;/p&gt;
&lt;h2 id="ce-que-jen-retiens"&gt;Ce que j’en retiens
&lt;/h2&gt;&lt;p&gt;Je suis parti d’une question sur WPQ et de l’idée, un peu coûteuse, d’ajouter un quatrième nœud. La première amélioration utile a finalement tenu dans trois horaires et une limite de débit.&lt;/p&gt;
&lt;p&gt;Le plus intéressant n’est pas que 100 Mio/s soit une valeur magique — elle ne l’est pas. C’est d’avoir trouvé le rythme réel du problème avant de toucher au scheduler ou au matériel. Les ralentissements revenaient toutes les deux heures parce que mes backups revenaient toutes les deux heures. Une fois la corrélation posée noir sur blanc, la solution est devenue beaucoup moins mystérieuse.&lt;/p&gt;
&lt;p&gt;Pour ceux qui se demandent déjà vers quoi je compte me tourner, je remplacerais progressivement les SSD concernés par des &lt;a class="link" href="https://www.amazon.fr/gp/product/B0B9C4DKKG/ref=ox_sc_act_title_1?smid=A1X6FK5RDHNB96&amp;amp;th=1" target="_blank" rel="noopener"
&gt;Samsung 990 PRO 2 To, référence &lt;code&gt;MZ-V9P2T0BW&lt;/code&gt;&lt;/a&gt;. Cela reste du matériel grand public, pas l’équivalent d’un NVMe datacenter avec protection contre les coupures, mais c’est le compromis que je retiendrais aujourd’hui pour mon homelab.&lt;/p&gt;
&lt;p&gt;Je vais maintenant laisser tourner cette configuration, comparer plusieurs fenêtres de sauvegarde et observer si les futurs SSD changent encore le profil des latences. Le quatrième PVE, lui, peut rester pour l’instant dans la boutique.&lt;/p&gt;</description></item><item><title>J’ai doublé mon firewall pour pouvoir en éteindre un</title><link>https://blog.homeblack.fr/p/opnsense-ha-carp-fw-core-p1-fw-core-p2/</link><pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate><guid>https://blog.homeblack.fr/p/opnsense-ha-carp-fw-core-p1-fw-core-p2/</guid><description>&lt;img src="https://blog.homeblack.fr/p/opnsense-ha-carp-fw-core-p1-fw-core-p2/cover.png" alt="Featured image of post J’ai doublé mon firewall pour pouvoir en éteindre un" /&gt;&lt;p&gt;Mon premier OPNsense fonctionnait très bien. C’était justement le problème.&lt;/p&gt;
&lt;p&gt;Tout le cœur du réseau reposait sur &lt;code&gt;fw-core-p1&lt;/code&gt; : le LAN, huit VLANs, l’accès Internet et les routes entre mes différentes zones. Tant que la VM tournait, je n’avais aucune raison d’y penser. Dès qu’une mise à jour demandait un redémarrage, la question revenait : qu’est-ce qui reste accessible si ce firewall s’arrête ?&lt;/p&gt;
&lt;p&gt;Pas grand-chose.&lt;/p&gt;
&lt;p&gt;Je ne cherchais pas à transformer mon homelab en infrastructure bancaire. Je voulais simplement pouvoir maintenir un firewall sans couper volontairement tout ce qui passait derrière lui. C’est comme ça que &lt;code&gt;fw-core-p2&lt;/code&gt; est arrivé.&lt;/p&gt;
&lt;h2 id="une-seconde-vm-ne-fait-pas-encore-un-cluster"&gt;Une seconde VM ne fait pas encore un cluster
&lt;/h2&gt;&lt;p&gt;Le plus facile aurait été de cloner &lt;code&gt;fw-core-p1&lt;/code&gt;, de démarrer la copie et d’appeler ça de la haute disponibilité. Deux firewalls mal coordonnés savent surtout produire deux fois plus de problèmes.&lt;/p&gt;
&lt;p&gt;J’ai donc commencé par leur donner la même forme. Les deux VM vivent sur deux nœuds Proxmox différents et possèdent exactement le même ordre d’interfaces : le WAN, le LAN, les huit VLANs du homelab, puis une dernière interface réservée à la synchronisation.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pve-forum pve-fuji
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fw-core-p1 fw-core-p2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; MASTER ─── VLAN 999 SYNC ─── BACKUP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ pfsync │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ XML-RPC │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └────── 9 VIP CARP partagées ──┘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Cette symétrie n’est pas seulement jolie dans Terraform. &lt;code&gt;pfsync&lt;/code&gt; associe les états aux interfaces : si leur ordre ou leur nom diffère entre les deux machines, la réplication ne raconte plus la même histoire des deux côtés.&lt;/p&gt;
&lt;h2 id="carp-pfsync-et-xml-rpc-ne-font-pas-le-même-travail"&gt;CARP, pfsync et XML-RPC ne font pas le même travail
&lt;/h2&gt;&lt;p&gt;J’avais tendance à ranger tout cela dans la boîte « HA ». En pratique, trois mécanismes distincts coopèrent.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CARP&lt;/strong&gt; (&lt;em&gt;Common Address Redundancy Protocol&lt;/em&gt;) détermine quel firewall porte les adresses IP virtuelles. Les machines du réseau utilisent ces VIP comme passerelles et n’ont pas besoin de savoir si &lt;code&gt;p1&lt;/code&gt; ou &lt;code&gt;p2&lt;/code&gt; répond derrière.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;pfsync&lt;/strong&gt; réplique la table d’états. Quand &lt;code&gt;p2&lt;/code&gt; reprend le trafic, il connaît déjà les connexions suivies par &lt;code&gt;p1&lt;/code&gt; au lieu de repartir avec une feuille blanche.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;XML-RPC&lt;/strong&gt; synchronise la configuration depuis le primaire : règles, alias, NAT et objets partagés. Le second nœud reste ainsi un vrai pair, pas une vieille copie que j’espère encore correcte six mois plus tard.&lt;/p&gt;
&lt;p&gt;La &lt;a class="link" href="https://docs.opnsense.org/manual/how-tos/carp.html" target="_blank" rel="noopener"
&gt;documentation HA d’OPNsense&lt;/a&gt; recommande justement une interface dédiée à &lt;code&gt;pfsync&lt;/code&gt;. J’ai appliqué ce principe avec le VLAN 999, utilisé également pour la synchronisation de configuration.&lt;/p&gt;
&lt;p&gt;Dans Terraform, ce choix tient dans quelques lignes :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-hcl" data-lang="hcl"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# vtnet10 -&amp;gt; SYNC (pfsync + xmlrpc HA)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;network_device&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; bridge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;fw_core_lan_bridge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; vlan_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;fw_core_sync_vlan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;virtio&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Ce petit &lt;code&gt;vtnet10&lt;/code&gt; est pourtant l’une des pièces les plus importantes du montage. Le trafic utilisateur et les échanges qui permettent au cluster de rester cohérent ne se disputent pas la même interface logique.&lt;/p&gt;
&lt;h2 id="le-moment-où-neuf-vip-ont-changé-de-côté"&gt;Le moment où neuf VIP ont changé de côté
&lt;/h2&gt;&lt;p&gt;Une interface verte dans OPNsense ne prouve pas grand-chose. Le cluster est devenu réel le jour où j’ai placé &lt;code&gt;fw-core-p1&lt;/code&gt; en maintenance et regardé &lt;code&gt;fw-core-p2&lt;/code&gt; reprendre les neuf VIP.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fw-core-p1 : BACKUP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fw-core-p2 : MASTER
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VIP CARP : 9/9 sur p2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Le DNS continuait de répondre et mes routes applicatives restaient accessibles. En quittant le mode maintenance, &lt;code&gt;p1&lt;/code&gt; a repris son rôle par préemption et &lt;code&gt;p2&lt;/code&gt; est retourné attendre en secours.&lt;/p&gt;
&lt;p&gt;C’est un test très simple, mais il change complètement la confiance que j’accorde au montage. Avant lui, j’avais deux VM configurées pour faire du CARP. Après lui, j’avais un cluster que je pouvais réellement utiliser pendant une intervention.&lt;/p&gt;
&lt;h2 id="la-haute-disponibilité-synchronise-aussi-les-erreurs"&gt;La haute disponibilité synchronise aussi les erreurs
&lt;/h2&gt;&lt;p&gt;Le piège le plus intéressant est arrivé plus tard. Une VIP utilisait un pair CARP unicast propre à &lt;code&gt;p1&lt;/code&gt;. XML-RPC a parfaitement synchronisé cette valeur vers &lt;code&gt;p2&lt;/code&gt;, qui s’est alors mis à envoyer ses annonces… à sa propre adresse.&lt;/p&gt;
&lt;p&gt;La synchronisation n’était pas cassée. Elle exécutait fidèlement une configuration qui n’aurait pas dû être identique sur les deux nœuds.&lt;/p&gt;
&lt;p&gt;J’ai raconté cette petite surprise dans &lt;a class="link" href="https://blog.homeblack.fr/p/revision-cluster-opnsense/" &gt;ma révision du cluster OPNsense&lt;/a&gt;. Elle m’a rappelé qu’un cluster ne rend pas une configuration correcte par magie. Il propage aussi très efficacement les mauvaises idées.&lt;/p&gt;
&lt;p&gt;Le retour au multicast CARP a supprimé cette exception locale et rendu les deux configurations réellement partageables. Depuis, mon test ne consiste plus seulement à vérifier que les deux firewalls affichent du vert : je provoque la bascule et je contrôle ce qui continue à fonctionner.&lt;/p&gt;
&lt;h2 id="ce-que-ce-second-firewall-a-réellement-changé"&gt;Ce que ce second firewall a réellement changé
&lt;/h2&gt;&lt;p&gt;Je n’ai pas supprimé tous les points de panne. Les deux VM dépendent toujours du réseau physique, des bridges Proxmox et de ce qui se trouve en amont. La haute disponibilité du firewall ne rend pas magiquement le reste du homelab redondant.&lt;/p&gt;
&lt;p&gt;Elle a en revanche retiré un blocage très concret : je peux éteindre un OPNsense sans considérer la coupure comme une étape normale de la maintenance.&lt;/p&gt;
&lt;p&gt;Le bénéfice n’est pas spectaculaire quand tout va bien. &lt;code&gt;fw-core-p2&lt;/code&gt; passe l’essentiel de son temps en BACKUP, ce qui est exactement ce que je lui demande. Sa valeur apparaît quand je mets à jour &lt;code&gt;p1&lt;/code&gt;, quand je redémarre une VM ou quand je veux vérifier une modification sans jouer toute la connectivité du homelab sur un seul clic.&lt;/p&gt;
&lt;p&gt;Au fond, j’ai doublé mon firewall pour pouvoir enfin en éteindre un sereinement. C’était tout le projet.&lt;/p&gt;</description></item></channel></rss>