chundev
日期:2026-05-12
環境:Nutanix AHV cluster(7 nodes),Ubuntu 18.04 guest VMs,AOS 6.10.1.5
一群 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 從「放大器」入手:
| 層 | 解法 | 效果 |
|---|---|---|
| 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)。
接續閱讀: