Skip to content

KubeVirt 从入门到精通 —— 系统全面教材

版本: v1.0(2026-09-03) 适用版本: KubeVirt v1.9.x、CDI v1.60.x、Kubernetes/RKE2 v1.28+ 配套实战文档: kubevirt-practical-operations-guide.md(部署实施与运维专题) 关联现网文档: ../rke2-kubevirt-deployment-guide.md../cdi-offline-deployment-guide.md../kubevirt-nas-storage-guide.md../kubevirt-storage-ha-guide.md../kubevirt-network-ssh-password-guide.md


目录

第一部分 入门篇

  1. 认识 KubeVirt
  2. 核心概念与整体架构
  3. 环境准备
  4. 安装 KubeVirt
  5. 第一台虚拟机
  6. 虚拟机生命周期管理

第二部分 进阶篇

  1. VirtualMachine Spec 概览
  2. 网络深入
  3. 存储深入
  4. cloud-init 与凭据注入
  5. 访问虚拟机的所有方式

第三部分 精通篇

  1. 热迁移(Live Migration)
  2. 高可用与驱逐策略
  3. 快照与备份恢复
  4. 克隆与黄金镜像体系
  5. 监控体系
  6. 性能调优
  7. 批量管理:副本集、Pool 与 InstanceType
  8. 升级与版本管理
  9. 故障排查方法论

附录


第一部分 入门篇

1. 认识 KubeVirt

1.1 什么是 KubeVirt

KubeVirt 是一个运行在 Kubernetes 之上的虚拟化扩展平台。它把"虚拟机"抽象成 Kubernetes 的自定义资源(CRD),让你可以像管理 Pod 一样,用 kubectl / YAML / GitOps 的方式声明、创建、启停、迁移虚拟机。

一句话定位:

容器编排平台 + 传统虚拟机负载 = KubeVirt。 它不是模拟器,底层就是 KVM + QEMU,性能等同原生 KVM 虚拟机。

1.2 为什么需要 KubeVirt

痛点KubeVirt 的解法
存量传统应用(单体、Windows、旧中间件)无法容器化以虚拟机形态继续运行,与容器同平台管理
同时维护 K8s 和 OpenStack/VMware 两套平台,团队割裂一套 K8s 平台统一管理容器与虚拟机
虚拟机的创建/扩缩/迁移依赖手工操作全部 API 化、声明式、可 GitOps
CI/CD 流水线无法覆盖虚拟机与容器走同一套流水线、镜像仓库、监控告警

1.3 与传统虚拟化平台对比

维度libvirt/KVM 裸用OpenStackPVEKubeVirt
管理接口virsh/XMLHorizon/APIWeb UIkubectl + CRD(声明式)
编排能力有(重)原生继承 K8s 编排
网络Linux BridgeNeutron(复杂)SDN 可选复用 CNI + Multus
存储本地文件/共享盘CinderZFS/Ceph复用 CSI/PVC(任何存储后端)
部署重量极重轻(一组 Operator 组件)
适合场景单机/小规模大型私有云中小虚拟化已有 K8s 团队承载 VM 负载

1.4 典型适用场景

  1. 存量传统应用迁移过渡(先搬上平台,再逐步容器化);
  2. 需要完整 OS 的负载:Windows 应用、需要特定内核模块的应用;
  3. 开发测试环境快速发放虚拟机(模板 + 克隆秒级开盘);
  4. 边缘/小规模场景替代重型虚拟化平台。

不适用场景:追求极致虚拟机密度与完整 IaaS 能力(计费、多租户网络、镜像市场) 的大型私有云,仍建议评估 OpenStack 或商业平台。


2. 核心概念与整体架构

2.1 整体架构图

                     kubectl / virtctl / GitOps

                    ┌─────────▼─────────┐
                    │  Kubernetes API    │
                    │  Server (CRD 扩展) │
                    └─────────┬─────────┘
        webhook/admission     │          watch 资源
              ┌───────────────┼────────────────────┐
              │               │                    │
      ┌───────▼──────┐  ┌─────▼────────┐   ┌───────▼────────┐
      │   virt-api   │  │virt-controller│  │  virt-operator  │
      │ (校验/转换/  │  │ (VM→VMI→      │   │ (组件生命周期/  │
      │  console代理)│  │  launcher调度)│   │  升级/自愈)     │
      └──────────────┘  └─────┬────────┘   └────────────────┘
                              │ 为每个 VMI 创建
                    ┌─────────▼─────────┐
                    │  virt-launcher Pod │  ← 每个运行中 VM 一个 Pod
                    │  ┌──────────────┐ │
                    │  │ libvirtd+QEMU│ │
                    │  │  (KVM 客户机) │ │
                    │  └──────────────┘ │
                    └─────────┬─────────┘
                              │ 节点内管理
                    ┌─────────▼─────────┐
                    │   virt-handler     │  ← DaemonSet,每节点一个
                    │ (节点代理:域定义、  │
                    │  迁移、磁盘热插拔)  │
                    └───────────────────┘

2.2 核心组件职责

组件部署形态职责挂了会怎样
virt-operatorDeployment(2 副本)管理 KubeVirt CR,部署/升级/自愈其余所有组件存量 VM 无感;无法升级/自愈
virt-apiDeployment(2 副本)校验/变更 Webhook、子资源 API(console/vnc 代理)、凭证签发存量 VM 无感;新建/控制台不可用
virt-controllerDeployment(2 副本)大脑:watch VM/VMI,创建 virt-launcher Pod、处理迁移/驱逐存量 VM 无感;无法启动新 VM
virt-handlerDaemonSet(每节点 1 个)节点代理:把 VMI 规格翻译为域定义交给 launcher、迁移目标端接收、磁盘热插拔该节点无法启停 VM
virt-launcher每 VMI 一个 Pod内含 libvirtd + QEMU,真正运行客户机;Pod 消亡 = VM 停止该 VM 停止
virt-exportproxyDeployment(2 副本)数据导出(VirtualMachineExport)的入口代理导出功能不可用
virt-template-*Deployment模板 API(可选能力)模板功能不可用

关键理解:virt-launcher Pod 与 VMI 是 1:1 关系。删除这个 Pod 等于强制关机; Pod 被调度到其他节点等于 VM 冷迁移。理解这一点后,很多排障思路与容器完全一致。

2.3 核心 CRD 一览

CRD缩写作用使用频率
virtualmachines.kubevirt.iovm虚拟机定义(期望状态),可反复启停⭐⭐⭐⭐⭐
virtualmachineinstances.kubevirt.iovmi运行中的实例(类似 Pod 之于 Deployment)⭐⭐⭐⭐⭐
virtualmachineinstancemigrations.kubevirt.iovmim一次热迁移任务⭐⭐⭐
virtualmachineinstancereplicasets.kubevirt.iovmirsVM 副本集(无状态批量)⭐⭐
virtualmachinepools.pool.kubevirt.iovmpoolVM 池(支持扩缩与滚动更新)⭐⭐
virtualmachineclones.clone.kubevirt.iovmclone一键克隆 VM 及其磁盘⭐⭐⭐
virtualmachinesnapshots.snapshot.kubevirt.iovmsnapshotVM 快照⭐⭐⭐
virtualmachinerestores.snapshot.kubevirt.iovmrestore从快照恢复⭐⭐⭐
virtualmachineexports.export.kubevirt.iovmexport把 VM 磁盘导出为镜像/文件⭐⭐⭐
datavolumes.cdi.kubevirt.iodvCDI:磁盘导入/克隆/上传/空白盘⭐⭐⭐⭐
kubevirts.kubevirt.iokvKubeVirt 平台自身配置⭐⭐
virtualmachineclusterinstancetypes.instancetype.kubevirt.iovmclusterinstancetype规格模板(类似 EC2 实例类型)⭐⭐
migrationpolicies.migrations.kubevirt.iomigrationpolicy迁移策略分组

2.4 一次"创建并启动 VM"的完整链路

① kubectl apply vm.yaml (spec.runStrategy: Always)

② virt-api webhook 校验字段、注入默认值

③ virt-controller 发现 VM 需要运行 → 创建 VMI 对象

④ virt-controller 创建 virt-launcher Pod(资源请求 = VM 的 CPU/内存)

⑤ Pod 调度到节点 → kubelet 拉起容器

⑥ 该节点的 virt-handler 读取 VMI → 生成域定义 → 通知 launcher 内 libvirtd

⑦ QEMU 启动客户机,挂载 PVC 磁盘、接入 CNI 网络

⑧ VMI status 变为 Running,VM status.ready = true

关机则反向:VMI 被删 → launcher Pod 退出 → 资源释放;磁盘(PVC)与定义(VM)保留


3. 环境准备

3.1 硬件与内核要求

要求说明检查命令
CPU 虚拟化扩展Intel VT-x / AMD-V,且宿主机开启嵌套虚拟化`egrep -c '(vmx
/dev/kvm 设备KVM 内核模块加载后产生ls -l /dev/kvm
内核模块kvm + kvm_intel/kvm_amd`lsmod
K8s 版本≥ 1.26(推荐 1.28+),RKE2/K3s/标准发行版均可kubectl version
节点资源每节点预留 ≥ 2C/4G 给平台组件,其余供 VM 使用kubectl describe node

开启嵌套虚拟化(裸机或云主机都要确认):

bash
# Intel
echo 'options kvm_intel nested=1' > /etc/modprobe.d/kvm-nested.conf
modprobe -r kvm_intel && modprobe kvm_intel nested=1
cat /sys/module/kvm_intel/parameters/nested    # 应输出 1 或 Y

# AMD
echo 'options kvm_amd nested=1' > /etc/modprobe.d/kvm-nested.conf
modprobe -r kvm_amd && modprobe kvm_amd nested=1
cat /sys/module/kvm_amd/parameters/nested

⚠️ 云主机上跑 KubeVirt 属于"嵌套虚拟化",必须选用支持嵌套虚拟化的实例规格 (如阿里云 ecs.ebm 裸金属、AWS *.metal、腾讯云 裸金属),否则 /dev/kvm 不存在。

3.2 节点预配置(Rocky/RHEL 系)

bash
# 1. 加载模块并持久化
modprobe kvm kvm_intel nested=1
cat > /etc/modules-load.d/kvm.conf <<'EOF'
kvm
kvm_intel
EOF

# 2. /dev/kvm 权限:让 kubelet 能把设备挂进 virt-launcher
chmod 666 /dev/kvm

# 3. RKE2 需允许特权设备(默认满足);若用 SELinux enforcing,
#    确认 kubevirt 命名空间资源可访问 /dev/kvm(或对该命名空间设 privileged 策略)

3.3 网络要求

  • CNI 必须支持跨节点 Pod 通信(VXLAN/IPIP 封装或真实路由)。现网踩坑: Calico 配成 ipipMode: Never, vxlanMode: Never 导致跨节点 502,必须改为 vxlanMode: Always(详见实战文档部署章节);
  • 若计划让 VM 直接使用物理网段 IP,需要 Multus + bridge/macvlan,并提前规划 宿主机网桥;
  • 镜像仓库(Harbor)用于离线分发 kubevirt/CDI 镜像。

4. 安装 KubeVirt

4.1 在线安装(官方两步法)

bash
export KUBEVIRT_VERSION="v1.9.0"   # 或 latest
# ① operator:CRD、RBAC、virt-operator Deployment
kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-operator.yaml
# ② KubeVirt CR:触发 operator 部署其余组件
kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-cr.yaml

# 等待部署完成
kubectl -n kubevirt wait kv kubevirt --for condition=Available --timeout=600s
kubectl get pods -n kubevirt

4.2 离线/私有仓库安装(生产常用)

隔离网络环境通过内部 Harbor 代理缓存(现网方案):

镜像映射(RKE2 registries.yaml mirror):
quay.io/kubevirt/virt-operator:v1.9.0    → 192.168.122.156:30000/kubevirt/kubevirt/virt-operator:v1.9.0
quay.io/kubevirt/virt-api:v1.9.0         → .../virt-api:v1.9.0
quay.io/kubevirt/virt-controller:v1.9.0  → .../virt-controller:v1.9.0
quay.io/kubevirt/virt-handler:v1.9.0     → .../virt-handler:v1.9.0
quay.io/kubevirt/virt-launcher:v1.9.0    → .../virt-launcher:v1.9.0

关键点:

  1. kubevirt-operator.yaml 中 virt-operator 的镜像地址替换为内部仓库;
  2. KubeVirt CR 指定 imageRegistryimageTag,operator 据此拉起其余组件:
yaml
apiVersion: kubevirt.io/v1
kind: KubeVirt
metadata:
  name: kubevirt
  namespace: kubevirt
spec:
  imagePullPolicy: IfNotPresent
  imageRegistry: 192.168.122.156:30000/kubevirt/kubevirt   # 内部仓库
  imageTag: v1.9.0

完整离线部署记录(含故障修复)见 ../rke2-kubevirt-deployment-guide.md

4.3 KubeVirt CR 常用字段

字段作用
spec.imageRegistry / spec.imageTag组件镜像源(离线必配)
spec.imagePullPolicy镜像拉取策略
spec.configuration.developerConfiguration.featureGates特性开关(如 CPUManagerSRIOVLiveMigration
spec.configuration.network默认网络绑定方式等
spec.customizeComponents给组件注入补丁/注解
spec.workloadUpdateStrategy升级时如何滚动存量 VM(LiveMigrate/LiveUpdate)

4.4 验证安装

bash
kubectl get kubevirt -n kubevirt            # PHASE=Deployed
kubectl get pods -n kubevirt                # 全部 Running
kubectl get crd | grep kubevirt.io          # 22 个 CRD

4.5 安装 virtctl 客户端

virtctl 是 VM 操作的瑞士军刀(console/vnc/migrate/expose/expand…):

bash
export VERSION=v1.9.0 ARCH=amd64
curl -Lo /usr/local/bin/virtctl \
  https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/virtctl-${VERSION}-linux-${ARCH}
chmod +x /usr/local/bin/virtctl
virtctl version      # Client 与服务端版本应一致

4.6 (可选)安装 CDI

CDI(Containerized Data Importer)提供磁盘的导入/克隆/上传能力, 是生产环境标配。安装方式与 KubeVirt 类似(operator + CR),离线环境见 ../cdi-offline-deployment-guide.md。验证:

bash
kubectl get pods -n cdi        # cdi-operator/apiserver/deployment/uploadproxy Running
kubectl get cdi                # PHASE=Deployed

5. 第一台虚拟机

5.1 最小可运行 VM 模板

下面是一个完整注释的最小示例,使用 containerDisk(容器内嵌磁盘,适合无状态演示):

yaml
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: demo-vm
  labels:
    app: demo-vm
spec:
  running: true                     # 创建后立即启动
  template:
    metadata:
      labels:
        app: demo-vm               # Service/监控靠它选择器匹配
    spec:
      domain:
        cpu:
          cores: 2                 # CPU 核数
        memory:
          guest: 2Gi               # 客户机内存
        devices:
          disks:
          - name: rootdisk
            disk:
              bus: virtio          # 磁盘总线:virtio 性能最佳
          - name: cloudinit
            disk:
              bus: virtio
          interfaces:
          - name: default
            masquerade: {}         # 默认 Pod 网络 + NAT
      networks:
      - name: default
        pod: {}                    # 使用 K8s Pod 网络
      volumes:
      - name: rootdisk
        containerDisk:             # 磁盘来自容器镜像
          image: quay.io/kubevirt/cirros-container-disk-demo:latest
      - name: cloudinit
        cloudInitNoCloud:
          userData: |
            #!/bin/sh
            echo 'Hello KubeVirt' > /tmp/hello

5.2 创建与观察

bash
kubectl apply -f demo-vm.yaml
kubectl get vm demo-vm             # STATUS=Running
kubectl get vmi demo-vm            # 查看运行实例与所在节点
kubectl get pods -l vm.kubevirt.io/name=demo-vm   # 找到 virt-launcher Pod
kubectl describe vmi demo-vm       # 事件与状态(排障首选)

5.3 接入控制台

bash
virtctl console demo-vm            # 串口控制台(需 VM 内有串口 tty)
virtctl vnc demo-vm                # 图形控制台(本地需图形环境)
virtctl ssh root@demo-vm           # 通过 virt-api 代理的 SSH
virtctl port-forward vm/demo-vm 2222:22   # 端口转发,再 ssh -p 2222

5.4 停止与删除

bash
virtctl stop demo-vm               # 优雅关机(走 ACPI,磁盘保留)
virtctl start demo-vm              # 再次启动
kubectl delete vm demo-vm          # 删除 VM 定义;其 PVC 是否保留取决于磁盘类型

磁盘去向:containerDisk / emptyDisk 随 VM 销毁;PVC 磁盘默认保留, 需要 kubectl delete pvc 手动清理。


6. 虚拟机生命周期管理

6.1 runStrategy 五种策略(重点)

spec.running: true/false 是老写法,生产推荐用 spec.runStrategy

runStrategy行为典型场景
Always始终保持运行,崩溃/节点故障自动拉起生产标配
RerunOnFailure失败后重跑,成功后不再重启批处理/一次性任务
Manual由用户显式 start/stop,不自动干预调试
Halted等同关机,保留定义长期停机
Once运行一次,退出即结束临时任务
yaml
spec:
  runStrategy: Always

设置 runStrategy不要再写 running,两者互斥。

6.2 virtctl 生命周期命令速查

命令作用
virtctl start/stop/restart/pause/unpause <vm>启/停/重启/暂停/恢复
virtctl migrate <vm>触发热迁移
virtctl vm expand <vm> --memory/--cpu在线扩内存/核数(需支持)
virtctl expose vm <vm> --port --type NodePort暴露服务
virtctl guestfs <pvc>用临时 Pod 挂载并修改 PVC 内磁盘
virtctl imageupload dv/pvc <name> -f disk.qcow2本地镜像上传为 PVC

6.3 理解状态字段

bash
kubectl get vm demo-vm -o jsonpath='{.status.printableStatus}'  # Stopped/Running/...
kubectl get vm demo-vm -o jsonpath='{.status.ready}'             # true=可对外提供服务
kubectl get vmi demo-vm -o jsonpath='{.status.phase}'            # Pending/Scheduling/Running/Succeeded/Failed

6.4 标签、注解与选择器

  • spec.template.metadata.labels:virt-launcher Pod、VMI、Service 选择器都依赖它, 克隆/模板化时必须改唯一,否则 Service 会误匹配;
  • 常用注解:kubevirt.io/allow-pod-bridge-network-live-migration 等,按需查阅文档。

第二部分 进阶篇

7. VirtualMachine Spec 概览

VM 的 YAML 分为三层,理解层次结构是进阶的关键:

VirtualMachine
├── metadata                     # 名称、命名空间、标签
└── spec
    ├── running / runStrategy    # 是否运行(二选一)
    ├── instancetype/preference  # (可选)规格与偏好引用
    ├── dataVolumeTemplates      # (可选)随 VM 创建的磁盘模板
    └── template                 # ★ 与 VMI 等价的部分
        ├── metadata.labels      # launcher Pod 的标签
        └── spec
            ├── domain           # 客户机硬件:cpu/memory/firmware/clock/features/devices
            │   └── devices      # disks / interfaces / rng / watchdog / inputs / gpus...
            ├── volumes          # 卷定义(PVC/containerDisk/cloudInit/...)
            ├── networks         # 网络定义(pod / multus)
            ├── nodeSelector/affinity/tolerations   # 调度
            ├── evictionStrategy # 驱逐/迁移策略
            └── accessCredentials# SSH 密钥/密码注入

每个字段的逐行详解见实战文档 kubevirt-practical-operations-guide.md 第 2 章(虚拟机 YAML 字段详解)。

新手最容易混淆的三个对应关系:

关系说明
domain.devices.disks[].namevolumes[].name设备与卷通过 name 绑定,一一对应
domain.devices.interfaces[].namenetworks[].name网卡与网络定义通过 name 绑定
template.metadata.labels ↔ Service selectorService/NodePort 靠它找到 VM

8. 网络深入

8.1 四种典型网络拓扑

A. masquerade(默认)        VM ──NAT──> Pod IP ──CNI──> 集群/外部
   外部访问需经 Service/NodePort

B. bridge(Pod 网络直通)     VM 直接持有 Pod IP(无 NAT)
   入站直连,但受 CNI 插件限制

C. Multus 辅助网络            VM 第二网卡挂物理网桥/macvlan
   → VM 获得物理网段 IP(如 192.168.122.x),外部直连

D. SR-IOV                    物理网卡 VF 直通,最高性能

8.2 默认 Pod 网络(masquerade)

yaml
domain:
  devices:
    interfaces:
    - name: default
      masquerade: {}        # VM 内部 10.0.2.x,NAT 借用 Pod IP
      ports:                # 可选:显式放行的端口(不写=全放行)
      - port: 80
networks:
- name: default
  pod: {}

特点:

  • VM 对外的源/目的都是 Pod IP,Pod IP 会随重建变化
  • 出方向默认全通;外部入站必须走 Service(ClusterIP/NodePort/LoadBalancer);
  • 适合内部服务、开发测试;
  • 热迁移要求 Pod 网络必须是 masquerade 绑定(bridge 绑定 Pod 网络禁止迁移)。

8.3 Multus 辅助网络(固定物理网段 IP 的核心手段)

前置:Multus + bridge/macvlan CNI 插件。核心对象是 NetworkAttachmentDefinition(NAD)

yaml
# bridge 模式:节点上先建好网桥 br-vm(把物理网卡加入网桥)
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
  name: vm-physnet
  namespace: default
spec:
  config: '{
    "cniVersion": "0.3.1",
    "type": "bridge",
    "bridge": "br-vm",
    "vlan": 0,
    "ipam": {}
  }'

VM 侧引用:

yaml
domain:
  devices:
    interfaces:
    - name: default
      masquerade: {}
    - name: physnet              # 第二块网卡
      bridge: {}                 # 绑定方式:bridge(macvlan 场景同样写 bridge)
networks:
- name: default
  pod: {}
- name: physnet
  multus:
    networkName: vm-physnet      # 指向 NAD

⚠️ 关键结论(现网验证):KubeVirt 的 Multus 辅助网络不会把 NAD 中 IPAM(whereabouts/host-local)分配的 IP 注入客户机。客户机内必须由 cloud-init networkData 写死静态 IP 或内部 DHCP 获取。

8.4 macvlan 模式

与 bridge 类似,只是 NAD 的 type 改为 macvlan,master 指向物理网卡, 无需在节点上建桥,但宿主机与 VM 互访受限(macvlan 特性)。

8.5 用 Multus 网络替代默认网络

networks 中名为 default 的网络改为 multus 引用,即可让物理网段网卡成为 VM 的唯一/主网卡(常用于"VM 必须使用固定业务网段"的强需求场景)。


9. 存储深入

9.1 KubeVirt 支持的卷类型

卷类型数据持久性典型用途
persistentVolumeClaim✅ 持久生产系统盘/数据盘(首选)
dataVolume✅ 持久通过 CDI 导入/克隆/上传生成 PVC
containerDisk❌ 随 VM 销毁无状态演示、金盘打包
emptyDisk❌ 随 VM 销毁临时缓存盘
cloudInitNoCloud / ConfigDrive-首次启动配置注入
configMap / secret / serviceAccount-把 K8s 资源挂进客户机
hostDisk依赖节点直接读写节点文件(谨慎使用)

9.2 磁盘设备形态与总线

yaml
devices:
  disks:
  - name: rootdisk
    disk:
      bus: virtio        # virtio(最快)/sata(兼容)/scsi
    serial: DISK001      # 可选:客户机按 serial 识别磁盘
    cache: none          # none/writeback/writethrough
  • disk = 块设备;cdrom = 光驱;floppy/lun 特殊用途;
  • 生产一律 bus: virtio,需要客户机有 virtio 驱动(现代 Linux 自带,Windows 需 virtio-win)。

9.3 PVC 作为磁盘的两种来源

手工 PV/PVC(现网早期方案,hostPath):

yaml
volumes:
- name: rootdisk
  persistentVolumeClaim:
    claimName: rocky9-vm2-disk    # 事先创建好的 PVC

hostPath PV 会把数据钉死在单节点,不能迁移。生产应使用共享存储的 StorageClass 动态供应(见实战文档 NAS 存储章节)。

dataVolumeTemplates(推荐):随 VM 一起声明,CDI 自动建盘:

yaml
spec:
  dataVolumeTemplates:
  - metadata:
      name: demo-rootdisk
    spec:
      source:
        http:
          url: "http://images.example.com/rocky9.qcow2"
      pvc:
        storageClassName: vm-nas
        accessModes: [ReadWriteMany]
        resources:
          requests:
            storage: 20Gi
  template:
    spec:
      volumes:
      - name: rootdisk
        dataVolume:
          name: demo-rootdisk

9.4 CDI 的四种数据来源

source说明
http/https从 URL 拉取 qcow2/raw/img(qcow2 会被自动转成 raw
registry从容器镜像仓库拉取磁盘镜像
pvc克隆已有 PVC(智能克隆/网络克隆)
uploadvirtctl imageuploadcdi-uploadproxy 本地上传
blank创建空白盘
s3/gcs对象存储

注意:Filesystem 模式 PVC 上磁盘文件固定为 disk.img(raw), CDI 会预留 5.5% 空间开销(CDIConfig.spec.filesystemOverhead)。


10. cloud-init 与凭据注入

10.1 cloudInitNoCloud(最常用)

yaml
volumes:
- name: cloudinit
  cloudInitNoCloud:
    userData: |-
      #cloud-config
      hostname: rocky9-vm2
      password: xxx
      chpasswd: { expire: false }
      ssh_pwauth: true
      disable_root: false
      users:
      - name: admin
        sudo: ALL=(ALL) NOPASSWD:xxx
        ssh_authorized_keys:
        - ssh-rsa AAAA...
    networkData: |-       # 静态 IP 在这里写(见实战文档)
      version: 1
      config:
      - type: physical
        name: eth1
        subnets:
        - type: static
          address: 192.168.122.100/24
          gateway: 192.168.122.1

重要特性cloudInitNoCloud 只在首次启动(无 cloud-init 实例标记)生效。 改 userData 后需删掉客户机内 /var/lib/cloud/instances 或重建磁盘才会重新应用。

10.2 accessCredentials(运行时可更新凭据)

比 cloud-init 更适合持续管理密钥:把 SSH 公钥放在 Secret 里,VM 通过 accessCredentials 注入,Secret 更新后 KubeVirt 会同步进客户机(需 guest agent)。

yaml
spec:
  template:
    spec:
      accessCredentials:
      - sshPublicKey:
          source:
            secret:
              secretName: my-ssh-keys
          propagationMethod:
            qemuGuestAgent:
              users: ["root", "admin"]

11. 访问虚拟机的所有方式

方式命令/手段适用特点
串口控制台virtctl console <vm>开机引导、网络故障抢救依赖 virt-api 代理
VNC 图形virtctl vnc <vm>图形界面、Windows本地需图形环境
SSH(代理)virtctl ssh user@<vm>集群内快速访问走 virt-api,无需 VM 有外网
端口转发virtctl port-forward vm/<vm> 2222:22临时调试本地 2222 → VM 22
Service NodePortvirtctl expose 或 YAML稳定外部访问(推荐)节点IP:端口永不变
LoadBalancer/Ingress标准 K8s 方式云上/有 LB 环境四层/七层入口
物理网段直连Multus bridge/macvlan外部按固定业务 IP 直连见网络章节

NodePort 声明式示例(生产推荐,可进 Git):

yaml
apiVersion: v1
kind: Service
metadata:
  name: rocky9-vm2-ssh
spec:
  type: NodePort
  selector:
    app: rocky9-vm2          # 与 VM template.metadata.labels 一致
  ports:
  - name: ssh
    port: 22
    targetPort: 22
    nodePort: 31022          # 固定端口,双固定:节点IP+端口

完整网络接入方案(含固定 IP 三选一决策)见实战文档第 3 章。


第三部分 精通篇

12. 热迁移(Live Migration)

12.1 原理与前提

热迁移 = 内存页增量复制 + 磁盘共享,客户机不断电不断网。前提:

条件说明
磁盘可共享PVC 必须 ReadWriteMany(NFS/共享块);RWO 本地盘无法热迁移
迁移网络节点间互通;可配专用迁移网络(spec.configuration.migrations.network
资源充足目标节点要有等量 CPU/内存
网络模式Pod 网络必须 masquerade 绑定(bridge 绑定禁止迁移);固定 IP 用 Multus 第二网卡承载则不影响迁移(见实战手册 3.4)
节点钉扎nodeSelector/亲和性钉死单节点后迁移找不到目标节点必然失败;钉节点 + 固定 Pod IP 的取舍方案见实战手册 3.5
非独占设备SR-IOV/GPU 直通默认不可迁移(有特性开关可部分支持)

12.2 发起迁移

bash
virtctl migrate rocky9-vm2                 # 命令行
# 或创建 VirtualMachineInstanceMigration CR(可声明目标节点/带宽限制)
kubectl get vmim                            # 查看迁移进度
kubectl get vm rocky9-vm2 -o wide         # 迁移后观察节点变化

12.3 迁移策略与调优

MigrationPolicy 可对不同 VM 分组设置带宽/并发:

yaml
apiVersion: migrations.kubevirt.io/v1alpha1
kind: MigrationPolicy
metadata:
  name: low-bandwidth
spec:
  bandwidthPerMigration: 64Mi
  completionsTimeoutSec: 1800
  selectors:
    virtualMachineInstanceSelector:
      workload-type: batch

全局参数在 KubeVirt CR:spec.configuration.migrationsbandwidthPerMigrationparallelMigrationsPerClusterallowAutoConverge 等)。


13. 高可用与驱逐策略

13.1 evictionStrategy

行为
LiveMigrate节点驱逐/维护时自动热迁移(需 RWX 磁盘)
LiveMigrateIfPossible能迁就迁,不能迁就驱逐重启
External交给外部控制器处理
None不动(默认,节点维护会卡住)

生产模板三件套

yaml
spec:
  template:
    spec:
      runStrategy 在 VM 层设 Always
      evictionStrategy: LiveMigrate        # 维护自动迁走
      tolerations:                          # 节点短暂失联不急于杀 VM
      - key: node.kubernetes.io/unreachable
        operator: Exists
        effect: NoExecute
        tolerationSeconds: 600
      - key: node.kubernetes.io/not-ready
        operator: Exists
        effect: NoExecute
        tolerationSeconds: 600

13.2 故障自愈链路

节点宕机
  ├─ 磁盘在共享存储(RWX)+ runStrategy: Always
  │    → virt-controller 在其他节点重建 launcher → VM 分钟级自愈 ✅
  └─ 磁盘在 local-path/单节点 hostPath
       → 数据钉死在故障节点,无法自愈 ❌(必须改造存储)

现网存储 HA 加固清单见 ../kubevirt-storage-ha-guide.md(挂载参数、 VM HA 声明、NAS 双控、3-2-1 备份)。


14. 快照与备份恢复

14.1 VirtualMachineSnapshot(推荐)

基于 CSI VolumeSnapshot 对磁盘做一致性快照(建议安装 qemu-guest-agent 以获得文件系统冻结):

yaml
apiVersion: snapshot.kubevirt.io/v1beta1
kind: VirtualMachineSnapshot
metadata:
  name: rocky9-snap-20260903
spec:
  source:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: rocky9-vm2
bash
kubectl get virtualmachinesnapshot          # PHASE=Succeeded 即成功
kubectl get virtualmachinesnapshotcontent   # 快照内容(对应磁盘快照)

⚠️ 要求底层 StorageClass 支持 VolumeSnapshot。NFS(subdir provisioner) 不支持快照,需使用支持快照的存储或改用备份方案(见实战文档备份章节)。

14.2 VirtualMachineRestore(从快照恢复)

yaml
apiVersion: snapshot.kubevirt.io/v1beta1
kind: VirtualMachineRestore
metadata:
  name: rocky9-restore
spec:
  target:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: rocky9-vm2          # 恢复到原 VM(也可改名恢复到新 VM)
  virtualMachineSnapshotName: rocky9-snap-20260903

恢复前建议先停掉目标 VM(virtctl stop)。

14.3 VirtualMachineExport(导出备份)

把 VM 磁盘导出为镜像或文件,适合跨集群迁移/异地备份

yaml
apiVersion: export.kubevirt.io/v1beta1
kind: VirtualMachineExport
metadata:
  name: rocky9-export
spec:
  source:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: rocky9-vm2
bash
virtctl export vm rocky9-vm2 --output=rocky9-backup.tar.gz

14.4 备份体系分层

层次工具覆盖
VM 定义GitOps(YAML 入库)配置可重建
磁盘数据VM Snapshot / Export / Velero数据可恢复
平台自身etcd 备份 + CRD 清单集群级灾备

15. 克隆与黄金镜像体系

15.1 数据卷克隆(CDI)

yaml
apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
  name: vm001-rootdisk
spec:
  source:
    pvc:
      namespace: default
      name: golden-rocky9          # 源"金盘"
  pvc:
    storageClassName: vm-nas
    accessModes: [ReadWriteMany]
    resources:
      requests:
        storage: 20Gi

CDI 智能克隆优先走 CSI 快照(秒级),不支持时退化为网络复制。

15.2 VirtualMachineClone(整台克隆)

yaml
apiVersion: clone.kubevirt.io/v1alpha1
kind: VirtualMachineClone
metadata:
  name: clone-rocky9
spec:
  source:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: rocky9-vm2
  target:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: rocky9-vm3

15.3 黄金镜像体系(生产最佳实践)

源 qcow2 → 导入一次生成金盘(DataVolume)
          → DataSource 作为版本化引用
          → 每台新 VM 从 DataSource 克隆(秒级开盘)
yaml
apiVersion: cdi.kubevirt.io/v1beta1
kind: DataSource
metadata:
  name: rocky9-golden
  namespace: default
spec:
  source:
    pvc:
      namespace: default
      name: golden-rocky9

DataVolumeTemplates 中把 source.pvc 换成 sourceRef: {kind: DataSource, name: rocky9-golden} 即可。配合 DataImportCron 可定时刷新金盘版本。


16. 监控体系

16.1 指标来源

virt-operator/api/controller/handler/launcher 均暴露 Prometheus 指标 (带 prometheus.kubevirt.io: "true" 标签)。

16.2 接入 Prometheus(kube-prometheus-stack / Rancher Monitoring)

yaml
# ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: kubevirt-metrics
  namespace: monitoring
spec:
  namespaceSelector:
    matchNames: [kubevirt]
  selector:
    matchLabels:
      prometheus.kubevirt.io: "true"
  endpoints:
  - port: metrics
    scheme: https
    tlsConfig:
      insecureSkipVerify: true

16.3 关键指标

指标含义告警建议
kubevirt_vmi_phase_count各状态 VMI 数量Failed > 0
kubevirt_vmi_memory_used_bytes客户机内存用量> 90%
kubevirt_vmi_cpu_system_usage_seconds_totalCPU 用量持续 > 80%
kubevirt_vmi_storage_read/write_traffic_bytes磁盘吞吐突增/为 0
kubevirt_migrations_in_flight进行中的迁移卡住超时
kubevirt_vmi_last_migration_attempt_time上次迁移时间-

官方提供多张 Grafana 仪表盘(带 kubevirt tag),现网已部署 4 张。

16.4 四层监控模型

第 4 层 业务层      客户机内部应用/系统               (guest agent、业务探针)
第 3 层 虚拟机层    kubevirt_vmi_*:CPU/内存/网络/磁盘/迁移   ← 现网已覆盖
第 2 层 K8s 对象层  kube-state-metrics:节点状态、Pod、requests ← 容量告警依据
第 1 层 宿主机层    node-exporter / kubelet:CPU/内存/磁盘/驱逐  ← 容量告警依据

只监控第 3/4 层(VM 自身)是不够的:"宿主机资源不足"发生在第 1/2 层。 Rancher Monitoring(kube-prometheus-stack)默认已部署 node-exporter 和 kube-state-metrics,指标是现成的,关键是补上告警规则。

16.5 宿主机资源不足:两类"不足"都要监控

类型定义信号后果
A. 实际资源耗尽CPU/内存/磁盘真实用满利用率、节点 Pressure 状态、kubelet 驱逐存量 VM 变慢、OOM、被驱逐
B. 调度容量耗尽requests 总和逼近 allocatable,新 Pod 放不下requests/allocatable 比值、Unschedulable Pod、VMI 卡 Scheduling存量无感,但新 VM 起不来、热迁移无目标节点

B 型最隐蔽:平时一切正常,节点故障时才发现"没有节点能接住迁移"。

关键指标

指标来源用途
node_cpu_seconds_totalnode-exporterCPU 利用率(按 mode)
node_memory_MemAvailable_bytesnode-exporter真实可用内存(比 free 准)
node_filesystem_avail_bytesnode-exporter文件系统剩余空间
kube_node_status_conditionkube-state-metricsMemoryPressure/DiskPressure/PIDPressure/Ready
kube_node_status_allocatablekube-state-metrics节点可调度容量
kube_pod_container_resource_requestskube-state-metricsPod 资源请求总量
kube_pod_status_unschedulablekube-state-metrics无法调度的 Pod
kubevirt_vmi_phase_count{phase=~"[Ss]cheduling"}virt-controller卡在调度中的 VM
container_memory_working_set_bytes{pod=~"virt-launcher-.*"}cAdvisorlauncher 真实内存占用

推荐告警规则(PrometheusRule,可直接 apply)

yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: node-resource-rules
  namespace: kubevirt
  labels:
    release: rancher-monitoring      # ★ 必须与 Prometheus 的 ruleSelector 匹配
spec:
  groups:
  - name: node-resource.rules
    rules:
    # ---------- A 类:实际资源耗尽 ----------
    - alert: NodeCPUHighUtilization
      expr: (1 - avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m]))) * 100 > 85
      for: 10m
      labels: { severity: warning }
      annotations:
        summary: "节点 {{ $labels.instance }} CPU 使用率超 85%"

    - alert: NodeMemoryLow
      expr: node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100 < 10
      for: 5m
      labels: { severity: critical }
      annotations:
        summary: "节点 {{ $labels.instance }} 可用内存不足 10%"

    - alert: NodeFilesystemAlmostFull
      expr: >
        node_filesystem_avail_bytes{fstype!~"tmpfs|overlay|squashfs"}
        / node_filesystem_size_bytes * 100 < 15
      for: 10m
      labels: { severity: warning }
      annotations:
        summary: "节点 {{ $labels.instance }} 分区 {{ $labels.mountpoint }} 剩余 <15%"

    - alert: NodeFilesystemWillFillIn24h
      expr: predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}[6h], 24*3600) < 0
      for: 30m
      labels: { severity: warning }
      annotations:
        summary: "按当前增速,{{ $labels.mountpoint }} 24h 内写满"

    - alert: NodeUnderPressure
      expr: >
        kube_node_status_condition{condition=~"MemoryPressure|DiskPressure|PIDPressure",status="true"} == 1
      for: 2m
      labels: { severity: critical }
      annotations:
        summary: "节点 {{ $labels.node }} 处于 {{ $labels.condition }}(接近驱逐阈值)"

    - alert: NodeNotReady
      expr: kube_node_status_condition{condition="Ready",status="true"} == 0
      for: 5m
      labels: { severity: critical }
      annotations:
        summary: "节点 {{ $labels.node }} NotReady"

    # ---------- B 类:调度容量耗尽(KubeVirt 重点) ----------
    - alert: NodeMemoryRequestsNearLimit
      expr: >
        sum by (node) (kube_pod_container_resource_requests{resource="memory"})
        / on(node) group_left()
        kube_node_status_allocatable{resource="memory"} > 0.85
      for: 10m
      labels: { severity: warning }
      annotations:
        summary: "节点 {{ $labels.node }} 内存 requests 已达 allocatable 的 85%,新 VM 可能无法调度"

    - alert: NodeCPURequestsNearLimit
      expr: >
        sum by (node) (kube_pod_container_resource_requests{resource="cpu"})
        / on(node) group_left()
        kube_node_status_allocatable{resource="cpu"} > 0.85
      for: 10m
      labels: { severity: warning }

    - alert: KubeVirtLauncherUnschedulable
      expr: kube_pod_status_unschedulable{pod=~"virt-launcher-.*"} == 1
      for: 3m
      labels: { severity: critical }
      annotations:
        summary: "虚拟机 {{ $labels.pod }} 无法调度:没有节点装得下(资源不足的直接证据)"

    - alert: KubeVirtVMISchedulingStuck
      expr: kubevirt_vmi_phase_count{phase=~"[Ss]cheduling"} > 0
      for: 5m
      labels: { severity: warning }
      annotations:
        summary: "有 VMI 卡在 Scheduling 超过 5 分钟,多为节点资源不足"

说明:

  1. kube-prometheus-stack 自带默认规则(NodeMemoryHighUtilizationNodeFilesystemAlmostOutOfSpaceKubeNodeNotReady 等)已覆盖 A 类一部分, 用 kubectl get prometheusrules -A 查看,按需调阈值;上面的规则重点补 **B 类(调度容量)**与 KubeVirt 专属信号
  2. phase 标签取值随版本可能是小写(现网 kubevirt-rulesfailed/running), 故用正则 [Ss]cheduling 兼容;
  3. release: rancher-monitoring 标签是现网 Prometheus 发现规则的前提 (与 ServiceMonitor 同理);
  4. 告警发出后还需在 Rancher 或 Alertmanager 中配置接收方式(钉钉/邮件/短信)。

告警发生后如何定位

bash
kubectl top nodes                                                   # 实时 CPU/内存(metrics-server)
kubectl describe node <node> | sed -n '/Allocated resources/,+12p'  # requests vs allocatable
kubectl get events -A --field-selector reason=FailedScheduling      # 调度失败原因
kubectl describe vmi <vm>                                           # Events: "Insufficient memory/cpu"
kubectl get pods -A --field-selector status.phase=Pending -o wide   # Pending 的 Pod

16.6 KubeVirt 特有的宿主机视角观测

# 每台虚拟机在宿主机上的真实内存占用(QEMU+libvirtd)
container_memory_working_set_bytes{pod=~"virt-launcher-.*"}

# 与请求量对比:working_set 持续明显超过 requests = 超卖风险
container_memory_working_set_bytes{pod=~"virt-launcher-.*"}
  / kube_pod_container_resource_requests{resource="memory",pod=~"virt-launcher-.*"}

# 每节点 VM 密度(容量规划)
sum by (node) (kubevirt_vmi_phase_count{phase=~"[Rr]unning"})

# 发现集群里所有 kubevirt_* 指标名
group by (__name__)({__name__=~"kubevirt_.*"})

16.7 预防:容量规划与水位线

措施说明
预留 launcher 开销每台 VM 在 memory.guest 之外,宿主机还要多耗约 256Mi~1Gi(QEMU/libvirtd/显存),规划时按 +10%~15% 计
80% 水位线节点 requests 总和 ≤ 80% allocatable;利用率长期 >85% 就扩容或疏散
驱逐阈值提前告警kubelet 默认 memory.available<100Minodefs<10%imagefs<15% 触发驱逐;告警阈值必须设在其之前
PriorityClassVM 设较高优先级,资源紧张时优先保 VM;避免普通容器抢占
ResourceQuota命名空间配额防止 VM 无序扩张
疏散预案evictionStrategy: LiveMigrate + RWX 磁盘,节点维护/告警时可 kubectl drain 自动迁走
Grafana导入 Node Exporter Full(ID 1860);kube-prometheus-stack 自带集群/节点仪表盘

一句话总结:用 node-exporter/KSM 盯"节点真实水位",用 requests/allocatable 比值和"VMI 卡 Scheduling"盯"还能不能再放一台虚拟机", 两者都告警才算监控到位。


17. 性能调优

手段配置收益代价
CPU 绑核cpu.dedicatedCpuPlacement: true消除调度抖动,延迟敏感负载必备该核被独占,容量下降
CPU 拓扑cpu: {sockets, cores, threads}匹配客户机 NUMA/许可-
CPU 模型透传cpu.model: host-passthrough最大指令集兼容热迁移仅限同构 CPU
大页内存memory.hugepages: {pageSize: 1Gi}降低 TLB miss,数据库/网络负载收益大节点需预留大页
ioThreadsdisk.dedicatedIOThread: true磁盘 IO 独立线程,降低延迟每盘一个线程
SR-IOVinterface.sriov: {} + VF 池网络接近裸金属需硬件/驱动支持
NUMA 对齐numa + 节点拓扑插件跨 NUMA 内存访问优化配置复杂

NUMA/CPU 示例:

yaml
domain:
  cpu:
    model: host-passthrough
    sockets: 1
    cores: 4
    threads: 1
    dedicatedCpuPlacement: true
    numa:
      guest:
        vcpu: 0
    features:
    - name: tsc-deadline
  memory:
    guest: 8Gi
    hugepages:
      pageSize: 1Gi

开启 CPUManager 特性门控(KubeVirt CR developerConfiguration.featureGates) 后绑核才生效。


18. 批量管理:副本集、Pool 与 InstanceType

18.1 VirtualMachineInstanceReplicaSet

无状态 VM 批量(磁盘必须是非独占,通常配合 containerDisk):

yaml
apiVersion: kubevirt.io/v1
kind: VirtualMachineInstanceReplicaSet
metadata:
  name: web-vmirs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      domain:
        cpu: { cores: 1 }
        memory: { guest: 1Gi }
        devices:
          disks:
          - name: root
            disk: { bus: virtio }
      volumes:
      - name: root
        containerDisk:
          image: quay.io/kubevirt/cirros-container-disk-demo

18.2 InstanceType 与 Preference

把"规格"从 VM 定义中抽离,像点菜一样选配置(类似云上选型):

yaml
apiVersion: instancetype.kubevirt.io/v1beta1
kind: VirtualMachineClusterInstancetype
metadata:
  name: u1.medium
spec:
  cpu:
    guest: 2
  memory:
    guest: 4Gi
---
apiVersion: instancetype.kubevirt.io/v1beta1
kind: VirtualMachineClusterPreference
metadata:
  name: linux
spec:
  devices:
    preferredDiskBus: virtio
    preferredInterfaceModel: virtio
---
# VM 里引用
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata: { name: app-vm }
spec:
  instancetype:
    name: u1.medium
  preference:
    name: linux
  template:
    spec:
      volumes: [...]

19. 升级与版本管理

19.1 组件升级

bash
# 在线:直接 apply 新版 operator 与 CR
kubectl apply -f kubevirt-operator-new.yaml

# 离线:改 KubeVirt CR 的 imageTag,operator 滚动重建组件
kubectl -n kubevirt patch kv kubevirt --type=merge \
  -p '{"spec":{"imageTag":"v1.10.0"}}'

19.2 workloadUpdateStrategy(存量 VM 如何升级)

升级组件时,已在运行的 launcher 还是旧版。需要策略让它们重建:

yaml
spec:
  workloadUpdateStrategy:
    methods: [LiveMigrate, LiveUpdate]   # 优先热迁移,不行再重启
    workloadUpdateMethods: [LiveMigrate]
  • LiveMigrate:能迁就迁,迁完旧 launcher 被新版替换(要求磁盘可共享);
  • LiveUpdate:原地更新部分可热改的字段;
  • 都不满足的 VM 会保持旧版运行,需人工重启。

19.3 升级注意

  • 先升级测试集群验证;
  • 备份 etcd 与关键 VM 磁盘;
  • 一次只升一个小版本,避免跨大版本;
  • 升级后 kubectl get kv -n kubevirt 确认 Deployed,回归验证核心 VM。

20. 故障排查方法论

20.1 排查顺序(由外到内)

① 平台组件     kubectl get pods -n kubevirt / -n cdi   是否 Running
② 资源对象     kubectl describe vm/vmi/dv               看 Events
③ launcher Pod kubectl logs virt-launcher-<vm>-<id>     qemu/libvirt 报错
④ 节点侧       journalctl -u kubelet;virt-handler 日志  设备/权限
⑤ 网络/存储    CNI 跨节点连通性;PVC Bound;挂载权限

20.2 高频故障速查表

症状常见原因处理
VMI 卡 Scheduling节点无 /dev/kvm / 资源不足检查嵌套虚拟化、节点余量
VMI Pending,Pod 不调度PVC 未 Bound / nodeSelector 不满足查 PVC、标签
启动报 Permission deniedNFS root_squash / uid 映射导出改 no_root_squash
webhook 502Calico 跨节点不通(无封装)vxlanMode: Always
console 连不上virt-api 未 Ready / 代理断查 virt-api 副本与网络
磁盘写不进权限/文件系统只读查挂载选项、磁盘权限
克隆慢走网络复制(无快照能力)换支持快照的存储
迁移失败磁盘非 RWX / 资源不足改共享存储 / 腾资源

20.3 常用排障命令

bash
kubectl describe vmi <vm>                     # 事件是排障第一手信息
kubectl logs -n kubevirt virt-controller-xxx  # 调度/编排决策
kubectl logs virt-launcher-<vm>-xxx -c compute   # qemu 真实日志
kubectl get events -n default --sort-by=.lastTimestamp
virtctl console <vm>                          # 进客户机看系统层

附录

附录 A:术语表

术语英文说明
VMVirtualMachine虚拟机定义(期望状态)
VMIVirtualMachineInstance运行中的虚拟机实例
virt-launcher-承载单个 VMI 的 Pod
CDIContainerized Data Importer磁盘导入/克隆/上传组件
DataVolumeDVCDI 声明的磁盘对象
金盘Golden Image可反复克隆的母盘
DataSource-金盘的版本化引用
NADNetworkAttachmentDefinitionMultus 网络定义
masquerade-VM 借用 Pod IP 出网的 NAT 模式
eviction驱逐节点维护/故障时迁走负载
live migration热迁移不关机迁移
CSIContainer Storage InterfaceK8s 存储插件标准
RWXReadWriteMany多节点可写(热迁移前提)
guest agentQEMU Guest Agent客户机内代理,支持冻结/凭据注入/扩容

附录 B:各章复习题

入门篇

  1. virt-controller 与 virt-handler 的分工是什么?哪个是 DaemonSet?
  2. VMI 与 virt-launcher Pod 是什么关系?删除 launcher Pod 会发生什么?
  3. runStrategy: Alwaysrunning: true 有何区别?
  4. 列出至少 3 个访问 VM 的方式。

进阶篇 5. disks[].namevolumes[].name 如何关联? 6. masquerade 模式下外部如何访问 VM?为什么 Pod IP 不能当固定 IP? 7. 为什么 Multus 辅助网络要配 cloud-init 静态 IP,而不是靠 NAD 的 IPAM? 8. CDI 导入 qcow2 后在 Filesystem PVC 上的文件名和格式是什么? 9. cloudInitNoCloud 为何只在首次启动生效?

精通篇 10. 热迁移对磁盘访问模式有什么硬性要求?为什么? 11. 节点宕机后,什么条件下 VM 能自动在其他节点恢复? 12. NFS(subdir provisioner)为什么不支持 VirtualMachineSnapshot?替代备份方案是什么? 13. 智能克隆何时退化为网络复制? 14. 升级组件时 workloadUpdateStrategy 的作用是什么?

附录 C:参考资料

本仓库配套文档(上一级目录):

文档内容
kubevirt-practical-operations-guide.md部署实施 + 10 大运维专题(本教材的实战配套)
../rke2-kubevirt-deployment-guide.mdRKE2 集群完整部署与故障修复记录
../cdi-offline-deployment-guide.mdCDI 离线部署
../kubevirt-nas-storage-guide.mdNAS 存储方案
../kubevirt-storage-ha-guide.md存储高可用
../kubevirt-network-ssh-password-guide.md固定 IP 与 SSH 密码管理

学习路径建议:先通读本教材(1~6 章上手),再跟随实战文档在真实集群完成 一次"部署 → 建盘 → 起 VM → 固定 IP → 备份 → 克隆 → 灾备演练"全流程。