KubeVirt Guest CPU / Memory 異常診斷 SOP (Linux & Windows)
本文件提供在 KubeVirt 生產環境下,因資安隔離規範「維運團隊無法登入使用者 VM」時,排查 CPU / Memory 飆高(Peak) 的標準作業程序(SOP)與專用診斷腳本。
背景與問題挑戰
在 KubeVirt 環境中,維運團隊通常只能透過 Prometheus 監控虛擬化層(Hypervisor / cgroup)的指標:
kubevirt_vmi_cpu_usage_seconds_totalkubevirt_vmi_memory_resident_bytes(RSS)kubevirt_vmi_memory_available_bytes(需依賴 Guest Agent)
監控盲點
- 黑盒子問題:虛擬化層指標只能看到 VM「總體」吃了多少 CPU 或 RAM,無法得知 Guest 內部究竟是哪一個行程(PID)、指令行、或是哪位使用者觸發。
- 記憶體誤判:Linux 的 Page Cache 或 Windows 的 Working Set 機制可能使 Hypervisor 觀測到的 RSS 長期維持高檔,但 Guest 內部可用記憶體(Available Memory)實際上仍充裕。
- 無法直接登入:基於資安合規與多租戶權限分離,維運人員無法直接 SSH 或 RDP 進入使用者虛擬機進行
top或檢視工作管理員。
解決方案架構
維運團隊提供免安裝依賴、開箱即用的診斷腳本。當使用者回報資源飆高或觸發監控告警時,請使用者在 VM 內執行腳本,腳本將自動收集瞬間快照與 30 秒動態採樣,並打包成單一壓縮檔回傳。
sequenceDiagram
autonumber
actor User as 使用者 (VM Guest)
participant Script as 診斷腳本
participant Ops as 維運團隊
participant Prom as Prometheus / Grafana
Prom->>Ops: 發出 VMI CPU / Memory Peak 告警
Ops->>User: 提供診斷 SOP 指引,請使用者執行腳本
User->>Script: 執行 collect-*-diag (無外加依賴)
Script->>Script: 收集系統規格、Top 行程、OOM 日誌、30s 動態採樣
Script->>User: 產出壓縮檔案 (.tar.gz / .zip)
User->>Ops: 回傳診斷日誌包
Ops->>Ops: 比對 Prometheus 時間戳與 Guest 行程日誌,定位根因
Linux VM 診斷 SOP
使用者操作步驟
-
下載 / 取得腳本: 在 VM 終端機執行以下指令下載腳本(或手動建立腳本檔案):
-
執行診斷收集: 建議使用
若希望延長動態採樣時間(例如觀察 60 秒),可在後面加上秒數:sudo權限執行,以利完整取得dmesg內核日誌與journalctl系統日誌: -
產出檔案: 腳本執行完畢後會顯示打包檔案路徑:
請使用者將此.tar.gz檔案回傳給維運團隊。
Windows VM 診斷 SOP
使用者操作步驟
-
以系統管理員身分開啟 PowerShell: 按下鍵盤
Win + X,選擇「Windows PowerShell (系統管理員)」或「Terminal (以系統管理員身分執行)」。 -
取得腳本: 在 PowerShell 視窗執行:
-
執行診斷收集: 執行腳本(若遇到執行原則限制,請加入
若希望動態採樣 60 秒:-ExecutionPolicy Bypass): -
產出檔案: 腳本執行完畢後,會在暫存目錄生成 ZIP 檔案:
請使用者將此.zip檔案回傳給維運團隊。
Windows VM 歷史事件回溯 SOP(事後分析用)
[!IMPORTANT] 當使用者在幾天後才回報異常,即時採樣腳本已無法捕捉現場。 請改用此腳本,指定事發時間段,從 Windows 內建日誌回溯歷史紀錄。
可回溯的歷史資料來源
| 來源 | 預設保留時間 | 能回答什麼問題 |
|---|---|---|
| Event Viewer (WinEvtLog) | System/Application 預設 20 MB(數週) | OOM 觸發、服務崩潰、異常關機、程式 Hang |
| Reliability Monitor | 28 天 | 每日穩定性評分、應用程式崩潰時間軸 |
| Scheduled Task History | 視設定 | 哪個排程任務在異常時間點執行(備份、掃毒、更新) |
| WER Crash Reports | 視磁碟空間 | 應用程式 Crash Dump、Hang Report |
| Windows Minidump | C:\Windows\Minidump\ |
BSOD 核心轉儲(需額外工具分析) |
關鍵 Windows Event ID 對照表
| Event ID | Log | 說明 |
|---|---|---|
| 2004 | System | Resource-Exhaustion-Detector:虛擬記憶體嚴重不足,直接列出當時前 3 名元兇 🔴 |
| 41 | System | Kernel-Power:非預期關機/重啟(可能由 OOM 導致)🔴 |
| 6008 | System | 上次關機是非預期的 🔴 |
| 1001 | Application | BugCheck(藍屏 BSOD)🔴 |
| 1002 | Application | Application Hang:程式無回應(資源耗盡常見症狀)🟠 |
| 1000 | Application | Application Error:程式崩潰 🟠 |
| 7034 | System | 服務意外終止(可能被系統強制終止)🟠 |
| 1074 | System | 系統被程式或使用者主動重啟 🟡 |
使用者操作步驟
-
以系統管理員身分開啟 PowerShell
-
下載歷史回溯腳本:
-
執行腳本,並指定事發時間段:
若不確定確切時間,預設查詢最近 3 天: -
產出檔案:
歷史回溯腳本收集內容
| 檔案名稱 | 收集內容 |
|---|---|
system_info.txt |
OS 版本、時區確認(確保與 Prometheus 時間對齊) |
critical_events.txt |
指定區間內所有 OOM / BSOD / Hang / 崩潰 / 服務異常 Event |
reliability_history.txt |
區間內所有 System + Application 告警的時間軸彙整 |
scheduled_tasks_history.txt |
排程任務執行紀錄(找出是否有排程任務觸發資源飆升) |
wer_crash_reports.txt |
WER Crash Report 清單與 Report.wer 摘要、Minidump 清單 |
診斷收集內容清單
腳本打包的檔案中包含以下關鍵資訊:
| 檔案名稱 (Linux / Windows) | 收集內容與目的 |
|---|---|
system_info.txt |
OS 版本、內核版本、vCPU 核心數、實體記憶體總量、開機運行時間、QEMU Guest Agent 狀態 |
process_snapshot.txt |
執行當下 CPU 佔用前 30 名與記憶體佔用前 30 名的行程(包含 PID, Command/Path, RSS/WorkingSet) |
sampling_30s.txt |
連續 30 秒(每 5 秒一次)的動態取樣,記錄 CPU 總負載、剩餘記憶體及該瞬間前 5 名行程,用於捕捉突發峰值 |
oom_and_kernel_alerts.txt / event_logs.txt |
Linux: dmesg 搜尋 OOM Killer、Page Fault、硬體節流。Windows: 搜尋 Event ID 2004(Resource-Exhaustion-Detector 低記憶體警告)及 System/App 錯誤 |
memory_details.txt |
Linux: free -h 與 /proc/meminfo(分析 AnonPages、Buffers/Cached、Slab 佔用) |
disk_io.txt / disk_info.txt |
磁碟空間使用量與 I/O 統計(判斷是否因磁碟寫滿或 I/O 瓶頸引發高負載) |
維運團隊分析手冊 (Ops Troubleshooting Playbook)
收到使用者提供的診斷封裝包後,請依循以下步驟進行交叉比對:
步驟 1:時間軸對齊
- 將 Prometheus 告警時間(如
2026-09-06 13:30:00 UTC)與system_info.txt中的 UTC / 本地時間進行校準。 - 確認使用者執行腳本時是否仍處於 Peak 狀態,或是在 Peak 結束後收集。
步驟 2:OOM (Out Of Memory) 檢查
- Linux:
開啟
oom_and_kernel_alerts.txt或dmesg_full.txt,搜尋關鍵字: 確認是哪支行程佔用最多anon-rss導致觸發內核 OOM-Killer。 - Windows:
開啟
event_logs.txt,檢查是否有 Event ID 2004: > Windows successfully diagnosed a low virtual memory condition. The following programs consumed the most virtual memory: ... Windows 會直接在該日誌中列出前三名吃光分頁記憶體的程式名稱。
步驟 3:CPU 佔用型態分析
比對 process_snapshot.txt 與 sampling_30s.txt:
1. 持續型高負載:特定行程持續維持在單核 100% 或多核吃滿(如自建腳本死迴圈、密集計算、Java GC 頻繁)。
2. 短暫尖峰(Spike):sampling_30s.txt 中負載忽高忽低,常見於 Cron 排程作業、日誌壓縮、Windows Defender 快速掃描、或是 Windows Update 背景安裝。
3. 假性 CPU 高負載(I/O Wait 瓶頸):
* 在 Linux 的 sampling_30s.txt 中檢視 vmstat 的 wa(wait)欄位。
* 若 wa 很高而 us(user)很低,代表不是算力不足,而是底層儲存(Ceph RBD / PVC)I/O 延遲過高,導致 CPU 在等待磁碟讀寫。
步驟 4:記憶體架構深入分析 (Linux)
檢視 memory_details.txt 內的 /proc/meminfo:
* Active(anon) + Inactive(anon) 高:代表是使用者行程(User-space Application)真實分配並持有的實體記憶體。
* Cached / Buffers 高:代表是 Linux 檔案系統快取,有需要時內核會自動回收,此為正常現象,非記憶體洩漏。
* SReclaimable / SUnreclaim (Slab) 高:若 SUnreclaim 異常巨大,代表可能是內核模組或網路 Socket 洩漏。
步驟 5:QEMU Guest Agent 狀態檢查 (關鍵!)
檢查 system_info.txt 中的 qemu-guest-agent 服務狀態:
[!IMPORTANT] 若 VM 內未安裝或未啟動
qemu-guest-agent,KubeVirt 與 Prometheus 無法取得 Guest 內部精確的memory_available與memory_usable。 監控系統看到的往往只是 Hypervisor 分配給 Pod 的完整 RSS 額度,容易產生「記憶體一直維持在 90%~100%」的假性警報。
腳本原始碼
Linux 收集腳本 (collect-linux-diag.sh)
完整腳本位於儲存庫 scripts/guest-diag/collect-linux-diag.sh。
Windows 即時採樣腳本 (collect-windows-diag.ps1)
完整腳本位於儲存庫 scripts/guest-diag/collect-windows-diag.ps1。