<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>Strafo - cloudnativepg</title>
      <link>https://strafo.net</link>
      <description>Personal blog of a cat disguised as a human</description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://strafo.net/tags/cloudnativepg/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Thu, 22 Oct 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>My homelab&#x27;s first real outage, and why the fix took 5 minutes</title>
          <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
          <author>Andrea Straforini</author>
          <link>https://strafo.net/blog/longhorn-disk-failure/</link>
          <guid>https://strafo.net/blog/longhorn-disk-failure/</guid>
          <description xml:base="https://strafo.net/blog/longhorn-disk-failure/">&lt;p&gt;My homelab&#x27;s first serious hardware failure: a disk that died slowly and quietly under a Kubernetes worker. It&#x27;s the outage I&#x27;d been preparing for, and it felt great to see all that SRE work pay off. 🎉&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;post-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Date:&lt;&#x2F;strong&gt; 2026-10-22 (all times CEST)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Duration:&lt;&#x2F;strong&gt; 22:03–23:05&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Root cause:&lt;&#x2F;strong&gt; bad sectors on the USB hard drive behind worker-node2&#x27;s Longhorn disk&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Fix:&lt;&#x2F;strong&gt; 5 minutes, from the disk swap at 22:30 to services back at 22:35&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Data loss:&lt;&#x2F;strong&gt; none&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;impact&quot;&gt;Impact&lt;a class=&quot;post-anchor&quot; href=&quot;#impact&quot; aria-label=&quot;Anchor link for: impact&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;What&lt;&#x2F;th&gt;&lt;th&gt;Down&lt;&#x2F;th&gt;&lt;th&gt;Effect&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;worker-node2&lt;&#x2F;td&gt;&lt;td&gt;22:03–22:31, 22:51–22:58&lt;&#x2F;td&gt;&lt;td&gt;Paused in &lt;code&gt;io-error&lt;&#x2F;code&gt;; later a network drop&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Apps on node2 (Jellyfin, *arr, …)&lt;&#x2F;td&gt;&lt;td&gt;22:03–22:35, 22:51–23:05&lt;&#x2F;td&gt;&lt;td&gt;Stuck Pending: node1 alone lacks the CPU&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Postgres standby&lt;&#x2F;td&gt;&lt;td&gt;22:03–22:47&lt;&#x2F;td&gt;&lt;td&gt;Only replica lost; rebuilt from the primary&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Cloudflare tunnel (LXC)&lt;&#x2F;td&gt;&lt;td&gt;22:30–22:55&lt;&#x2F;td&gt;&lt;td&gt;Disk on the same drive; recreated&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Longhorn volumes&lt;&#x2F;td&gt;&lt;td&gt;22:03–23:05&lt;&#x2F;td&gt;&lt;td&gt;Degraded, served from node1&#x27;s copies&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;background&quot;&gt;Background&lt;a class=&quot;post-anchor&quot; href=&quot;#background&quot; aria-label=&quot;Anchor link for: background&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Each Kubernetes worker is a Proxmox VM with a second, 128 GB disk at &lt;code&gt;&#x2F;mnt&#x2F;data&lt;&#x2F;code&gt; for Longhorn replicas. Most volumes keep one replica per worker; CloudNativePG volumes keep one in total, since CNPG replicates itself. worker-node2&#x27;s data disk sat on &lt;code&gt;external-lvm&lt;&#x2F;code&gt;, a thin pool on a &lt;strong&gt;1 TB 2.5&quot; USB hard drive&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;timeline&quot;&gt;Timeline&lt;a class=&quot;post-anchor&quot; href=&quot;#timeline&quot; aria-label=&quot;Anchor link for: timeline&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;figure style=&quot;width: min(1100px, 96vw); position: relative; left: 50%; transform: translateX(-50%); margin-left: 0; margin-right: 0;&quot;&gt;
&lt;svg viewBox=&quot;0 0 900 470&quot; width=&quot;100%&quot; role=&quot;img&quot; aria-label=&quot;Outage timeline: backups failing silently from Sep 5; disk errors on worker-node2 from 18:00; the node went NotReady at 22:03; the disk was swapped at 22:30, the node froze again at 22:51 and everything was healthy at 23:05&quot; style=&quot;color: var(--text-color); font-size: 16px;&quot;&gt;
  &lt;g fill=&quot;currentColor&quot; fill-opacity=&quot;0.05&quot;&gt;
    &lt;rect x=&quot;185&quot; y=&quot;72&quot; width=&quot;145&quot; height=&quot;264&quot;&#x2F;&gt;
    &lt;rect x=&quot;350&quot; y=&quot;72&quot; width=&quot;530&quot; height=&quot;264&quot;&#x2F;&gt;
  &lt;&#x2F;g&gt;
  &lt;g fill=&quot;currentColor&quot; font-weight=&quot;bold&quot;&gt;
    &lt;text x=&quot;257.5&quot; y=&quot;24&quot; text-anchor=&quot;middle&quot;&gt;Weeks before&lt;&#x2F;text&gt;
    &lt;text x=&quot;615&quot; y=&quot;24&quot; text-anchor=&quot;middle&quot;&gt;Oct 22, night&lt;&#x2F;text&gt;
  &lt;&#x2F;g&gt;
  &lt;g fill=&quot;currentColor&quot; fill-opacity=&quot;0.7&quot; font-size=&quot;14&quot;&gt;
    &lt;text x=&quot;185&quot; y=&quot;60&quot;&gt;Sep 5&lt;&#x2F;text&gt;
    &lt;text x=&quot;330&quot; y=&quot;60&quot; text-anchor=&quot;end&quot;&gt;Oct 22&lt;&#x2F;text&gt;
    &lt;text x=&quot;438.3&quot; y=&quot;60&quot; text-anchor=&quot;middle&quot;&gt;22:00&lt;&#x2F;text&gt;
    &lt;text x=&quot;615&quot; y=&quot;60&quot; text-anchor=&quot;middle&quot;&gt;22:30&lt;&#x2F;text&gt;
    &lt;text x=&quot;791.7&quot; y=&quot;60&quot; text-anchor=&quot;middle&quot;&gt;23:00&lt;&#x2F;text&gt;
  &lt;&#x2F;g&gt;
  &lt;g stroke=&quot;currentColor&quot; stroke-opacity=&quot;0.15&quot;&gt;
    &lt;line x1=&quot;438.3&quot; y1=&quot;72&quot; x2=&quot;438.3&quot; y2=&quot;336&quot;&#x2F;&gt;&lt;line x1=&quot;791.7&quot; y1=&quot;72&quot; x2=&quot;791.7&quot; y2=&quot;336&quot;&#x2F;&gt;
  &lt;&#x2F;g&gt;
  &lt;g fill=&quot;currentColor&quot; text-anchor=&quot;end&quot;&gt;
    &lt;text x=&quot;174&quot; y=&quot;100&quot;&gt;Backups&lt;&#x2F;text&gt;
    &lt;text x=&quot;174&quot; y=&quot;144&quot;&gt;worker-node2&lt;&#x2F;text&gt;
    &lt;text x=&quot;174&quot; y=&quot;188&quot;&gt;Longhorn volumes&lt;&#x2F;text&gt;
    &lt;text x=&quot;174&quot; y=&quot;232&quot;&gt;Apps on node2&lt;&#x2F;text&gt;
    &lt;text x=&quot;174&quot; y=&quot;276&quot;&gt;Postgres standby&lt;&#x2F;text&gt;
    &lt;text x=&quot;174&quot; y=&quot;320&quot;&gt;Cloudflare tunnel&lt;&#x2F;text&gt;
  &lt;&#x2F;g&gt;
  &lt;g fill=&quot;#e0a83a&quot;&gt;
    &lt;rect x=&quot;185&quot; y=&quot;82&quot; width=&quot;145&quot; height=&quot;24&quot; rx=&quot;3&quot;&#x2F;&gt;
    &lt;rect x=&quot;350&quot; y=&quot;126&quot; width=&quot;106&quot; height=&quot;24&quot;&#x2F;&gt;
    &lt;rect x=&quot;456&quot; y=&quot;170&quot; width=&quot;247.3&quot; height=&quot;24&quot; rx=&quot;3&quot;&#x2F;&gt;&lt;rect x=&quot;738.7&quot; y=&quot;170&quot; width=&quot;82.4&quot; height=&quot;24&quot; rx=&quot;3&quot;&#x2F;&gt;
  &lt;&#x2F;g&gt;
  &lt;g fill=&quot;#e5534b&quot;&gt;
    &lt;rect x=&quot;456&quot; y=&quot;126&quot; width=&quot;164.9&quot; height=&quot;24&quot; rx=&quot;3&quot;&#x2F;&gt;&lt;rect x=&quot;738.7&quot; y=&quot;126&quot; width=&quot;41.2&quot; height=&quot;24&quot; rx=&quot;3&quot;&#x2F;&gt;
    &lt;rect x=&quot;456&quot; y=&quot;214&quot; width=&quot;188.4&quot; height=&quot;24&quot; rx=&quot;3&quot;&#x2F;&gt;&lt;rect x=&quot;738.7&quot; y=&quot;214&quot; width=&quot;82.4&quot; height=&quot;24&quot; rx=&quot;3&quot;&#x2F;&gt;
    &lt;rect x=&quot;456&quot; y=&quot;258&quot; width=&quot;259.1&quot; height=&quot;24&quot; rx=&quot;3&quot;&#x2F;&gt;
    &lt;rect x=&quot;615&quot; y=&quot;302&quot; width=&quot;147.2&quot; height=&quot;24&quot; rx=&quot;3&quot;&#x2F;&gt;
  &lt;&#x2F;g&gt;
  &lt;g stroke=&quot;currentColor&quot; stroke-opacity=&quot;0.6&quot; stroke-dasharray=&quot;4 4&quot;&gt;
    &lt;line x1=&quot;456&quot; y1=&quot;72&quot; x2=&quot;456&quot; y2=&quot;346&quot;&#x2F;&gt;&lt;line x1=&quot;715.1&quot; y1=&quot;72&quot; x2=&quot;715.1&quot; y2=&quot;346&quot;&#x2F;&gt;
    &lt;line x1=&quot;615&quot; y1=&quot;72&quot; x2=&quot;615&quot; y2=&quot;368&quot;&#x2F;&gt;&lt;line x1=&quot;821.1&quot; y1=&quot;72&quot; x2=&quot;821.1&quot; y2=&quot;368&quot;&#x2F;&gt;
    &lt;line x1=&quot;738.7&quot; y1=&quot;72&quot; x2=&quot;738.7&quot; y2=&quot;392&quot;&#x2F;&gt;
  &lt;&#x2F;g&gt;
  &lt;g fill=&quot;currentColor&quot; font-size=&quot;14&quot;&gt;
    &lt;text x=&quot;456&quot; y=&quot;360&quot; text-anchor=&quot;middle&quot;&gt;22:03 node2 NotReady&lt;&#x2F;text&gt;
    &lt;text x=&quot;715.1&quot; y=&quot;360&quot; text-anchor=&quot;middle&quot;&gt;22:47 standby ok&lt;&#x2F;text&gt;
    &lt;text x=&quot;615&quot; y=&quot;382&quot; text-anchor=&quot;middle&quot;&gt;22:30 SSD swapped in&lt;&#x2F;text&gt;
    &lt;text x=&quot;821.1&quot; y=&quot;382&quot; text-anchor=&quot;middle&quot;&gt;23:05 healthy&lt;&#x2F;text&gt;
    &lt;text x=&quot;734&quot; y=&quot;404&quot; text-anchor=&quot;end&quot;&gt;22:51 cable knocked&lt;&#x2F;text&gt;
  &lt;&#x2F;g&gt;
  &lt;g font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;
    &lt;rect x=&quot;185&quot; y=&quot;440&quot; width=&quot;18&quot; height=&quot;14&quot; rx=&quot;3&quot; fill=&quot;#e5534b&quot;&#x2F;&gt;&lt;text x=&quot;210&quot; y=&quot;452&quot;&gt;down&lt;&#x2F;text&gt;
    &lt;rect x=&quot;275&quot; y=&quot;440&quot; width=&quot;18&quot; height=&quot;14&quot; rx=&quot;3&quot; fill=&quot;#e0a83a&quot;&#x2F;&gt;&lt;text x=&quot;300&quot; y=&quot;452&quot;&gt;degraded or failing (node2 disk errors since 18:00)&lt;&#x2F;text&gt;
  &lt;&#x2F;g&gt;
&lt;&#x2F;svg&gt;
&lt;&#x2F;figure&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Time&lt;&#x2F;th&gt;&lt;th&gt;Event&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;09-05&lt;&#x2F;td&gt;&lt;td&gt;First failed Proxmox backup of a container on the same drive. No alert.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;09-12&lt;&#x2F;td&gt;&lt;td&gt;First failed Longhorn backup of a volume on node2. No alert.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;about 18:00&lt;&#x2F;td&gt;&lt;td&gt;node2 logs medium errors; ext4 remounts a volume read-only.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;22:03&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;node2 stops responding:&lt;&#x2F;strong&gt; &lt;code&gt;NotReady&lt;&#x2F;code&gt;, VM paused in &lt;code&gt;io-error&lt;&#x2F;code&gt;.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;22:30&lt;&#x2F;td&gt;&lt;td&gt;Disk swapped for a 1 TB SSD; node2 back at 22:31.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;22:35&lt;&#x2F;td&gt;&lt;td&gt;Longhorn rebuilds replicas onto the new disk.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;22:47&lt;&#x2F;td&gt;&lt;td&gt;CloudNativePG rebuilds the standby from the primary.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;22:51&lt;&#x2F;td&gt;&lt;td&gt;pve2&#x27;s Ethernet cable gets knocked while unplugging the old drive; node2 drops out, VM restarted.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;23:05&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;All volumes healthy, all pods running.&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;root-cause&quot;&gt;Root cause&lt;a class=&quot;post-anchor&quot; href=&quot;#root-cause&quot; aria-label=&quot;Anchor link for: root-cause&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The USB drive developed unreadable sectors:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;critical medium error, dev sdb, sector 61086440 op 0x0:(READ)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Longhorn saw these as &lt;code&gt;no data available&lt;&#x2F;code&gt;. Once enough reads failed, QEMU paused the VM and Kubernetes lost the node.&lt;&#x2F;p&gt;
&lt;p&gt;Contributing factors:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Silent backups.&lt;&#x2F;strong&gt; Bad sectors broke backups 40 days before they broke the node, and nothing alerted.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Replicas couldn&#x27;t heal.&lt;&#x2F;strong&gt; Rebuilds onto node1 read from node2 and failed, so the second copy never existed.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;A USB spinning disk under the storage layer.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;detection&quot;&gt;Detection&lt;a class=&quot;post-anchor&quot; href=&quot;#detection&quot; aria-label=&quot;Anchor link for: detection&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Me, noticing Jellyfin was down. Nothing alerted: not the node going &lt;code&gt;NotReady&lt;&#x2F;code&gt;, and none of the earlier signals.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;resolution&quot;&gt;Resolution&lt;a class=&quot;post-anchor&quot; href=&quot;#resolution&quot; aria-label=&quot;Anchor link for: resolution&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;swap-the-disk-keep-every-name&quot;&gt;Swap the disk, keep every name&lt;a class=&quot;post-anchor&quot; href=&quot;#swap-the-disk-keep-every-name&quot; aria-label=&quot;Anchor link for: swap-the-disk-keep-every-name&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;The SSD got the old drive&#x27;s exact layout, so IaC, Proxmox, fstab and Longhorn needed no changes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;qm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; stop&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 202&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;qm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; set&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 202 --delete&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; scsi2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;                    # detach the old data disk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;umount&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; &#x2F;mnt&#x2F;dirstore&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;vgchange&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; -an&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; external-lvm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;vgrename&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; external-lvm external-lvm-old&lt;&#x2F;span&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;       # keep the old drive, don&amp;#39;t wipe it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;pvcreate&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; &#x2F;dev&#x2F;sdc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;vgcreate&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; external-lvm &#x2F;dev&#x2F;sdc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;               # same VG name on the SSD&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;lvcreate&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; -L&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; 128G&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; -n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; dirstore external-lvm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;mkfs.ext4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; -q&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; &#x2F;dev&#x2F;external-lvm&#x2F;dirstore&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;lvcreate&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; -l&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; 99%FREE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; --thinpool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; data external-lvm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;mount&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; &#x2F;mnt&#x2F;dirstore&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;qm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; set&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 202 --scsi2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; external-lvm:128,iothread=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;qm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; start&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 202&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;give-longhorn-the-old-disk-s-identity&quot;&gt;Give Longhorn the old disk&#x27;s identity&lt;a class=&quot;post-anchor&quot; href=&quot;#give-longhorn-the-old-disk-s-identity&quot; aria-label=&quot;Anchor link for: give-longhorn-the-old-disk-s-identity&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Longhorn tracks a disk by &lt;code&gt;longhorn-disk.cfg&lt;&#x2F;code&gt; at its root, so it kept waiting for the old one, and refused to remove it while stale replicas were listed. After deleting the dead replica records:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; &amp;#39;{&amp;quot;diskName&amp;quot;:&amp;quot;default-disk-23c2c7425e81b15d&amp;quot;,&amp;quot;diskUUID&amp;quot;:&amp;quot;&amp;lt;old disk UUID&amp;gt;&amp;quot;,&amp;quot;diskDriver&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;state&amp;quot;:&amp;quot;ready&amp;quot;}&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; tee &#x2F;mnt&#x2F;data&#x2F;longhorn-disk.cfg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Longhorn saw an empty, ready disk and rebuilt every replica from node1. Not an official procedure, but fine on an empty disk.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;let-cloudnativepg-heal-postgres&quot;&gt;Let CloudNativePG heal Postgres&lt;a class=&quot;post-anchor&quot; href=&quot;#let-cloudnativepg-heal-postgres&quot; aria-label=&quot;Anchor link for: let-cloudnativepg-heal-postgres&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Deleting the dead standby&#x27;s PVC and pod was enough; CNPG cloned a new one from the primary.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-went-well&quot;&gt;What went well&lt;a class=&quot;post-anchor&quot; href=&quot;#what-went-well&quot; aria-label=&quot;Anchor link for: what-went-well&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;No data lost on any two-replica volume.&lt;&#x2F;li&gt;
&lt;li&gt;CloudNativePG healed itself.&lt;&#x2F;li&gt;
&lt;li&gt;Same names meant zero IaC changes, and the fix took 5 minutes.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;what-went-wrong&quot;&gt;What went wrong&lt;a class=&quot;post-anchor&quot; href=&quot;#what-went-wrong&quot; aria-label=&quot;Anchor link for: what-went-wrong&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;40 days of failing backups, and nobody listening.&lt;&#x2F;li&gt;
&lt;li&gt;A replica stuck rebuilding looked like redundancy.&lt;&#x2F;li&gt;
&lt;li&gt;Knocking pve2&#x27;s Ethernet cable while unplugging the old drive caused a second, short outage.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;take-home&quot;&gt;Take home&lt;a class=&quot;post-anchor&quot; href=&quot;#take-home&quot; aria-label=&quot;Anchor link for: take-home&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Page on a &lt;code&gt;NotReady&lt;&#x2F;code&gt; node.&lt;&#x2F;strong&gt; A worker gone for more than a few minutes should reach my phone, instead of waiting for me to notice Jellyfin is down.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Alert on failed backups.&lt;&#x2F;strong&gt; A Longhorn or Proxmox backup that fails, or hasn&#x27;t succeeded in a day, should page me. This alone would have caught the disk 40 days early.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Alert on replicas stuck rebuilding.&lt;&#x2F;strong&gt; A replica that never becomes healthy means the source is broken, not that redundancy is on its way.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
    </channel>
</rss>
