03-Harvester 虚拟机管理
前两篇已经完成了 Harvester 的定位、核心架构和安装部署。到了第三篇,重点从“平台能不能跑起来”转向“虚拟机能不能被稳定、可重复、可排障地交付”。对于习惯 VMware、Proxmox 或传统 KVM 的运维人员来说,Harvester 的虚拟机管理界面并不难上手,但真正需要理解。

1. 概述
前两篇已经完成了 Harvester 的定位、核心架构和安装部署。到了第三篇,重点从“平台能不能跑起来”转向“虚拟机能不能被稳定、可重复、可排障地交付”。对于习惯 VMware、Proxmox 或传统 KVM 的运维人员来说,Harvester 的虚拟机管理界面并不难上手,但真正需要理解的是:Harvester 不是把一个传统虚拟化平台简单换了 UI,而是把虚拟机声明成 Kubernetes 资源,再由 KubeVirt、Longhorn、Multus、调度器和 Harvester 控制器共同完成生命周期管理。
本文按一个典型运维场景展开:在已经安装好的 Harvester 集群上创建 Linux 虚拟机,完成镜像、磁盘、网络、cloud-init、访问、扩容、迁移、快照备份和排障闭环。读完之后,你应该能够回答三个问题:
- 一台 Harvester 虚拟机从创建到运行,背后经过哪些资源和控制器。
- 虚拟机的 CPU、内存、磁盘、网络、启动策略和调度规则如何影响后续运维。
- 当虚拟机无法启动、无法访问、无法迁移或快照失败时,应该按什么顺序收集证据。
本文中的功能说明以 Harvester 官方 v1.7/v1.8 文档核对,生产版本选择仍应以 SUSE Support Matrix 标记的 Stable 版本为准。验证环境建议至少包含 3 个 Harvester 节点、可用的 Longhorn 默认 StorageClass、一个可访问的 VLAN 或管理网络,以及一份已导入的 Linux cloud image。
2. 虚拟机不是孤立对象
在 Harvester UI 中,虚拟机看起来像一个单独的对象:有名称、CPU、内存、磁盘、网卡和电源状态。但从 Kubernetes 视角看,它至少牵涉以下几类资源:
| 层级 | 关键对象 | 作用 |
|---|---|---|
| 用户入口 | Harvester VM、VM Image、SSH Key、CloudInit | 给运维人员提供表单化管理入口 |
| KubeVirt | VirtualMachine、VirtualMachineInstance、virt-launcher Pod |
把虚拟机声明、运行实例和 QEMU/KVM 进程串起来 |
| Kubernetes | Namespace、Pod、Secret、PVC、Affinity、Node Selector | 提供调度、配置、访问控制和资源隔离 |
| Longhorn | Volume、Replica、Snapshot、Backup | 为虚拟机磁盘提供分布式块存储 |
| 网络插件 | mgmt network、VLAN network、NetworkAttachmentDefinition | 决定虚拟机从哪个网络收发流量 |
| 运维能力 | Migration、Snapshot、Backup、Console、Guest Agent | 支撑迁移、保护、访问和状态采集 |
下面的依赖图把一台虚拟机的主要对象放在一起。它不是为了记住所有 CRD 名称,而是提醒你:修改虚拟机配置时,不要只盯着 UI 表单,要同时考虑调度、存储、网络和来宾系统状态。
图中将虚拟机依赖关系整理成可复盘结构,下面的内容会沿着这些边界继续展开。
创建虚拟机时,Harvester 会把 UI 中的选择落到 KubeVirt 和 Kubernetes 资源上。虚拟机真正启动后,VirtualMachineInstance 会对应一个 virt-launcher Pod,Pod 内部承载 QEMU/KVM 进程,磁盘通过 PVC 连接到 Longhorn Volume,网络则由默认管理网络或额外 VLAN 网络提供。
3. 创建前的准备清单
不要急着点“Create VM”。在 Harvester 中,很多后续问题都来自创建阶段没有把镜像、网络、磁盘和启动策略想清楚。建议每次创建新业务虚拟机前先完成下面的准备。
3.1 明确命名和命名空间
Harvester 支持把虚拟机放在不同 namespace 中。官方文档中特别提醒,只有 harvester-public namespace 对所有用户可见。实际生产中建议不要把所有虚拟机都丢进 default:
| namespace 规划 | 适用方式 |
|---|---|
prod-* |
生产业务,如 prod-erp、prod-monitoring |
test-* |
测试、验证、升级演练 |
infra-* |
DNS、NTP、跳板机、监控采集器等基础服务 |
harvester-public |
需要被多用户共享查看的通用资源 |
命名建议使用 业务-角色-序号,例如 erp-db-01、mon-zbx-proxy-01、k8s-rke2-master-01。这样排障时从 VM 名称就能判断所属系统和角色,也方便用标签、监控和备份策略做分组。
3.2 准备镜像
Harvester 创建虚拟机通常依赖 VM Image。Linux 场景优先选择 cloud image,例如 Ubuntu Cloud Image、Rocky Linux GenericCloud、openSUSE Cloud Image。这类镜像已经适配 cloud-init,适合通过 SSH Key、用户数据和网络数据完成首次启动配置。
镜像准备时重点检查四件事:
- 镜像格式是否为 Harvester 支持的格式,常见为
qcow2或raw。 - 镜像虚拟大小是否小于或等于创建虚拟机时配置的根磁盘大小。
- 镜像内是否安装并启用了
qemu-guest-agent。 - 镜像内的 cloud-init datasource 是否能识别 NoCloud 配置。
官方文档明确提醒:使用 VM image 创建 volume 时,volume 大小必须大于或等于镜像大小,尤其是 qcow2 镜像,因为 qcow2 的虚拟大小通常大于物理文件大小。如果配置的 volume 小于底层镜像虚拟大小,可能导致卷损坏。
3.3 准备 SSH Key 和 cloud-init
对于 Linux 虚拟机,建议把密码登录视为例外,而不是默认。标准做法是:
- 在 Harvester 中提前维护 SSH Key。
- 使用 cloud-init 创建默认运维用户。
- 禁止 root 密码登录。
- 首次启动后通过配置管理工具继续收敛系统状态。
示例 cloud-init 可以从最小配置开始:
#cloud-config
hostname: demo-linux-01
manage_etc_hosts: true
users:
- name: ops
groups: sudo
shell: /bin/bash
sudo: "ALL=(ALL) NOPASSWD:ALL"
ssh_authorized_keys:
- ssh-ed25519 AAAA_REPLACE_WITH_REAL_KEY ops@example
ssh_pwauth: false
package_update: true
packages:
- qemu-guest-agent
runcmd:
- systemctl enable --now qemu-guest-agent || true
这个配置的目标很简单:让虚拟机首次启动后有可登录用户、有主机名、有 guest agent,并尽量避免弱密码入口。不同发行版的包名和服务名可能略有差异,生产模板应在同版本镜像上验证。
3.4 规划网络入口
Harvester 默认会给虚拟机添加 management network。官方文档说明,如果已经配置 VLAN 网络,可以移除默认 management network。更重要的是,官方也提醒了一个常见陷阱:当虚拟机同时连接 mgmt 网络和 VLAN 网络时,来宾系统中的默认路由可能被 VLAN 网关覆盖,导致节点无法通过虚拟机的 mgmt IP 访问它。
因此建议按用途选择网络模型:
| 网络模型 | 适用场景 | 注意事项 |
|---|---|---|
| 仅 mgmt | 实验、基础测试、临时工具机 | 简单,但不适合承载正式业务流量 |
| 仅 VLAN | 生产业务虚拟机 | 需要先建好 cluster network、network config 和 VM network |
| mgmt + VLAN | 需要平台侧管理 IP 和业务 IP 分离 | 必须明确默认路由、DNS 和回包路径 |
| 多 VLAN | 多网卡业务、网络设备、代理节点 | 注意节点覆盖范围和迁移目标可用性 |
3.5 确认资源与调度边界
Harvester 文档建议,分配给单台虚拟机的 vCPU 数量不要超过宿主机物理处理器线程数。这个建议很朴素,但很容易被忽略。资源规划时至少要确认:
- CPU 和内存是否有足够余量。
- 是否启用了资源 overcommit,是否符合业务 SLA。
- 根磁盘和数据盘的 StorageClass 是否正确。
- 是否设置了 strict affinity 或 node selector。
- 是否计划后续 live migration。
如果虚拟机未来需要在节点维护、升级或故障处置时迁移,不要把它强绑定到单个节点,也不要随意启用只有少数节点满足的 CPU pinning、网络或标签约束。
4. 从 UI 创建一台 Linux 虚拟机
Harvester 官方文档把创建入口分为 UI、API 和 Terraform。日常运维中 UI 最直观,适合首次建立模板和验证参数;批量交付则应转向 API、Terraform 或 GitOps。
4.1 基础信息
进入 Virtual Machines 页面,选择创建单台或多台 VM。基础信息建议这样填写:
| 字段 | 建议 |
|---|---|
| Namespace | 使用业务或环境命名空间 |
| Name | 使用 业务-角色-序号 |
| Template | Linux cloud image 可选择 raw-image 或对应模板 |
| CPU | 从 2 vCPU 起步,按业务压测调整 |
| Memory | 从 2 GiB 或 4 GiB 起步,不要把全部节点内存分完 |
| SSHKey | 选择已验证的公钥 |
| Run Strategy | 默认 RerunOnFailure,关键服务可按策略调整 |
Run Strategy 是 Harvester 虚拟机管理中很重要但容易被跳过的字段。官方文档说明,旧版本曾使用布尔型 running 字段,但它无法表达“用户在来宾系统内正常关机后不要自动拉起”这类需求,因此引入 RunStrategy。常见值可以这样理解:
| RunStrategy | 行为 | 适用场景 |
|---|---|---|
Always |
实例应始终存在,异常退出会重新创建 | 强要求常驻的基础服务 |
RerunOnFailure |
失败后重建,来宾系统正常关机后不重建 | 默认选择,适合大多数业务 VM |
Manual |
只通过显式 start/stop/restart 控制 | 测试机、模板机、临时机 |
Stop |
不应存在运行实例 | 保留配置但停止运行 |
如果你来自 VMware,容易把 Run Strategy 理解成“开机状态”。更准确地说,它表达的是控制器应该如何维持虚拟机实例的期望状态。
4.2 磁盘配置
在 Volumes 页签中选择镜像并配置根磁盘。官方文档说明,第一个磁盘默认作为 root disk,启动顺序可以通过拖拽或箭头调整。磁盘类型常见有两类:
| 类型 | 说明 | 建议 |
|---|---|---|
disk |
普通可读写磁盘 | 根盘和数据盘默认选择 |
cd-rom |
只读光驱 | ISO 安装、驱动盘、Windows virtio 驱动 |
如果使用外部存储,文档要求正确选择 StorageClass 和 Volume Mode。例如 nfs-csi StorageClass 需要 Filesystem volume mode。对于普通 Harvester + Longhorn 环境,默认 StorageClass 通常已经足够,但生产环境仍建议把不同业务级别拆成不同 StorageClass,例如:
| StorageClass | 用途 |
|---|---|
longhorn |
默认通用块存储 |
longhorn-repl-2 |
测试环境或容量敏感场景 |
longhorn-repl-3 |
生产默认 |
longhorn-fast |
NVMe 节点池、数据库或高 I/O 场景 |
如果后续会做快照、备份或跨节点迁移,根盘和关键数据盘应使用具备多副本能力的持久卷,不要用只适合临时分发的 container disk 承载核心数据。官方文档对 container disk 的定位也很清楚:它适合批量复制大量 VM 工作负载或注入不要求持久化的驱动与只读输入,不适合要求 root disk 跨重启持久保存的工作负载。
4.3 网络配置
在 Networks 页签中,至少需要决定是否保留 management network,以及是否添加 VLAN network。Harvester 支持通过不同 interface type 暴露给来宾系统,常见是 masquerade 和 bridge。在实际使用中,建议采用下面的决策方式:
图中把网络配置拆成虚拟机接口、网络对象和节点数据面的关系,下面的内容会沿着这些边界继续展开。 这张决策图的重点是先决定业务流量从哪里走,再决定是否保留 mgmt。不要为了“多一条路更安全”随意加双网卡,双网卡最常见的问题就是默认路由、DNS、源地址选择和回包路径不一致。
如果业务 VLAN 使用 DHCP,虚拟机内的网卡应设置为 DHCP。如果使用静态地址,建议通过 cloud-init network data 写入,不要依赖人工登录后再改。示例:
version: 2
ethernets:
enp1s0:
dhcp4: false
addresses:
- 10.20.30.51/24
gateway4: 10.20.30.1
nameservers:
addresses:
- 10.20.30.10
- 10.20.30.11
不同 Linux 发行版的网卡命名可能不同,模板化前应先在同一镜像上启动一台测试机确认接口名。对于 Ubuntu,需要特别注意 machine-id 与 DHCP client identifier 的关系。Harvester 备份恢复文档提醒,如果没有设置 dhcp-identifier: mac,恢复后的 Ubuntu VM 可能因为 netplan 默认使用 machine ID 作为 DHCP client identifier 而拿到与原 VM 相同的 IP,导致网络冲突。
4.4 高级选项
高级选项包括 OS Type、cloud-init、调度规则、资源预留、CPU 模型、CPU pinning、注解等。不要一次性打开所有高级能力,建议按业务需求逐项启用。
| 高级能力 | 何时启用 | 风险 |
|---|---|---|
| cloud-init | Linux 初始化、SSH Key、网络、软件包 | YAML 错误会导致首次启动配置失败 |
| Node Scheduling | 合规、硬件依赖、网络覆盖限制 | 可能导致不可调度或不可迁移 |
| VM Scheduling | 同业务亲和、反亲和、高可用分布 | strict 规则会影响升级 pre-drain |
| CPU Pinning | NFV、数据库、低延迟负载 | 依赖节点 CPU Manager,影响迁移范围 |
| Reserved Memory | OOM、内存开销明显的 VM | 设置过高降低集群资源利用率 |
| Custom IP annotation | guest agent 缺失时手工显示 IP | 只是 UI 展示,不代表网络真实可达 |
官方文档说明,Harvester 会根据网络、CPU pinning 等定义自动给 VM 添加调度约束。例如连接某个 cluster network 的 VM 只会调度到覆盖该 network configuration 的节点;启用 CPU pinning 的 VM 只会调度到启用 CPU Manager 的节点。自动规则由 Harvester webhook 维护,手工改动可能被回滚。
5. 用 YAML 理解虚拟机定义
即使日常主要使用 UI,也建议至少能读懂 VirtualMachine YAML。下面是一个经过简化的 Linux 虚拟机定义,用于理解 Harvester 与 KubeVirt 的边界。
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: demo-linux-01
namespace: prod-demo
labels:
app: demo
role: web
spec:
runStrategy: RerunOnFailure
template:
metadata:
labels:
kubevirt.io/domain: demo-linux-01
spec:
domain:
cpu:
cores: 2
sockets: 1
threads: 1
memory:
guest: 4Gi
devices:
disks:
- name: rootdisk
disk:
bus: virtio
- name: cloudinitdisk
disk:
bus: virtio
interfaces:
- name: default
masquerade: {}
model: virtio
machine:
type: q35
networks:
- name: default
pod: {}
volumes:
- name: rootdisk
persistentVolumeClaim:
claimName: demo-linux-01-rootdisk
- name: cloudinitdisk
cloudInitNoCloud:
userDataSecretRef:
name: demo-linux-01-cloudinit
这段 YAML 里有几个排障时很有用的观察点:
spec.runStrategy决定控制器如何维持运行状态。domain.cpu和domain.memory决定来宾系统可见资源。devices.disks与volumes通过名称关联。interfaces与networks通过名称关联。- cloud-init 可以通过 Secret 注入,避免把敏感内容直接写进公开 YAML。
你可以用下面的命令观察 Harvester UI 创建后的实际资源。命令中的 namespace 和 VM 名称需要替换成自己的值:
NS=prod-demo
VM=demo-linux-01
kubectl get vm -n "$NS" "$VM" -o wide
kubectl get vmi -n "$NS" "$VM" -o wide
kubectl get pod -n "$NS" -l vm.kubevirt.io/name="$VM" -o wide
kubectl get pvc -n "$NS" | grep "$VM"
kubectl describe vm -n "$NS" "$VM"
当 UI 展示的信息不够时,describe vm 和 describe vmi 往往能看到调度失败、磁盘挂载失败、网络附加失败、迁移失败等事件。
6. 首次启动后的验证
创建完成不等于交付完成。建议每台新虚拟机至少经过“平台侧、网络侧、来宾侧、保护侧”四类验证。
图中把首次启动后的验证点整理为启动、网络、存储和来宾系统几条证据线。 这张时序图适合用来定位问题在哪一段:如果 PVC 没有创建或绑定,问题在存储;如果 VMI 没有调度,问题在调度或资源;如果 VM 已运行但没有 IP,问题在 guest agent、DHCP、cloud-init 或网络路由。
6.1 平台侧验证
NS=prod-demo
VM=demo-linux-01
kubectl get vm -n "$NS" "$VM"
kubectl get vmi -n "$NS" "$VM"
kubectl get pod -n "$NS" -l vm.kubevirt.io/name="$VM"
kubectl get events -n "$NS" --sort-by=.lastTimestamp | tail -n 30
正常情况下,你应该看到 VM 处于 Running 或期望的状态,VMI 已创建,virt-launcher Pod 处于 Running。事件中不应反复出现 FailedScheduling、FailedMount、FailedCreatePodSandBox、ErrImagePull 等错误。
6.2 存储侧验证
kubectl get pvc -n "$NS" | grep "$VM"
kubectl -n longhorn-system get volumes.longhorn.io | grep "$VM"
如果 PVC 一直 Pending,优先检查 StorageClass、节点可用磁盘、Longhorn 节点状态和副本调度。如果 Longhorn Volume degraded,需要先恢复副本健康,再考虑业务层操作。
6.3 网络侧验证
在 Harvester UI 中确认 VM IP 后,从管理网络或业务网络测试:
ping -c 4 10.20.30.51
ssh ops@10.20.30.51
如果 UI 没有显示 IP,不一定代表虚拟机没有 IP。官方文档说明,可以通过 harvesterhci.io/custom-ip annotation 在 UI 中手工显示 IP,这对缺少 qemu-guest-agent 的虚拟机有帮助。但这只是展示能力,不是连通性验证。真正的验证仍应进入虚拟机控制台或从网络侧测试。
6.4 来宾系统验证
登录虚拟机后建议执行:
hostnamectl
ip addr
ip route
cloud-init status --long || true
systemctl status qemu-guest-agent --no-pager || true
df -h
lsblk
重点看主机名、路由、DNS、磁盘大小、guest agent 状态和 cloud-init 是否成功完成。cloud-init 失败并不总是阻止虚拟机启动,但会影响用户、SSH Key、网络和软件包安装,后续排障成本很高。
7. 生命周期操作
Harvester 的虚拟机生命周期操作包括启动、停止、重启、编辑、克隆、快照、备份、迁移和删除。不同操作对底层资源的影响不同,不能只按按钮名称理解。
7.1 启动、停止和重启
如果 Run Strategy 是 Manual,启动和停止基本由操作员控制。如果是 Always 或 RerunOnFailure,控制器会根据策略维持期望状态。建议:
- 计划停机前,在来宾系统内正常关机,确保文件系统和数据库优雅退出。
- 如果只是平台侧维护,不要随意把 Run Strategy 改成
Stop后忘记恢复。 - 如果 VM 反复自动拉起,先检查 Run Strategy,再检查来宾系统关机原因。
7.2 编辑 CPU 和内存
CPU 和内存调整看似简单,但需要区分“配置已修改”和“来宾系统已生效”。某些能力支持热插拔,某些修改需要重启虚拟机。操作建议:
- 先确认业务是否支持资源在线变化。
- 记录修改前的 CPU、内存、节点和业务负载。
- 低峰期修改配置。
- 在来宾系统内确认
lscpu、free -h、业务进程和监控指标。
不要用资源扩容掩盖应用内存泄漏、数据库慢查询或磁盘 I/O 饱和。虚拟机层面的 CPU Ready、节点压力、Longhorn 延迟和来宾系统负载应该结合判断。
7.3 热插拔磁盘
Harvester 官方文档在 v1.7 中列出 Hot-Plug Volumes。热插拔数据盘适合业务扩容、迁移数据或临时挂载工具盘。操作前要确认:
- 来宾系统内核和发行版能识别热插拔块设备。
- 文件系统扩容步骤已验证。
- 备份或快照已完成。
- 新卷 StorageClass、副本数和容量符合业务需求。
Linux 内常见验证命令:
lsblk
dmesg | tail -n 50
sudo file -s /dev/vdb
sudo mkfs.xfs /dev/vdb
sudo mkdir -p /data
sudo mount /dev/vdb /data
df -h /data
生产环境不建议直接用裸设备名写 /etc/fstab,因为设备名可能变化。应优先使用 UUID:
sudo blkid /dev/vdb
echo 'UUID=<uuid> /data xfs defaults,nofail 0 2' | sudo tee -a /etc/fstab
sudo mount -a
7.4 克隆虚拟机
克隆适合快速复制测试环境、创建同版本节点或生成一次性验证机。克隆前必须处理身份唯一性:
| 项目 | 为什么要处理 |
|---|---|
| hostname | 避免监控、日志和配置管理混淆 |
| machine-id | 避免 DHCP、systemd、日志身份冲突 |
| SSH host key | 避免 SSH 安全警告和身份复用 |
| 应用实例 ID | 避免业务集群误认为同一节点 |
| IP 地址 | 避免网络冲突 |
Linux 模板机在关闭前可执行类似清理动作,具体命令需按发行版验证:
sudo cloud-init clean --logs
sudo truncate -s 0 /etc/machine-id
sudo rm -f /var/lib/dbus/machine-id
sudo rm -f /etc/ssh/ssh_host_*
sudo shutdown -h now
不要在没有清理身份的情况下把生产数据库、域控、许可证服务器或集群控制节点直接克隆出来并接入同一网络。
8. Live Migration 与节点维护
Harvester 的 live migration 依赖 KubeVirt。手工迁移可以在 VM 菜单中选择 Migrate,自动批量迁移则常见于 Harvester 升级和节点维护场景。官方文档说明,迁移触发后会创建 VirtualMachineInstanceMigration 对象,并通过 VMI 的迁移状态关联。手工触发的迁移对象名称通常以前缀 VM 名称开头,自动批量迁移对象通常带有 kubevirt-evacuation- 前缀。
图中把 Live Migration 与节点维护的前置条件和验证路径串联起来,后续步骤按这些边界展开。 迁移失败常见原因包括:
- 集群只有一个节点。
- VM 被判定为 non-migratable。
- 已有迁移正在运行或等待。
- 节点调度规则、网络覆盖、CPU pinning 或 CPU model 限制导致目标节点不满足条件。
- 写入速率过高,内存页或磁盘块复制无法在合理时间内完成。
官方文档对 CPU model matching 有明确说明:如果 VM 没有指定 CPU model,默认使用 host-model,迁移时会要求目标节点支持相同迁移 CPU model 标签。若集群节点 CPU 型号差异较大,就可能出现某些 VM 只能在部分节点之间迁移的情况。
迁移前建议执行:
NS=prod-demo
VM=demo-linux-01
kubectl get vm -n "$NS" "$VM" -o yaml | grep -A30 -E 'nodeSelector|affinity|cpu:|networks:'
kubectl get nodes --show-labels | grep -E 'cpu-model|network.harvesterhci.io|cpumanager'
kubectl get vmi -n "$NS" "$VM" -o wide
如果迁移失败,检查迁移对象:
kubectl get vmim -A
kubectl describe vmim -n "$NS" <migration-name>
kubectl get vmi -n "$NS" "$VM" -o jsonpath='{.status.migrationState}'
对生产 VM 的建议是:在设计阶段就把可迁移性当作要求,而不是等节点维护时再修。尤其要谨慎使用单节点网络覆盖、严格反亲和、CPU pinning、特定主机标签和本地化存储。
9. 快照、备份与恢复
虚拟机管理不能只关注创建和运行。Harvester 通过 Longhorn 提供 VM snapshot、VM backup 和 restore 能力。快照更适合短期回滚点,备份更适合跨故障域保护。两者都不是数据库一致性和业务连续性的全部答案。
9.1 快照与备份的边界
| 能力 | 主要用途 | 适合保留多久 | 注意事项 |
|---|---|---|---|
| VM Snapshot | 升级前、配置变更前、短期回滚 | 短期 | 占用集群本地存储,不应长期堆积 |
| VM Backup | 故障恢复、跨集群恢复、长期保护 | 按备份策略 | 需要稳定的 NFS 或 S3 目标 |
| 应用备份 | 数据库、业务数据一致性 | 按业务 RPO/RTO | 应用层仍需自有备份机制 |
官方文档说明,当 guest VM 连接了 QEMU Guest Agent 时,Harvester controller 会通过 KubeVirt 的 virt-freezer 对文件系统执行 freeze 操作,以提高备份和快照的一致性。这对高 I/O 或关键数据 VM 很重要,但它依赖来宾系统配置:部分 Linux 发行版可能受 SELinux 权限影响,Windows 则依赖 VSS 服务。
9.2 创建快照前检查
NS=prod-demo
VM=demo-linux-01
kubectl get vmi -n "$NS" "$VM" -o wide
kubectl get pod -n "$NS" -l vm.kubevirt.io/name="$VM"
kubectl -n longhorn-system get volumes.longhorn.io | grep "$VM"
来宾系统内检查:
systemctl status qemu-guest-agent --no-pager || true
cloud-init status --long || true
df -h
对于数据库 VM,建议在应用层也做一致性处理,例如数据库自身备份、停止写入、进入维护窗口或通过数据库原生工具创建恢复点。不要把虚拟机快照当成数据库备份的唯一手段。
9.3 恢复新虚拟机的网络风险
官方备份恢复文档特别提到 Ubuntu 的 DHCP 风险:恢复后的虚拟机会保留原 VM 的 machine ID,如果没有设置 dhcp-identifier: mac,netplan 默认可能使用 machine ID 作为 DHCP client identifier,从而拿到与原 VM 相同的 IP。这个问题在“从备份恢复一台新 VM 做验证”时尤其危险,因为原 VM 可能还在线。
建议在 Ubuntu cloud-init network data 中加入:
version: 2
ethernets:
enp1s0:
dhcp4: true
dhcp-identifier: mac
如果是静态地址,恢复新 VM 时必须先断开业务网络,修改 IP、hostname、machine-id 和应用身份后再接入正式网络。
9.4 Longhorn V2 卷注意事项
Harvester v1.7 文档中提到,从 v1.7.0 开始,Harvester 支持 Longhorn V2 volumes 的备份和快照;但同一文档也警告,删除最新备份或最新快照、或者启用 Longhorn 的 Auto Cleanup Snapshot When Delete Backup 设置,可能阻塞相关 volume 后续操作,包括 volume snapshot、backup 和 live migration。官方说明当前没有可行 workaround,恢复 Longhorn Manager 功能可能需要删除受影响 volume。
这类限制对生产运维的含义很直接:
- 不要在不了解影响的情况下清理“最新”的备份或快照。
- 不要把备份清理策略和 Longhorn 设置交给多人随意修改。
- 对使用 Longhorn V2 volumes 的 VM,先在测试环境演练快照、备份、删除和恢复。
- 重要业务 VM 的保护策略应写成 runbook,而不是只靠 UI 操作习惯。
10. 常见故障排查
虚拟机故障排查要先定位层级,再处理具体原因。下面这张决策树适合放在值班手册中。
图中把常见故障按调度、镜像、网络、存储和来宾系统分层,排查时先定位层级再处理。
10.1 虚拟机创建后一直 Pending
排查顺序:
NS=prod-demo
VM=demo-linux-01
kubectl describe vm -n "$NS" "$VM"
kubectl describe vmi -n "$NS" "$VM" || true
kubectl get pod -n "$NS" -l vm.kubevirt.io/name="$VM"
kubectl get events -n "$NS" --sort-by=.lastTimestamp | tail -n 50
kubectl describe nodes | grep -A8 "Allocated resources"
常见原因:
| 现象 | 可能原因 | 处理 |
|---|---|---|
FailedScheduling |
CPU/内存不足 | 降低 VM 规格或扩容节点 |
| node selector 不满足 | 绑定了不存在的标签 | 修正调度规则 |
| 网络相关事件 | VLAN network 未覆盖目标节点 | 检查 cluster network 和 network config |
| PVC Pending | StorageClass 或 Longhorn 不健康 | 检查 Longhorn 节点和磁盘 |
10.2 虚拟机 Running 但没有 IP
先判断“没有 IP”是 UI 没显示,还是来宾系统真的没有拿到地址。
kubectl get vmi -n "$NS" "$VM" -o yaml | grep -A20 interfaces
kubectl get pod -n "$NS" -l vm.kubevirt.io/name="$VM" -o wide
进入控制台后检查:
ip addr
ip route
resolvectl status || cat /etc/resolv.conf
cloud-init status --long || true
journalctl -u systemd-networkd -u NetworkManager --no-pager -n 100
systemctl status qemu-guest-agent --no-pager || true
常见原因包括:cloud-init network data 接口名错误、DHCP 不可达、VLAN ID 配错、默认路由被第二张网卡覆盖、guest agent 未安装或未启动。解决时不要只在来宾系统手工改一次,而要回到模板、cloud-init 和 Harvester 网络定义中修正。
10.3 虚拟机无法迁移
检查:
kubectl get vmim -A
kubectl describe vmi -n "$NS" "$VM"
kubectl get nodes --show-labels | grep -E 'cpu-model|network.harvesterhci.io|cpumanager'
kubectl get vm -n "$NS" "$VM" -o yaml | grep -A60 -E 'affinity|nodeSelector|networks|cpu'
处理原则:
- 如果只有一个节点满足网络覆盖或 CPU 条件,迁移失败是预期结果。
- 如果 strict anti-affinity 导致无目标节点,先评估是否可改成 preferred。
- 如果 CPU model 不匹配,统一节点硬件或按官方文档规划 cluster-level / individual VM CPU model。
- 如果迁移超时,观察业务写入速率、磁盘 I/O 和迁移完成超时设置。
10.4 快照或备份失败
检查:
kubectl get volumesnapshot -A | grep "$VM" || true
kubectl -n longhorn-system get volumes.longhorn.io | grep "$VM"
kubectl -n harvester-system logs -l app=harvester --tail=200
来宾系统内检查 guest agent 与文件系统:
systemctl status qemu-guest-agent --no-pager || true
df -h
mount
journalctl -u qemu-guest-agent --no-pager -n 100 || true
如果错误指向 filesystem freeze,按官方文档思路确认来宾系统是否支持 freeze/thaw,SELinux 或 Windows VSS 是否阻止操作。必要时在业务维护窗口内执行应用一致性备份,而不是强行依赖在线快照。
11. 批量交付与自动化建议
当 VM 创建流程稳定后,不建议长期依赖人工 UI 表单。Harvester 官方文档提供 API 和 Terraform 示例,生产交付可以按成熟度逐步演进。
在进入自动化之前,还要把 VM 扩容和迁移验收固化下来。虚拟机 CPU、内存、磁盘和网卡变更看起来只是几个字段,但它们分别影响调度、来宾系统、存储副本和网络策略。没有验收清单的自动化会把错误快速复制到更多 VM 上。
CPU 和内存扩容后,应确认 VM 是否需要关机、来宾系统是否识别新资源、监控阈值是否更新、应用授权是否按 CPU 或内存计费。磁盘扩容后,应确认 PVC 容量、Longhorn Volume 容量、来宾块设备、分区和文件系统都完成扩展。网卡变更后,应确认 NetworkAttachmentDefinition、VLAN、DHCP、默认路由和防火墙策略都符合预期。
Live Migration 的验收也不能只看任务成功。迁移前要确认目标节点有对应网络覆盖、存储副本健康、CPU model 兼容、目标节点资源足够;迁移中观察 VMI migration 对象和事件;迁移后验证业务端口、默认路由、磁盘 I/O、监控指标和备份任务。若迁移成功但业务丢包严重,说明前置条件或观察指标不完整。
这些验收项应作为 Terraform 模块、GitOps 流程或工单模板的输出,而不是写在个人笔记里。自动化越成熟,越要把“何时允许修改、修改后如何验证、失败后如何回滚”写成显式规则。
11.1 从 UI 到模板
第一阶段适合建立标准模板:
- 导入官方 cloud image。
- 创建一台最小 VM。
- 验证 cloud-init、SSH、guest agent、网络和快照。
- 清理 machine-id、SSH host key 和 cloud-init 状态。
- 关闭 VM,作为模板来源。
模板不是“装好软件的黄金镜像”这么简单。更好的模板应尽量保持基础、可升级、可审计,把业务差异留给 cloud-init、配置管理和部署流水线。
11.2 用 Terraform 描述虚拟机
当同类 VM 数量增加时,可以用 Terraform 管理。官方文档示例中,harvester_virtualmachine resource 可以描述 CPU、内存、run strategy、SSH key、网络接口、磁盘和 cloud-init Secret。团队使用 Terraform 时建议:
| 内容 | 建议 |
|---|---|
| VM 规格 | 变量化,但限制可选档位 |
| cloud-init | 模板化,敏感内容放 Secret 管理 |
| 网络 | 不允许随意填 VLAN,使用模块封装 |
| 磁盘 | 区分根盘、数据盘、临时盘 |
| 标签 | 强制写入业务、环境、负责人 |
| 输出 | 输出 VM 名称、namespace、IP、SSH 入口 |
不要让每个项目组都复制一份 Terraform 资源块自行修改。更稳妥的方式是把“公司标准 VM”封装为模块,只开放必要参数。
11.3 用 GitOps 管理声明式资源
如果团队已经使用 Rancher、Fleet 或 Argo CD,可以把虚拟机相关资源纳入 GitOps。但要注意虚拟机不是无状态容器,GitOps 对 VM 的控制边界要谨慎:
- 适合声明 namespace、网络、镜像引用、标准 VM 模板和非敏感配置。
- 适合审计 Run Strategy、调度规则、标签和注解。
- 不适合频繁把运行中 VM 的临时状态强行收敛。
- 不适合把一次性迁移、恢复、故障处置操作直接写成长期期望状态。
虚拟机自动化的关键不是“所有东西都 YAML 化”,而是把可重复交付、可审计变更和可恢复状态区分清楚。
12. 生产管理基线
下面是一份可以直接放进 Harvester 运维规范的 VM 管理基线。
12.1 创建基线
- 每台 VM 必须有明确 namespace、业务标签、负责人和用途。
- Linux VM 默认使用 cloud-init 注入 SSH Key,不开放弱密码登录。
- 根盘大小必须不小于镜像虚拟大小,并预留业务增长空间。
- 生产 VM 默认使用多副本持久卷,不使用 container disk 承载持久数据。
- VM 网络必须明确默认路由,不允许无说明的 mgmt + VLAN 双网卡配置。
- 需要迁移能力的 VM 不绑定单节点,不使用只有单节点满足的网络或 CPU 规则。
创建基线还应覆盖镜像来源。镜像必须有来源、版本、校验方式、维护人和废弃日期。公共镜像只提供最小系统和标准 agent,不应把业务配置、临时账号、测试证书或个人 SSH Key 固化进去。模板越“万能”,越容易把历史包袱复制到所有新 VM。
命名也要在创建阶段解决。namespace 表达团队或业务域,VM 名称表达环境、业务和序号,标签表达负责人、重要性、备份等级和成本归属。不要把这些信息写在描述字段里。Harvester 背后是 Kubernetes,对象标签和命名会直接影响查询、审计、GitOps 和自动化筛选。
12.2 变更基线
- CPU、内存、磁盘、网卡、调度规则和 Run Strategy 变更都应记录。
- 变更前确认快照或备份策略,但数据库类业务还要做应用层保护。
- VM 规格扩容后必须在来宾系统和监控系统中验证。
- 删除 VM 前确认备份、快照、DNS、监控、CMDB 和配置管理记录。
变更基线要区分“平台配置变更”和“来宾系统变更”。给 VM 增加一块数据盘只是平台层动作,来宾系统还要识别磁盘、分区、格式化、挂载、写入 /etc/fstab 或更新应用路径。平台层显示 Volume 已 attached,不代表业务已经可用。变更单中应同时包含平台验收和来宾验收。
网卡和网络变更尤其需要回程路径检查。双网卡 VM 很容易出现默认路由漂移、源地址选择错误或安全组策略遗漏。变更后只 ping 网关不够,还要验证业务端口、DNS、NTP、监控探针和备份流量是否走预期网络。对数据库、中间件和域控类 VM,还要确认客户端访问路径没有被非预期网卡接管。
12.3 保护基线
- 所有生产 VM 必须纳入备份策略。
- 快照只作为短期回滚点,不作为长期备份。
- 备份目标必须定期做恢复演练。
- Ubuntu 或依赖 DHCP 的 VM 必须处理 machine-id 与 DHCP identifier 风险。
- guest agent 应作为标准组件安装并启用。
保护基线不能只看是否存在备份任务。还要记录恢复等级:哪些 VM 只需要整机恢复,哪些需要文件级恢复,哪些需要应用一致性,哪些可以从模板重建。不同等级决定是否需要 guest agent、停写脚本、应用备份、外部数据库备份和定期恢复演练。
快照治理也要有上限。平台快照适合短期回滚,如果长期堆积,会增加容量压力和恢复复杂度。应用上线、系统补丁、配置调整前创建快照是合理的,但变更完成后应在规定时间内删除或转成备份。快照保留策略应由业务重要性和恢复窗口决定,而不是由操作人员习惯决定。
12.4 排障基线
图中把生产排障固化为平台对象、网络与存储、来宾与业务三层证据链,强调先取证、再修复、最后归档。
- 平台侧先看 VM、VMI、Pod、PVC、Event。
- 存储侧看 Longhorn Volume、Replica、节点磁盘和 StorageClass。
- 网络侧看 VM network、节点覆盖、来宾路由和 DHCP。
- 来宾侧看 cloud-init、guest agent、系统日志和业务日志。
- 迁移侧看
VirtualMachineInstanceMigration、CPU model、网络覆盖和调度规则。
12.5 运行态巡检
VM 运行后要有固定巡检。每日检查 VMI 状态、重启次数、Volume health、备份任务和关键告警;每周检查未使用快照、长期停止但未退役 VM、没有负责人标签的 VM、无备份策略的生产 VM;每月抽样做恢复演练和迁移演练。巡检不是为了生成报告,而是为了及时发现“能运行但不可恢复”的风险。
运行态巡检还要和容量治理联动。CPU 和内存长期过高可能需要扩容或应用优化,长期过低可能说明资源浪费;磁盘增长快要提前评估 Volume 扩容和备份窗口;网络错误和丢包要回到 VM Network、节点接口和交换机侧排查。Harvester 提供平台对象,监控系统提供指标,两者结合才能判断 VM 是否处于健康状态。
退役巡检同样重要。停止状态超过一定天数、没有监控目标、没有业务访问、备份长期失败的 VM,应进入确认流程。确认退役后,要释放 DNS、IP、监控、备份、CMDB 和配置管理记录,再删除 VM 和卷。直接删除 VM 容易留下孤立资源,长期保留无主 VM 则会消耗存储和安全治理精力。
13. 总结
Harvester 的虚拟机管理表面上是创建、开机、关机和改配置,实际核心是把虚拟机作为 Kubernetes 资源进行声明式管理。这个模型带来的好处是自动化、调度、存储、网络和 API 能力更统一;代价是排障时必须同时理解 KubeVirt、Longhorn、Kubernetes 调度和来宾系统。
本文从创建一台 Linux VM 开始,串起了镜像、磁盘、网络、cloud-init、Run Strategy、YAML 定义、首次验证、生命周期操作、live migration、快照备份、故障排查和自动化交付。实际落地时,建议先建立一套可验证的标准 VM 模板,再逐步把常见规格、网络、cloud-init 和保护策略固化为模块或 GitOps 资源。
下一篇将进入 Harvester 的《存储管理》,重点分析 Longhorn 存储池、磁盘、副本、StorageClass、性能、容量和故障恢复。