Share Notes

chundev

View the Project on GitHub latteouka/share-notes

跨層除錯 Nutanix VM 偶發 read-only:從 SATA reset 追到 Cassandra GC

日期:2026-05-12

環境:Nutanix AHV cluster(7 nodes),Ubuntu 18.04 guest VMs,AOS 6.10.1.5


TL;DR

一群 VM 每隔幾週就會 ext4 變 read-only 需要 fsck,使用者以為是「隨機事件」。 逐層追下去發現完整因果鏈:Cassandra heap 累積 → CMS GC 1.5-2 秒 stop-the-world → ZK session timeout → Stargate FATAL → guest SATA NCQ 寫入卡 30 秒 → kernel hard reset link → partial write 沒落地 → ext4 metadata 不一致。 規律是每週六晚 20:00 後(不是隨機,使用者沒注意到時間 pattern)。


背景

Cluster 上有一批從同一個 snapshot 多次 clone 出來的 Linux VM,跑分散式 DB / search / message queue。 使用者觀察:特定幾台高寫入 VM 反覆出現 ext4 read-only,必須 fsck 才能修復,頻率每 1-2 週一次,「看不出規律」。

直接的症狀只在 guest 看得到,所以一開始的調查方向偏向 guest OS 或 VM 配置。但這是個跨多層的問題,單看一層永遠看不到全貌。


問題 / 錯誤訊息

Guest 端 dmesg 看到 SATA NCQ 集體 timeout 後硬重置:

ata3.00: exception Emask 0x0 SAct 0x1b SErr 0x0 action 0x6 frozen
ata3.00: failed command: WRITE FPDMA QUEUED
ata3.00:   cmd 61/08:00:f0:c3:38/00:00:02:00:00/40 tag 0 ncq dma 4096 out
            res 40/00:00:00:00:00/00:00:00:00:00/00 Emask 0x4 (timeout)
ata3.00: failed command: WRITE FPDMA QUEUED  (× 多筆同類型)
ata3: hard resetting link
ata3: SATA link up 1.5 Gbps (SStatus 113 SControl 300)
ata3: EH complete

CVM 端 Stargate 同時段 FATAL:

F20260509 12:57:47 zeus.cc:2573]
  QFATAL Timed out waiting for Zookeeper session establishment

Cassandra 在 FATAL 前 26 秒看到 gossip 落差:

W 2026-05-09 12:57:21 TokenMetadata.java:
  We last received a heartbeat 9211 ms ago.
  Recent reads may not be leader-only reads

除錯過程

嘗試 / 觀察 動作 收穫
❌ 看 guest log 只看 dmesg 只看到 SATA reset,看不出觸發源
❌ 問使用者規律 使用者初判「隨機」 後來實際是每週六晚 20:40-21:00
❌ 假設外部備份 查 NFS whitelist 那個 IP 該 IP 已停用,無外部寫入
❌ 假設 cron 全 CVM + AHV host + VM 內 crontab 都看 沒有週六排程
❌ 假設 PD snapshot PD daily 在 22:00 CST 比事件晚 1 小時,不是主因
✅ Stargate FATAL log grep QFATAL 找到 Zookeeper session establishment timeout
✅ Cassandra system.log grep TokenMetadata heartbeat 9.2 秒沒收到 heartbeat — 找到 GC 嫌疑
✅ GCInspector log grep ConcurrentMarkSweep 每幾天就有一次 1.5-2 秒 STW GC
✅ vdisk_config_printer 查中招 VM 的 vdisk chain chain depth 7-14,全部 4.5 年前的同一個 root vdisk

根因 — 完整因果鏈

[UPSTREAM] Cassandra heap 累積(cluster metadata 物件多)
                    │
                    ▼
[GC] CMS Old Gen 1.3-1.6 GB → 觸發 CMS GC 1.5-2 秒 STW
                    │
                    ▼
[TRIGGER] 多 CVM 同時段 GC → gossip heartbeat 落差 8-9 秒
                    │
                    ▼
[CASCADE] Cassandra Paxos read timeout → ZK session expire
                    │
                    ▼
[FAILURE] Stargate / 多個 service 同時 FATAL
                    │
                    ▼
[GUEST SYMPTOM] VM I/O hang 30+ 秒
                    │
                    ▼
[AMP 1] clone vdisk with parent_chain → 寫入要查 parent metadata(雪上加霜)
                    │
                    ▼
[AMP 2] SATA NCQ 單 queue → 一個指令卡住,整條 queue freeze
                    │
                    ▼
[OUTCOME] kernel `ata*: hard resetting link` → in-flight write 丟失
                    │
                    ▼
[LONG TAIL] 部分 write 沒 sync → ext4 metadata 不一致
                    │
                    ▼
[CLEANUP] fs 設 RO + 需 fsck,或事件後 metadata drift 持續累積

為什麼每週六晚 20:40 觸發:cluster metadata 累積到某個臨界值後,每週六晚的某個 cluster-wide event(精確 trigger 尚未鎖定,可能是內部 maintenance task)會把 GC 推到 cascade。weekday 雖然也會有 1.5-2 秒 GC,但沒達到觸發 cascade 的閾值。


解法 / 核心知識

不修上游 (Cassandra GC) 也能止血,因為 fix 從「放大器」入手:

三層 defense

解法 效果
Amp 1 (clone parent_chain) vm.disk_create clone_from_vmdisk 建立全新 fully-populated vmdisk,消除 metadata 鎖定 寫入路徑少一層 metadata 查詢
Amp 2 (SATA single queue) Disk bus 從 SATA → virtio-scsi(multi-queue,128+ depth) 一條 queue 卡住,其他 queue 還能服務
Defense in depth SCSI timeout 從 30 → 180 秒 給底層 storage 充足時間恢復,不誤判 controller 死掉

bus change 動作本身一個指令同時解決 Amp 1 + Amp 2(建新 vmdisk 順便 inflate)。

上游修不修?

仍需要修,但不阻塞下游 fix:

下游 fix 後,即使週六 GC 又把 ZK 推爆,guest 也撐得住(不會 RO + fsck)。


學到的事

  1. 使用者說「隨機」前先自己對時間 grep。dmesg 跟 cluster log 一對齊,每週六同時段這件事一秒就看到。使用者對時間規律的感知有時候要靠數據幫他/她發現
  2. 跨層問題 = 跨層證據:guest dmesg + CVM Stargate FATAL + Cassandra system.log + ZK monitor.ERROR + vdisk metadata,任何一層單看都會誤判。要把時間軸對齊後一起讀
  3. emulated SATA 的「hard reset」在虛擬化環境是 over-reaction:實體硬碟卡住 reset 是救命,虛擬 storage 卡住 reset 是丟資料。詳見 virtio-scsi vs emulated SATA 深入
  4. clone vdisk 的 parent_chain 是隱性風險:從 snapshot clone 出來的 VM 寫入時要走 metadata lookup 比 fresh vdisk 多一層,平時無感,metadata layer 慢的時候就放大
  5. fsck 是壞,但常常是症狀不是病因。看到 fsck 不要急著 tune ext4,往儲存層走

參考資料

接續閱讀: