ᕕ( ᐛ )ᕗ Jimyag's Blog

kubevirt 源码阅读

· 10810 字 · 约 51 分钟

KubeVirt 是一个基于 Kubernetes 的虚拟化平台,它通过 CRD 扩展 Kubernetes API,在 Kubernetes 之上提供虚拟机管理能力。本文将从架构、组件、工作流程等方面对 KubeVirt 进行深入分析。

一、整体架构

KubeVirt 采用服务导向架构编排模式,通过 CRD 扩展 Kubernetes API,在 Kubernetes 之上提供虚拟化管理能力。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
+---------------------+
| KubeVirt            |  ← 虚拟化层
+---------------------+
| Orchestration (K8s) |  ← 编排层
+---------------------+
| Container Runtime   |  ← 容器运行时
+---------------------+
| Operating System    |  ← 操作系统层
+---------------------+
| Physical            |  ← 物理硬件
+---------------------+

核心设计理念:将虚拟机作为 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。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
apiVersion: kubevirt.io/v1
kind: VirtualMachineInstance
metadata:
  name: my-vmi
spec:
  domain:
    cpu:
      cores: 2
    memory:
      guest: 4Gi
    devices:
      disks:
      - disk:
          bus: virtio
        name: containerdisk
  volumes:
  - containerDisk:
      image: quay.io/containerdisks/fedora:latest
    name: containerdisk

VirtualMachine (VM)

VM 是有状态虚拟机,可以停止/启动,保持数据。

VM 结构概览

1
2
3
4
5
6
type VirtualMachine struct {
    metav1.TypeMeta
    metav1.ObjectMeta
    Spec   VirtualMachineSpec   // 虚拟机规格
    Status VirtualMachineStatus // 虚拟机状态
}

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
func (vm *VirtualMachine) RunStrategy() (VirtualMachineRunStrategy, error) {
    // running 和 runStrategy 互斥
    if vm.Spec.Running != nil && vm.Spec.RunStrategy != nil {
        return RunStrategyUnknown, fmt.Errorf("running and runstrategy are mutually exclusive")
    }
    RunStrategy := RunStrategyHalted
    if vm.Spec.Running != nil {
        if (*vm.Spec.Running) == true {
            RunStrategy = RunStrategyAlways
        }
    } else if vm.Spec.RunStrategy != nil {
        RunStrategy = *vm.Spec.RunStrategy
    }
    return RunStrategy, nil
}

处理逻辑pkg/virt-controller/watch/vm/vm.go:969-1150

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
func (c *Controller) syncRunStrategy(vm *virtv1.VirtualMachine, vmi *virtv1.VirtualMachineInstance, runStrategy virtv1.VirtualMachineRunStrategy) {
    switch runStrategy {
    case virtv1.RunStrategyAlways:
        // VMI 应该始终运行
        if vmi == nil { c.startVMI(vm) }
    case virtv1.RunStrategyHalted:
        // 不应该有 VMI 运行
        if vmi != nil { c.stopVMI(vm, vmi) }
    case virtv1.RunStrategyManual:
        // 手动启停
        if vmi == nil && hasStartRequest(vm) { c.startVMI(vm) }
    case virtv1.RunStrategyRerunOnFailure:
        // 失败时重启
    case virtv1.RunStrategyOnce:
        // 只运行一次
        if vmi == nil { c.startVMI(vm) }
    }
}

instancetype 和 preference 字段说明

字段 作用 示例
instancetype 预定义的实例规格(CPU、内存) Standard-2Memory-Optimized-4
preference 预定义的设备偏好设置 磁盘总线类型、网络模型等

使用示例

1
2
3
4
5
6
7
8
9
spec:
  instancetype:
    name: "standard-2"      # 引用集群级别的 instancetype
    # kind: "VirtualMachineInstancetype" 或 "VirtualMachineClusterInstancetype"
  preference:
    name: "fedora"          # 引用偏好设置
  template:
    spec:
      domain: {}            # instancetype 会自动填充

处理逻辑pkg/virt-controller/watch/vm/vm.go:3227

1
syncedVM, err := c.instancetypeController.Sync(vm, vmi)

template 字段说明

template 定义 VMI 的模板,当创建 VMI 时会从此模板复制。

源码位置pkg/virt-controller/watch/vm/vm.go:1867-1896

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
func SetupVMIFromVM(vm *virtv1.VirtualMachine) *virtv1.VirtualMachineInstance {
    vmi := libvmi.New()
    // 从 template 复制元数据和规格
    vmi.ObjectMeta = *vm.Spec.Template.ObjectMeta.DeepCopy()
    vmi.ObjectMeta.Name = vm.ObjectMeta.Name
    vmi.ObjectMeta.Namespace = vm.ObjectMeta.Namespace
    vmi.Spec = *vm.Spec.Template.Spec.DeepCopy()
    // 设置 OwnerReference
    vmi.ObjectMeta.OwnerReferences = []metav1.OwnerReference{
        *metav1.NewControllerRef(vm, virtv1.VirtualMachineGroupVersionKind),
    }
    return vmi
}

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 字段详解

domainVirtualMachineInstanceSpec 的核心字段,定义了虚拟机的硬件配置。

源码位置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
2
3
4
5
6
7
8
9
domain:
  resources:
    requests:
      memory: "4Gi"
      cpu: "2"
    limits:
      memory: "8Gi"
      cpu: "4"
    overcommitGuestOverhead: false

字段用途详解

1. 资源请求(resources.requests)

用途:定义虚拟机启动所需的最小资源,Kubernetes 调度器根据此值选择节点。

使用场景

  • 调度决策:确保节点有足够资源
  • 资源预留:为 VM 预留最小资源
  • QoS 保证:配合 limits 实现 Guaranteed QoS
  • 节点规划:集群容量规划依据

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 场景1:最小资源保证
resources:
  requests:
    memory: "2Gi"          # 最小内存
    cpu: "1"               # 最小 CPU

# 场景2:与 limits 相同(Guaranteed QoS)
resources:
  requests:
    memory: "4Gi"
    cpu: "2"
  limits:
    memory: "4Gi"
    cpu: "2"

注意事项

  • requests ≤ limits(否则调度失败)
  • 影响调度决策
  • 过小导致性能问题
  • 过大导致资源浪费

2. 资源限制(resources.limits)

用途:定义虚拟机可使用的最大资源,防止资源耗尽。

使用场景

  • 资源隔离:防止 VM 占用过多资源
  • 性能保证:确保 VM 有足够资源
  • 节点稳定性:防止资源争抢
  • 成本控制:限制资源使用

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 场景1:限制最大资源
resources:
  limits:
    memory: "8Gi"          # 最大内存
    cpu: "4"               # 最大 CPU

# 场景2:开发测试环境(宽松限制)
resources:
  requests:
    memory: "1Gi"
    cpu: "500m"
  limits:
    memory: "2Gi"
    cpu: "1"

# 场景3:生产环境(Guaranteed QoS)
resources:
  requests:
    memory: "16Gi"
    cpu: "8"
  limits:
    memory: "16Gi"         # 与 requests 相同
    cpu: "8"

QoS 等级

  • Guaranteed:requests == limits(最高优先级)
  • Burstable:requests < limits(中等优先级)
  • BestEffort:无 requests/limits(最低优先级)

注意事项

  • 超过 limits 可能被 OOMKilled
  • CPU limits 使用 CFS quota 限制
  • 内存限制强制生效(硬限制)
  • 生产环境建议 Guaranteed QoS

3. Guest 开销超卖(overcommitGuestOverhead)

用途:控制是否将虚拟化开销(QEMU、libvirt 等)计入容器内存限制。

使用场景

  • 内存超卖:提高节点内存利用率
  • 资源优化:减少预留资源
  • 开发测试:节省资源成本
  • 生产环境:谨慎使用

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 场景1:默认行为(保守)
resources:
  requests:
    memory: "4Gi"
  limits:
    memory: "4Gi"
  overcommitGuestOverhead: false  # 开销不计入限制

# 场景2:超卖模式(激进)
resources:
  requests:
    memory: "4Gi"
  limits:
    memory: "4Gi"
  overcommitGuestOverhead: true   # 开销计入限制
  # 实际可用内存 = 4Gi - 开销(约 100-300MB)

工作原理

  • false(默认):容器内存限制 = VM 内存 + 开销
  • true:容器内存限制 = VM 内存(开销从 VM 内存中扣除)

注意事项

  • 开销通常 100-300MB(取决于 VM 配置)
  • true 时可能影响 VM 性能
  • 建议仅在内存充足时使用
  • 生产环境建议 false

内存配置最佳实践

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 生产环境推荐配置
resources:
  requests:
    memory: "8Gi"           # VM 需要的内存
    cpu: "4"
  limits:
    memory: "8Gi"           # 与 requests 相同(Guaranteed QoS)
    cpu: "4"
  overcommitGuestOverhead: false  # 保守配置

# 开发测试环境配置
resources:
  requests:
    memory: "2Gi"
    cpu: "1"
  limits:
    memory: "4Gi"           # 允许突发
    cpu: "2"
  overcommitGuestOverhead: true   # 节省资源
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 拓扑

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 场景1:单 socket 多 core(节省许可证成本)
cpu:
  sockets: 1
  cores: 8
  threads: 1      # 总 vCPU = 8,但只有 1 个 socket

# 场景2:多 socket(模拟 NUMA 拓扑)
cpu:
  sockets: 2
  cores: 4
  threads: 1      # 总 vCPU = 8,2 个 socket,模拟 NUMA

# 场景3:启用超线程
cpu:
  sockets: 1
  cores: 4
  threads: 2      # 总 vCPU = 8,每个 core 有 2 个线程

注意事项

  • 总 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

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 场景1:高兼容性(适合迁移)
cpu:
  model: "host-model"

# 场景2:嵌套虚拟化
cpu:
  model: "host-passthrough"

# 场景3:特定 CPU 特性
cpu:
  model: "Skylake-Client"
  features:
  - name: "avx512f"
    policy: "require"

注意事项

  • host-passthrough 会降低迁移能力(目标节点 CPU 必须完全相同)
  • 某些 CPU 特性可能影响安全性(需评估)

3. CPU Pinning(dedicatedCpuPlacement)

用途:将虚拟机 CPU 绑定到物理 CPU,提供确定性性能。

使用场景

  • 实时应用:低延迟要求的金融交易、电信应用
  • 高性能计算:科学计算、AI 训练
  • 性能隔离:防止其他虚拟机干扰

示例

1
2
3
4
5
cpu:
  dedicatedCpuPlacement: true
  isolateEmulatorThread: true   # 隔离模拟器线程,进一步降低延迟
  realtime:
    mask: "0-3"                 # 使用 CPU 0-3 进行实时任务

注意事项

  • 需要节点有足够的空闲 CPU
  • 会降低资源利用率(独占 CPU)
  • 需要配合资源请求使用

4. CPU 热插拔(maxSockets)

用途:支持运行时动态调整 CPU 数量。

使用场景

  • 弹性扩展:根据负载动态调整 CPU
  • 维护窗口:临时增加 CPU 处理峰值负载

示例

1
2
3
4
cpu:
  sockets: 2
  cores: 4
  maxSockets: 4      # 可以热插拔到 4 个 socket(16 vCPU)

注意事项

  • 需要 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: 如果主机支持该特性则创建失败

示例

1
2
3
4
5
6
7
domain:
  cpu:
    features:
    - name: "vmx"
      policy: "require"
    - name: "sse4.1"
      policy: "optional"
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
  • 成本控制:合理配置避免资源浪费

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 场景1:小型应用
memory:
  guest: "2Gi"

# 场景2:大型数据库
memory:
  guest: "64Gi"

# 场景3:内存与资源请求不同
resources:
  requests:
    memory: "4Gi"
  limits:
    memory: "4Gi"
memory:
  guest: "3.5Gi"      # Guest 看到的内存略小于请求(预留 overhead)

注意事项

  • Guest 内存应 ≤ 资源请求
  • 需要考虑虚拟化开销(通常 5-10%)
  • 过大的内存可能导致调度困难

2. 内存热插拔(maxGuest)

用途:支持运行时动态调整内存大小。

使用场景

  • 弹性扩展:根据负载动态调整内存
  • 维护窗口:临时增加内存处理峰值负载

示例

1
2
3
memory:
  guest: "4Gi"
  maxGuest: "8Gi"      # 可以热插拔到 8Gi

注意事项

  • 需要 Guest OS 支持内存热插拔
  • Linux 内核需要启用相关选项
  • Windows 需要特定版本支持

3. 大页内存(hugepages)

用途:使用大页内存提高性能,减少 TLB miss。

使用场景

  • 高性能数据库:Oracle、PostgreSQL 等大型数据库
  • 实时应用:需要低延迟的应用
  • 内存密集型应用:AI 训练、大数据分析

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 场景1:使用 2Mi 大页
memory:
  guest: "16Gi"
  hugepages:
    pageSize: "2Mi"

# 场景2:使用 1Gi 大页(需要节点支持)
memory:
  guest: "64Gi"
  hugepages:
    pageSize: "1Gi"

配置要求

  • 节点必须预分配大页内存
  • 需要在节点启动时配置(如 default_hugepagesz=2M hugepagesz=2M hugepages=1024
  • Kubernetes 需要配置 --feature-gates=HugePages=true

性能优势

  • 减少 TLB miss,提高内存访问速度
  • 减少页表大小,节省内存
  • 适合内存密集型应用

注意事项

  • 大页内存不能 swap
  • 需要精确规划内存使用
  • 过大的大页可能导致内存碎片

4. 内存锁定(memLock)

用途:锁定内存防止 swap,保证性能和安全性。

使用场景

  • 实时应用:防止 swap 导致延迟
  • 安全应用:防止敏感数据 swap 到磁盘
  • VFIO/DPDK:硬件设备 DMA 需要

示例

1
2
3
4
memory:
  guest: "8Gi"
  reservedOverhead:
    memLock: "Required"      # 锁定内存

注意事项

  • 需要 ulimit 配置(memlock
  • 可能影响节点内存管理
  • 适合专用节点
domain.machine 字段详解

源码位置staging/src/kubevirt.io/api/core/v1/schema.go:499-503

字段路径 类型 必填 默认值 说明
machine.type string 架构相关 QEMU 机器类型(如 “q35”, “pc-q35-6.2”)

示例

1
2
3
domain:
  machine:
    type: "q35"
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
2
3
4
5
6
7
8
domain:
  firmware:
    uuid: "5d30b294-1f6d-11e9-bb3a-0242ac130002"
    bootloader:
      efi:
        secureBoot: true
        persistent: true
    serial: "my-vm-serial"

字段用途详解

1. BIOS UUID(firmware.uuid)

用途:设置虚拟机的 BIOS UUID,用于标识虚拟机。

使用场景

  • 许可证管理:软件许可绑定 UUID
  • 资产追踪:唯一标识 VM
  • 集群软件:UUID 作为节点标识
  • 迁移一致性:迁移后保持 UUID 不变

示例

1
2
3
4
# 场景:许可证绑定 UUID
volumes:
firmware:
  uuid: "5d30b294-1f6d-11e9-bb3a-0242ac130002"  # 固定 UUID

注意事项

  • 未指定时随机生成
  • 迁移时保持不变
  • 某些软件依赖 UUID 唯一性

2. 引导加载程序(firmware.bootloader)

用途:配置虚拟机的引导方式(BIOS 或 EFI)。

使用场景

  • BIOS 引导:传统引导方式,兼容性好(默认)
  • UEFI 引导:现代引导方式,支持大磁盘、Secure Boot
  • Secure Boot:安全启动,防止未授权代码执行
  • 串口输出:BIOS 输出到串口(无头服务器)

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 场景1:UEFI + Secure Boot
firmware:
  bootloader:
    efi:
      secureBoot: true       # 启用 Secure Boot
      persistent: true       # NVRAM 持久化

# 场景2:BIOS 串口输出
firmware:
  bootloader:
    bios:
      useSerial: true        # BIOS 输出到串口

# 场景3:传统 BIOS(默认)
firmware:
  bootloader:
    bios: {}                 # 或省略

注意事项

  • Secure Boot 需要 SMM 支持
  • UEFI 适合 GPT 分区、大磁盘
  • persistent: true 保存 EFI 变量
  • 某些 OS 需要 UEFI(如 Windows 11)

3. SMBIOS 序列号(firmware.serial)

用途:设置 SMBIOS 序列号,用于资产管理和软件识别。

使用场景

  • 资产管理:硬件资产追踪
  • 软件激活:序列号绑定软件
  • 许可证管理:基于序列号的授权
  • 合规性:满足审计要求

示例

1
2
3
# 场景:资产管理序列号
firmware:
  serial: "VM-PROD-001"      # 自定义序列号

注意事项

  • 未指定时为空
  • 可通过 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
 2
 3
 4
 5
 6
 7
 8
 9
10
11
domain:
  devices:
    disks:
    - name: "root-disk"
      disk:
        bus: virtio
    interfaces:
    - name: "default"
      masquerade: {}
    autoattachGraphicsDevice: true
    autoattachSerialConsole: true

自动附加字段用途详解

1. 自动附加 Pod 网络(autoattachPodInterface)

用途:控制是否自动将 Pod 网络附加到虚拟机。

使用场景

  • 默认行为:自动附加 Pod 网络(默认 true)
  • 无网络 VM:禁用网络连接
  • 多网络:使用 Multus 配置多个网络接口
  • 安全隔离:完全禁用网络

示例

1
2
3
4
5
6
7
8
# 场景1:禁用网络
devices:
  autoattachPodInterface: false  # 无网络连接

# 场景2:使用 Multus 多网络
devices:
  autoattachPodInterface: false  # 禁用默认 Pod 网络
# 然后通过 interfaces 配置 Multus 网络

注意事项

  • 默认 true,自动附加 eth0
  • 设为 false 需要显式配置网络接口
  • 无网络 VM 适合离线处理

2. 自动附加图形设备(autoattachGraphicsDevice)

用途:控制是否自动附加 VNC 图形设备。

使用场景

  • 图形界面:需要 VNC 连接(默认 true)
  • 无头服务器:禁用图形设备节省资源
  • 控制台访问:仅使用串口控制台
  • 资源优化:减少不必要设备

示例

1
2
3
4
5
6
7
8
# 场景1:无头服务器
devices:
  autoattachGraphicsDevice: false  # 禁用 VNC
  autoattachSerialConsole: true    # 启用串口

# 场景2:图形界面
devices:
  autoattachGraphicsDevice: true   # 启用 VNC(默认)

注意事项

  • 禁用后无法使用 VNC
  • 建议配合串口控制台使用
  • 可节省少量内存和 CPU

3. 自动附加串口控制台(autoattachSerialConsole)

用途:控制是否自动附加串口控制台,用于命令行访问。

使用场景

  • 命令行访问:SSH 或 virtctl console 连接
  • 日志输出:捕获启动日志
  • 自动化脚本:通过串口执行命令
  • 调试诊断:查看内核消息

示例

1
2
3
4
5
6
7
8
9
# 场景1:启用串口控制台(默认)
devices:
  autoattachSerialConsole: true
  logSerialConsole: true  # 记录串口日志

# 场景2:仅串口,无图形
devices:
  autoattachGraphicsDevice: false
  autoattachSerialConsole: true

注意事项

  • 默认 true
  • 可通过 virtctl console <vm> 连接
  • logSerialConsole 记录日志到文件

4. 自动附加内存气球(autoattachMemBalloon)

用途:控制是否自动附加内存气球设备,用于动态内存管理。

使用场景

  • 内存超卖:释放未使用内存给其他 VM
  • 内存监控:监控 VM 实际内存使用
  • 资源优化:提高内存利用率
  • 性能敏感:禁用以避免性能波动

示例

1
2
3
4
5
6
7
# 场景1:启用内存气球(默认)
devices:
  autoattachMemBalloon: true  # 默认值

# 场景2:性能敏感应用
devices:
  autoattachMemBalloon: false  # 禁用内存气球

注意事项

  • 默认 true
  • 需要 virtio 驱动支持
  • 可能导致内存性能波动
  • 适合内存超卖场景

5. 块设备多队列(blockMultiQueue)

用途:启用块设备多队列,提高磁盘 I/O 性能。

使用场景

  • 高 I/O 负载:数据库、大数据应用
  • 多 vCPU:多核 VM 并行 I/O
  • 高性能存储:NVMe、SSD
  • 延迟敏感:实时应用

示例

1
2
3
# 场景:高性能数据库
devices:
  blockMultiQueue: true  # 启用多队列

注意事项

  • 需要多 vCPU 才有明显效果
  • 增加少量 CPU 开销
  • Linux 内核 4.x+ 支持
  • 适合 I/O 密集型应用

6. 网络接口多队列(networkInterfaceMultiqueue)

用途:启用网络接口多队列,提高网络性能。

使用场景

  • 高网络流量:Web 服务器、流媒体
  • 多 vCPU:多核 VM 并行网络处理
  • 低延迟网络:实时应用、金融交易
  • 高性能网络:10Gbps+ 网络

示例

1
2
3
# 场景:高流量 Web 服务器
devices:
  networkInterfaceMultiqueue: true  # 启用多队列

注意事项

  • 需要多 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
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
domain:
  devices:
    disks:
    - name: "root-disk"
      disk:
        bus: virtio
      bootOrder: 1
      cache: "none"
    - name: "cdrom"
      cdrom:
        bus: sata
        readonly: true

字段用途详解

1. 磁盘总线类型(disk.bus)

用途:定义磁盘的总线类型,影响性能和兼容性。

使用场景

  • virtio:高性能虚拟化环境,推荐用于 Linux/Windows
  • sata:兼容性好,适合旧版 OS 或需要热迁移
  • scsi:支持 SCSI 命令,适合需要高级功能的场景
  • usb:适合可移动设备或临时挂载

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 场景1:高性能 Linux VM
disks:
- name: "root-disk"
  disk:
    bus: virtio        # 推荐用于现代 OS

# 场景2:需要 SCSI 持久预留
disks:
- name: "shared-disk"
  lun:
    bus: scsi
    reservation: true  # SCSI PR 支持

性能对比

  • virtio: 最快(需要 virtio 驱动)
  • scsi: 较快(支持多队列)
  • sata: 中等(兼容性好)
  • usb: 最慢(适合临时使用)

注意事项

  • Windows 需要安装 virtio 驱动
  • 热迁移需要相同总线类型
  • 不同总线类型支持不同的功能

2. 缓存模式(cache)

用途:控制磁盘 I/O 缓存策略,影响性能和数据安全。

使用场景

  • none:无缓存,数据安全性最高,适合数据库
  • writethrough:写透缓存,平衡性能和安全
  • writeback:回写缓存,性能最高但有数据丢失风险
  • unsafe:不安全缓存,仅用于测试

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 场景1:数据库磁盘
disks:
- name: "db-data"
  disk:
    bus: virtio
  cache: "none"          # 数据安全优先

# 场景2:只读数据
disks:
- name: "static-data"
  disk:
    bus: virtio
  cache: "writeback"     # 性能优先

# 场景3:临时数据
disks:
- name: "temp-data"
  disk:
    bus: virtio
  cache: "unsafe"        # 仅测试环境

注意事项

  • 生产环境避免使用 unsafe
  • 数据库建议使用 none
  • 结合 io: native 获得最佳性能

3. 启动顺序(bootOrder)

用途:定义磁盘启动优先级。

使用场景

  • 多磁盘 VM:指定从哪个磁盘启动
  • 网络启动:与网络接口配合使用
  • CDROM 启动:从 ISO 启动安装

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 场景1:从磁盘启动
disks:
- name: "root-disk"
  disk:
    bus: virtio
  bootOrder: 1           # 第一启动
- name: "cdrom"
  cdrom:
    bus: sata
  bootOrder: 2           # 第二启动

# 场景2:PXE 安装后从磁盘启动
disks:
- name: "install-cdrom"
  cdrom:
    bus: sata
  bootOrder: 2
interfaces:
- name: "pxe-net"
  bootOrder: 1           # PXE 启动优先

注意事项

  • 值越小优先级越高
  • 未设置 bootOrder 的设备优先级最低
  • 可用于磁盘和网络接口

4. 错误策略(errorPolicy)

用途:定义磁盘 I/O 错误时的处理策略。

使用场景

  • stop:停止 VM,适合关键应用(默认)
  • ignore:忽略错误,适合非关键数据
  • report:报告错误但继续运行
  • enospace:仅在空间不足时停止

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 场景1:关键数据库
disks:
- name: "db-data"
  disk:
    bus: virtio
  errorPolicy: "stop"     # 错误时停止 VM

# 场景2:日志磁盘
disks:
- name: "logs"
  disk:
    bus: virtio
  errorPolicy: "ignore"   # 忽略错误继续运行

注意事项

  • 生产环境建议使用 stop
  • ignore 可能导致数据损坏
  • 需要监控错误事件

5. 专用 I/O 线程(dedicatedIOThread)

用途:为磁盘分配专用的 I/O 线程,提高性能。

使用场景

  • 高 I/O 负载:数据库、大数据应用
  • 延迟敏感:实时应用
  • 多磁盘竞争:多个高 I/O 磁盘

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 场景1:高性能数据库
disks:
- name: "db-data"
  disk:
    bus: virtio
  dedicatedIOThread: true  # 专用 I/O 线程

# 场景2:多个高 I/O 磁盘
disks:
- name: "data-1"
  disk:
    bus: virtio
  dedicatedIOThread: true
- name: "data-2"
  disk:
    bus: virtio
  dedicatedIOThread: true

注意事项

  • 增加 CPU 开销
  • 适合 I/O 密集型应用
  • 需要足够的 CPU 资源

6. 可共享磁盘(shareable)

用途:允许多个 VM 同时访问同一磁盘。

使用场景

  • 集群文件系统:GFS2、OCFS2
  • 共享存储:多节点应用
  • 读写一致性:需要应用层协调

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 场景1:共享数据磁盘
disks:
- name: "shared-data"
  disk:
    bus: virtio
  shareable: true        # 多 VM 可同时访问

# 场景2:集群文件系统
disks:
- name: "gfs2-disk"
  lun:
    bus: scsi
  shareable: true

注意事项

  • 需要集群文件系统或应用层锁
  • 不能用于普通文件系统(会导致损坏)
  • 建议 SCSI 总线 + reservation

7. 变更块追踪(changedBlockTracking)

用途:启用变更块追踪,支持增量备份。

使用场景

  • 备份系统:支持增量备份
  • 快照管理:减少备份时间和空间
  • 灾难恢复:快速增量复制

示例

1
2
3
4
5
6
# 场景:启用增量备份
disks:
- name: "data-disk"
  disk:
    bus: virtio
  changedBlockTracking: true  # 支持增量备份

注意事项

  • 需要备份软件支持
  • 增加少量性能开销
  • 适合定期备份的磁盘
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
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
volumes:
- name: "root-disk"
  persistentVolumeClaim:
    claimName: "my-pvc"
- name: "containerdisk"
  containerDisk:
    image: "quay.io/containerdisks/fedora:latest"
    imagePullPolicy: "IfNotPresent"
- name: "cloudinit"
  cloudInitNoCloud:
    userData: |
      #cloud-config
      password: fedora
      chpasswd: { expire: False }

卷类型用途详解

1. PersistentVolumeClaim(PVC)卷

用途:使用 Kubernetes PVC 作为虚拟机磁盘,支持持久化存储。

使用场景

  • 持久化数据:数据库、应用数据
  • 动态供给:使用 StorageClass 动态创建 PV
  • 存储迁移:数据独立于 VM 生命周期
  • 热插拔:支持运行时挂载/卸载(hotpluggable: true)

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 场景1:使用 PVC 作为根磁盘
volumes:
- name: "root-disk"
  persistentVolumeClaim:
    claimName: "vm-root-pvc"  # 引用已存在的 PVC

# 场景2:可热插拔数据盘
volumes:
- name: "data-disk"
  persistentVolumeClaim:
    claimName: "data-pvc"
    hotpluggable: true       # 支持热插拔

注意事项

  • PVC 必须先创建或使用 DataVolume 自动创建
  • 支持 Block 和 Filesystem 模式
  • 热插拔需要 VM 运行时操作
  • 删除 VM 时 PVC 默认保留

2. ContainerDisk(容器磁盘)

用途:使用容器镜像作为虚拟机磁盘,适合只读或临时使用。

使用场景

  • 操作系统镜像:快速启动标准 OS
  • 只读数据:静态内容、工具镜像
  • 测试环境:快速迭代、无需持久化
  • 镜像分发:通过容器仓库分发磁盘镜像

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 场景1:使用标准 OS 镜像
volumes:
- name: "os-disk"
  containerDisk:
    image: "quay.io/containerdisks/fedora:latest"
    imagePullPolicy: "IfNotPresent"  # 本地优先

# 场景2:私有镜像仓库
volumes:
- name: "custom-os"
  containerDisk:
    image: "registry.example.com/vm-images/ubuntu:20.04"
    imagePullSecret: "registry-credentials"  # 拉取密钥
    path: "disk.img"  # 磁盘文件在容器中的路径

注意事项

  • 容器镜像中的磁盘文件通常是只读的
  • 每次启动都会拉取新镜像(除非 imagePullPolicy: Never)
  • 不适合持久化数据
  • 支持多种格式:qcow2, raw, img

3. EmptyDisk(临时磁盘)

用途:创建与 VM 生命周期相同的临时磁盘,VM 删除时数据丢失。

使用场景

  • 临时数据:缓存、临时文件
  • 交换分区:swap 空间
  • 测试数据:测试环境的临时存储
  • 无持久化需求:数据无需保留

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 场景1:临时数据盘
volumes:
- name: "temp-data"
  emptyDisk:
    capacity: "10Gi"  # 大小

# 场景2:交换分区
volumes:
- name: "swap"
  emptyDisk:
    capacity: "4Gi"

注意事项

  • VM 删除后数据丢失
  • 使用节点本地存储
  • 性能较好(无网络开销)
  • 不适合重要数据

4. CloudInitNoCloud(cloud-init 配置)

用途:通过 cloud-init 在启动时配置虚拟机。

使用场景

  • 初始化配置:设置主机名、用户、密码
  • 网络配置:静态 IP、DNS、路由
  • 软件安装:启动时安装软件包
  • SSH 密钥:注入 SSH 公钥

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 场景1:基础用户配置
volumes:
- name: "cloudinit"
  cloudInitNoCloud:
    userData: |
      #cloud-config
      hostname: my-vm
      users:
      - name: admin
        sudo: ALL=(ALL) NOPASSWD:ALL
        ssh_authorized_keys:
        - ssh-rsa AAAA... [email protected]
      packages:
      - nginx
      - docker

# 场景2:网络配置
volumes:
- name: "cloudinit"
  cloudInitNoCloud:
    userData: |
      #cloud-config
      hostname: web-server
    networkData: |
      version: 2
      ethernets:
        eth0:
          addresses:
          - 192.168.1.100/24
          gateway4: 192.168.1.1
          nameservers:
            addresses:
            - 8.8.8.8

注意事项

  • 需要 cloud-init 软件包
  • userData 和 userDataBase64 互斥
  • 支持 NoCloud 和 ConfigDrive 两种数据源
  • 配置仅在首次启动生效

5. HostDisk(主机磁盘)

用途:使用节点主机上的文件作为虚拟机磁盘。

使用场景

  • 本地存储:使用节点本地磁盘
  • 高性能:避免网络存储开销
  • 特定节点:数据固定在特定节点
  • 迁移限制:不适合跨节点迁移

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 场景1:使用已存在的磁盘文件
volumes:
- name: "local-disk"
  hostDisk:
    path: "/data/vms/vm1.qcow2"
    type: Disk  # 文件必须存在

# 场景2:自动创建磁盘文件
volumes:
- name: "auto-disk"
  hostDisk:
    path: "/data/vms/auto.qcow2"
    type: DiskOrCreate  # 不存在则创建
    capacity: "20Gi"

注意事项

  • 节点必须有足够磁盘空间
  • 跨节点迁移受限(需要共享存储)
  • 适合节点本地高性能场景
  • 需要节点访问权限

6. DataVolume(数据卷)

用途:使用 CDI(Containerized Data Importer)自动创建和管理 PVC。

使用场景

  • 自动导入:从 URL、容器镜像、上传导入磁盘镜像
  • 克隆 PVC:从现有 PVC 克隆
  • 空白磁盘:创建空白块设备
  • 自动化管理:无需手动创建 PVC

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 场景1:从 URL 导入镜像
volumes:
- name: "root-disk"
  dataVolume:
    name: "fedora-dv"  # 引用 DataVolume
---
# DataVolume 定义(需要单独创建)
apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
  name: fedora-dv
spec:
  source:
    http:
      url: "https://example.com/fedora.qcow2"
  pvc:
    accessModes:
    - ReadWriteOnce
    resources:
      requests:
        storage: 10Gi

# 场景2:可热插拔 DataVolume
volumes:
- name: "data-disk"
  dataVolume:
    name: "data-dv"
    hotpluggable: true

注意事项

  • 需要 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
2
3
4
5
6
7
interfaces:
- name: "primary"
  bridge: {}
  acpiIndex: 1        # 稳定的索引,不会因 PCI 地址变化而改变
- name: "secondary"
  bridge: {}
  acpiIndex: 2

注意事项

  • 值必须在所有设备中唯一(包括磁盘等设备)
  • 值范围:1 到 16383

2. dhcpOptions - 自定义 DHCP 选项

用途:为虚拟机网络接口传递额外的 DHCP 配置选项。

主要应用场景

a) PXE 网络启动

1
2
3
4
5
6
7
interfaces:
- name: "pxe-boot"
  bridge: {}
  dhcpOptions:
    bootFileName: "pxelinux.0"        # DHCP 选项 67:引导文件名
    tftpServerName: "192.168.1.100"   # DHCP 选项 66:TFTP 服务器地址
  bootOrder: 1                        # 从网络启动

b) NTP 时间同步

1
2
3
4
5
6
7
interfaces:
- name: "default"
  masquerade: {}
  dhcpOptions:
    ntpServers:
    - "192.168.1.1"
    - "192.168.1.2"                   # DHCP 选项 042:NTP 服务器列表

c) 自定义私有选项

1
2
3
4
5
6
7
interfaces:
- name: "custom"
  bridge: {}
  dhcpOptions:
    privateOptions:
    - option: 224                     # 私有选项编号(224-254)
      value: "custom-value"           # 选项值

DHCP 选项编号对照

  • 选项 66:TFTP 服务器名称
  • 选项 67:引导文件名
  • 选项 042:NTP 服务器
  • 选项 224-254:私有选项(用户自定义)

3. tag - 网络接口元数据标签

用途:通过 config drive 将网络接口信息暴露给 Guest OS。

工作原理

  1. KubeVirt 将网络接口的元数据(IP 地址、MAC 地址、标签)写入 config drive
  2. Guest OS 通过 cloud-init 读取这些元数据
  3. 应用可以根据标签识别特定的网络接口

使用场景

  • 多网卡虚拟机:区分不同用途的网络接口(管理网、存储网、业务网)
  • 自动化配置:Guest 内部脚本根据标签自动配置网络
  • 网络隔离:标识不同安全级别的网络接口

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
interfaces:
- name: "management"
  bridge: {}
  tag: "management-network"      # 管理网络
- name: "storage"
  bridge: {}
  tag: "storage-network"         # 存储网络
- name: "application"
  bridge: {}
  tag: "app-network"             # 业务网络

Guest 内部访问: Guest OS 可以通过 cloud-init 的 metadata 服务访问这些标签:

1
2
# 在 Guest OS 内
curl http://169.254.169.254/openstack/latest/network_data.json

4. state - 接口操作状态控制

用途:动态控制网络接口的运行状态。

状态值说明

a) up(默认)- 启动接口

  • 将网络接口设置为启动状态
  • 接口可以正常收发数据包
  • 默认行为

b) down - 关闭接口

  • 将网络接口设置为关闭状态
  • 接口停止收发数据包
  • 但接口仍然存在(未删除)

c) absent - 删除接口

  • 请求删除网络接口
  • 接口从虚拟机中移除(热拔出)
  • 用于动态移除网络接口

使用场景

热拔出网络接口

1
2
3
4
interfaces:
- name: "temporary"
  bridge: {}
  state: absent          # 删除这个接口

临时关闭接口

1
2
3
4
interfaces:
- name: "backup"
  bridge: {}
  state: down            # 关闭但不删除,需要时可以重新启用

动态接口管理

  • 根据运行时条件动态添加/删除网络接口
  • 维护窗口期间临时关闭接口
  • 故障排查时隔离特定网络

注意事项

  • 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 网卡

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 场景1:高性能网络(推荐)
interfaces:
- name: "default"
  masquerade: {}
  model: "virtio"           # 最佳性能

# 场景2:兼容性优先(旧版 OS)
interfaces:
- name: "legacy"
  bridge: {}
  model: "e1000"            # 无需 virtio 驱动

# 场景3:Windows 旧版本
interfaces:
- name: "win-network"
  bridge: {}
  model: "e1000e"           # Windows 7/Server 2008

性能对比

  • virtio: 最快(需要驱动)
  • e1000e: 中等(兼容性好)
  • e1000: 较慢(广泛兼容)
  • rtl8139: 最慢(仅测试用)

注意事项

  • 生产环境推荐 virtio
  • Windows 需要安装 virtio 驱动
  • 热迁移需要相同型号
  • 某些 OS 可能不支持 virtio

6. macAddress - MAC 地址

用途:指定虚拟网卡的 MAC 地址。

使用场景

  • 固定 MAC:软件许可绑定 MAC 地址
  • 网络策略:基于 MAC 的访问控制
  • DHCP 保留:固定 IP 分配
  • 资产追踪:唯一标识网络接口

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 场景1:固定 MAC 地址
interfaces:
- name: "default"
  bridge: {}
  macAddress: "de:ad:00:00:be:af"  # 自定义 MAC

# 场景2:软件许可绑定
interfaces:
- name: "license-if"
  bridge: {}
  macAddress: "52:54:00:12:34:56"  # 许可证绑定的 MAC

# 场景3:多网卡固定 MAC
interfaces:
- name: "eth0"
  bridge: {}
  macAddress: "52:54:00:01:02:03"
- name: "eth1"
  bridge: {}
  macAddress: "52:54:00:04:05:06"

注意事项

  • 未指定时自动生成
  • 建议使用 “52:54:00” 前缀(QEMU 分配)
  • 必须在同一网络中唯一
  • 迁移后 MAC 地址保持不变

7. ports - 端口转发

用途:配置端口转发规则,仅用于 masquerade 模式。

使用场景

  • 服务暴露:从集群外部访问 VM 服务
  • 端口映射:将 VM 端口映射到宿主机端口
  • 负载均衡:配合 Service 使用
  • 开发测试:本地访问 VM 服务

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 场景1:Web 服务端口转发
interfaces:
- name: "default"
  masquerade:
    ports:
    - name: "http"
      port: 80              # VM 内部端口
      protocol: "TCP"
    - name: "https"
      port: 443
      protocol: "TCP"

# 场景2:SSH 访问
interfaces:
- name: "default"
  masquerade:
    ports:
    - name: "ssh"
      port: 22
      protocol: "TCP"

# 场景3:自定义应用端口
interfaces:
- name: "default"
  masquerade:
    ports:
    - name: "app-port"
      port: 8080
      protocol: "TCP"

注意事项

  • 仅用于 masquerade 模式
  • 需要配合 Service 暴露端口
  • 协议支持 TCP 和 UDP
  • 端口名称可用于 Service 定义

8. bootOrder - 网络启动

用途:设置网络接口的启动优先级,用于 PXE 网络启动。

使用场景

  • PXE 安装:通过网络安装操作系统
  • 无盘工作站:无本地磁盘,从网络启动
  • 集群部署:批量部署虚拟机
  • 救援模式:系统故障时网络引导

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 场景1:PXE 安装
interfaces:
- name: "pxe-boot"
  bridge: {}
  bootOrder: 1              # 网络启动优先
  dhcpOptions:
    bootFileName: "pxelinux.0"
    tftpServerName: "192.168.1.100"

disks:
- name: "local-disk"
  disk:
    bus: virtio
  bootOrder: 2              # 本地磁盘第二启动

# 场景2:无盘工作站
interfaces:
- name: "network-boot"
  bridge: {}
  bootOrder: 1              # 仅网络启动

注意事项

  • 值越小优先级越高
  • 可与磁盘启动配合使用
  • 需要 DHCP/TFTP 服务器支持
  • 建议配合 dhcpOptions 使用

9. pciAddress - PCI 地址

用途:指定网卡的 PCI 地址,用于设备固定。

使用场景

  • 设备固定:确保网卡在特定 PCI 位置
  • 驱动绑定:绑定特定驱动程序
  • 设备命名:基于 PCI 地址的接口命名
  • 硬件兼容:模拟特定硬件布局

示例

1
2
3
4
5
6
7
8
# 场景:固定 PCI 地址
interfaces:
- name: "primary"
  bridge: {}
  pciAddress: "0000:01:00.0"  # 固定 PCI 地址
- name: "secondary"
  bridge: {}
  pciAddress: "0000:02:00.0"

注意事项

  • 格式: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 模式

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
spec:
  networks:
  - name: "default"
    pod: {}
  - name: "multus-net"
    multus:
      networkName: "macvlan-network"
  interfaces:
  - name: "default"
    masquerade: {}
    model: "virtio"
  - name: "multus-net"
    bridge: {}
    macAddress: "02:00:00:00:00:01"

dataVolumeTemplates 字段说明

dataVolumeTemplates 用于声明式地管理虚拟机磁盘。

作用

  • 自动创建 DataVolume 和对应的 PVC
  • DataVolume 的生命周期与 VM 绑定
  • 支持从多种源导入数据(HTTP、S3、PVC 克隆等)

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
spec:
  dataVolumeTemplates:
  - metadata:
      name: "root-disk"
    spec:
      source:
        http:
          url: "https://example.com/disk.qcow2"
      pvc:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 10Gi
  template:
    spec:
      domain:
        devices:
          disks:
          - disk: {}
            name: "root-disk"
      volumes:
      - dataVolume:
          name: "root-disk"
        name: "root-disk"

处理逻辑pkg/virt-controller/watch/vm/vm.go:511-572

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
func (c *Controller) handleDataVolumes(vm *virtv1.VirtualMachine) (bool, error) {
    for _, template := range vm.Spec.DataVolumeTemplates {
        curDataVolume, err := storagetypes.GetDataVolumeFromCache(vm.Namespace, template.Name, c.dataVolumeStore)
        if curDataVolume == nil {
            // 创建 DataVolume
            newDataVolume, err := watchutil.CreateDataVolumeManifest(c.clientset, template, vm)
            curDataVolume, err = c.clientset.CdiClient().CdiV1beta1().DataVolumes(vm.Namespace).Create(ctx, newDataVolume, metav1.CreateOptions{})
        }
    }
}

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 等待接收迁移

完整示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: my-vm
  labels:
    app: my-app
spec:
  runStrategy: Always                      # 运行策略
  instancetype:                            # 实例类型
    name: "standard-2"
  preference:                              # 偏好设置
    name: "fedora"
  dataVolumeTemplates:                     # 数据卷模板
  - metadata:
      name: "root-disk"
    spec:
      source:
        registry:
          url: "docker://quay.io/containerdisks/fedora:latest"
      pvc:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 10Gi
  template:                                # VMI 模板
    metadata:
      labels:
        kubevirt.io/vm: my-vm
    spec:
      domain:
        cpu:
          cores: 2
        memory:
          guest: 4Gi
        devices:
          disks:
          - disk:
              bus: virtio
            name: "root-disk"
      volumes:
      - dataVolume:
          name: "root-disk"
        name: "root-disk"

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
func (c *VMController) syncRunStrategy(vm *virtv1.VirtualMachine, vmi *virtv1.VirtualMachineInstance, createVMI bool) (bool, error) {
    switch runStrategy {
    case virtv1.RunStrategyAlways:
        // 总是保持 VMI 运行
        if vmi == nil {
            return c.startVMI(vm)  // 创建 VMI
        }
        if vmi.IsFinal() {
            return c.startVMI(vm)  // 重启 VMI
        }
        
    case virtv1.RunStrategyHalted:
        // 停止状态,删除 VMI
        if vmi != nil {
            return c.stopVMI(vm, vmi)
        }
        
    case virtv1.RunStrategyManual:
        // 手动控制,不自动操作
        // 需要通过 virtctl start/stop 控制
        
    case virtv1.RunStrategyRerunOnFailure:
        // 仅在失败时重启
        if vmi != nil && vmi.Status.Phase == virtv1.Failed {
            return c.startVMI(vm)
        }
        
    case virtv1.RunStrategyOnce:
        // 只运行一次
        if vmi == nil {
            return c.startVMI(vm)
        }
        // 退出后不再重启
    }
}

RunStrategy 使用场景

1. Always(生产环境推荐)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: production-vm
spec:
  runStrategy: Always
  template:
    spec:
      domain:
        cpu:
          cores: 4
        memory:
          guest: "8Gi"

使用场景

  • 生产环境关键服务
  • 需要高可用的应用
  • 7x24 运行的服务

行为

  • ✅ VM 创建时自动启动
  • ✅ VMI 崩溃后自动重启
  • ✅ 节点故障后重新调度
  • ❌ 手动停止无效(会自动重启)

2. Halted(停止状态)

1
2
3
4
5
6
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: stopped-vm
spec:
  runStrategy: Halted

使用场景

  • 临时停止的 VM
  • 模板 VM
  • 备份前的 VM

行为

  • ✅ VM 创建时不启动
  • ✅ 显式启动后才运行
  • ✅ 手动停止后保持停止

3. Manual(手动控制)

1
2
3
4
5
6
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: manual-vm
spec:
  runStrategy: Manual

使用场景

  • 开发测试环境
  • 需要精确控制的场景
  • 按需启动的 VM

行为

  • ✅ VM 创建时不启动
  • ✅ 需要 virtctl start 启动
  • ✅ 需要 virtctl stop 停止
  • ❌ 崩溃后不自动重启

4. RerunOnFailure(失败重启)

1
2
3
4
5
6
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: batch-vm
spec:
  runStrategy: RerunOnFailure

使用场景

  • 批处理任务
  • 失败需要重试的应用
  • 非关键服务

行为

  • ✅ VM 创建时自动启动
  • ✅ VMI 失败(Failed)后重启
  • ❌ VMI 成功(Succeeded)后不重启
  • ❌ 手动停止后不重启

5. Once(单次运行)

1
2
3
4
5
6
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: once-vm
spec:
  runStrategy: Once

使用场景

  • 一次性任务
  • 安装程序
  • 初始化脚本

行为

  • ✅ VM 创建时自动启动
  • ✅ 只运行一次
  • ❌ 退出后不再重启(无论成功或失败)

6. WaitAsReceiver(迁移接收)

1
2
3
4
5
6
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: migration-target
spec:
  runStrategy: WaitAsReceiver

使用场景

  • 跨集群迁移
  • 接收迁移的 VMI
  • 灾难恢复

行为

  • ✅ 等待接收迁移的 VMI
  • ✅ 迁移完成后变为 Running
  • ⚠️ 高级特性,需要特殊配置

RunStrategy vs Running

注意running 字段已废弃,推荐使用 runStrategy

1
2
3
4
5
6
7
# 旧方式(已废弃)
spec:
  running: true  # 等价于 runStrategy: Always

# 新方式(推荐)
spec:
  runStrategy: Always

为什么废弃 running

  • running 只有 true/false,无法表达复杂策略
  • runStrategy 提供更细粒度的控制
  • runningrunStrategy 互斥,不能同时使用

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

状态查看方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 查看 VMI 状态
kubectl get vmi <vmi-name> -o wide

# 查看详细信息
kubectl describe vmi <vmi-name>

# 查看 VM 状态
kubectl get vm <vm-name>

# 查看 VM 详细状态
kubectl describe vm <vm-name>

状态异常排查

VMI 停留在 Pending

1
2
3
4
5
6
# 检查 Pod 是否创建
kubectl get pod -l kubevirt.io/vmi=<vmi-name>

# 检查事件
kubectl describe vmi <vmi-name>
kubectl get events --field-selector involvedObject.name=<vmi-name>

VMI 停留在 Scheduling

1
2
3
4
5
# 检查节点资源
kubectl describe nodes

# 检查 Pod 调度事件
kubectl describe pod <pod-name>

VMI 停留在 Scheduled

1
2
3
4
5
# 检查 virt-handler 日志
kubectl logs -n kubevirt <virt-handler-pod> -c virt-handler

# 检查节点状态
kubectl get nodes

VMI 进入 Failed

1
2
3
4
5
# 检查 virt-launcher 日志
kubectl logs <virt-launcher-pod> -c compute

# 检查 libvirt 日志
kubectl exec <virt-launcher-pod> -- cat /var/run/libvirt/qemu/vmi-<name>.log

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

1
2
3
4
5
6
7
apiVersion: kubevirt.io/v1
kind: VirtualMachineInstanceMigration
metadata:
  name: migration-job-1
spec:
  vmiName: my-vmi              # 要迁移的 VMI
  priority: user-triggered      # 优先级:system-critical/user-triggered/system-maintenance

迁移阶段(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 迁移(默认)

工作原理

  1. 在 VM 运行时持续传输内存页
  2. 迭代传输脏页,直到脏页率足够低
  3. 最后停止 VM,传输剩余内存,切换到目标

优点

  • 迁移失败可回滚
  • 停机时间短(通常 < 100ms)
  • 适合大多数场景

缺点

  • 迁移时间长(总传输量大)
  • 高内存修改率时可能无法完成

配置

1
2
3
4
5
6
7
8
9
apiVersion: kubevirt.io/v1
kind: KubeVirt
metadata:
  name: kubevirt
  namespace: kubevirt
spec:
  configuration:
    migrations:
      allowPostCopy: false  # 使用 Pre-copy(默认)

Post-copy 迁移

工作原理

  1. 传输少量内存后立即切换到目标
  2. VM 在目标节点运行,按需拉取内存页
  3. 使用用户态缺页中断(UFFD)

优点

  • 迁移时间短
  • 能完成高内存修改率的迁移
  • 减少网络带宽占用

缺点

  • 迁移失败无法回滚
  • 目标节点故障会导致 VM 丢失
  • 需要内核支持(Linux 4.3+)

配置

1
2
3
4
5
6
7
8
9
apiVersion: kubevirt.io/v1
kind: KubeVirt
metadata:
  name: kubevirt
  namespace: kubevirt
spec:
  configuration:
    migrations:
      allowPostCopy: true  # 允许 Post-copy

迁移策略(MigrationPolicy)

源码位置staging/src/kubevirt.io/api/migrations/v1alpha1/types.go

MigrationPolicy 允许为不同的 VM 配置不同的迁移策略。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
apiVersion: migrations.kubevirt.io/v1alpha1
kind: MigrationPolicy
metadata:
  name: production-policy
spec:
  selectors:
    namespaceSelector:
      environment: production
    virtualMachineInstanceSelector:
      critical: "true"
  
  # 迁移配置
  allowAutoConverge: true          # 允许自动降低 CPU 频率
  bandwidthPerMigration: "64Mi"    # 每个迁移的带宽限制
  completionTimeoutPerGiB: 800     # 每GiB内存的超时时间(秒)
  allowPostCopy: false             # 不允许 Post-copy

迁移条件

源码位置pkg/virt-controller/watch/migration/migration.go:handlMigrationCondition()

必要条件

  1. VMI 状态必须是 Running

    1
    2
    3
    
    if vmi.Status.Phase != virtv1.Running {
        return fmt.Errorf("VMI is not running")
    }
    
  2. VMI 必须已调度到节点

    1
    2
    3
    
    if vmi.Status.NodeName == "" {
        return fmt.Errorf("VMI is not scheduled")
    }
    
  3. 存储必须支持迁移

    • ReadWriteMany (RWX) PVC
    • 网络附加存储(如 Ceph, NFS)
    • 本地存储不支持迁移
  4. 网络必须支持迁移

    • Bridge 模式:需要网络配置
    • Masquerade 模式:默认支持
    • SR-IOV:需要特殊配置
  5. 节点资源充足

    • 目标节点有足够 CPU/内存
    • 目标节点可访问相同存储

迁移限制

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 查看迁移限制
kubectl get kubevirt -n kubevirt -o yaml | grep -A 20 migrations

# 常见限制
migrations:
  parallelMigrationsPerCluster: 5      # 集群并行迁移数
  parallelOutboundMigrationsPerNode: 2 # 每节点并行出站迁移数
  bandwidthPerMigration: "64Mi"         # 迁移带宽限制
  completionTimeoutPerGiB: 800          # 超时时间
  progressTimeout: 150                  # 进度超时(秒)

迁移执行详解

1. 目标 Pod 创建

源码位置pkg/virt-controller/watch/migration/migration.go:createTargetPod()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
func (c *MigrationController) createTargetPod(migration *virtv1.VirtualMachineInstanceMigration, vmi *virtv1.VirtualMachineInstance) error {
    // 创建目标 Pod,使用相同的 PVC
    targetPod := &k8score.Pod{
        ObjectMeta: metav1.ObjectMeta{
            Name:      "migration-target-" + migration.Name,
            Namespace: migration.Namespace,
        },
        Spec: vmi.Spec.Volumes..., // 相同的卷配置
    }
    return c.client.CoreV1().Pods(targetPod.Namespace).Create(targetPod)
}

2. 迁移代理设置

源码位置pkg/virt-handler/migration-proxy/proxy.go

virt-handler 在源节点和目标节点之间建立代理连接,用于:

  • libvirt 迁移流量
  • QEMU 数据传输
1
2
3
4
5
6
7
type MigrationProxy struct {
    // 监听本地端口,转发到目标节点
    tcpProxy *TCPProxy
    
    // Unix socket 代理
    unixSocketProxy *UnixSocketProxy
}

3. 内存传输

源码位置pkg/virt-launcher/virtwrap/converter/converter.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// Pre-copy 迭代传输
func (l *LibvirtDomainManager) Migrate(vmi *v1.VirtualMachineInstance) error {
    // 1. 启动迁移
    err := dom.MigrateToURI3(targetURI, &flags)
    
    // 2. 监控迁移进度
    for {
        jobInfo, _ := dom.GetJobInfo()
        if jobInfo.Type == DOMAIN_JOB_NONE {
            break // 迁移完成
        }
        
        // 迭代传输脏页
        time.Sleep(1 * time.Second)
    }
}

迁移监控

查看迁移状态

1
2
3
4
5
6
7
8
# 查看所有迁移
kubectl get vmim

# 查看迁移详情
kubectl describe vmim <migration-name>

# 查看 VMI 迁移状态
kubectl get vmi <vmi-name> -o yaml | grep -A 20 migrationState

迁移进度指标

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
status:
  migrationState:
    startTimestamp: "2024-01-01T00:00:00Z"
    endTimestamp: "2024-01-01T00:01:30Z"
    targetNode: "node-2"
    sourceNode: "node-1"
    completed: true
    failed: false
    
    # 内存传输统计
    totalGuestMemory: "8Gi"
    remainingGuestMemory: "256Mi"     # 剩余传输内存
    dataProcessed: "7.75Gi"           # 已传输数据
    dataRemaining: "256Mi"            # 剩余数据
    
    # 迁移性能
    downtime: "85ms"                  # 停机时间
    downtimeSeconds: 0.085
    throughput: "512Mi/s"             # 传输速率

迁移故障排查

迁移卡在 Pending

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 检查 VMI 状态
kubectl get vmi <vmi-name> -o wide

# 检查事件
kubectl describe vmim <migration-name>
kubectl get events --field-selector involvedObject.name=<migration-name>

# 常见原因
# 1. VMI 不是 Running 状态
# 2. 存储不支持迁移(本地存储)
# 3. 网络不支持迁移

迁移卡在 Scheduling

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 检查节点资源
kubectl describe nodes | grep -A 5 "Allocated resources"

# 检查 Pod 调度事件
kubectl describe pod migration-target-<name>

# 常见原因
# 1. 节点资源不足
# 2. 节点选择器限制
# 3. 污点和容忍度问题

迁移卡在 Running

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 检查迁移进度
kubectl get vmi <vmi-name> -o yaml | grep -A 20 migrationState

# 检查 virt-handler 日志
kubectl logs -n kubevirt <virt-handler-pod> | grep migration

# 检查 libvirt 日志
kubectl exec <virt-launcher-pod> -- cat /var/run/libvirt/qemu/vmi-<name>.log

# 常见原因
# 1. 内存修改率过高
# 2. 网络带宽不足
# 3. 目标节点性能问题

迁移失败

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 查看失败原因
kubectl describe vmim <migration-name>

# 检查失败条件
kubectl get vmim <migration-name> -o yaml | grep -A 10 conditions

# 常见失败原因
# 1. 超时(completionTimeoutPerGiB)
# 2. 进度停滞(progressTimeout)
# 3. 目标节点故障
# 4. 存储访问失败

关键源码路径

功能 源码位置
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. 生产环境配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
apiVersion: kubevirt.io/v1
kind: KubeVirt
spec:
  configuration:
    migrations:
      parallelMigrationsPerCluster: 5
      parallelOutboundMigrationsPerNode: 2
      bandwidthPerMigration: "64Mi"
      completionTimeoutPerGiB: 800
      progressTimeout: 150
      allowPostCopy: false  # 生产环境建议禁用

2. 存储选择

  • ✅ 使用 RWX PVC(ReadWriteMany)
  • ✅ 使用网络存储(Ceph, NFS, GlusterFS)
  • ❌ 避免使用本地存储

3. 网络配置

  • Bridge 模式:需要网络团队支持
  • Masquerade 模式:默认支持迁移
  • SR-IOV:需要 VF 迁移支持

4. 监控和告警

1
2
3
4
5
6
# Prometheus 告警规则
- alert: MigrationStuck
  expr: kubevirt_vmi_migration_remaining_memory_bytes > 0
  for: 5m
  annotations:
    summary: "Migration {{ $labels.name }} stuck for more than 5 minutes"

八、故障排查指南

常见问题分类

1. VMI 启动失败

症状:VMI 停留在 Pending/Scheduling 状态

排查步骤

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 1. 检查 VMI 状态
kubectl get vmi <vmi-name> -o wide
kubectl describe vmi <vmi-name>

# 2. 检查 Pod 状态
kubectl get pod -l kubevirt.io/vmi=<vmi-name>
kubectl describe pod <pod-name>

# 3. 检查事件
kubectl get events --field-selector involvedObject.name=<vmi-name>

# 4. 检查节点资源
kubectl describe nodes | grep -A 10 "Allocated resources"

常见原因及解决方案

问题 原因 解决方案
Pending PVC 未绑定 检查 StorageClass,确保 PV 可用
Pending 节点资源不足 扩容节点或减少资源请求
Scheduling 节点选择器不匹配 检查 nodeSelector/nodeAffinity
Scheduling 污点/容忍度问题 添加合适的 tolerations
Scheduled → Failed 镜像拉取失败 检查 imagePullSecrets
Scheduled → Failed 存储挂载失败 检查 PVC 访问权限

2. VMI 运行异常

症状:VMI 进入 Failed 状态或频繁重启

排查步骤

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 1. 查看 VMI 详细状态
kubectl describe vmi <vmi-name>

# 2. 查看 virt-launcher Pod 日志
kubectl logs <virt-launcher-pod> -c compute

# 3. 查看 libvirt 日志
kubectl exec <virt-launcher-pod> -- cat /var/log/libvirt/qemu/vmi-<name>.log

# 4. 进入 virt-launcher 调试
kubectl exec -it <virt-launcher-pod> -- /bin/bash
virsh list --all
virsh dominfo vmi-<name>

常见原因及解决方案

问题 原因 解决方案
OOMKilled 内存不足 增加 memory limits
CrashLoopBackOff 应用崩溃 检查 Guest OS 日志
节点 NotReady 节点故障 检查节点状态,迁移 VMI
网络不通 网络配置错误 检查 CNI 配置

3. 热迁移失败

症状:迁移卡住或失败

排查步骤

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 1. 查看迁移状态
kubectl get vmim <migration-name>
kubectl describe vmim <migration-name>

# 2. 查看 VMI 迁移状态
kubectl get vmi <vmi-name> -o yaml | grep -A 30 migrationState

# 3. 查看 virt-handler 日志
kubectl logs -n kubevirt <virt-handler-pod> -c virt-handler | grep migration

# 4. 检查存储
kubectl get pvc
kubectl describe pv <pv-name>

常见原因及解决方案

问题 原因 解决方案
Pending VMI 不是 Running 等待 VMI 运行
Scheduling 目标节点无资源 扩容或清理节点
Running 卡住 内存脏页率高 降低负载或使用 Post-copy
Failed 超时 调整 completionTimeoutPerGiB
Failed 存储不支持迁移 使用 RWX PVC

4. 存储问题

症状:PVC 无法挂载或数据丢失

排查步骤

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 1. 检查 PVC 状态
kubectl get pvc
kubectl describe pvc <pvc-name>

# 2. 检查 PV 状态
kubectl get pv
kubectl describe pv <pv-name>

# 3. 检查存储类
kubectl get storageclass
kubectl describe storageclass <sc-name>

# 4. 检查 Pod 挂载
kubectl exec <virt-launcher-pod> -- mount | grep <volume-name>
kubectl exec <virt-launcher-pod> -- df -h

常见原因及解决方案

问题 原因 解决方案
Pending StorageClass 不存在 创建 StorageClass
Pending PV 容量不足 扩容存储或清理
FailedMount 存储系统故障 检查 Ceph/NFS 等后端存储
FailedMount 权限问题 检查 SELinux/AppArmor
数据丢失 使用 emptyDisk 改用 PVC

5. 网络问题

症状:VMI 网络不通或性能差

排查步骤

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 1. 检查网络配置
kubectl get vmi <vmi-name> -o yaml | grep -A 30 networks

# 2. 检查网络附件定义(Multus)
kubectl get network-attachment-definitions

# 3. 进入 VMI 检查网络
kubectl exec -it <virt-launcher-pod> -- ip addr
kubectl exec -it <virt-launcher-pod> -- ip route
kubectl exec -it <virt-launcher-pod> -- iptables -L -n -v

# 4. 测试网络连通性
kubectl exec -it <virt-launcher-pod> -- ping <target-ip>
kubectl exec -it <virt-launcher-pod> -- curl http://<service-name>

常见原因及解决方案

问题 原因 解决方案
无法访问 网络策略限制 检查 NetworkPolicy
无法访问 DNS 解析失败 配置正确的 DNS
性能差 网卡型号不匹配 使用 virtio 网卡
性能差 未启用多队列 设置 networkInterfaceMultiqueue: true

调试工具和技巧

1. virtctl 工具

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 连接到 VMI 控制台
virtctl console <vmi-name>

# 通过 VNC 连接
virtctl vnc <vmi-name>

# SSH 连接(需要配置 SSH)
virtctl ssh <vmi-name>

# 查看日志
virtctl logs <vmi-name>

# 启动/停止 VM
virtctl start <vm-name>
virtctl stop <vm-name>

# 热迁移
virtctl migrate <vm-name>

# 暂停/恢复
virtctl pause <vm-name>
virtctl unpause <vm-name>

2. 日志查看

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# virt-operator 日志
kubectl logs -n kubevirt deployment/virt-operator

# virt-controller 日志
kubectl logs -n kubevirt deployment/virt-controller

# virt-handler 日志(每个节点一个)
kubectl logs -n kubevirt <virt-handler-pod> -c virt-handler

# virt-launcher 日志(每个 VMI 一个)
kubectl logs <virt-launcher-pod> -c compute

# libvirt 日志
kubectl exec <virt-launcher-pod> -- cat /var/log/libvirt/qemu/vmi-<name>.log

# QEMU 日志
kubectl exec <virt-launcher-pod> -- cat /var/run/libvirt/qemu/vmi-<name>.log

3. 性能诊断

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 查看 VMI 资源使用
kubectl top pod <virt-launcher-pod>

# 查看 QEMU 进程资源
kubectl exec <virt-launcher-pod> -- ps aux | grep qemu

# 查看内存使用
kubectl exec <virt-launcher-pod> -- cat /proc/$(pidof qemu-system-x86_64)/status | grep -i mem

# 查看块设备 I/O
kubectl exec <virt-launcher-pod> -- iostat -x 1

# 查看网络流量
kubectl exec <virt-launcher-pod> -- ifconfig

4. Libvirt 调试

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 进入 virt-launcher
kubectl exec -it <virt-launcher-pod> -- /bin/bash

# 查看域列表
virsh list --all

# 查看域信息
virsh dominfo vmi-<name>

# 查看域 XML
virsh dumpxml vmi-<name>

# 查看域状态
virsh domstate vmi-<name>

# 查看域块统计
virsh domblkstat vmi-<name>

# 查看域接口统计
virsh domifstat vmi-<name>

故障诊断流程图

  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

常用排查命令速查表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 查看 KubeVirt 组件状态
kubectl get kubevirt -n kubevirt -o yaml

# 查看 VMI 列表
kubectl get vmi -o wide

# 查看 Pod 列表(KubeVirt 相关)
kubectl get pod -n kubevirt
kubectl get pod -l kubevirt.io

# 查看事件
kubectl get events --sort-by='.lastTimestamp'

# 查看资源使用
kubectl top nodes
kubectl top pods

# 查看存储
kubectl get pvc,pv,storageclass

# 查看网络策略
kubectl get networkpolicy

# 查看节点详情
kubectl describe node <node-name>

# 查看命名空间事件
kubectl get events -n <namespace> --sort-by='.lastTimestamp'

十、高级特性

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(完整透传)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: gpu-vm
spec:
  template:
    spec:
      domain:
        devices:
          gpus:
          - deviceName: "nvidia.com/GA100_Graphics"  # GPU 设备名称
            name: "gpu-0"
            virtualGPUOptions:
              display:
                enabled: true  # 启用 GPU 显示

前提条件

  • 节点有 GPU 设备
  • 安装 GPU 设备插件(如 NVIDIA device plugin)
  • 启用 IOMMU
  • 禁用 Nouveau 驱动(NVIDIA)

2. vGPU(虚拟 GPU)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: vgpu-vm
spec:
  template:
    spec:
      domain:
        devices:
          gpus:
          - deviceName: "nvidia.com/A100-10C"  # vGPU 类型
            name: "vgpu-0"

前提条件

  • NVIDIA vGPU 许可证
  • vGPU Manager 安装
  • vGPU 设备插件

GPU 配置步骤

1. 节点配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 启用 IOMMU(BIOS 设置)
# Intel: Intel VT-d
# AMD: AMD-Vi

# 内核参数
GRUB_CMDLINE_LINUX="intel_iommu=on iommu=pt"

# 禁用 Nouveau 驱动
cat <<EOF > /etc/modprobe.d/blacklist-nouveau.conf
blacklist nouveau
options nouveau modeset=0
EOF

# 更新 initramfs
dracut --force
reboot

2. 安装 GPU 设备插件

1
2
# 安装 NVIDIA device plugin
kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.14.0/nvidia-device-plugin.yml

3. 验证 GPU 资源

1
2
3
4
5
6
# 查看节点 GPU 资源
kubectl describe node <node-name> | grep nvidia.com

# 示例输出
nvidia.com/GA100_Graphics:  2
nvidia.com/GA100_Compute:   2

GPU 使用示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# AI/ML 训练 VM
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: ml-training
spec:
  template:
    spec:
      domain:
        cpu:
          cores: 8
        memory:
          guest: "32Gi"
        devices:
          gpus:
          - deviceName: "nvidia.com/A100"
            name: "gpu-0"
      volumes:
      - name: training-data
        persistentVolumeClaim:
          claimName: ml-dataset-pvc

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. 节点配置

1
2
3
4
5
6
7
8
9
# 启用 IOMMU(BIOS 设置)
# 内核参数
GRUB_CMDLINE_LINUX="intel_iommu=on iommu=pt"

# 创建 VF
echo 4 > /sys/class/net/eth0/device/sriov_numvfs

# 验证 VF
ip link show eth0

2. 安装 SR-IOV Network Operator

1
kubectl apply -f https://raw.githubusercontent.com/k8snetworkplumbingwg/sriov-network-operator/master/manifests/operator.yaml

3. 配置 SR-IOV Network

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
  name: sriov-net
  namespace: openshift-sriov-network-operator
spec:
  resourceName: intel_nics
  networkNamespace: default
  ipam: |
    {
      "type": "host-local",
      "subnet": "192.168.1.0/24",
      "rangeStart": "192.168.1.100",
      "rangeEnd": "192.168.1.200"
    }

4. VM 使用 SR-IOV

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: sriov-vm
spec:
  template:
    spec:
      domain:
        devices:
          interfaces:
          - name: sriov-net
            sriov: {}
      networks:
      - name: sriov-net
        multus:
          networkName: sriov-net

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 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: cpu-pinning-vm
spec:
  template:
    spec:
      domain:
        cpu:
          cores: 4
          dedicatedCpuPlacement: true  # 启用 CPU Pinning
        resources:
          requests:
            memory: "8Gi"
            cpu: "4"
          limits:
            memory: "8Gi"
            cpu: "4"  # requests == limits (Guaranteed QoS)

CPU Pinning 工作原理

1
2
3
4
5
6
7
8
物理 CPU 布局:
┌─────────────────────────────────────┐
│ Node 0: CPU 0-3                     │
│   VM1: vCPU0 → CPU0                 │
│   VM1: vCPU1 → CPU1                 │
│   VM1: vCPU2 → CPU2                 │
│   VM1: vCPU3 → CPU3                 │
└─────────────────────────────────────┘

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 拓扑示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
┌─────────────────────────────────────────┐
│          物理服务器 NUMA 拓扑             │
├─────────────────────────────────────────┤
│ NUMA Node 0:                            │
│   CPU: 0-15                             │
│   Memory: 64Gi                          │
│   Devices: GPU0, NIC0                   │
├─────────────────────────────────────────┤
│ NUMA Node 1:                            │
│   CPU: 16-31                            │
│   Memory: 64Gi                          │
│   Devices: GPU1, NIC1                   │
└─────────────────────────────────────────┘

NUMA 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: numa-vm
spec:
  template:
    spec:
      domain:
        cpu:
          cores: 8
          numa:
            guestMappingPassthrough: {}  # NUMA 透传
        memory:
          guest: "32Gi"

NUMA 优化策略

1. 自动 NUMA 对齐

1
2
3
domain:
  cpu:
    numa: {}  # KubeVirt 自动分配 NUMA 节点

2. 手动 NUMA 配置

1
2
3
4
5
6
7
8
domain:
  cpu:
    numa:
      guestMappingPassthrough: {}
  memory:
    guest: "32Gi"
    hugepages:
      pageSize: "1Gi"

NUMA 性能影响

访问类型 延迟 带宽
本地 NUMA 内存
远程 NUMA 内存

优化建议

  • ✅ 将 VM 内存限制在一个 NUMA 节点
  • ✅ GPU 和网卡在相同 NUMA 节点
  • ✅ 使用 Hugepages 减少内存开销

实时 VM

源码位置staging/src/kubevirt.io/api/core/v1/schema.go:387-389

实时 VM 用于需要极低延迟的场景(如工业控制、音频处理)。

实时 VM 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: realtime-vm
spec:
  template:
    spec:
      domain:
        cpu:
          cores: 4
          dedicatedCpuPlacement: true
          realtime:
            mask: "0-3"  # 实时 CPU 掩码
        resources:
          requests:
            memory: "8Gi"
            cpu: "4"
          limits:
            memory: "8Gi"
            cpu: "4"

实时 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 模式
  • 网络:万兆网卡推荐

内核要求

1
2
3
4
5
6
7
8
9
# 启用 KVM
lsmod | grep kvm

# 启用嵌套虚拟化(可选)
modprobe kvm_intel nested=1

# 启用 IOMMU(GPU/SR-IOV 需要)
# BIOS: Intel VT-d / AMD-Vi
# 内核参数: intel_iommu=on iommu=pt

系统配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 增加文件描述符限制
echo "* soft nofile 65536" >> /etc/security/limits.conf
echo "* hard nofile 65536" >> /etc/security/limits.conf

# 禁用 swap(Kubernetes 要求)
swapoff -a
sed -i '/swap/d' /etc/fstab

# 配置 ulimit(Hugepages 需要)
echo "memlock: -1" >> /etc/security/limits.conf

2. 网络方案选择

网络方案 优点 缺点 适用场景
Masquerade 默认支持,无需额外配置 性能有开销,端口转发限制 开发测试、简单应用
Bridge 高性能,直接网络访问 需要网络配置,可能 IP 冲突 生产环境、高性能应用
SR-IOV 极致性能,低延迟 不支持热迁移,配置复杂 NFV、金融交易
Macvtap 高性能,无需 Bridge 不支持宿主机通信 隔离环境

推荐配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 生产环境:Bridge 模式
spec:
  networks:
  - name: bridge-network
    pod: {}
  interfaces:
  - name: bridge-network
    bridge: {}

# 开发测试:Masquerade 模式
spec:
  networks:
  - name: default
    pod: {}
  interfaces:
  - name: default
    masquerade: {}

3. 存储配置建议

存储类选择

存储类型 性能 迁移支持 适用场景
Local PV 极高 ❌ 不支持 高性能数据库
Ceph RBD ✅ 支持 生产环境通用
NFS 中等 ✅ 支持 文件共享、开发测试
HostPath ❌ 不支持 临时测试

存储最佳实践

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 生产环境推荐:Ceph RBD
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ceph-rbd
provisioner: rbd.csi.ceph.com
parameters:
  pool: kubevirt-pool
  clusterID: ceph-cluster
  csi.storage.k8s.io/provisioner-secret-name: ceph-secret
  csi.storage.k8s.io/provisioner-secret-namespace: ceph
reclaimPolicy: Delete
allowVolumeExpansion: true

存储优化建议

  • ✅ 使用 SSD 存储提高性能
  • ✅ 启用存储压缩(Ceph)
  • ✅ 配置存储 QoS 限制
  • ✅ 定期备份重要数据

性能调优技巧

1. CPU 性能优化

CPU Pinning 配置

1
2
3
4
5
6
# 高性能数据库
domain:
  cpu:
    cores: 8
    dedicatedCpuPlacement: true  # CPU Pinning
    isolateEmulatorThread: true  # 隔离模拟器线程

NUMA 优化

1
2
3
4
5
domain:
  cpu:
    cores: 8
    numa:
      guestMappingPassthrough: {}  # NUMA 透传

CPU 特性启用

1
2
3
4
5
domain:
  cpu:
    features:
    - name: "vmx"
      policy: "require"  # 嵌套虚拟化

2. 内存性能优化

Hugepages 配置

1
2
3
4
5
domain:
  memory:
    guest: "64Gi"
    hugepages:
      pageSize: "1Gi"  # 大页内存

节点预留大页

1
2
3
4
5
6
7
8
# 预留 64 个 1GiB 大页
echo 64 > /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages

# 持久化配置
cat <<EOF >> /etc/default/grub
GRUB_CMDLINE_LINUX="default_hugepagesz=1G hugepagesz=1G hugepages=64"
EOF
update-grub

内存气球配置

1
2
3
domain:
  devices:
    autoattachMemBalloon: false  # 禁用内存气球(性能敏感场景)

3. I/O 性能优化

磁盘缓存配置

1
2
3
4
5
6
7
8
# 高性能数据库
disks:
- name: "db-disk"
  disk:
    bus: virtio
  cache: "none"        # 无缓存,数据安全
  io: "native"         # 原生 I/O
  dedicatedIOThread: true  # 专用 I/O 线程

多队列优化

1
2
3
4
domain:
  devices:
    blockMultiQueue: true              # 块设备多队列
    networkInterfaceMultiqueue: true   # 网络接口多队列

Virtiofs 高性能文件共享

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
domain:
  devices:
    filesystems:
    - name: "shared-data"
      virtiofs: {}

volumes:
- name: "shared-data"
  containerPath:
    path: "/data/shared"

资源规划指导

1. 资源配额管理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Namespace 资源配额
apiVersion: v1
kind: ResourceQuota
metadata:
  name: kubevirt-quota
  namespace: production
spec:
  hard:
    requests.cpu: "100"
    requests.memory: 200Gi
    limits.cpu: "200"
    limits.memory: 400Gi
    count/virtualmachineinstances: "20"

2. QoS 策略

QoS 等级 配置要求 优先级 适用场景
Guaranteed requests == limits 生产关键应用
Burstable requests < limits 开发测试环境
BestEffort 无 requests/limits 临时任务

生产环境推荐

1
2
3
4
5
6
7
8
domain:
  resources:
    requests:
      memory: "16Gi"
      cpu: "8"
    limits:
      memory: "16Gi"  # 与 requests 相同,Guaranteed QoS
      cpu: "8"

3. 资源规划建议

节点规划

  • 每节点预留 10-20% 资源给系统进程
  • VM 资源不超过节点资源的 80%
  • 考虑迁移时的资源需求

容量规划公式

1
2
可用 VM 数量 = (节点 CPU 总数 × 0.8) / 单个 VM CPU 需求
可用 VM 数量 = (节点内存总数 × 0.8) / 单个 VM 内存需求

安全最佳实践

1. Secure Boot 配置

1
2
3
4
5
domain:
  firmware:
    bootloader:
      efi:
        secureBoot: true  # 启用 Secure Boot

前提条件

  • UEFI 固件支持
  • SMM(System Management Mode)
  • 签名的引导加载程序

2. TPM 设备

1
2
3
domain:
  devices:
    tpm: {}  # 启用 TPM 设备

用途

  • 密钥存储
  • 远程证明
  • 安全启动度量

3. 网络安全

网络策略

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: vm-isolation
spec:
  podSelector:
    matchLabels:
      kubevirt.io/vmi: "sensitive-vm"
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: trusted-ns
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/8

4. 访问控制

RBAC 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 限制 VM 创建权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: vm-creator
  namespace: production
rules:
- apiGroups: ["kubevirt.io"]
  resources: ["virtualmachines", "virtualmachineinstances"]
  verbs: ["create", "get", "list", "update", "delete"]

备份和恢复策略

1. 快照管理

创建快照

1
2
# 创建 VM 快照
virtctl snapshot create <vm-name> --snapshot-name <snapshot-name>

快照配置

1
2
3
4
5
6
7
8
9
apiVersion: snapshot.kubevirt.io/v1beta1
kind: VirtualMachineSnapshot
metadata:
  name: vm-snapshot-1
spec:
  source:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: production-vm

恢复快照

1
2
# 从快照恢复
virtctl snapshot restore <vm-name> --snapshot-name <snapshot-name>

2. 定期备份策略

使用 Velero 备份

1
2
3
4
5
6
7
8
# 安装 Velero
velero install --provider aws --bucket kubevirt-backup

# 备份 VM
velero backup create vm-backup --include-resources virtualmachines,virtualmachineinstances,persistentvolumeclaims

# 定期备份
velero schedule create daily-backup --schedule="0 2 * * *" --include-resources virtualmachines

3. 灾难恢复

跨集群迁移

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 目标集群配置
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: dr-vm
spec:
  template:
    spec:
      volumes:
      - name: root-disk
        persistentVolumeClaim:
          claimName: restored-pvc  # 从备份恢复的 PVC

监控和告警

1. Prometheus 集成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 启用 ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: kubevirt-monitor
  namespace: monitoring
spec:
  selector:
    matchLabels:
      kubevirt.io: ""
  endpoints:
  - port: metrics
    interval: 30s

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. 告警规则示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: kubevirt-alerts
spec:
  groups:
  - name: kubevirt.rules
    rules:
    - alert: VMIHighMemoryUsage
      expr: kubevirt_vmi_memory_available_bytes / kubevirt_vmi_memory_requested_bytes < 0.1
      for: 5m
      labels:
        severity: critical
      annotations:
        summary: "VMI {{ $labels.name }} high memory usage"
        description: "Memory usage is above 90% for more than 5 minutes"
    
    - alert: VMICrashLooping
      expr: rate(kubevirt_vmi_phase_count{phase="Failed"}[5m]) > 0.1
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "VMI {{ $labels.name }} is crash looping"
        description: "VMI has restarted more than 3 times in the last 5 minutes"

运维最佳实践总结

✅ 生产环境检查清单

  • 节点启用硬件虚拟化
  • 禁用 swap
  • 配置足够的 ulimit
  • 存储支持 RWX(迁移需要)
  • 网络方案选择合适
  • 资源配额配置
  • 监控和告警配置
  • 定期备份策略
  • 灾难恢复计划
  • RBAC 权限配置
  • 网络策略配置

⚠️ 常见陷阱

  1. 资源不足:未预留足够资源,导致调度失败
  2. 存储模式:使用 ReadWriteOnce(RWO),无法迁移
  3. 网络冲突:Bridge 模式 IP 地址冲突
  4. 权限不足:RBAC 配置不当,无法创建 VM
  5. 性能问题:未启用 CPU Pinning/Hugepages

📚 学习路径

  1. 入门:使用 Masquerade 模式、ContainerDisk
  2. 进阶:使用 Bridge 网络、PVC 存储、热迁移
  3. 高级:GPU 透传、SR-IOV、CPU Pinning
  4. 生产:监控告警、备份恢复、灾难恢复

十二、工作流程

创建 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 关键逻辑

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
func SetupVMIFromVM(vm *virtv1.VirtualMachine) *virtv1.VirtualMachineInstance {
    vmi := libvmi.New()
    
    // 从 VM.spec.template 复制元数据和规格
    vmi.ObjectMeta = *vm.Spec.Template.ObjectMeta.DeepCopy()
    vmi.ObjectMeta.Name = vm.ObjectMeta.Name  // VMI 名称 = VM 名称
    vmi.ObjectMeta.Namespace = vm.ObjectMeta.Namespace
    vmi.Spec = *vm.Spec.Template.Spec.DeepCopy()
    
    // 设置 OwnerReference,VMI 归 VM 所有
    vmi.ObjectMeta.OwnerReferences = []metav1.OwnerReference{
        *metav1.NewControllerRef(vm, virtv1.VirtualMachineGroupVersionKind),
    }
    
    return vmi
}

六、关键代码目录

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
kubevirt/
├── cmd/                    # 各组件的入口点
   ├── virt-operator/      # Operator 入口
   ├── virt-controller/    # Controller 入口
   ├── virt-handler/       # Handler 入口
   ├── virt-launcher/      # Launcher 入口
   ├── virt-api/           # API 入口
   └── virtctl/            # CLI 工具入口
├── pkg/                    # 核心功能实现
   ├── controller/         # 控制器逻辑
   ├── virt-handler/       # virt-handler 功能实现
   ├── virt-launcher/      # virt-launcher 功能实现
   ├── virt-api/           # API 服务器实现
   ├── virt-operator/      # Operator 实现
   ├── virtctl/            # CLI 工具实现
   ├── network/            # 网络功能
   ├── storage/            # 存储功能
   ├── hypervisor/         # Hypervisor 抽象层
   ├── cloud-init/         # Cloud-init 支持
   ├── hooks/              # Hook 机制
   └── monitoring/         # 监控指标
├── staging/src/kubevirt.io/api/  # API 类型定义
   ├── core/v1/            # 核心 API(VMI, VM 等)
   ├── snapshot/           # 快照 API
   ├── export/             # 导出 API
   ├── clone/              # 克隆 API
   ├── pool/               # VM 池 API
   └── instancetype/       # 实例类型 API
└── tests/                  # 测试代码

七、CDI (Containerized Data Importer)

CDI 项目提供了通过 DataVolume 将 PVC 用作 KubeVirt VM 磁盘的功能:

功能 说明
镜像导入 从 HTTP/S3/Registry 等源导入磁盘镜像
镜像上传 支持用户上传虚拟机磁盘镜像
空白磁盘 创建空白磁盘供虚拟机使用
数据卷克隆 克隆现有的数据卷

八、总结

KubeVirt 通过以下方式扩展 Kubernetes:

扩展方式 说明
CRD 扩展 添加虚拟化相关的资源类型(VM、VMI 等)
控制器 实现集群级别的虚拟机编排逻辑
代理 实现节点级别的虚拟机生命周期管理
CLI 工具 提供用户友好的命令行接口

这种设计使得 KubeVirt 能够无缝集成到 Kubernetes 生态中,用户可以使用熟悉的 kubectl 和 Kubernetes API 来管理虚拟机,同时容器和虚拟机可以在同一个集群中并存。

参考

#Kubevirt