Skip to content

Monitoring — 核心功能分析

本頁深入分析 kubevirt/monitoring 專案的五大核心功能:告警 Runbook、Prometheus 指標、Grafana 儀表板、指標 Linter 工具,以及指標文件生成器。

相關章節

告警 Runbook

docs/runbooks/ 目錄收錄了 73 份 告警 Runbook,每份對應一條 Prometheus 告警規則,提供統一的四段式排錯指南。

Runbook 格式

每份 Runbook 嚴格遵循以下結構:

markdown
# <AlertName>

## Meaning      ← 告警觸發的條件與背景說明
## Impact       ← 對叢集/虛擬機的影響程度
## Diagnosis    ← 逐步診斷命令(kubectl / systemctl / journalctl)
## Mitigation   ← 修復步驟與參考資源連結

來源路徑

monitoring/docs/runbooks/*.md — 每個 .md 檔案對應一條告警規則

Runbook 分類

分類數量代表 Runbook
KubeVirt 核心元件~25VirtAPIDown, VirtControllerDown, VirtHandlerDown, VirtOperatorDown, NoReadyVirtAPI, NoReadyVirtController, LowReadyVirtHandlerCount
虛擬機 (VM/VMI)~12KubeVirtVMIExcessiveMigrations, KubeVirtNoAvailableNodesToRunVMs, VMCannotBeEvicted, OrphanedVirtualMachineInstances, OutdatedVirtualMachineInstanceWorkloads
CDI(儲存匯入)8CDIDataImportCronOutdated, CDINotReady, CDIOperatorDown, CDIStorageProfilesIncomplete, CDINoDefaultStorageClass
HCO(超融合管理)6HCOInstallationIncomplete, HCOOperatorConditionsUnhealthy, UnsupportedHCOModification, HCOMisconfiguredDescheduler
SSP(排程/效能/範本)5SSPCommonTemplatesModificationReverted, SSPDown, SSPFailingToReconcile, SSPHighRateRejectedVms, SSPTemplateValidatorDown
CNAO(網路附加元件)3CnaoDown, CnaoNmstateMigration, NetworkAddonsConfigNotReady
HPP(HostPath Provisioner)3HPPOperatorDown, HPPNotReady, HPPSharingPoolPathWithOS
網路2NodeNetworkInterfaceDown, KubemacpoolDown
其他~9DeprecatedMachineType, HighCPUWorkload, PersistentVolumeFillingUp, GuestFilesystemAlmostOutOfSpace

範例 Runbook 1:KubeVirtVMIExcessiveMigrations

markdown
# KubeVirtVMIExcessiveMigrations

## Meaning
此告警在虛擬機實例 (VMI) 於 24 小時內遷移超過 12 次時觸發。
此遷移率即使在升級期間也屬異常偏高,可能代表叢集基礎設施問題。

## Impact
頻繁遷移的 VM 可能因記憶體分頁錯誤而效能下降。

## Diagnosis
1. 驗證 worker 節點是否有足夠資源:
   $ kubectl get nodes -l node-role.kubernetes.io/worker= -o json \
       | jq .items[].status.allocatable
2. 檢查 worker 節點狀態(MemoryPressure / DiskPressure / PIDPressure)
3. 登入節點確認 kubelet 服務運行中:$ systemctl status kubelet
4. 檢查 kubelet 日誌:$ journalctl -r -u kubelet

## Mitigation
確保 worker 節點有足夠 CPU / 記憶體 / 磁碟資源以無中斷運行 VM 工作負載。

來源

monitoring/docs/runbooks/KubeVirtVMIExcessiveMigrations.md

範例 Runbook 2:CDIDataImportCronOutdated

markdown
# CDIDataImportCronOutdated

## Meaning
DataImportCron 無法輪詢或匯入最新磁碟映像版本。
DataImportCron 會輪詢磁碟映像以檢查最新版本,並匯入至 PVC 或
VolumeSnapshot,確保 golden image 保持最新。

## Impact
- VM 可能以過時的磁碟映像建立
- VM 可能因無可用 boot source 進行複製而無法啟動

## Diagnosis
1. 檢查是否有預設 StorageClass:
   $ kubectl get sc -o jsonpath='{.items[?(.metadata.annotations
     .storageclass\.kubernetes\.io\/is-default-class=="true")]
     .metadata.name}'
2. 列出未更新的 DataImportCron:
   $ kubectl get dataimportcron -A \
     -o jsonpath='{range .items[*]}{.status.conditions
     [?(@.type=="UpToDate")].status}{"\t"}{.metadata.namespace}
     {"/"}{.metadata.name}{"\n"}{end}' | grep False

## Mitigation
設定預設 StorageClass 或在 DataImportCron spec 中指定 StorageClass。
若為離線環境,停用 enableCommonBootImageImport feature gate。

來源

monitoring/docs/runbooks/CDIDataImportCronOutdated.md

範例 Runbook 3:SSPCommonTemplatesModificationReverted

markdown
# SSPCommonTemplatesModificationReverted

## Meaning
SSP Operator 在 reconciliation 過程中回復了 common template 的變更。
SSP Operator 部署並 reconcile common templates 與 Template Validator,
若有人修改了 common template,SSP 會將變更回復。

## Impact
對 common templates 的變更會被覆寫。

## Diagnosis
1. 設定 NAMESPACE 環境變數:
   $ export NAMESPACE="$(kubectl get deployment -A \
       | grep ssp-operator | awk '{print $1}')"
2. 檢查 ssp-operator 日誌中被回復的 templates:
   $ kubectl -n $NAMESPACE logs --tail=-1 \
     -l control-plane=ssp-operator | grep 'common template' -C 3

## Mitigation
確保僅修改 template 的副本,而非 template 本身。

來源

monitoring/docs/runbooks/SSPCommonTemplatesModificationReverted.md


Prometheus 指標

docs/metrics.md 彙整了來自 8 個 Operator212 項指標(128 項 Metric + 84 項 Recording Rule),由 tools/metricsdocs 自動生成。

指標來源 Operator

Operator 短名專案名稱Metric 數量Recording Rule 數量
KUBEVIRTkubevirt~100~53
CDIcontainerized-data-importer~10~6
SSPssp-operator~5~10
HCOhyperconverged-cluster-operator~8~5
CNAOcluster-network-addons-operator~3~6
HPPOhostpath-provisioner-operator~2~1
HPPhostpath-provisioner~1
KMPkubemacpool~2

來源路徑

monitoring/docs/metrics.md — 由 tools/metricsdocs/metricsdocs.go 自動生成

指標命名前綴規範

根據 monitoring-guidelines.md,所有指標遵循統一的前綴命名:

前綴適用範圍範例
kubevirt_vmi_*運行中的 VMI 指標kubevirt_vmi_cpu_usage_seconds_total, kubevirt_vmi_memory_available_bytes
kubevirt_vm_*VM 層級指標kubevirt_vm_info, kubevirt_vm_resource_requests
kubevirt_hco_*HCO Operator 指標kubevirt_hco_hyperconverged_cr_exists
kubevirt_cdi_*Storage/CDI Operator 指標kubevirt_cdi_clone_progress_total, kubevirt_cdi_cr_ready
kubevirt_network_*網路 Operator 指標kubevirt_cnao_cr_ready
kubevirt_ssp_*SSP Operator 指標kubevirt_ssp_operator_reconcile_succeeded
kubevirt_hpp_*HPP Operator 指標kubevirt_hpp_pool_path_shared_with_os

命名對齊原則

指標命名需與 Kubernetes 內建指標對齊。例如 Kubernetes 有 node_network_receive_packets_totalcontainer_network_receive_packets_total,KubeVirt 對應地使用 kubevirt_vmi_network_receive_packets_total

來源:monitoring/monitoring-guidelines.md

指標類型分布

類型數量說明
Gauge157可升可降的瞬時值(如 kubevirt_vmi_memory_available_bytes
Counter47只增不減的累計值(如 kubevirt_vmi_cpu_usage_seconds_total
Histogram8分佈直方圖(如 kubevirt_vmi_phase_transition_time_from_creation_seconds

代表性指標範例

VM 生命週期:

kubevirt_vmi_phase_transition_time_from_creation_seconds  (Histogram)
  → VMI 從建立到各階段(Pending/Scheduling/Running)的延遲分佈

kubevirt_vmi_info  (Gauge)
  → VMI 的詳細資訊(namespace, name, phase 等 label)

資源用量:

kubevirt_vmi_memory_available_bytes   (Gauge) — VM 可用記憶體
kubevirt_vmi_memory_usable_bytes      (Gauge) — 可回收記憶體(不含 cache)
kubevirt_vmi_cpu_usage_seconds_total  (Counter) — CPU 總使用時間
kubevirt_vmi_filesystem_capacity_bytes (Gauge) — 檔案系統總容量

遷移監控:

kubevirt_vmi_migration_data_processed_bytes    (Gauge) — 已遷移資料量
kubevirt_vmi_migration_data_remaining_bytes    (Gauge) — 剩餘遷移資料量
kubevirt_vmi_migration_dirty_memory_rate_bytes (Gauge) — 記憶體髒頁速率
kubevirt_vmi_migrations_in_running_phase       (Gauge) — 正在執行的遷移數

網路流量:

kubevirt_vmi_network_receive_bytes_total     (Counter)
kubevirt_vmi_network_transmit_bytes_total    (Counter)
kubevirt_vmi_network_receive_packets_total   (Counter)
kubevirt_vmi_network_transmit_packets_total  (Counter)

Recording Rule 命名規範

Recording Rule 使用冒號分隔的三段式命名 level:metric:operations

Recording Rule 命名規範


Grafana 儀表板

dashboards/ 目錄提供兩組預建儀表板,分別針對 Grafana 原生環境與 OpenShift Console。

dashboards/ 目錄結構

kubevirt-control-plane.json

此儀表板包含 6 個分區(Row)、超過 30 個面板(Panel),全方位監控 KubeVirt 控制面板效能。

分區面板類型關鍵 PromQL
Virtual MachinesVMI Creation Timegraphhistogram_quantile(0.95, sum(rate(kubevirt_vmi_phase_transition_time_from_creation_seconds_bucket{...}[5m])) by (phase, le))
VMI Start Rategraphsum(rate(kubevirt_vmi_phase_transition_time_from_creation_seconds_count{phase="Running"}[5m])) by (instance)
VMI Phase Transition Latencygraph6 條查詢分別追蹤 Pending/Scheduling/Scheduled/Running/Succeeded/Failed 的 P95 延遲
VMI Count (approx.)graph使用 increase() 統計 Failed 與 Running VMI 數量
KubeVirt API AccessAPI Server Read/Write Requests Rategraphsum(rate(apiserver_request_total{group=~".*kubevirt.*", verb=~"LIST|GET"}[5m])) by (code, group)
API Server Read/Write Durationgraphhistogram_quantile(0.90, ...) 計算 P90 延遲
API Client Rate Limiter Durationgraphhistogram_quantile(0.99, sum(irate(rest_client_rate_limiter_duration_seconds_bucket{...}[5m])))
KubeVirt Work QueueWork Queue Add Rategraphsum(rate(kubevirt_workqueue_adds_total{...}[1m])) by (instance, name)
Work Queue Depthgraphkubevirt_workqueue_depth{...}
Queue/Work DurationgraphP99 分位數計算
Unfinished Work / Retry Rategraphkubevirt_workqueue_unfinished_work_seconds, rate(kubevirt_workqueue_retries_total[1m])
K8s API Access非 KubeVirt API 的讀寫速率與延遲graph使用 pod!~"virt-.*" 排除 KubeVirt 元件
Schedule / Pod Start Latencygraphhistogram_quantile(0.99, ...)
Resource UsageMemory / CPU / Open Filesgraphprocess_resident_memory_bytes, rate(process_cpu_seconds_total[5m])
Network / GC Duration / Goroutines / ThreadsgraphGo runtime 指標
Storage OperationsStorage Operation Rate/Error Rategraphstorage_operation_duration_seconds_count
etcdRPC Rate / DB Size / Wal Fsync / RTTgraphetcd 底層效能指標

來源路徑

monitoring/dashboards/grafana/kubevirt-control-plane.json — 5,195 行 JSON

kubevirt-top-consumers.json

此儀表板專注於 VM 資源消耗排行榜,包含 2 個分區14 個面板

分區面板類型PromQL 查詢
Top ConsumersTop Consumers of Memorytablesort_desc(topk(5, sum(avg_over_time(kubevirt_vmi_memory_available_bytes[$__range]) - avg_over_time(kubevirt_vmi_memory_usable_bytes[$__range])) by(name, namespace)))>0
Top Consumers of CPUtablesort_desc(topk(5, sum(rate(container_cpu_usage_seconds_total{container="compute", pod=~"virt-launcher-.*"}[$__range])) by (namespace, pod)))>0
Top Consumers of Storage Traffictablesum(rate(kubevirt_vmi_storage_read_traffic_bytes_total[...]) + rate(kubevirt_vmi_storage_write_traffic_bytes_total[...]))
Top Consumers of Storage IOPStablekubevirt_vmi_storage_iops_read_total + kubevirt_vmi_storage_iops_write_total
Top Consumers of Network Traffictablekubevirt_vmi_network_receive_bytes_total + kubevirt_vmi_network_transmit_bytes_total
Top Consumers of vCPU Waittablekubevirt_vmi_vcpu_wait_seconds_total
Top Consumers of Memory Swap Traffictablekubevirt_vmi_memory_swap_in_traffic_bytes + kubevirt_vmi_memory_swap_out_traffic_bytes
Top Consumers Over TimeMemory/CPU/Storage/Network/vCPU/Swap 趨勢圖graph與上方相同指標的 irate() 時序版本

來源路徑

monitoring/dashboards/openshift/kubevirt-top-consumers.json — 1,955 行 JSON


指標 Linter 工具

KubeVirt Monitoring 提供兩層 Linter,確保所有 Operator 的監控程式碼遵循一致的品質標準。

第一層:Monitoring Linter(Go 靜態分析器)

位於 monitoringlinter/ 的 Go analysis.Analyzer,以 AST 分析方式強制執行監控程式碼的存放位置規範。

go
// monitoring/monitoringlinter/analyzer.go

func NewAnalyzer() *analysis.Analyzer {
    return &analysis.Analyzer{
        Name: "monitoringlinter",
        Doc:  "Ensures that in Kubernetes operators projects, " +
              "monitoring related practices are implemented " +
              "within pkg/monitoring directory, " +
              "using operator-observability packages.",
        Run: run,
    }
}

核心規則:

規則說明
禁止在 pkg/monitoring/ 以外呼叫 operatormetrics.RegisterMetrics()指標註冊必須集中在監控目錄
禁止在 pkg/monitoring/ 以外呼叫 operatorrules.RegisterAlerts()告警規則註冊必須集中在監控目錄
全面禁止直接使用 prometheus.Register() / prometheus.MustRegister()即使在 pkg/monitoring/ 內也不允許直接用 Prometheus SDK 註冊

檢測流程:

  1. 掃描每個 Go 檔案的 import 宣告,辨識是否引入了 Prometheus 或 operator-observability 套件
  2. 透過 AST 走訪找出 Call Expression(函數呼叫)
  3. 比對呼叫的套件名稱與方法名稱(支援自訂 alias import)
  4. 檢查檔案路徑是否在 pkg/monitoring 目錄中

來源

monitoring/monitoringlinter/analyzer.go

第二層:Prometheus Metrics Linter(自訂命名規則)

位於 test/metrics/prom-metrics-linter/,負責驗證指標名稱與 Recording Rule 的命名正確性。

程式架構

test/metrics/prom-metrics-linter/
├── custom_linter_rules.go     ← 入口:解析 JSON 輸入、執行 promlint + 自訂驗證
├── metric_name_linter.go      ← 核心驗證邏輯:指標前綴、Recording Rule 結構
└── allowlist.json             ← 豁免清單:各 Operator 的歷史遺留指標

指標名稱驗證(CustomMetricsValidation)

go
// monitoring/test/metrics/prom-metrics-linter/metric_name_linter.go

func CustomMetricsValidation(problems []promlint.Problem, mf *dto.MetricFamily,
    operatorName, subOperatorName string) []promlint.Problem {

    // 規則 1:指標名稱必須以 operatorName 開頭(如 "kubevirt_")
    // 規則 2:若 subOperatorName 不同,需以 "operatorName_subOperatorName_" 開頭
    // 規則 3:Counter 類型允許 "_total" 或 "_timestamp_seconds" 後綴
}

Recording Rule 驗證(CustomRecordingRuleValidation)

四項驗證規則依序執行:

驗證函數規則說明範例
validateRecordingRuleNameStructure名稱必須為 level:metric:operations 三段式cluster:kubevirt_vmi_phase_count:sum
validateRecordingRuleMetricPrefixmetric 段必須以 operator_suboperator 開頭cluster:kubevirt_vmi_*:sum
validateRecordingRuleOpsSuffixoperations 段必須包含 expr 中偵測到的運算偵測到 sum → 末尾需含 sum
validateRecordingRuleNoDuplicateOpsoperations 段不得有重複 tokenmin_min → 應為 min

可偵測的 Prometheus 運算

go
// monitoring/test/metrics/prom-metrics-linter/metric_name_linter.go

// 聚合運算(14 種)
promAggOps = []string{
    "sum", "avg", "min", "max", "count", "quantile",
    "stddev", "stdvar", "group", "count_values",
    "limitk", "limit_ratio", "topk", "bottomk",
}

// 時間運算(14 種)
promTimeOps = []string{
    "rate", "irate", "increase", "delta", "idelta", "deriv",
    "avg_over_time", "min_over_time", "max_over_time",
    "sum_over_time", "count_over_time", "quantile_over_time",
    "stddev_over_time", "stdvar_over_time",
}

Allowlist 豁免機制

allowlist.json 透過 Go //go:embed 嵌入二進位檔中,為各 Operator 的歷史遺留指標提供豁免:

json
// monitoring/test/metrics/prom-metrics-linter/allowlist.json(節錄)
{
  "operators": {
    "kubevirt": [
      "kubevirt_allocatable_nodes",
      "kubevirt_virt_api_up",
      "kubevirt_virt_controller_ready",
      "kubevirt_vmi_phase_count",
      "kubevirt_number_of_vms"
      // ... 共 22 項
    ],
    "hco": [
      "cnv_abnormal",
      "kubevirt_hyperconverged_operator_health_status",
      "cluster:vmi_request_cpu_cores:sum"
    ],
    "cdi": [
      "kubevirt_cdi_clone_pods_high_restart",
      "kubevirt_cdi_operator_up"
      // ... 共 4 項
    ],
    "ssp": [
      "cnv:vmi_status_running:count",
      "kubevirt_ssp_operator_up"
      // ... 共 6 項
    ]
  }
}

來源

monitoring/test/metrics/prom-metrics-linter/custom_linter_rules.gometric_name_linter.goallowlist.json


指標文件生成器

tools/metricsdocs/ 是一套 Go 工具,負責從 9 個 Operator 的 Git 倉庫拉取指標文件,合併生成統一的 docs/metrics.md

架構總覽

tools/metricsdocs/
├── metricsdocs.go   ← 主程式:參數解析、checkout、文件解析、模板渲染
├── types.go         ← 資料結構:projectInfo、Metric、TemplateOperator
├── git.go           ← Git 操作:clone / pull / checkout branch
├── metrics.tmpl     ← Go template:最終 metrics.md 的輸出模板
├── config           ← 各 Operator 版本設定檔
└── go.mod           ← 依賴:github.com/joho/godotenv

支援的 9 個 Operator

go
// monitoring/tools/metricsdocs/types.go

var projectsInfo = []*projectInfo{
    {"KUBEVIRT", "kubevirt", "kubevirt", "docs/observability/metrics.md"},
    {"CDI", "containerized-data-importer", "kubevirt", "doc/metrics.md"},
    {"NETWORK_ADDONS", "cluster-network-addons-operator", "kubevirt", "docs/metrics.md"},
    {"SSP", "ssp-operator", "kubevirt", "docs/metrics.md"},
    {"NMO", "node-maintenance-operator", "kubevirt", "docs/metrics.md"},
    {"HPPO", "hostpath-provisioner-operator", "kubevirt", "docs/metrics.md"},
    {"HPP", "hostpath-provisioner", "kubevirt", "docs/metrics.md"},
    {"HCO", "hyperconverged-cluster-operator", "kubevirt", "docs/metrics.md"},
    {"KMP", "kubemacpool", "k8snetworkplumbingwg", "doc/metrics.md"},
}

版本設定檔

bash
# monitoring/tools/metricsdocs/config

KUBEVIRT_VERSION="main"
CDI_VERSION="main"
NETWORK_ADDONS_VERSION="main"
SSP_VERSION="main"
NMO_VERSION="master"      # 注意:NMO 使用 master 分支
HPPO_VERSION="main"
HPP_VERSION="main"
HCO_VERSION="main"
KMP_VERSION="main"

生成流程

1. 解析參數          parseArguments()
   │                 ├── --config-file: 版本設定檔路徑
   │                 └── --cache-dir: Git 快取目錄

2. Checkout 各專案    checkoutProjects()
   │                 ├── gitCloneUpstream() 或 gitUpdateFromUpstream()
   │                 └── gitSwitchToBranch(version)

3. 解析指標文件       parseMetrics()
   │                 ├── 讀取各專案的 metrics.md
   │                 └── parseMetricsDoc() 解析 Markdown 表格
   │                     → 提取 Name | Kind | Type | Description

4. 排序指標           sortMetrics()
   │                 ├── kubevirt 的指標排在最前面
   │                 ├── 同 Operator 內 Metric 排在 Recording Rule 之前
   │                 └── 同類型按名稱字母排序

5. 渲染模板          writeMetrics()
                     └── metricsTmpl.Execute() 生成 docs/metrics.md

模板與格式化函數

go
// monitoring/tools/metricsdocs/metricsdocs.go

metricsTmpl = template.New("metrics").Funcs(template.FuncMap{
    "escapePipe": func(s string) string {
        return strings.ReplaceAll(s, "|", "\\|")  // 跳脫 Markdown 表格分隔符
    },
    "normalizeDescription": func(s string) string {
        // 跳脫 pipe、移除換行、去除前後空白
    },
    "codeSpan": func(s string) string {
        return "`" + s + "`"  // 包裹為行內程式碼
    },
})

輸出模板結構:

// monitoring/tools/metricsdocs/metrics.tmpl

# KubeVirt components metrics

## Operator Repositories
| Operator Name |
|---------------|
{{range .Operators}}| {{.Link}} |
{{end}}

## Metrics
| Operator Name | Name | Kind | Type | Description |
|----------|------|------|------|-------------|
{{range .Metrics}}| {{.Operator}} | {{.Name}} | {{.Kind}} | {{.Type}} | {{.Description}} |
{{end}}

來源路徑

monitoring/tools/metricsdocs/metricsdocs.gotypes.gogit.gometrics.tmplconfig

基於 Apache 2.0 授權