<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ceph on Mook’s Lab Chronicles</title><link>https://blog.homeblack.fr/tags/ceph/</link><description>Recent content in Ceph on Mook’s Lab Chronicles</description><generator>Hugo -- gohugo.io</generator><language>fr-FR</language><lastBuildDate>Fri, 14 Aug 2026 12:40:31 +0200</lastBuildDate><atom:link href="https://blog.homeblack.fr/tags/ceph/index.xml" rel="self" type="application/rss+xml"/><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>12 Mo de SQLite, 28 Go d’écritures par jour : le piège des Query Logs de Technitium</title><link>https://blog.homeblack.fr/p/technitium-query-logs-sqlite/</link><pubDate>Thu, 30 Jul 2026 11:00:00 +0200</pubDate><guid>https://blog.homeblack.fr/p/technitium-query-logs-sqlite/</guid><description>&lt;img src="https://blog.homeblack.fr/p/technitium-query-logs-sqlite/cover.png" alt="Featured image of post 12 Mo de SQLite, 28 Go d’écritures par jour : le piège des Query Logs de Technitium" /&gt;&lt;p&gt;Ma VM DNS écrivait près de 28 Go par jour sur Ceph. Avec un tel chiffre, je m’attendais à trouver un volume anormal de requêtes, un service bavard ou un buffer Vector qui débordait.&lt;/p&gt;
&lt;p&gt;La réalité tenait dans une base SQLite de 12 Mo.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;trust-dns-01&lt;/code&gt; résout environ deux à trois requêtes par seconde. Ce n’est ni une attaque ni une charge impressionnante. Pourtant, le stockage travaillait suffisamment pour que la VM passe bien plus de temps à attendre ses entrées-sorties qu’à calculer.&lt;/p&gt;
&lt;h2 id="le-dns-nétait-pas-débordé"&gt;Le DNS n’était pas débordé
&lt;/h2&gt;&lt;p&gt;Le 30 juillet 2026, j’ai repris les métriques sur les dernières 24 heures et l’état réel de la machine :&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mesure&lt;/th&gt;
&lt;th style="text-align: right"&gt;Valeur observée&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;trafic DNS&lt;/td&gt;
&lt;td style="text-align: right"&gt;environ 2,5 requêtes/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU actif, hors attente I/O&lt;/td&gt;
&lt;td style="text-align: right"&gt;6,3 % en moyenne&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;attente I/O (&lt;em&gt;iowait&lt;/em&gt;)&lt;/td&gt;
&lt;td style="text-align: right"&gt;29,1 % en moyenne&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;données écrites sur le disque&lt;/td&gt;
&lt;td style="text-align: right"&gt;27,89 Go en 24 h&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;occupation du disque&lt;/td&gt;
&lt;td style="text-align: right"&gt;8,8 Go sur 20 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;La nuance entre CPU actif et &lt;em&gt;iowait&lt;/em&gt; est importante. Un graphique calculé simplement comme &lt;code&gt;100 - idle&lt;/code&gt; donne l’impression que le processeur est occupé à 35 %. En réalité, sur cette VM limitée à un vCPU, près de 29 points correspondent au temps passé à attendre le stockage.&lt;/p&gt;
&lt;p&gt;Le serveur DNS lui-même ne manque donc pas de puissance. Il attend surtout Ceph.&lt;/p&gt;
&lt;h2 id="une-petite-base-qui-réécrit-sans-arrêt"&gt;Une petite base qui réécrit sans arrêt
&lt;/h2&gt;&lt;p&gt;Technitium possède une application nommée &lt;code&gt;Query Logs (Sqlite)&lt;/code&gt;. Elle permet de retrouver précisément quel client a demandé quel domaine, à quelle heure et avec quelle réponse.&lt;/p&gt;
&lt;p&gt;Sur mon instance, sa configuration contient notamment :&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;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&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-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;enableLogging&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;maxLogDays&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;maxLogRecords&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;enableVacuum&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;useInMemoryDb&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;sqliteDbPath&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;querylogs.db&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&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;La base fait environ 12 Mo et conserve autour de 10 000 entrées. Pendant une vérification, elle contenait 12 102 lignes couvrant un peu plus de 80 minutes, soit environ 2,5 requêtes par seconde.&lt;/p&gt;
&lt;p&gt;Ce léger dépassement est normal : le plafond n’est pas appliqué à chaque insertion. Le nettoyage se déclenche toutes les quinze minutes. Entre deux passages, la table continue de grossir.&lt;/p&gt;
&lt;p&gt;Dit comme cela, rien d’inquiétant. Le détail qui change tout se trouve dans les réglages effectifs de SQLite :&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;/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;journal_mode = delete
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;synchronous = 2
&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 &lt;code&gt;2&lt;/code&gt; correspond au mode &lt;code&gt;FULL&lt;/code&gt;. Avec le journal &lt;code&gt;DELETE&lt;/code&gt;, SQLite crée un journal de rollback pour la transaction, synchronise les données, puis supprime le journal une fois le commit terminé. Ces choix privilégient la durabilité, comme l’explique la &lt;a class="link" href="https://sqlite.org/pragma.html#pragma_journal_mode" target="_blank" rel="noopener"
&gt;documentation officielle de SQLite sur les modes de journalisation&lt;/a&gt; et la &lt;a class="link" href="https://sqlite.org/pragma.html#pragma_synchronous" target="_blank" rel="noopener"
&gt;synchronisation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ici, chaque nouvelle requête ajoute une ligne et met à jour treize index en plus de la clé primaire. L’application consomme les requêtes disponibles sans attendre de remplir un gros lot ; à faible trafic, elle peut donc committer très peu de lignes à la fois. Lorsque la limite est dépassée, les anciennes lignes sont aussi supprimées. La base reste petite, mais elle tourne en permanence : insertions, index, suppressions, journal, synchronisations.&lt;/p&gt;
&lt;p&gt;Sur un disque local, cette activité passerait probablement inaperçue. Sur un stockage distribué comme Ceph, une succession de petites écritures synchrones coûte beaucoup plus cher que sa taille apparente. Le fichier &lt;code&gt;querylogs.db-journal&lt;/code&gt;, présent et ouvert pendant le diagnostic, était le petit témoin de cette mécanique.&lt;/p&gt;
&lt;p&gt;Deux mesures supplémentaires renforcent le diagnostic : le compteur du processus Technitium indiquait environ 15,5 Go écrits en 23 heures et, sur un échantillon de quinze secondes, 32 nouvelles requêtes ont accompagné 2,97 Mo d’écritures processus.&lt;/p&gt;
&lt;p&gt;Je garde tout de même une réserve : Technitium écrit aussi ses statistiques et ses journaux, tandis que la métrique des 27,89 Go couvre toute la VM. Query Logs est la cause principale la mieux étayée, mais la preuve définitive viendra de la comparaison sur 24 heures après sa désactivation. Sans cet avant/après, lui attribuer chaque octet serait aller un peu vite.&lt;/p&gt;
&lt;h2 id="lespace-disque-racontait-une-autre-histoire"&gt;L’espace disque racontait une autre histoire
&lt;/h2&gt;&lt;p&gt;L’amplification d’écriture n’explique pas à elle seule les 8,8 Go déjà occupés. Les plus gros consommateurs évitables étaient ailleurs :&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Données&lt;/th&gt;
&lt;th style="text-align: right"&gt;Taille observée&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;sauvegardes Technitium&lt;/td&gt;
&lt;td style="text-align: right"&gt;3,7 Gio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;statistiques DNS&lt;/td&gt;
&lt;td style="text-align: right"&gt;568 Mio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;journaux systemd&lt;/td&gt;
&lt;td style="text-align: right"&gt;623 Mio&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Le script de sauvegarde actuel supprime les archives âgées de plus de 30 jours. Cela laisse tout de même 36 fichiers, car une sauvegarde quotidienne pèse désormais entre 100 et 123 Mo et quelques sauvegardes manuelles s’ajoutent au lot.&lt;/p&gt;
&lt;p&gt;Ce sont donc deux problèmes distincts :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Query Logs use le stockage avec beaucoup de petites écritures ;&lt;/li&gt;
&lt;li&gt;les sauvegardes, statistiques et journaux consomment réellement l’espace disponible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Supprimer la base SQLite ne libérerait qu’une douzaine de mégaoctets. Pour faire maigrir la VM, il faut aussi agir sur les rétentions.&lt;/p&gt;
&lt;h2 id="garder-les-requêtes-sans-garder-sqlite"&gt;Garder les requêtes, sans garder SQLite
&lt;/h2&gt;&lt;p&gt;Ma première idée était de désactiver complètement les journaux détaillés et de conserver seulement les statistiques agrégées dans Grafana. C’était efficace, mais je perdais une fonction à laquelle je tiens : pouvoir rechercher les requêtes DNS dans VictoriaLogs.&lt;/p&gt;
&lt;p&gt;Le compromis que je prépare est donc le suivant :&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;/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;Technitium Log Exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓ HTTP local
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Vector
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓ NDJSON compressé
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; VictoriaLogs
&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;L’application officielle &lt;a class="link" href="https://github.com/TechnitiumSoftware/DnsServer/tree/master/Apps/LogExporterApp" target="_blank" rel="noopener"
&gt;Log Exporter de Technitium&lt;/a&gt; peut expédier les requêtes par HTTP ou Syslog sans les écrire dans un fichier local. Vector recevra les lots en mémoire, extraira les champs utiles — client, nom demandé, type, code de réponse et temps de traitement — puis les enverra vers VictoriaLogs.&lt;/p&gt;
&lt;p&gt;Vector n’est pas seulement là pour faire joli au milieu du schéma. Le sink HTTP utilisé par Technitium produit des lots JSON enveloppés par Serilog, alors que l’endpoint &lt;code&gt;/insert/jsonline&lt;/code&gt; de VictoriaLogs attend &lt;a class="link" href="https://docs.victoriametrics.com/victorialogs/data-ingestion/#json-stream-api" target="_blank" rel="noopener"
&gt;un objet JSON par ligne&lt;/a&gt;. Il faut donc convertir et normaliser les événements.&lt;/p&gt;
&lt;p&gt;Je préfère un buffer mémoire borné pour ce flux. Cela évite de recréer une nouvelle source d’écritures locales, au prix d’un compromis assumé : une panne ou un redémarrage peut faire perdre quelques requêtes. Pour mon homelab, la visibilité opérationnelle compte davantage qu’une conservation forensique parfaitement exhaustive.&lt;/p&gt;
&lt;p&gt;Ces données restent sensibles. Une suite de requêtes DNS raconte rapidement les habitudes d’un réseau. Les noms demandés et les adresses clientes resteront des champs recherchables, mais pas des champs de &lt;em&gt;stream&lt;/em&gt; à forte cardinalité, et leur accès devra être plus restreint que celui des journaux système ordinaires.&lt;/p&gt;
&lt;h2 id="la-suite-avec-un-vrai-avantaprès"&gt;La suite, avec un vrai avant/après
&lt;/h2&gt;&lt;p&gt;Au moment où j’écris ces lignes, aucune modification de production n’a encore été appliquée. Le déploiement suivra volontairement plusieurs étapes :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;activer Log Exporter et le flux Vector tout en gardant temporairement SQLite ;&lt;/li&gt;
&lt;li&gt;comparer les événements pendant 30 à 60 minutes ;&lt;/li&gt;
&lt;li&gt;mesurer pendant 24 à 72 heures le volume ingéré, la RAM et les écritures Ceph ;&lt;/li&gt;
&lt;li&gt;désactiver Query Logs SQLite seulement après cette validation.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Je conserverai ensuite la base quelques jours comme possibilité de retour arrière. Si les écritures chutent comme prévu, j’aurai enfin le chiffre qui manque à ce diagnostic : le gain réel, pas seulement le coupable le plus crédible.&lt;/p&gt;
&lt;p&gt;Je pensais devoir redimensionner un serveur DNS. En réalité, il fallait surtout l’empêcher de tenir son journal intime sur Ceph.&lt;/p&gt;</description></item></channel></rss>