kubevirt 源码阅读
· 10810 字 · 约 51 分钟
KubeVirt 是一个基于 Kubernetes 的虚拟化平台,它通过 CRD 扩展 Kubernetes API,在 Kubernetes 之上提供虚拟机管理能力。本文将从架构、组件、工作流程等方面对 KubeVirt 进行深入分析。
一、整体架构
KubeVirt 采用服务导向架构和编排模式,通过 CRD 扩展 Kubernetes API,在 Kubernetes 之上提供虚拟化管理能力。
|
|
核心设计理念:将虚拟机作为 Kubernetes 的一等公民,通过 Kubernetes 原生的 API 和工具来管理虚拟机,实现容器和虚拟机的统一管理。
二、核心组件
KubeVirt 的核心组件协同工作,实现虚拟机的完整生命周期管理。
组件交互概览
graph TB
subgraph 集群级别
VO[virt-operator]
VC[virt-controller]
VA[virt-api]
end
subgraph 节点级别
VH[virt-handler]
end
subgraph Pod级别
VL[virt-launcher]
LIB[libvirtd]
QEMU[QEMU/KVM]
end
subgraph 用户
CLI[virtctl]
KCTL[kubectl]
end
CLI --> VA
KCTL --> VA
VO --> VC
VO --> VA
VO --> VH
VC --> VH
VH --> VL
VL --> LIB
LIB --> QEMU
virt-operator
类型: Deployment(集群级别)
作用:KubeVirt 的生命周期管理器,负责整个 KubeVirt 平台的安装、升级和维护。
核心功能:
| 功能 | 说明 |
|---|---|
| 组件安装 | 部署 virt-controller、virt-api、virt-handler 等组件 |
| 版本升级 | 实现滚动更新,最小化对运行中虚拟机的影响 |
| 配置管理 | 管理 KubeVirt 的配置和特性开关 |
| 健康监控 | 监控各组件的健康状态,自动修复故障 |
可以做什么:
- 安装 KubeVirt 到 Kubernetes 集群
- 升级 KubeVirt 版本
- 启用/禁用特定功能(如 GPU、SR-IOV 等)
- 查看组件状态和日志
源码位置:cmd/virt-operator/,核心逻辑在 pkg/virt-operator/
virt-controller
类型: Deployment(集群级别)
作用:集群范围的虚拟机编排器,管理 VMI 的生命周期和调度决策。
核心功能:
| 功能 | 说明 |
|---|---|
| VMI 管理 | 监控 VMI 资源,创建/删除对应的 Pod |
| 调度协调 | 处理虚拟机调度决策,支持亲和性/反亲和性 |
| 迁移管理 | 协调实时迁移,管理源节点和目标节点 |
| 状态同步 | 维护 VMI 的期望状态与实际状态一致 |
可以做什么:
- 创建虚拟机实例(VMI)
- 执行虚拟机实时迁移
- 处理虚拟机优先级和抢占
- 管理虚拟机副本集(VMIRS)
源码位置:cmd/virt-controller/,核心逻辑在 pkg/virt-controller/
virt-handler
类型: DaemonSet(每个节点一个)
作用:节点级别的虚拟机代理,负责本节点上虚拟机的生命周期管理。
核心功能:
| 功能 | 说明 |
|---|---|
| VMI 同步 | 将集群级 VMI 规范同步到本地 libvirt 域 |
| 状态上报 | 向集群报告虚拟机的状态和健康信息 |
| 设备管理 | 准备和配置虚拟机所需的设备(磁盘、网络等) |
| 迁移执行 | 执行虚拟机的迁移操作 |
可以做什么:
- 启动/停止本节点上的虚拟机
- 配置虚拟机的网络和存储
- 收集虚拟机指标和日志
- 执行热插拔操作(CPU、内存、磁盘)
源码位置:cmd/virt-handler/,核心逻辑在 pkg/virt-handler/
virt-launcher
类型: Pod 中的主容器
作用:虚拟机进程管理器,每个虚拟机对应一个 virt-launcher Pod。
核心功能:
| 功能 | 说明 |
|---|---|
| 进程管理 | 通过 libvirtd 管理 QEMU 进程 |
| 资源隔离 | 提供 cgroups 和 namespaces 隔离 |
| 信号处理 | 处理 Kubernetes 的终止信号,优雅关闭虚拟机 |
| 状态监控 | 监控虚拟机进程状态,异常时上报 |
可以做什么:
- 启动和停止虚拟机进程
- 管理虚拟机的 CPU 和内存资源
- 处理虚拟机的控制台连接
- 支持虚拟机的暂停和恢复
源码位置:cmd/virt-launcher/,核心逻辑在 pkg/virt-launcher/
virt-api
类型: Deployment(集群级别)
作用:KubeVirt 的 API 入口,处理所有虚拟化相关的 API 请求。
核心功能:
| 功能 | 说明 |
|---|---|
| API 扩展 | 提供 VirtualMachine、VMI 等 CRD 的 API |
| 验证准入 | 验证用户提交的资源配置 |
| 默认值填充 | 为未指定的字段设置合理默认值 |
| 子资源处理 | 处理 console、vnc、start、stop 等子资源请求 |
可以做什么:
- 创建和管理虚拟机资源
- 连接虚拟机控制台
- 执行虚拟机启停操作
- 管理虚拟机快照和导出
源码位置:cmd/virt-api/,核心逻辑在 pkg/virt-api/
virtctl
类型: CLI 命令行工具
作用:用户友好的命令行工具,简化虚拟机操作。
核心命令:
| 命令 | 功能 |
|---|---|
virtctl start <vm> |
启动虚拟机 |
virtctl stop <vm> |
停止虚拟机 |
virtctl restart <vm> |
重启虚拟机 |
virtctl console <vmi> |
连接串口控制台 |
virtctl vnc <vmi> |
连接 VNC 图形界面 |
virtctl migrate <vmi> |
迁移虚拟机 |
virtctl image-upload |
上传磁盘镜像 |
virtctl expand-spec |
展开虚拟机规格 |
可以做什么:
- 管理虚拟机的启停和重启
- 连接虚拟机控制台进行调试
- 上传和管理磁盘镜像
- 创建和管理虚拟机快照
- 执行实时迁移
源码位置:cmd/virtctl/,核心逻辑在 pkg/virtctl/
三、辅助组件
virt-exportserver
作用:虚拟机镜像导出服务器。
可以做什么:
- 导出虚拟机磁盘镜像
- 支持多种导出格式(qcow2、raw 等)
- 提供 HTTP 端点供外部下载
virt-exportproxy
作用:导出代理,处理导出请求的路由和认证。
可以做什么:
- 验证导出请求的权限
- 路由导出请求到对应的导出服务器
- 管理 TLS 证书
virt-freezer
作用:虚拟机文件系统冻结工具。
可以做什么:
- 在备份前冻结虚拟机文件系统
- 确保备份的一致性
- 备份完成后解冻文件系统
virt-tail
作用:虚拟机日志追踪工具。
可以做什么:
- 追踪虚拟机串口控制台输出
- 支持日志过滤和搜索
- 与 Kubernetes 日志系统集成
virt-chroot
作用:chroot 工具,用于安全隔离。
可以做什么:
- 在隔离环境中执行命令
- 访问宿主机文件系统
- 执行需要特权的操作
pr-helper
作用:SCSI 持久预留助手。
可以做什么:
- 处理 SCSI 设备的持久预留命令
- 支持共享存储的集群功能
- 与 multipath 配合使用
libguestfs
作用:磁盘镜像操作工具集。
可以做什么:
- 修改虚拟机磁盘镜像内容
- 注入文件和配置
- 查看和编辑磁盘内容
sidecars
作用:边车容器,支持 Hook 扩展机制。
可以做什么:
- 在虚拟机启动前修改配置
- 注入自定义设备
- 实现自定义认证和授权
四、核心资源类型(CRD)
资源层级关系
graph TD
A[VirtualMachine VM] -->|创建| B[VirtualMachineInstance VMI]
B -->|创建| C[Pod]
C -->|启动| D[virt-launcher 容器]
D -->|管理| E[libvirtd]
E -->|运行| F[虚拟机进程 QEMU]
style A fill:#e1f5fe
style B fill:#fff3e0
style C fill:#e8f5e9
| 资源 | 生命周期 | 持久性 | 用途 |
|---|---|---|---|
| VM | 用户管理 | 持久 | 声明式管理,支持启停、重启 |
| VMI | VM 创建(自动) | 临时 | 运行时实例,类似 Pod |
| Pod | VMI 创建(自动) | 临时 | 提供隔离环境和资源限制 |
VirtualMachineInstance (VMI)
VMI 是 KubeVirt 的基础虚拟机实例资源,是临时性的,类似于 Pod。
|
|
VirtualMachine (VM)
VM 是有状态虚拟机,可以停止/启动,保持数据。
VM 结构概览
|
|
Spec 字段详解
| 字段 | 类型 | 说明 |
|---|---|---|
running |
*bool | 已弃用。控制是否创建 VMI,与 runStrategy 互斥 |
runStrategy |
*VirtualMachineRunStrategy | 运行策略,控制 VMI 的启停行为 |
instancetype |
*InstancetypeMatcher | 引用实例类型模板,自动填充 CPU、内存等配置 |
preference |
*PreferenceMatcher | 引用偏好设置模板,自动填充设备配置 |
template |
*VirtualMachineInstanceTemplateSpec | VMI 模板,定义虚拟机实例的规格 |
dataVolumeTemplates |
[]DataVolumeTemplateSpec | 数据卷模板,动态创建 PVC |
updateVolumesStrategy |
*UpdateVolumesStrategy | 卷更新策略(Migration/Replacement) |
runStrategy 字段说明
源码位置:staging/src/kubevirt.io/api/core/v1/types.go:1894-1907
|
|
处理逻辑:pkg/virt-controller/watch/vm/vm.go:969-1150
|
|
instancetype 和 preference 字段说明
| 字段 | 作用 | 示例 |
|---|---|---|
instancetype |
预定义的实例规格(CPU、内存) | Standard-2、Memory-Optimized-4 |
preference |
预定义的设备偏好设置 | 磁盘总线类型、网络模型等 |
使用示例:
|
|
处理逻辑:pkg/virt-controller/watch/vm/vm.go:3227
|
|
template 字段说明
template 定义 VMI 的模板,当创建 VMI 时会从此模板复制。
源码位置:pkg/virt-controller/watch/vm/vm.go:1867-1896
|
|
template.spec 底层字段详解
template.spec 的类型是 VirtualMachineInstanceSpec,包含虚拟机实例的完整规格。
源码位置:staging/src/kubevirt.io/api/core/v1/types.go:28-198
顶层字段
| 字段路径 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
spec.domain |
DomainSpec | 是 | - | 虚拟机域规格,包含 CPU、内存、设备等配置 |
spec.volumes |
[]Volume | 否 | [] | 卷列表,定义虚拟机可用的存储卷(最多 256 个) |
spec.networks |
[]Network | 否 | [] | 网络列表,定义虚拟机可用的网络(最多 256 个) |
spec.affinity |
*Affinity | 否 | nil | 调度亲和性配置,与 Pod 亲和性相同 |
spec.nodeSelector |
map[string]string | 否 | nil | 节点选择器 |
spec.tolerations |
[]Toleration | 否 | [] | 容忍度配置 |
spec.evacuationStrategy |
*EvictionStrategy | 否 | nil | 驱逐策略(None/LiveMigrate/LiveMigrateIfPossible/External) |
spec.startStrategy |
*StartStrategy | 否 | nil | 启动策略(Paused) |
spec.terminationGracePeriodSeconds |
*int64 | 否 | 30 | 优雅终止时间(秒) |
spec.livenessProbe |
*Probe | 否 | nil | 存活探针 |
spec.readinessProbe |
*Probe | 否 | nil | 就绪探针 |
spec.hostname |
string | 否 | VMI 名称 | 虚拟机主机名 |
spec.subdomain |
string | 否 | "" | 子域名,完整主机名为 <hostname>.<subdomain>.<namespace>.svc.<cluster> |
spec.dnsPolicy |
DNSPolicy | 否 | ClusterFirst | DNS 策略 |
spec.dnsConfig |
*PodDNSConfig | 否 | nil | DNS 配置 |
spec.schedulerName |
string | 否 | default-scheduler | 调度器名称 |
domain 字段详解
domain 是 VirtualMachineInstanceSpec 的核心字段,定义了虚拟机的硬件配置。
源码位置:staging/src/kubevirt.io/api/core/v1/schema.go:217-261
domain 顶层字段
| 字段路径 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
domain.resources |
ResourceRequirements | 否 | - | 资源请求和限制 |
domain.cpu |
*CPU | 否 | nil | CPU 配置 |
domain.memory |
*Memory | 否 | nil | 内存配置 |
domain.machine |
*Machine | 否 | nil | 机器类型配置 |
domain.firmware |
*Firmware | 否 | nil | 固件配置 |
domain.clock |
*Clock | 否 | nil | 时钟配置 |
domain.features |
*Features | 否 | nil | 特性配置(ACPI, APIC, Hyperv 等) |
domain.devices |
Devices | 是 | - | 设备配置(磁盘、网络接口等) |
domain.ioThreadsPolicy |
*IOThreadsPolicy | 否 | nil | IO 线程策略(shared/auto/supplementalPool) |
domain.chassis |
*Chassis | 否 | nil | 机箱信息 |
domain.launchSecurity |
*LaunchSecurity | 否 | nil | 启动安全配置(SEV, TDX) |
domain.rebootPolicy |
*RebootPolicy | 否 | Reboot | 重启策略(Reboot/Terminate) |
domain.resources 字段详解
源码位置:staging/src/kubevirt.io/api/core/v1/schema.go:335-348
| 字段路径 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
resources.requests |
ResourceList | 否 | - | 资源请求,有效键为 “memory” 和 “cpu” |
resources.requests["memory"] |
Quantity | 否 | - | 请求的内存大小(如 “4Gi”) |
resources.requests["cpu"] |
Quantity | 否 | - | 请求的 CPU 数量(如 “2”) |
resources.limits |
ResourceList | 否 | - | 资源限制,有效键为 “memory” 和 “cpu” |
resources.limits["memory"] |
Quantity | 否 | - | 内存限制 |
resources.limits["cpu"] |
Quantity | 否 | - | CPU 限制 |
resources.overcommitGuestOverhead |
bool | 否 | false | 是否将 Guest 开销计入容器内存限制 |
示例:
|
|
字段用途详解:
1. 资源请求(resources.requests)
用途:定义虚拟机启动所需的最小资源,Kubernetes 调度器根据此值选择节点。
使用场景:
- 调度决策:确保节点有足够资源
- 资源预留:为 VM 预留最小资源
- QoS 保证:配合 limits 实现 Guaranteed QoS
- 节点规划:集群容量规划依据
示例:
|
|
注意事项:
- requests ≤ limits(否则调度失败)
- 影响调度决策
- 过小导致性能问题
- 过大导致资源浪费
2. 资源限制(resources.limits)
用途:定义虚拟机可使用的最大资源,防止资源耗尽。
使用场景:
- 资源隔离:防止 VM 占用过多资源
- 性能保证:确保 VM 有足够资源
- 节点稳定性:防止资源争抢
- 成本控制:限制资源使用
示例:
|
|
QoS 等级:
- Guaranteed:requests == limits(最高优先级)
- Burstable:requests < limits(中等优先级)
- BestEffort:无 requests/limits(最低优先级)
注意事项:
- 超过 limits 可能被 OOMKilled
- CPU limits 使用 CFS quota 限制
- 内存限制强制生效(硬限制)
- 生产环境建议 Guaranteed QoS
3. Guest 开销超卖(overcommitGuestOverhead)
用途:控制是否将虚拟化开销(QEMU、libvirt 等)计入容器内存限制。
使用场景:
- 内存超卖:提高节点内存利用率
- 资源优化:减少预留资源
- 开发测试:节省资源成本
- 生产环境:谨慎使用
示例:
|
|
工作原理:
false(默认):容器内存限制 = VM 内存 + 开销true:容器内存限制 = VM 内存(开销从 VM 内存中扣除)
注意事项:
- 开销通常 100-300MB(取决于 VM 配置)
- true 时可能影响 VM 性能
- 建议仅在内存充足时使用
- 生产环境建议 false
内存配置最佳实践:
|
|
domain.cpu 字段详解
源码位置:staging/src/kubevirt.io/api/core/v1/schema.go:351-390
| 字段路径 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
cpu.cores |
uint32 | 否 | 1 | CPU 核心数,必须 ≥ 1 |
cpu.sockets |
uint32 | 否 | 1 | CPU 插槽数,必须 ≥ 1 |
cpu.maxSockets |
uint32 | 否 | 0 | 最大插槽数(热插拔上限) |
cpu.threads |
uint32 | 否 | 1 | 每核心线程数,必须 ≥ 1 |
cpu.model |
string | 否 | host-model | CPU 型号,如 “host-passthrough”、“host-model” 或具体型号 |
cpu.features |
[]CPUFeature | 否 | [] | CPU 特性列表 |
cpu.dedicatedCpuPlacement |
bool | 否 | false | 是否使用专用 CPU(CPU Pinning) |
cpu.isolateEmulatorThread |
bool | 否 | false | 是否隔离模拟器线程 |
cpu.numa |
*NUMA | 否 | nil | NUMA 配置 |
cpu.realtime |
*Realtime | 否 | nil | 实时配置 |
CPU 拓扑计算:总 vCPU 数 = cores × sockets × threads
字段用途详解:
1. CPU 拓扑配置(cores, sockets, threads)
用途:定义虚拟机的 CPU 拓扑结构,影响性能和许可证成本。
使用场景:
- 性能优化:根据应用特性选择合适的拓扑(如数据库应用适合多 socket)
- 许可证管理:某些软件按 socket 收费,可以配置为单 socket 多 core
- NUMA 优化:多 socket 配置可以模拟 NUMA 拓扑
示例:
|
|
注意事项:
- 总 vCPU 数不能超过节点的物理 CPU 数
- 某些操作系统对 CPU 拓扑有特定要求
- 超线程(threads > 1)性能提升取决于工作负载类型
2. CPU 型号配置(model)
用途:控制虚拟机看到的 CPU 特性集,影响性能和迁移能力。
可选值:
host-model(默认):使用与主机最接近的 CPU 型号host-passthrough:直接透传主机 CPU 特性- 具体型号:如 “Skylake-Client”, “Haswell” 等
使用场景:
- 高兼容性:
host-model适合集群内迁移(节点 CPU 不必完全相同) - 高性能:
host-passthrough适合需要特定 CPU 指令集的应用(如加密、AI) - 嵌套虚拟化:嵌套虚拟机需要
host-passthrough
示例:
|
|
注意事项:
host-passthrough会降低迁移能力(目标节点 CPU 必须完全相同)- 某些 CPU 特性可能影响安全性(需评估)
3. CPU Pinning(dedicatedCpuPlacement)
用途:将虚拟机 CPU 绑定到物理 CPU,提供确定性性能。
使用场景:
- 实时应用:低延迟要求的金融交易、电信应用
- 高性能计算:科学计算、AI 训练
- 性能隔离:防止其他虚拟机干扰
示例:
|
|
注意事项:
- 需要节点有足够的空闲 CPU
- 会降低资源利用率(独占 CPU)
- 需要配合资源请求使用
4. CPU 热插拔(maxSockets)
用途:支持运行时动态调整 CPU 数量。
使用场景:
- 弹性扩展:根据负载动态调整 CPU
- 维护窗口:临时增加 CPU 处理峰值负载
示例:
|
|
注意事项:
- 需要 Guest OS 支持 CPU 热插拔
- 不是所有操作系统都支持
- 热插拔操作需要 virtctl 命令触发
cpu.features 字段详解
源码位置:staging/src/kubevirt.io/api/core/v1/schema.go:413-426
| 字段路径 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
features[].name |
string | 是 | - | CPU 特性名称(如 “vmx”, “sse4.1”) |
features[].policy |
string | 否 | require | 特性策略:force/require/optional/disable/forbid |
策略说明:
force: 强制启用该特性require: 必须支持该特性,否则创建失败optional: 如果主机支持则启用disable: 禁用该特性forbid: 如果主机支持该特性则创建失败
示例:
|
|
domain.memory 字段详解
源码位置:staging/src/kubevirt.io/api/core/v1/schema.go:429-445
| 字段路径 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
memory.guest |
*Quantity | 否 | resources.requests.memory | Guest 可见的内存大小 |
memory.maxGuest |
*Quantity | 否 | nil | 最大内存(热插拔上限) |
memory.hugepages |
*Hugepages | 否 | nil | 大页内存配置 |
memory.hugepages.pageSize |
string | 否 | - | 大页大小(x86_64: “2Mi” 或 “1Gi”) |
memory.reservedOverhead |
*ReservedOverhead | 否 | nil | 内存开销预留配置 |
memory.reservedOverhead.addedOverhead |
*Quantity | 否 | nil | 额外预留的内存开销 |
memory.reservedOverhead.memLock |
*MemLockRequirement | 否 | NotRequired | 内存锁定需求(NotRequired/Required) |
字段用途详解:
1. 内存大小配置(guest)
用途:定义虚拟机可用的内存大小。
使用场景:
- 应用需求:根据应用程序内存需求配置
- 性能优化:足够内存避免频繁 swap
- 成本控制:合理配置避免资源浪费
示例:
|
|
注意事项:
- Guest 内存应 ≤ 资源请求
- 需要考虑虚拟化开销(通常 5-10%)
- 过大的内存可能导致调度困难
2. 内存热插拔(maxGuest)
用途:支持运行时动态调整内存大小。
使用场景:
- 弹性扩展:根据负载动态调整内存
- 维护窗口:临时增加内存处理峰值负载
示例:
|
|
注意事项:
- 需要 Guest OS 支持内存热插拔
- Linux 内核需要启用相关选项
- Windows 需要特定版本支持
3. 大页内存(hugepages)
用途:使用大页内存提高性能,减少 TLB miss。
使用场景:
- 高性能数据库:Oracle、PostgreSQL 等大型数据库
- 实时应用:需要低延迟的应用
- 内存密集型应用:AI 训练、大数据分析
示例:
|
|
配置要求:
- 节点必须预分配大页内存
- 需要在节点启动时配置(如
default_hugepagesz=2M hugepagesz=2M hugepages=1024) - Kubernetes 需要配置
--feature-gates=HugePages=true
性能优势:
- 减少 TLB miss,提高内存访问速度
- 减少页表大小,节省内存
- 适合内存密集型应用
注意事项:
- 大页内存不能 swap
- 需要精确规划内存使用
- 过大的大页可能导致内存碎片
4. 内存锁定(memLock)
用途:锁定内存防止 swap,保证性能和安全性。
使用场景:
- 实时应用:防止 swap 导致延迟
- 安全应用:防止敏感数据 swap 到磁盘
- VFIO/DPDK:硬件设备 DMA 需要
示例:
|
|
注意事项:
- 需要 ulimit 配置(
memlock) - 可能影响节点内存管理
- 适合专用节点
domain.machine 字段详解
源码位置:staging/src/kubevirt.io/api/core/v1/schema.go:499-503
| 字段路径 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
machine.type |
string | 否 | 架构相关 | QEMU 机器类型(如 “q35”, “pc-q35-6.2”) |
示例:
|
|
domain.firmware 字段详解
源码位置:staging/src/kubevirt.io/api/core/v1/schema.go:505-519
| 字段路径 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
firmware.uuid |
types.UID | 否 | 随机生成 | BIOS UUID |
firmware.bootloader |
*Bootloader | 否 | nil | 引导加载程序配置 |
firmware.serial |
string | 否 | "" | SMBIOS 序列号 |
firmware.kernelBoot |
*KernelBoot | 否 | nil | 内核启动配置 |
firmware.bootloader 字段详解:
| 字段路径 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
bootloader.bios |
*BIOS | 否 | nil | BIOS 引导(默认) |
bootloader.bios.useSerial |
*bool | 否 | false | BIOS 输出是否通过串口 |
bootloader.efi |
*EFI | 否 | nil | EFI 引导 |
bootloader.efi.secureBoot |
*bool | 否 | false | 是否启用 Secure Boot(需要 SMM) |
bootloader.efi.persistent |
*bool | 否 | false | EFI NVRAM 是否持久化 |
示例:
|
|
字段用途详解:
1. BIOS UUID(firmware.uuid)
用途:设置虚拟机的 BIOS UUID,用于标识虚拟机。
使用场景:
- 许可证管理:软件许可绑定 UUID
- 资产追踪:唯一标识 VM
- 集群软件:UUID 作为节点标识
- 迁移一致性:迁移后保持 UUID 不变
示例:
|
|
注意事项:
- 未指定时随机生成
- 迁移时保持不变
- 某些软件依赖 UUID 唯一性
2. 引导加载程序(firmware.bootloader)
用途:配置虚拟机的引导方式(BIOS 或 EFI)。
使用场景:
- BIOS 引导:传统引导方式,兼容性好(默认)
- UEFI 引导:现代引导方式,支持大磁盘、Secure Boot
- Secure Boot:安全启动,防止未授权代码执行
- 串口输出:BIOS 输出到串口(无头服务器)
示例:
|
|
注意事项:
- Secure Boot 需要 SMM 支持
- UEFI 适合 GPT 分区、大磁盘
- persistent: true 保存 EFI 变量
- 某些 OS 需要 UEFI(如 Windows 11)
3. SMBIOS 序列号(firmware.serial)
用途:设置 SMBIOS 序列号,用于资产管理和软件识别。
使用场景:
- 资产管理:硬件资产追踪
- 软件激活:序列号绑定软件
- 许可证管理:基于序列号的授权
- 合规性:满足审计要求
示例:
|
|
注意事项:
- 未指定时为空
- 可通过
dmidecode在 VM 内查看 - 建议使用唯一且有意义的值
domain.devices 字段详解
源码位置:staging/src/kubevirt.io/api/core/v1/schema.go:531-614
| 字段路径 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
devices.disks |
[]Disk | 否 | [] | 磁盘列表(最多 256 个) |
devices.interfaces |
[]Interface | 否 | [] | 网络接口列表(最多 256 个) |
devices.inputs |
[]Input | 否 | [] | 输入设备列表(tablet/keyboard) |
devices.watchdog |
*Watchdog | 否 | nil | 看门狗设备 |
devices.rng |
*Rng | 否 | nil | 随机数生成器 |
devices.gpus |
[]GPU | 否 | [] | GPU 设备列表 |
devices.hostDevices |
[]HostDevice | 否 | [] | 主机设备列表 |
devices.filesystems |
[]Filesystem | 否 | [] | 文件系统列表(virtiofs) |
devices.autoattachPodInterface |
*bool | 否 | true | 是否自动附加 Pod 网络 |
devices.autoattachGraphicsDevice |
*bool | 否 | true | 是否自动附加图形设备(VNC) |
devices.autoattachSerialConsole |
*bool | 否 | true | 是否自动附加串口控制台 |
devices.logSerialConsole |
*bool | 否 | false | 是否记录串口控制台日志 |
devices.autoattachMemBalloon |
*bool | 否 | true | 是否自动附加内存气球设备 |
devices.autoattachInputDevice |
*bool | 否 | false | 是否自动附加输入设备 |
devices.autoattachVSOCK |
*bool | 否 | false | 是否附加 VSOCK |
devices.blockMultiQueue |
*bool | 否 | false | 是否启用块设备多队列 |
devices.networkInterfaceMultiqueue |
*bool | 否 | false | 是否启用网络接口多队列 |
devices.useVirtioTransitional |
*bool | 否 | false | 是否使用传统 virtio 0.9 |
devices.disableHotplug |
bool | 否 | false | 是否禁用热插拔 |
devices.sound |
*SoundDevice | 否 | nil | 声卡设备 |
devices.tpm |
*TPMDevice | 否 | nil | TPM 设备 |
devices.video |
*VideoDevice | 否 | nil | 视频设备配置 |
示例:
|
|
自动附加字段用途详解:
1. 自动附加 Pod 网络(autoattachPodInterface)
用途:控制是否自动将 Pod 网络附加到虚拟机。
使用场景:
- 默认行为:自动附加 Pod 网络(默认 true)
- 无网络 VM:禁用网络连接
- 多网络:使用 Multus 配置多个网络接口
- 安全隔离:完全禁用网络
示例:
|
|
注意事项:
- 默认 true,自动附加 eth0
- 设为 false 需要显式配置网络接口
- 无网络 VM 适合离线处理
2. 自动附加图形设备(autoattachGraphicsDevice)
用途:控制是否自动附加 VNC 图形设备。
使用场景:
- 图形界面:需要 VNC 连接(默认 true)
- 无头服务器:禁用图形设备节省资源
- 控制台访问:仅使用串口控制台
- 资源优化:减少不必要设备
示例:
|
|
注意事项:
- 禁用后无法使用 VNC
- 建议配合串口控制台使用
- 可节省少量内存和 CPU
3. 自动附加串口控制台(autoattachSerialConsole)
用途:控制是否自动附加串口控制台,用于命令行访问。
使用场景:
- 命令行访问:SSH 或 virtctl console 连接
- 日志输出:捕获启动日志
- 自动化脚本:通过串口执行命令
- 调试诊断:查看内核消息
示例:
|
|
注意事项:
- 默认 true
- 可通过
virtctl console <vm>连接 - logSerialConsole 记录日志到文件
4. 自动附加内存气球(autoattachMemBalloon)
用途:控制是否自动附加内存气球设备,用于动态内存管理。
使用场景:
- 内存超卖:释放未使用内存给其他 VM
- 内存监控:监控 VM 实际内存使用
- 资源优化:提高内存利用率
- 性能敏感:禁用以避免性能波动
示例:
|
|
注意事项:
- 默认 true
- 需要 virtio 驱动支持
- 可能导致内存性能波动
- 适合内存超卖场景
5. 块设备多队列(blockMultiQueue)
用途:启用块设备多队列,提高磁盘 I/O 性能。
使用场景:
- 高 I/O 负载:数据库、大数据应用
- 多 vCPU:多核 VM 并行 I/O
- 高性能存储:NVMe、SSD
- 延迟敏感:实时应用
示例:
|
|
注意事项:
- 需要多 vCPU 才有明显效果
- 增加少量 CPU 开销
- Linux 内核 4.x+ 支持
- 适合 I/O 密集型应用
6. 网络接口多队列(networkInterfaceMultiqueue)
用途:启用网络接口多队列,提高网络性能。
使用场景:
- 高网络流量:Web 服务器、流媒体
- 多 vCPU:多核 VM 并行网络处理
- 低延迟网络:实时应用、金融交易
- 高性能网络:10Gbps+ 网络
示例:
|
|
注意事项:
- 需要多 vCPU 和 virtio 驱动
- 增加少量 CPU 开销
- 适合网络密集型应用
- 需要网卡支持多队列
devices.disks 字段详解
源码位置:staging/src/kubevirt.io/api/core/v1/schema.go:759-807
| 字段路径 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
disks[].name |
string | 是 | - | 磁盘名称,必须与 volumes[] 中的名称匹配 |
disks[].disk |
*DiskTarget | 否 | - | 作为磁盘挂载 |
disks[].disk.bus |
DiskBus | 否 | virtio | 总线类型:virtio/sata/scsi/usb |
disks[].disk.readonly |
bool | 否 | false | 是否只读 |
disks[].disk.pciAddress |
string | 否 | "" | PCI 地址(如 “0000:81:01.10”) |
disks[].cdrom |
*CDRomTarget | 否 | - | 作为 CDROM 挂载 |
disks[].cdrom.bus |
DiskBus | 否 | sata | 总线类型 |
disks[].cdrom.readonly |
*bool | 否 | true | 是否只读 |
disks[].cdrom.tray |
TrayState | 否 | closed | 托盘状态:open/closed |
disks[].lun |
*LunTarget | 否 | - | 作为 LUN 挂载(透传) |
disks[].lun.bus |
DiskBus | 否 | virtio | 总线类型 |
disks[].lun.readonly |
bool | 否 | false | 是否只读 |
disks[].lun.reservation |
bool | 否 | false | 是否支持 SCSI 持久预留 |
disks[].bootOrder |
*uint | 否 | nil | 启动顺序(值越小优先级越高) |
disks[].serial |
string | 否 | "" | 磁盘序列号 |
disks[].dedicatedIOThread |
*bool | 否 | false | 是否使用专用 IO 线程 |
disks[].cache |
DriverCache | 否 | none | 缓存模式:none/writethrough/writeback |
disks[].io |
DriverIO | 否 | native | IO 模式:native/threads |
disks[].tag |
string | 否 | "" | 通过 config drive 暴露给 Guest 的标签 |
disks[].blockSize |
*BlockSize | 否 | nil | 块大小配置 |
disks[].shareable |
*bool | 否 | false | 是否可共享(多 VM 写) |
disks[].errorPolicy |
*DiskErrorPolicy | 否 | stop | 错误策略:stop/ignore/report/enospace |
disks[].changedBlockTracking |
*bool | 否 | false | 是否启用变更块追踪 |
示例:
|
|
字段用途详解:
1. 磁盘总线类型(disk.bus)
用途:定义磁盘的总线类型,影响性能和兼容性。
使用场景:
- virtio:高性能虚拟化环境,推荐用于 Linux/Windows
- sata:兼容性好,适合旧版 OS 或需要热迁移
- scsi:支持 SCSI 命令,适合需要高级功能的场景
- usb:适合可移动设备或临时挂载
示例:
|
|
性能对比:
- virtio: 最快(需要 virtio 驱动)
- scsi: 较快(支持多队列)
- sata: 中等(兼容性好)
- usb: 最慢(适合临时使用)
注意事项:
- Windows 需要安装 virtio 驱动
- 热迁移需要相同总线类型
- 不同总线类型支持不同的功能
2. 缓存模式(cache)
用途:控制磁盘 I/O 缓存策略,影响性能和数据安全。
使用场景:
- none:无缓存,数据安全性最高,适合数据库
- writethrough:写透缓存,平衡性能和安全
- writeback:回写缓存,性能最高但有数据丢失风险
- unsafe:不安全缓存,仅用于测试
示例:
|
|
注意事项:
- 生产环境避免使用 unsafe
- 数据库建议使用 none
- 结合
io: native获得最佳性能
3. 启动顺序(bootOrder)
用途:定义磁盘启动优先级。
使用场景:
- 多磁盘 VM:指定从哪个磁盘启动
- 网络启动:与网络接口配合使用
- CDROM 启动:从 ISO 启动安装
示例:
|
|
注意事项:
- 值越小优先级越高
- 未设置 bootOrder 的设备优先级最低
- 可用于磁盘和网络接口
4. 错误策略(errorPolicy)
用途:定义磁盘 I/O 错误时的处理策略。
使用场景:
- stop:停止 VM,适合关键应用(默认)
- ignore:忽略错误,适合非关键数据
- report:报告错误但继续运行
- enospace:仅在空间不足时停止
示例:
|
|
注意事项:
- 生产环境建议使用 stop
- ignore 可能导致数据损坏
- 需要监控错误事件
5. 专用 I/O 线程(dedicatedIOThread)
用途:为磁盘分配专用的 I/O 线程,提高性能。
使用场景:
- 高 I/O 负载:数据库、大数据应用
- 延迟敏感:实时应用
- 多磁盘竞争:多个高 I/O 磁盘
示例:
|
|
注意事项:
- 增加 CPU 开销
- 适合 I/O 密集型应用
- 需要足够的 CPU 资源
6. 可共享磁盘(shareable)
用途:允许多个 VM 同时访问同一磁盘。
使用场景:
- 集群文件系统:GFS2、OCFS2
- 共享存储:多节点应用
- 读写一致性:需要应用层协调
示例:
|
|
注意事项:
- 需要集群文件系统或应用层锁
- 不能用于普通文件系统(会导致损坏)
- 建议 SCSI 总线 + reservation
7. 变更块追踪(changedBlockTracking)
用途:启用变更块追踪,支持增量备份。
使用场景:
- 备份系统:支持增量备份
- 快照管理:减少备份时间和空间
- 灾难恢复:快速增量复制
示例:
|
|
注意事项:
- 需要备份软件支持
- 增加少量性能开销
- 适合定期备份的磁盘
volumes 字段详解
源码位置:staging/src/kubevirt.io/api/core/v1/schema.go:929-1004
| 字段路径 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
volumes[].name |
string | 是 | - | 卷名称,必须与 disks[].name 或 interfaces[].name 匹配 |
卷源类型(互斥,只能指定一个):
| 字段路径 | 类型 | 说明 |
|---|---|---|
volumes[].persistentVolumeClaim |
*PersistentVolumeClaimVolumeSource | 引用 PVC |
volumes[].persistentVolumeClaim.claimName |
string | PVC 名称 |
volumes[].persistentVolumeClaim.hotpluggable |
bool | 是否可热插拔 |
volumes[].dataVolume |
*DataVolumeSource | 引用 DataVolume |
volumes[].dataVolume.name |
string | DataVolume 名称 |
volumes[].dataVolume.hotpluggable |
bool | 是否可热插拔 |
volumes[].containerDisk |
*ContainerDiskSource | 容器磁盘镜像 |
volumes[].containerDisk.image |
string | 容器镜像地址 |
volumes[].containerDisk.imagePullPolicy |
PullPolicy | 镜像拉取策略:Always/Never/IfNotPresent |
volumes[].containerDisk.imagePullSecret |
string | 镜像拉取密钥 |
volumes[].containerDisk.path |
string | 磁盘文件在容器中的路径 |
volumes[].emptyDisk |
*EmptyDiskSource | 临时磁盘(与 VM 生命周期相同) |
volumes[].emptyDisk.capacity |
Quantity | 磁盘大小 |
volumes[].ephemeral |
*EphemeralVolumeSource | 临时卷(CoW) |
volumes[].hostDisk |
*HostDisk | 主机磁盘 |
volumes[].hostDisk.path |
string | 磁盘路径 |
volumes[].hostDisk.type |
HostDiskType | 类型:Disk/DiskOrCreate |
volumes[].hostDisk.capacity |
Quantity | 磁盘大小(DiskOrCreate 时使用) |
volumes[].hostDisk.shared |
*bool | 是否在节点间共享 |
volumes[].cloudInitNoCloud |
*CloudInitNoCloudSource | cloud-init NoCloud 数据源 |
volumes[].cloudInitNoCloud.userData |
string | 用户数据(明文) |
volumes[].cloudInitNoCloud.userDataBase64 |
string | 用户数据(Base64 编码) |
volumes[].cloudInitNoCloud.networkData |
string | 网络数据(明文) |
volumes[].cloudInitNoCloud.networkDataBase64 |
string | 网络数据(Base64 编码) |
volumes[].cloudInitConfigDrive |
*CloudInitConfigDriveSource | cloud-init ConfigDrive 数据源 |
volumes[].sysprep |
*SysprepSource | Sysprep 配置 |
volumes[].configMap |
*ConfigMapVolumeSource | ConfigMap 卷 |
volumes[].secret |
*SecretVolumeSource | Secret 卷 |
volumes[].serviceAccount |
*ServiceAccountVolumeSource | ServiceAccount 卷 |
volumes[].downwardAPI |
*DownwardAPIVolumeSource | DownwardAPI 卷 |
volumes[].downwardMetrics |
*DownwardMetricsVolumeSource | DownwardMetrics 卷 |
volumes[].memoryDump |
*MemoryDumpVolumeSource | 内存转储卷 |
volumes[].containerPath |
*ContainerPathVolumeSource | 容器路径卷(virtiofs) |
示例:
|
|
卷类型用途详解:
1. PersistentVolumeClaim(PVC)卷
用途:使用 Kubernetes PVC 作为虚拟机磁盘,支持持久化存储。
使用场景:
- 持久化数据:数据库、应用数据
- 动态供给:使用 StorageClass 动态创建 PV
- 存储迁移:数据独立于 VM 生命周期
- 热插拔:支持运行时挂载/卸载(hotpluggable: true)
示例:
|
|
注意事项:
- PVC 必须先创建或使用 DataVolume 自动创建
- 支持 Block 和 Filesystem 模式
- 热插拔需要 VM 运行时操作
- 删除 VM 时 PVC 默认保留
2. ContainerDisk(容器磁盘)
用途:使用容器镜像作为虚拟机磁盘,适合只读或临时使用。
使用场景:
- 操作系统镜像:快速启动标准 OS
- 只读数据:静态内容、工具镜像
- 测试环境:快速迭代、无需持久化
- 镜像分发:通过容器仓库分发磁盘镜像
示例:
|
|
注意事项:
- 容器镜像中的磁盘文件通常是只读的
- 每次启动都会拉取新镜像(除非 imagePullPolicy: Never)
- 不适合持久化数据
- 支持多种格式:qcow2, raw, img
3. EmptyDisk(临时磁盘)
用途:创建与 VM 生命周期相同的临时磁盘,VM 删除时数据丢失。
使用场景:
- 临时数据:缓存、临时文件
- 交换分区:swap 空间
- 测试数据:测试环境的临时存储
- 无持久化需求:数据无需保留
示例:
|
|
注意事项:
- VM 删除后数据丢失
- 使用节点本地存储
- 性能较好(无网络开销)
- 不适合重要数据
4. CloudInitNoCloud(cloud-init 配置)
用途:通过 cloud-init 在启动时配置虚拟机。
使用场景:
- 初始化配置:设置主机名、用户、密码
- 网络配置:静态 IP、DNS、路由
- 软件安装:启动时安装软件包
- SSH 密钥:注入 SSH 公钥
示例:
|
|
注意事项:
- 需要 cloud-init 软件包
- userData 和 userDataBase64 互斥
- 支持 NoCloud 和 ConfigDrive 两种数据源
- 配置仅在首次启动生效
5. HostDisk(主机磁盘)
用途:使用节点主机上的文件作为虚拟机磁盘。
使用场景:
- 本地存储:使用节点本地磁盘
- 高性能:避免网络存储开销
- 特定节点:数据固定在特定节点
- 迁移限制:不适合跨节点迁移
示例:
|
|
注意事项:
- 节点必须有足够磁盘空间
- 跨节点迁移受限(需要共享存储)
- 适合节点本地高性能场景
- 需要节点访问权限
6. DataVolume(数据卷)
用途:使用 CDI(Containerized Data Importer)自动创建和管理 PVC。
使用场景:
- 自动导入:从 URL、容器镜像、上传导入磁盘镜像
- 克隆 PVC:从现有 PVC 克隆
- 空白磁盘:创建空白块设备
- 自动化管理:无需手动创建 PVC
示例:
|
|
注意事项:
- 需要 CDI 组件支持
- 支持多种数据源(HTTP, S3, Registry, Upload, Clone)
- 自动创建 PVC
- 支持热插拔
networks 和 interfaces 字段详解
源码位置:
- Network:
staging/src/kubevirt.io/api/core/v1/types.go - Interface:
staging/src/kubevirt.io/api/core/v1/schema.go
networks 字段:
| 字段路径 | 类型 | 必填 | 说明 |
|---|---|---|---|
networks[].name |
string | 是 | 网络名称,必须与 interfaces[].name 匹配 |
网络源类型(互斥):
| 字段路径 | 类型 | 说明 |
|---|---|---|
networks[].pod |
*PodNetwork | Pod 网络(默认) |
networks[].multus |
*MultusNetwork | Multus 网络 |
networks[].multus.networkName |
string | NetworkAttachmentDefinition 名称 |
interfaces 字段:
| 字段路径 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
interfaces[].name |
string | 是 | - | 接口名称,必须与 networks[].name 匹配 |
interfaces[].model |
string | 否 | virtio | 网卡型号:virtio/e1000/e1000e/igb/ne2k_pci/pcnet/rtl8139 |
interfaces[].macAddress |
string | 否 | 自动分配 | MAC 地址(如 “de:ad:00:00:be:af” 或 “DE-AD-00-00-BE-AF”) |
interfaces[].ports |
[]Port | 否 | [] | 端口列表,用于端口转发 |
interfaces[].ports[].name |
string | 否 | - | 端口名称 |
interfaces[].ports[].port |
int | 是 | - | 端口号 |
interfaces[].ports[].protocol |
string | 否 | TCP | 协议:TCP/UDP |
interfaces[].bootOrder |
*uint | 否 | nil | 启动顺序(值越小优先级越高) |
interfaces[].pciAddress |
string | 否 | "" | PCI 地址(如 “0000:81:01.10”) |
interfaces[].dhcpOptions |
*DHCPOptions | 否 | nil | 额外的 DHCP 选项 |
interfaces[].dhcpOptions.bootFileName |
string | 否 | - | DHCP 选项 67:引导文件名,用于 PXE 启动 |
interfaces[].dhcpOptions.tftpServerName |
string | 否 | - | DHCP 选项 66:TFTP 服务器名称,用于 PXE 启动 |
interfaces[].dhcpOptions.ntpServers |
[]string | 否 | [] | DHCP 选项 042:NTP 服务器列表 |
interfaces[].dhcpOptions.privateOptions |
[]DHCPPrivateOptions | 否 | [] | 私有 DHCP 选项(范围:224-254) |
interfaces[].tag |
string | 否 | "" | 通过 config drive 暴露给 Guest 的标签 |
interfaces[].acpiIndex |
int | 否 | 0 | ACPI 索引,范围:1-16383 |
interfaces[].state |
InterfaceState | 否 | up | 接口操作状态:absent/down/up |
字段用途详解:
1. acpiIndex - 稳定的网络接口命名
用途:解决虚拟机迁移或重启后网络接口名称变化的问题。
问题背景:
- 虚拟机重启或迁移后,PCI 地址可能发生变化
- Linux 网络接口名称通常基于 PCI 地址(如 eth0、ens3)
- 如果 PCI 地址变化,接口名称也会变化,导致网络配置失效
解决方案:
- 使用
acpiIndex提供稳定的设备命名 - 即使 PCI 地址变化,接口名称也能保持稳定
- Guest OS 可以通过 ACPI 表获取稳定的设备索引
使用场景:
- 虚拟机迁移(Live Migration)
- 虚拟机重启后需要保持网络配置
- 多网卡虚拟机的网络配置管理
示例:
|
|
注意事项:
- 值必须在所有设备中唯一(包括磁盘等设备)
- 值范围:1 到 16383
2. dhcpOptions - 自定义 DHCP 选项
用途:为虚拟机网络接口传递额外的 DHCP 配置选项。
主要应用场景:
a) PXE 网络启动
|
|
b) NTP 时间同步
|
|
c) 自定义私有选项
|
|
DHCP 选项编号对照:
- 选项 66:TFTP 服务器名称
- 选项 67:引导文件名
- 选项 042:NTP 服务器
- 选项 224-254:私有选项(用户自定义)
3. tag - 网络接口元数据标签
用途:通过 config drive 将网络接口信息暴露给 Guest OS。
工作原理:
- KubeVirt 将网络接口的元数据(IP 地址、MAC 地址、标签)写入 config drive
- Guest OS 通过 cloud-init 读取这些元数据
- 应用可以根据标签识别特定的网络接口
使用场景:
- 多网卡虚拟机:区分不同用途的网络接口(管理网、存储网、业务网)
- 自动化配置:Guest 内部脚本根据标签自动配置网络
- 网络隔离:标识不同安全级别的网络接口
示例:
|
|
Guest 内部访问: Guest OS 可以通过 cloud-init 的 metadata 服务访问这些标签:
|
|
4. state - 接口操作状态控制
用途:动态控制网络接口的运行状态。
状态值说明:
a) up(默认)- 启动接口
- 将网络接口设置为启动状态
- 接口可以正常收发数据包
- 默认行为
b) down - 关闭接口
- 将网络接口设置为关闭状态
- 接口停止收发数据包
- 但接口仍然存在(未删除)
c) absent - 删除接口
- 请求删除网络接口
- 接口从虚拟机中移除(热拔出)
- 用于动态移除网络接口
使用场景:
热拔出网络接口:
|
|
临时关闭接口:
|
|
动态接口管理:
- 根据运行时条件动态添加/删除网络接口
- 维护窗口期间临时关闭接口
- 故障排查时隔离特定网络
注意事项:
state字段是请求状态,实际状态可能需要时间同步- 热拔出(
absent)操作需要 Guest OS 和 KubeVirt 共同支持 - 状态变更可能会触发虚拟机重启或迁移,取决于具体实现
5. model - 网卡型号
用途:指定虚拟网卡型号,影响性能和兼容性。
使用场景:
a) virtio(推荐)
- 高性能虚拟化环境
- 现代 Linux/Windows 系统
- 需要 virtio 驱动支持
b) e1000/e1000e
- Intel PRO/1000 网卡模拟
- 兼容性好,无需额外驱动
- 性能较低
c) 其他型号
- rtl8139: Realtek 网卡
- ne2k_pci: NE2000 网卡
- pcnet: AMD PCnet 网卡
- igb: Intel Gigabit 网卡
示例:
|
|
性能对比:
- virtio: 最快(需要驱动)
- e1000e: 中等(兼容性好)
- e1000: 较慢(广泛兼容)
- rtl8139: 最慢(仅测试用)
注意事项:
- 生产环境推荐 virtio
- Windows 需要安装 virtio 驱动
- 热迁移需要相同型号
- 某些 OS 可能不支持 virtio
6. macAddress - MAC 地址
用途:指定虚拟网卡的 MAC 地址。
使用场景:
- 固定 MAC:软件许可绑定 MAC 地址
- 网络策略:基于 MAC 的访问控制
- DHCP 保留:固定 IP 分配
- 资产追踪:唯一标识网络接口
示例:
|
|
注意事项:
- 未指定时自动生成
- 建议使用 “52:54:00” 前缀(QEMU 分配)
- 必须在同一网络中唯一
- 迁移后 MAC 地址保持不变
7. ports - 端口转发
用途:配置端口转发规则,仅用于 masquerade 模式。
使用场景:
- 服务暴露:从集群外部访问 VM 服务
- 端口映射:将 VM 端口映射到宿主机端口
- 负载均衡:配合 Service 使用
- 开发测试:本地访问 VM 服务
示例:
|
|
注意事项:
- 仅用于 masquerade 模式
- 需要配合 Service 暴露端口
- 协议支持 TCP 和 UDP
- 端口名称可用于 Service 定义
8. bootOrder - 网络启动
用途:设置网络接口的启动优先级,用于 PXE 网络启动。
使用场景:
- PXE 安装:通过网络安装操作系统
- 无盘工作站:无本地磁盘,从网络启动
- 集群部署:批量部署虚拟机
- 救援模式:系统故障时网络引导
示例:
|
|
注意事项:
- 值越小优先级越高
- 可与磁盘启动配合使用
- 需要 DHCP/TFTP 服务器支持
- 建议配合 dhcpOptions 使用
9. pciAddress - PCI 地址
用途:指定网卡的 PCI 地址,用于设备固定。
使用场景:
- 设备固定:确保网卡在特定 PCI 位置
- 驱动绑定:绑定特定驱动程序
- 设备命名:基于 PCI 地址的接口命名
- 硬件兼容:模拟特定硬件布局
示例:
|
|
注意事项:
- 格式:
domain:bus:slot.function - 需要了解 PCI 地址空间
- 不正确配置可能导致冲突
- 建议使用 acpiIndex 替代
接口类型(互斥):
| 字段路径 | 说明 |
|---|---|
interfaces[].bridge |
桥接模式 |
interfaces[].masquerade |
Masquerade 模式(NAT) |
interfaces[].masquerade.ports |
端口转发列表 |
interfaces[].slirp |
Slirp 模式(已弃用) |
interfaces[].sriov |
SR-IOV 模式 |
interfaces[].macvtap |
Macvtap 模式 |
示例:
|
|
dataVolumeTemplates 字段说明
dataVolumeTemplates 用于声明式地管理虚拟机磁盘。
作用:
- 自动创建 DataVolume 和对应的 PVC
- DataVolume 的生命周期与 VM 绑定
- 支持从多种源导入数据(HTTP、S3、PVC 克隆等)
示例:
|
|
处理逻辑:pkg/virt-controller/watch/vm/vm.go:511-572
|
|
Status 字段详解
| 字段 | 类型 | 说明 |
|---|---|---|
created |
bool | VM 是否已在集群中创建 |
ready |
bool | VMI 是否正在运行且就绪 |
printableStatus |
VirtualMachinePrintableStatus | 人类可读的状态字符串 |
conditions |
[]VirtualMachineCondition | 状态条件列表 |
stateChangeRequests |
[]VirtualMachineStateChangeRequest | 状态变更请求队列 |
volumeRequests |
[]VirtualMachineVolumeRequest | 热插拔卷请求 |
volumeSnapshotStatuses |
[]VolumeSnapshotStatus | 各卷的快照状态 |
startFailure |
*VirtualMachineStartFailure | 启动失败信息(CrashLoopBackOff) |
memoryDumpRequest |
*VirtualMachineMemoryDumpRequest | 内存转储请求状态 |
observedGeneration |
int64 | VMI 启动时观察到的 VM generation |
desiredGeneration |
int64 | 期望的 generation,用于判断是否需要重启 |
PrintableStatus 状态值
| 状态 | 说明 |
|---|---|
Stopped |
虚拟机已停止 |
Provisioning |
正在准备资源(如 DataVolume) |
Starting |
正在启动 |
Running |
正在运行 |
Paused |
已暂停 |
Stopping |
正在停止 |
Terminating |
正在终止 |
CrashLoopBackOff |
启动失败,等待重试 |
Migrating |
正在迁移 |
Unknown |
状态未知 |
ErrorUnschedulable |
调度失败 |
ErrImagePull |
镜像拉取失败 |
ImagePullBackOff |
镜像拉取退避 |
ErrorPvcNotFound |
PVC 不存在 |
DataVolumeError |
DataVolume 错误 |
WaitingForVolumeBinding |
等待卷绑定 |
WaitingForReceiver |
等待接收迁移 |
完整示例
|
|
RunStrategy 说明
| 值 | 行为 | 使用场景 |
|---|---|---|
Always |
VMI 总是存在,被删除后会自动重建 | 服务类虚拟机,需要高可用 |
Manual |
需要手动启停,不会自动重建 | 开发测试环境,需要手动控制 |
Halted |
不创建 VMI,相当于 stopped 状态 | 暂时停用的虚拟机 |
RerunOnFailure |
仅当 VMI 失败时才重新创建 | 批处理任务,失败后自动重试 |
Once |
只运行一次,结束后不重启 | 一次性任务 |
其他资源类型
| 资源 | 描述 |
|---|---|
| VirtualMachineInstanceReplicaSet | VMI 副本集,类似 Pod ReplicaSet |
| VirtualMachinePool | VM 池,批量管理 VM |
| VirtualMachineSnapshot | VM 快照 |
| VirtualMachineExport | VM 导出 |
| VirtualMachineClone | VM 克隆 |
| VirtualMachineMigration | VM 迁移 |
| VirtualMachineInstancetype | 实例类型模板 |
五、VM 生命周期管理
RunStrategy 详解
源码位置:staging/src/kubevirt.io/api/core/v1/types.go:1918-1932
VirtualMachineRunStrategy 定义了虚拟机的运行策略,控制 VMI 的创建和生命周期。
| RunStrategy | 值 | 行为说明 |
|---|---|---|
Always |
“Always” | VM 总是运行,VMI 异常退出后自动重启 |
Halted |
“Halted” | VM 停止状态,不创建 VMI |
Manual |
“Manual” | 手动控制,需要显式启动/停止 |
RerunOnFailure |
“RerunOnFailure” | VMI 失败时重启,成功退出不重启 |
Once |
“Once” | 只运行一次,退出后不再重启 |
WaitAsReceiver |
“WaitAsReceiver” | 等待接收迁移的 VMI |
RunStrategy 行为对比
源码位置:pkg/virt-controller/watch/vm/vm.go:969-1087
|
|
RunStrategy 使用场景
1. Always(生产环境推荐)
|
|
使用场景:
- 生产环境关键服务
- 需要高可用的应用
- 7x24 运行的服务
行为:
- ✅ VM 创建时自动启动
- ✅ VMI 崩溃后自动重启
- ✅ 节点故障后重新调度
- ❌ 手动停止无效(会自动重启)
2. Halted(停止状态)
|
|
使用场景:
- 临时停止的 VM
- 模板 VM
- 备份前的 VM
行为:
- ✅ VM 创建时不启动
- ✅ 显式启动后才运行
- ✅ 手动停止后保持停止
3. Manual(手动控制)
|
|
使用场景:
- 开发测试环境
- 需要精确控制的场景
- 按需启动的 VM
行为:
- ✅ VM 创建时不启动
- ✅ 需要
virtctl start启动 - ✅ 需要
virtctl stop停止 - ❌ 崩溃后不自动重启
4. RerunOnFailure(失败重启)
|
|
使用场景:
- 批处理任务
- 失败需要重试的应用
- 非关键服务
行为:
- ✅ VM 创建时自动启动
- ✅ VMI 失败(Failed)后重启
- ❌ VMI 成功(Succeeded)后不重启
- ❌ 手动停止后不重启
5. Once(单次运行)
|
|
使用场景:
- 一次性任务
- 安装程序
- 初始化脚本
行为:
- ✅ VM 创建时自动启动
- ✅ 只运行一次
- ❌ 退出后不再重启(无论成功或失败)
6. WaitAsReceiver(迁移接收)
|
|
使用场景:
- 跨集群迁移
- 接收迁移的 VMI
- 灾难恢复
行为:
- ✅ 等待接收迁移的 VMI
- ✅ 迁移完成后变为 Running
- ⚠️ 高级特性,需要特殊配置
RunStrategy vs Running
注意:running 字段已废弃,推荐使用 runStrategy。
|
|
为什么废弃 running:
running只有 true/false,无法表达复杂策略runStrategy提供更细粒度的控制running和runStrategy互斥,不能同时使用
VMI 状态机
源码位置:staging/src/kubevirt.io/api/core/v1/types.go:1054-1076
VirtualMachineInstancePhase 定义了 VMI 的生命周期状态。
| Phase | 值 | 说明 |
|---|---|---|
VmPhaseUnset |
"" | 初始状态,未设置 |
Pending |
“Pending” | VMI 已创建,等待调度 |
Scheduling |
“Scheduling” | Pod 已创建,等待调度 |
Scheduled |
“Scheduled” | Pod 已调度,virt-handler 接管 |
Running |
“Running” | VMI 正在运行 |
Succeeded |
“Succeeded” | VMI 正常退出 |
Failed |
“Failed” | VMI 异常退出或被删除 |
WaitingForSync |
“WaitingForSync” | 等待同步(迁移场景) |
Unknown |
“Unknown” | 状态未知(通信错误) |
VMI 状态转换流程
stateDiagram-v2
[*] --> VmPhaseUnset: VMI 创建
VmPhaseUnset --> Pending: virt-controller 处理
Pending --> Scheduling: 创建 Pod
Scheduling --> Scheduled: Pod 调度成功
Scheduled --> Running: virt-handler 启动 VM
Running --> Succeeded: 正常关机
Running --> Failed: 崩溃/被删除
Succeeded --> [*]
Failed --> [*]
Pending --> Failed: 超时/错误
Scheduling --> Failed: 调度失败
Scheduled --> Failed: 启动失败
Running --> WaitingForSync: 迁移同步
WaitingForSync --> Running: 同步完成
状态转换详细说明
1. VmPhaseUnset → Pending
- 触发:VMI CRD 创建
- 处理:virt-controller 监听到创建事件
- 源码:
pkg/virt-controller/watch/vmi.go
2. Pending → Scheduling
- 触发:virt-controller 创建 Pod
- 处理:Pod 请求调度
- 源码:
pkg/virt-controller/watch/vmi.go:setupVMI()
3. Scheduling → Scheduled
- 触发:Kubernetes 调度器分配节点
- 处理:virt-controller 更新 nodeName
- 源码:
pkg/virt-controller/watch/vmi.go:updateVMIStatus()
4. Scheduled → Running
- 触发:virt-handler 检测到本节点 VMI
- 处理:启动 virt-launcher,创建 libvirt domain
- 源码:
pkg/virt-handler/vm.go:syncVMI()
5. Running → Succeeded
- 触发:Guest OS 正常关机(SIGTERM/ACPI shutdown)
- 处理:virt-launcher 检测到 domain 关闭
- 源码:
pkg/virt-launcher/virtwrap/manager.go
6. Running → Failed
- 触发:
- Guest OS 崩溃(kernel panic)
- QEMU 进程崩溃
- VMI 被强制删除
- 节点故障
- 处理:virt-handler 检测到异常退出
- 源码:
pkg/virt-handler/vm.go
状态查看方法
|
|
状态异常排查
VMI 停留在 Pending
|
|
VMI 停留在 Scheduling
|
|
VMI 停留在 Scheduled
|
|
VMI 进入 Failed
|
|
VM 和 VMI 关系
graph TD
A[VirtualMachine] -->|创建| B[VirtualMachineInstance]
A -->|runStrategy 控制| C{RunStrategy}
C -->|Always| D[自动启动/重启]
C -->|Halted| E[停止状态]
C -->|Manual| F[手动控制]
C -->|RerunOnFailure| G[失败重启]
C -->|Once| H[单次运行]
B -->|状态转换| I[Pending → Scheduling → Scheduled → Running]
I -->|正常退出| J[Succeeded]
I -->|异常退出| K[Failed]
J -->|触发| L{RunStrategy 决定}
K -->|触发| L
L -->|Always/RerunOnFailure| D
L -->|Manual/Once| M[保持停止]
关键源码路径
| 功能 | 源码位置 |
|---|---|
| VM RunStrategy 处理 | pkg/virt-controller/watch/vm/vm.go:969 |
| VM 创建 VMI | pkg/virt-controller/watch/vm/vm.go:1256 |
| VM 删除 VMI | pkg/virt-controller/watch/vm/vm.go:1400 |
| VMI 状态管理 | pkg/virt-controller/watch/vmi.go:763 |
| VMI 调度 | pkg/virt-controller/watch/vmi.go:598 |
| virt-handler 启动 VM | pkg/virt-handler/vm.go:196 |
| virt-launcher 管理 libvirt | pkg/virt-launcher/virtwrap/manager.go:290 |
六、热迁移源码分析
热迁移概述
源码位置:
- API 定义:
staging/src/kubevirt.io/api/core/v1/types.go:1691-1800 - 迁移控制器:
pkg/virt-controller/watch/migration/migration.go - 迁移代理:
pkg/virt-handler/migration-proxy/
热迁移允许在不中断服务的情况下将运行中的虚拟机从一个节点迁移到另一个节点。
VirtualMachineInstanceMigration CRD
|
|
迁移阶段(MigrationPhase)
| Phase | 值 | 说明 |
|---|---|---|
MigrationPhaseUnset |
"" | 未设置 |
MigrationPending |
“Pending” | 迁移已接受,等待调度 |
MigrationScheduling |
“Scheduling” | 目标 Pod 正在调度 |
MigrationScheduled |
“Scheduled” | 目标 Pod 已调度 |
MigrationPreparingTarget |
“PreparingTarget” | 正在准备目标 Pod |
MigrationTargetReady |
“TargetReady” | 目标 Pod 准备就绪 |
MigrationRunning |
“Running” | 迁移进行中 |
MigrationSucceeded |
“Succeeded” | 迁移成功 |
MigrationFailed |
“Failed” | 迁移失败 |
MigrationWaitingForSync |
“WaitingForSync” | 等待同步(跨集群迁移) |
MigrationSynchronizing |
“Synchronizing” | 正在同步(跨集群迁移) |
迁移流程
sequenceDiagram
participant User as 用户
participant API as K8s API
participant MC as Migration Controller
participant VC as VMI Controller
participant VH_S as virt-handler (源)
participant VH_T as virt-handler (目标)
participant VL_S as virt-launcher (源)
participant VL_T as virt-launcher (目标)
User->>API: 创建 Migration CR
API->>MC: 监听 Migration 创建
MC->>MC: MigrationPending
MC->>API: 创建目标 Pod
MC->>MC: MigrationScheduling
API->>VC: 调度目标 Pod
VC->>MC: MigrationScheduled
VH_T->>VH_T: 准备目标环境
MC->>MC: MigrationPreparingTarget
MC->>MC: MigrationTargetReady
VH_S->>VL_S: 启动迁移
MC->>MC: MigrationRunning
VL_S->>VL_T: 传输内存页(迭代)
VL_S->>VL_T: 传输脏页
VL_S->>VL_T: 停止源 VM,切换到目标
MC->>MC: MigrationSucceeded
MC->>API: 更新 VMI nodeName
MC->>API: 删除源 Pod
Pre-copy vs Post-copy 迁移
源码位置:pkg/virt-controller/watch/migration/migration.go
Pre-copy 迁移(默认)
工作原理:
- 在 VM 运行时持续传输内存页
- 迭代传输脏页,直到脏页率足够低
- 最后停止 VM,传输剩余内存,切换到目标
优点:
- 迁移失败可回滚
- 停机时间短(通常 < 100ms)
- 适合大多数场景
缺点:
- 迁移时间长(总传输量大)
- 高内存修改率时可能无法完成
配置:
|
|
Post-copy 迁移
工作原理:
- 传输少量内存后立即切换到目标
- VM 在目标节点运行,按需拉取内存页
- 使用用户态缺页中断(UFFD)
优点:
- 迁移时间短
- 能完成高内存修改率的迁移
- 减少网络带宽占用
缺点:
- 迁移失败无法回滚
- 目标节点故障会导致 VM 丢失
- 需要内核支持(Linux 4.3+)
配置:
|
|
迁移策略(MigrationPolicy)
源码位置:staging/src/kubevirt.io/api/migrations/v1alpha1/types.go
MigrationPolicy 允许为不同的 VM 配置不同的迁移策略。
|
|
迁移条件
源码位置:pkg/virt-controller/watch/migration/migration.go:handlMigrationCondition()
必要条件
-
VMI 状态必须是 Running
1 2 3if vmi.Status.Phase != virtv1.Running { return fmt.Errorf("VMI is not running") } -
VMI 必须已调度到节点
1 2 3if vmi.Status.NodeName == "" { return fmt.Errorf("VMI is not scheduled") } -
存储必须支持迁移
- ReadWriteMany (RWX) PVC
- 网络附加存储(如 Ceph, NFS)
- 本地存储不支持迁移
-
网络必须支持迁移
- Bridge 模式:需要网络配置
- Masquerade 模式:默认支持
- SR-IOV:需要特殊配置
-
节点资源充足
- 目标节点有足够 CPU/内存
- 目标节点可访问相同存储
迁移限制
|
|
迁移执行详解
1. 目标 Pod 创建
源码位置:pkg/virt-controller/watch/migration/migration.go:createTargetPod()
|
|
2. 迁移代理设置
源码位置:pkg/virt-handler/migration-proxy/proxy.go
virt-handler 在源节点和目标节点之间建立代理连接,用于:
- libvirt 迁移流量
- QEMU 数据传输
|
|
3. 内存传输
源码位置:pkg/virt-launcher/virtwrap/converter/converter.go
|
|
迁移监控
查看迁移状态
|
|
迁移进度指标
|
|
迁移故障排查
迁移卡在 Pending
|
|
迁移卡在 Scheduling
|
|
迁移卡在 Running
|
|
迁移失败
|
|
关键源码路径
| 功能 | 源码位置 |
|---|---|
| Migration CRD 定义 | staging/src/kubevirt.io/api/core/v1/types.go:1691 |
| 迁移控制器 | pkg/virt-controller/watch/migration/migration.go |
| 迁移策略 | staging/src/kubevirt.io/api/migrations/v1alpha1/types.go |
| 迁移代理 | pkg/virt-handler/migration-proxy/proxy.go |
| libvirt 迁移接口 | pkg/virt-launcher/virtwrap/manager.go |
| 迁移状态管理 | pkg/virt-handler/vm.go |
| 网络迁移 | pkg/network/migration/ |
迁移最佳实践
1. 生产环境配置
|
|
2. 存储选择
- ✅ 使用 RWX PVC(ReadWriteMany)
- ✅ 使用网络存储(Ceph, NFS, GlusterFS)
- ❌ 避免使用本地存储
3. 网络配置
- Bridge 模式:需要网络团队支持
- Masquerade 模式:默认支持迁移
- SR-IOV:需要 VF 迁移支持
4. 监控和告警
|
|
八、故障排查指南
常见问题分类
1. VMI 启动失败
症状:VMI 停留在 Pending/Scheduling 状态
排查步骤:
|
|
常见原因及解决方案:
| 问题 | 原因 | 解决方案 |
|---|---|---|
| Pending | PVC 未绑定 | 检查 StorageClass,确保 PV 可用 |
| Pending | 节点资源不足 | 扩容节点或减少资源请求 |
| Scheduling | 节点选择器不匹配 | 检查 nodeSelector/nodeAffinity |
| Scheduling | 污点/容忍度问题 | 添加合适的 tolerations |
| Scheduled → Failed | 镜像拉取失败 | 检查 imagePullSecrets |
| Scheduled → Failed | 存储挂载失败 | 检查 PVC 访问权限 |
2. VMI 运行异常
症状:VMI 进入 Failed 状态或频繁重启
排查步骤:
|
|
常见原因及解决方案:
| 问题 | 原因 | 解决方案 |
|---|---|---|
| OOMKilled | 内存不足 | 增加 memory limits |
| CrashLoopBackOff | 应用崩溃 | 检查 Guest OS 日志 |
| 节点 NotReady | 节点故障 | 检查节点状态,迁移 VMI |
| 网络不通 | 网络配置错误 | 检查 CNI 配置 |
3. 热迁移失败
症状:迁移卡住或失败
排查步骤:
|
|
常见原因及解决方案:
| 问题 | 原因 | 解决方案 |
|---|---|---|
| Pending | VMI 不是 Running | 等待 VMI 运行 |
| Scheduling | 目标节点无资源 | 扩容或清理节点 |
| Running 卡住 | 内存脏页率高 | 降低负载或使用 Post-copy |
| Failed | 超时 | 调整 completionTimeoutPerGiB |
| Failed | 存储不支持迁移 | 使用 RWX PVC |
4. 存储问题
症状:PVC 无法挂载或数据丢失
排查步骤:
|
|
常见原因及解决方案:
| 问题 | 原因 | 解决方案 |
|---|---|---|
| Pending | StorageClass 不存在 | 创建 StorageClass |
| Pending | PV 容量不足 | 扩容存储或清理 |
| FailedMount | 存储系统故障 | 检查 Ceph/NFS 等后端存储 |
| FailedMount | 权限问题 | 检查 SELinux/AppArmor |
| 数据丢失 | 使用 emptyDisk | 改用 PVC |
5. 网络问题
症状:VMI 网络不通或性能差
排查步骤:
|
|
常见原因及解决方案:
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 无法访问 | 网络策略限制 | 检查 NetworkPolicy |
| 无法访问 | DNS 解析失败 | 配置正确的 DNS |
| 性能差 | 网卡型号不匹配 | 使用 virtio 网卡 |
| 性能差 | 未启用多队列 | 设置 networkInterfaceMultiqueue: true |
调试工具和技巧
1. virtctl 工具
|
|
2. 日志查看
|
|
3. 性能诊断
|
|
4. Libvirt 调试
|
|
故障诊断流程图
graph TD
A["VMI 故障"] --> B{"VMI 状态?"}
B -->|Pending| C["检查 Pod 创建"]
B -->|Scheduling| D["检查节点资源"]
B -->|Scheduled| E["检查 virt-handler"]
B -->|Running| F["检查应用"]
B -->|Failed| G["查看日志"]
C --> C1{"Pod 创建了吗?"}
C1 -->|否| C2["检查 PVC/存储"]
C1 -->|是| C3["检查调度事件"]
D --> D1{"节点资源足够?"}
D1 -->|否| D2["扩容或清理"]
D1 -->|是| D3["检查节点选择器"]
E --> E1{"virt-handler 正常?"}
E1 -->|否| E2["检查 virt-handler Pod"]
E1 -->|是| E3["检查 virt-launcher 日志"]
F --> F1{"网络正常?"}
F1 -->|否| F2["检查网络配置"]
F1 -->|是| F3["检查应用日志"]
G --> G1{"查看哪个日志?"}
G1 -->|virt-launcher| G2["kubectl logs"]
G1 -->|libvirt| G3["/var/log/libvirt"]
G1 -->|QEMU| G4["/var/run/libvirt/qemu"]
关键日志路径
| 组件 | 日志路径 | 查看命令 |
|---|---|---|
| virt-operator | Pod 日志 | kubectl logs -n kubevirt deployment/virt-operator |
| virt-controller | Pod 日志 | kubectl logs -n kubevirt deployment/virt-controller |
| virt-handler | Pod 日志 | kubectl logs -n kubevirt <virt-handler-pod> |
| virt-launcher | Pod 日志 | kubectl logs <virt-launcher-pod> |
| libvirt | /var/log/libvirt/ |
kubectl exec <pod> -- ls /var/log/libvirt/ |
| QEMU | /var/run/libvirt/qemu/ |
kubectl exec <pod> -- cat /var/run/libvirt/qemu/vmi-*.log |
常用排查命令速查表
|
|
十、高级特性
GPU 透传
源码位置:
- GPU API:
staging/src/kubevirt.io/api/core/v1/schema.go:616-632 - GPU 处理:
pkg/virt-handler/device/
GPU 透传允许虚拟机直接访问主机 GPU,适合 AI/ML、图形渲染等场景。
GPU 透传类型
1. GPU Passthrough(完整透传)
|
|
前提条件:
- 节点有 GPU 设备
- 安装 GPU 设备插件(如 NVIDIA device plugin)
- 启用 IOMMU
- 禁用 Nouveau 驱动(NVIDIA)
2. vGPU(虚拟 GPU)
|
|
前提条件:
- NVIDIA vGPU 许可证
- vGPU Manager 安装
- vGPU 设备插件
GPU 配置步骤
1. 节点配置
|
|
2. 安装 GPU 设备插件
|
|
3. 验证 GPU 资源
|
|
GPU 使用示例
|
|
GPU 注意事项
- ⚠️ GPU 透传不支持热迁移
- ⚠️ 每个 GPU 只能分配给一个 VM
- ⚠️ 需要 GPU 驱动安装在 Guest OS
- ✅ vGPU 支持多个 VM 共享物理 GPU
SR-IOV 网络配置
源码位置:
- SR-IOV API:
staging/src/kubevirt.io/api/core/v1/schema.go:1463-1468 - SR-IOV 实现:
pkg/network/sriov/
SR-IOV 提供高性能网络,适合低延迟、高吞吐场景。
SR-IOV 工作原理
SR-IOV(Single Root I/O Virtualization)允许一个物理网卡虚拟成多个虚拟功能(VF),每个 VF 可以直接分配给虚拟机。
SR-IOV 配置步骤
1. 节点配置
|
|
2. 安装 SR-IOV Network Operator
|
|
3. 配置 SR-IOV Network
|
|
4. VM 使用 SR-IOV
|
|
SR-IOV 性能优势
| 特性 | SR-IOV | Bridge/Masquerade |
|---|---|---|
| 网络延迟 | 极低(< 10μs) | 较高(> 100μs) |
| 吞吐量 | 接近线速 | 较低(有开销) |
| CPU 开销 | 极低 | 较高(需要转发) |
| 热迁移 | 不支持 | 支持 |
SR-IOV 使用场景
- ✅ 金融交易系统(低延迟)
- ✅ NFV(网络功能虚拟化)
- ✅ 高性能计算(HPC)
- ❌ 需要热迁移的场景
CPU Pinning
源码位置:
- CPU Pinning API:
staging/src/kubevirt.io/api/core/v1/schema.go:376-380 - CPU Pinning 实现:
pkg/virt-controller/services/
CPU Pinning(CPU 绑定)将虚拟机 vCPU 绑定到物理 CPU,提高性能和确定性。
CPU Pinning 配置
|
|
CPU Pinning 工作原理
|
|
CPU Pinning 性能优势
| 特性 | CPU Pinning | 普通 VM |
|---|---|---|
| CPU 缓存命中率 | 高 | 低 |
| 上下文切换 | 少 | 多 |
| 性能确定性 | 高 | 低 |
| 延迟波动 | 小 | 大 |
CPU Pinning 使用场景
- ✅ 实时系统(RT Linux)
- ✅ 高性能数据库
- ✅ 游戏服务器
- ✅ 金融交易系统
CPU Pinning 注意事项
- ⚠️ 需要 Guaranteed QoS(requests == limits)
- ⚠️ 节点资源必须充足
- ⚠️ 可能影响节点其他工作负载
- ⚠️ 需要合理规划 CPU 资源
NUMA 亲和性
源码位置:
- NUMA API:
staging/src/kubevirt.io/api/core/v1/schema.go:383-385 - NUMA 实现:
pkg/virt-launcher/virtwrap/
NUMA(Non-Uniform Memory Access)亲和性优化内存访问性能。
NUMA 拓扑示例
|
|
NUMA 配置
|
|
NUMA 优化策略
1. 自动 NUMA 对齐
|
|
2. 手动 NUMA 配置
|
|
NUMA 性能影响
| 访问类型 | 延迟 | 带宽 |
|---|---|---|
| 本地 NUMA 内存 | 低 | 高 |
| 远程 NUMA 内存 | 高 | 低 |
优化建议:
- ✅ 将 VM 内存限制在一个 NUMA 节点
- ✅ GPU 和网卡在相同 NUMA 节点
- ✅ 使用 Hugepages 减少内存开销
实时 VM
源码位置:staging/src/kubevirt.io/api/core/v1/schema.go:387-389
实时 VM 用于需要极低延迟的场景(如工业控制、音频处理)。
实时 VM 配置
|
|
实时 VM 要求
- ✅ CPU Pinning(dedicatedCpuPlacement)
- ✅ Guaranteed QoS
- ✅ 内核支持 PREEMPT_RT
- ✅ 隔离 CPU(isolcpus=)
实时 VM 使用场景
- ✅ 工业控制系统
- ✅ 音频/视频处理
- ✅ 通信系统(5G、LTE)
- ✅ 金融交易系统
关键源码路径
| 功能 | 源码位置 |
|---|---|
| GPU 设备定义 | staging/src/kubevirt.io/api/core/v1/schema.go:616 |
| GPU 设备处理 | pkg/virt-handler/device/ |
| SR-IOV 配置 | staging/src/kubevirt.io/api/core/v1/schema.go:1463 |
| SR-IOV 实现 | pkg/network/sriov/ |
| CPU Pinning | staging/src/kubevirt.io/api/core/v1/schema.go:376 |
| NUMA 配置 | staging/src/kubevirt.io/api/core/v1/schema.go:383 |
| 实时 VM | staging/src/kubevirt.io/api/core/v1/schema.go:387 |
十一、最佳实践
生产环境部署建议
1. 节点要求
硬件要求:
- CPU:支持硬件虚拟化(Intel VT-x / AMD-V)
- 内存:建议 ≥ 64GiB(每节点)
- 存储:SSD 推荐,支持 RWX 模式
- 网络:万兆网卡推荐
内核要求:
|
|
系统配置:
|
|
2. 网络方案选择
| 网络方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Masquerade | 默认支持,无需额外配置 | 性能有开销,端口转发限制 | 开发测试、简单应用 |
| Bridge | 高性能,直接网络访问 | 需要网络配置,可能 IP 冲突 | 生产环境、高性能应用 |
| SR-IOV | 极致性能,低延迟 | 不支持热迁移,配置复杂 | NFV、金融交易 |
| Macvtap | 高性能,无需 Bridge | 不支持宿主机通信 | 隔离环境 |
推荐配置:
|
|
3. 存储配置建议
存储类选择:
| 存储类型 | 性能 | 迁移支持 | 适用场景 |
|---|---|---|---|
| Local PV | 极高 | ❌ 不支持 | 高性能数据库 |
| Ceph RBD | 高 | ✅ 支持 | 生产环境通用 |
| NFS | 中等 | ✅ 支持 | 文件共享、开发测试 |
| HostPath | 高 | ❌ 不支持 | 临时测试 |
存储最佳实践:
|
|
存储优化建议:
- ✅ 使用 SSD 存储提高性能
- ✅ 启用存储压缩(Ceph)
- ✅ 配置存储 QoS 限制
- ✅ 定期备份重要数据
性能调优技巧
1. CPU 性能优化
CPU Pinning 配置:
|
|
NUMA 优化:
|
|
CPU 特性启用:
|
|
2. 内存性能优化
Hugepages 配置:
|
|
节点预留大页:
|
|
内存气球配置:
|
|
3. I/O 性能优化
磁盘缓存配置:
|
|
多队列优化:
|
|
Virtiofs 高性能文件共享:
|
|
资源规划指导
1. 资源配额管理
|
|
2. QoS 策略
| QoS 等级 | 配置要求 | 优先级 | 适用场景 |
|---|---|---|---|
| Guaranteed | requests == limits | 高 | 生产关键应用 |
| Burstable | requests < limits | 中 | 开发测试环境 |
| BestEffort | 无 requests/limits | 低 | 临时任务 |
生产环境推荐:
|
|
3. 资源规划建议
节点规划:
- 每节点预留 10-20% 资源给系统进程
- VM 资源不超过节点资源的 80%
- 考虑迁移时的资源需求
容量规划公式:
|
|
安全最佳实践
1. Secure Boot 配置
|
|
前提条件:
- UEFI 固件支持
- SMM(System Management Mode)
- 签名的引导加载程序
2. TPM 设备
|
|
用途:
- 密钥存储
- 远程证明
- 安全启动度量
3. 网络安全
网络策略:
|
|
4. 访问控制
RBAC 配置:
|
|
备份和恢复策略
1. 快照管理
创建快照:
|
|
快照配置:
|
|
恢复快照:
|
|
2. 定期备份策略
使用 Velero 备份:
|
|
3. 灾难恢复
跨集群迁移:
|
|
监控和告警
1. Prometheus 集成
|
|
2. 关键指标
| 指标名称 | 说明 | 告警阈值 |
|---|---|---|
kubevirt_vmi_memory_available_bytes |
可用内存 | < 10% |
kubevirt_vmi_cpu_usage_seconds_total |
CPU 使用率 | > 90% |
kubevirt_vmi_storage_usage_bytes |
存储使用 | > 85% |
kubevirt_vmi_network_receive_bytes_total |
网络接收 | - |
kubevirt_vmi_network_transmit_bytes_total |
网络发送 | - |
3. 告警规则示例
|
|
运维最佳实践总结
✅ 生产环境检查清单
- 节点启用硬件虚拟化
- 禁用 swap
- 配置足够的 ulimit
- 存储支持 RWX(迁移需要)
- 网络方案选择合适
- 资源配额配置
- 监控和告警配置
- 定期备份策略
- 灾难恢复计划
- RBAC 权限配置
- 网络策略配置
⚠️ 常见陷阱
- 资源不足:未预留足够资源,导致调度失败
- 存储模式:使用 ReadWriteOnce(RWO),无法迁移
- 网络冲突:Bridge 模式 IP 地址冲突
- 权限不足:RBAC 配置不当,无法创建 VM
- 性能问题:未启用 CPU Pinning/Hugepages
📚 学习路径
- 入门:使用 Masquerade 模式、ContainerDisk
- 进阶:使用 Bridge 网络、PVC 存储、热迁移
- 高级:GPU 透传、SR-IOV、CPU Pinning
- 生产:监控告警、备份恢复、灾难恢复
十二、工作流程
创建 VM 的完整流程
sequenceDiagram
participant User as 用户
participant K8sAPI as K8s API Server
participant VM as VM CR
participant VMC as VM Controller
participant VMI as VMI CR
participant VC as VMI Controller
participant VH as virt-handler
participant VL as virt-launcher
User->>K8sAPI: 创建 VM 资源
K8sAPI->>VM: 创建 VM CRD 对象
VMC->>VM: WATCH 监听到 VM 创建
VMC->>VMC: execute() 处理 VM
VMC->>VMC: sync() 同步状态
alt RunStrategy = Always/Once
VMC->>VMC: syncRunStrategy() 判断需要启动
VMC->>VMC: startVMI()
VMC->>VMC: SetupVMIFromVM() 从 VM.template 创建 VMI
VMC->>K8sAPI: 创建 VMI 资源
K8sAPI->>VMI: 创建 VMI CRD 对象
Note over VC,VL: VMI 创建流程
VC->>VMI: WATCH 监听到 VMI 创建
VC->>K8sAPI: 创建关联的 Pod
K8sAPI->>Pod: 调度 Pod 到节点
VC->>VMI: 更新 nodeName
VH->>VMI: WATCH 监听到 VMI 分配到本节点
VH->>VL: 传递 VMI CRD 对象
VL->>VL: 启动虚拟机进程
else RunStrategy = Halted
VMC->>VMC: 不创建 VMI
end
核心源码路径
| 步骤 | 源码位置 | 函数名 |
|---|---|---|
| VM 事件处理 | pkg/virt-controller/watch/vm/vm.go:185-189 |
addVirtualMachine |
| 执行入口 | pkg/virt-controller/watch/vm/vm.go:335 |
Execute |
| 核心逻辑 | pkg/virt-controller/watch/vm/vm.go:356 |
execute |
| 同步逻辑 | pkg/virt-controller/watch/vm/vm.go:3173 |
sync |
| RunStrategy 处理 | pkg/virt-controller/watch/vm/vm.go:969 |
syncRunStrategy |
| 创建 VMI | pkg/virt-controller/watch/vm/vm.go:1256 |
startVMI |
| 从 VM 生成 VMI | pkg/virt-controller/watch/vm/vm.go:1867 |
SetupVMIFromVM |
SetupVMIFromVM 关键逻辑
|
|
六、关键代码目录
|
|
七、CDI (Containerized Data Importer)
CDI 项目提供了通过 DataVolume 将 PVC 用作 KubeVirt VM 磁盘的功能:
| 功能 | 说明 |
|---|---|
| 镜像导入 | 从 HTTP/S3/Registry 等源导入磁盘镜像 |
| 镜像上传 | 支持用户上传虚拟机磁盘镜像 |
| 空白磁盘 | 创建空白磁盘供虚拟机使用 |
| 数据卷克隆 | 克隆现有的数据卷 |
八、总结
KubeVirt 通过以下方式扩展 Kubernetes:
| 扩展方式 | 说明 |
|---|---|
| CRD 扩展 | 添加虚拟化相关的资源类型(VM、VMI 等) |
| 控制器 | 实现集群级别的虚拟机编排逻辑 |
| 代理 | 实现节点级别的虚拟机生命周期管理 |
| CLI 工具 | 提供用户友好的命令行接口 |
这种设计使得 KubeVirt 能够无缝集成到 Kubernetes 生态中,用户可以使用熟悉的 kubectl 和 Kubernetes API 来管理虚拟机,同时容器和虚拟机可以在同一个集群中并存。