Skip to content

01 · 入门篇:Harvester 架构全景与核心概念

目标:读完这一章,你能在白板上画出 Harvester 的分层架构,说清每个组件的职责, 并解释「一台虚拟机在 Harvester 里到底是什么」。 版本基准:Harvester v1.8.2(内置 RKE2 v1.35.7+rke2r1、KubeVirt 1.7.4、Longhorn 1.11.2)。


1. 一句话认识 Harvester

Harvester 是一个开源的超融合基础设施(HCI)平台,它把「虚拟机」变成 Kubernetes 的一等公民: VM 不再是独立虚拟化平台里的对象,而是一个qemu-kvm 进程的 Pod, 和容器共享同一套调度器、同一套存储、同一套网络、同一套 RBAC、同一套 GitOps 流水线。

它由四层能力叠加而成:

容器编排      Kubernetes(RKE2)        —— 调度、声明式 API、自愈、RBAC
   +
虚拟化        KubeVirt + CDI            —— 把 VM 跑成 Pod,把镜像灌成 PVC
   +
分布式存储    Longhorn                  —— 块存储多副本、快照、备份、RWX
   +
产品化        Harvester 控制面 + UI      —— Dashboard、Webhook、20+ 控制器、Steve 聚合 API
   =
超融合        Harvester                 —— 一台机器既是计算节点,也是存储节点,也是管理节点

1.1 为什么现在需要它

驱动力说明
VM 与容器长期共存数据库、有状态中间件、Windows 应用、需要内核模块的业务,短期内不会容器化;但平台团队只想维护一套 K8s
VMware 授权模式变化2023 年后订阅制与捆绑销售推高成本,大量企业评估开源 HCI 替代(Harvester / OpenStack / Proxmox)
边缘与分支机构3 台服务器起步、无专职虚拟化团队、需要「装完就能用」的一体机形态
GitOps 统一交付VM 定义变成 YAML,就能进 Git、走 ArgoCD/Fleet、被 CI 校验,这是传统虚拟化平台做不到的
AI/GPU 场景GPU 直通给 VM 与给 Pod 用同一套设备插件与调度语义

1.2 它不是什么

  • ❌ 不是公有云 IaaS 的等价物:没有多区域、没有弹性公网 IP 市场、没有按秒计费的商业结算体系;
  • ❌ 不是「K8s 的皮肤」:它自带不可变操作系统与装机器(ISO 形态),是一整套交付物;
  • ❌ 不替代 KubeVirt,而是封装并加固 KubeVirt:所有 VM 语义仍是 KubeVirt CRD,Harvester 在其上加校验、默认值、UI 与运维闭环。

2. 七层架构全景(实测拓扑)

┌──────────────────────────────────────────────────────────────────────────┐
│ L7  入口层   Dashboard(UI) / kubectl / Terraform / Rancher Virtualization Mgmt │
│              ISO 形态:VIP + kube-vip(https://<VIP>/)                      │
│              容器化形态:Service NodePort + SNI 主机名校验                    │
├──────────────────────────────────────────────────────────────────────────┤
│ L6  产品层   harvester / harvester-webhook(Deployment,各 3 副本)           │
│              Steve 聚合 API(APIService: harvesterhci.io …)                  │
│              20+ 控制器:vm-image / vlan / lb / node-manager / promote-node …  │
│              vm-import-controller(v2v)×2                                    │
├──────────────────────────────────────────────────────────────────────────┤
│ L5  虚拟化层 virt-operator → virt-api(校验/默认化 webhook)                   │
│              virt-controller(调和 VM→VMI) virt-handler(DaemonSet,每节点)   │
│              virt-launcher Pod(每 VMI 一个,内含 qemu-kvm + libvirtd)        │
│              CDI:cdi-operator / cdi-deployment / cdi-upload / importer Pod    │
├──────────────────────────────────────────────────────────────────────────┤
│ L4  存储层   Longhorn:longhorn-manager(DS) / longhorn-csi / instance-manager  │
│              share-manager(RWX 用,依赖 NFS) / backupstore(NFS/S3)          │
│              CSI 快照:rke2-snapshot-controller 或 csi-snapshotter 子 chart     │
├──────────────────────────────────────────────────────────────────────────┤
│ L3  网络层   CNI(ISO:Canal/Flannel+Calico;容器化:随既有集群,如 Calico VXLAN)│
│              harvester-network-controller(VlanConfig / Network-Attachment-Def)│
│              whereabouts(VLAN 网络 IPAM) harvester-load-balancer + kube-vip    │
├──────────────────────────────────────────────────────────────────────────┤
│ L2  编排层   RKE2(kube-apiserver / etcd / kubelet / containerd)              │
│              CoreDNS(forward . /etc/resolv.conf)                            │
├──────────────────────────────────────────────────────────────────────────┤
│ L1  操作系统 Harvester OS(Elemental 不可变系统,A/B 分区 + oem 挂载)           │
│              或:既有集群节点的任意 Linux(容器化形态)                          │
│              硬件:VT-x/AMD-V(嵌套虚拟化需透传 vmx)、NVMe、virtio/直通网卡     │
└──────────────────────────────────────────────────────────────────────────┘

2.1 组件职责速查

组件归属职责出问题时的典型症状
harvesterHarvester主 API/控制器集合,Steve 聚合层UI 打不开、API 5xx;启动期依赖 VolumeSnapshotClass 会重启
harvester-webhookHarvester校验与默认化(如要求 masquerade 接口、running/runStrategy 互斥)admission webhook "validator.harvesterhci.io" denied
virt-apiKubeVirtVM/VMI 的校验与默认化 webhook,feature gate 只在进程启动时加载snapshot feature gate not enabled
virt-controllerKubeVirt调和 VM → VMI → PodVM 长期 Starting
virt-handlerKubeVirt节点上的 VM 生命周期代理(DaemonSet)无硬件虚拟化支持、VMI 起不来
virt-launcherKubeVirt每个 VMI 一个 Pod,内含 qemu-kvmVM「就是」这个 Pod
CDI importerKubeVirt/CDI下载/转换镜像写入 PVC镜像导入进度回退、卡在 99.62%
longhorn-managerLonghorn卷/副本/引擎的编排degradedVolumeAttachment sync 失败
instance-managerLonghorn每节点的数据面进程(engine/replica)卷无法 attach
share-managerLonghornRWX 卷的 NFS 服务端没有它 RWX 数据面不可用 → 热迁移阻塞
kube-vip网络承载管理 VIP / Service LBVIP 无响应、Dashboard 打不开
whereabouts网络VLAN 网络的 IPAMVM 拿不到二层网段 IP
harvester-promote-node-controllerHarvester自动把 join 节点提升为 control-plane+etcd节点短暂 Ready,SchedulingDisabled(正常)
vm-import-controllerHarvesterv2v(从 VMware 等导入)导入任务不推进

3. 资源模型:一台 VM 到底是什么

3.1 对象层级(自上而下)

VirtualMachine (kubevirt.io/v1)             ← 期望状态(用户写的 YAML)
   ├── dataVolumeTemplates[]                ← 磁盘模板
   │      └── DataVolume (cdi.kubevirt.io/v1beta1)
   │             └── PVC → PV → volumes.longhorn.io   ← ★ 四层状态要分别确认
   │                    └── engine / replica(Longhorn 数据面)
   ├── volumes[].cloudInitNoCloud            ← cloud-init(Secret 或 userData)
   └── template.spec                         ← VMI 模板
          └── VirtualMachineInstance (VMI)   ← 运行实例(每次启动生成,停机即回收)
                 └── virt-launcher-<vm>-xxxxx Pod(内含 qemu-kvm)
                        └── domain(libvirt 定义的虚机)

关键认知kubectl get pod -l kubevirt.io/domain=<vm> 看到的那个 Pod, 就是这台虚拟机。VM 的 CPU/内存申请就是 Pod 的 requests/limits,因此它参与 K8s 调度、被 ResourceQuota 限制、被 PriorityClass 抢占、被节点污点排斥—— 这是「VM 成为 K8s 一等公民」的确切含义。

3.2 核心 CRD 与 API group

API group关键对象用途备注
kubevirt.io/v1VirtualMachine(vm)、VirtualMachineInstance(vmi)、VirtualMachineInstanceMigrationVM 定义/实例/热迁移KubeVirt 原生
snapshot.kubevirt.io/v1beta1VirtualMachineSnapshotVirtualMachineSnapshotContentVirtualMachineRestoreVM 快照与恢复★ Harvester v1.8 无自有快照 CRD,一律用这套
cdi.kubevirt.io/v1beta1DataVolume(dv)镜像导入/克隆/空盘状态含 phase + progress%
harvesterhci.io/v1beta1VirtualMachineImageVirtualMachineBackupVirtualMachineRestoreVolumeRemoteRestoreSettingSupportBundleHarvester 产品化对象镜像库、设置项、支持包
network.harvesterhci.io/v1beta1VlanConfigNetworkAttachmentDefinitionVLAN/二层网络配合 whereabouts IPAM
longhorn.io/v1beta2VolumeNodeEngineReplicaSnapshotBackupTargetSetting分布式块存储数据面真相在这里
snapshot.storage.k8s.io/v1VolumeSnapshotClassVolumeSnapshotVolumeSnapshotContentCSI 快照⚠️ 短名 vsc 有歧义
node.harvesterhci.io/v1beta1NodeConfigProvisionRequest节点级配置/自动装机ISO 形态用

实测枚举方法(确认聚合层与 CRD 都正常):

bash
curl -sk --resolve &lt;SNI_HOST&gt;:&lt;NODEPORT&gt;:&lt;NODE_IP&gt; \
     https://&lt;SNI_HOST&gt;:&lt;NODEPORT&gt;/v1/harvester | tr ',' '\n' | grep -i snapshot
# snapshot.kubevirt.io.virtualmachinesnapshots / …snapshotcontents / …restores
# harvesterhci.io.virtualmachinerestores / volumeremoterestores
# groupsnapshot.storage.k8s.io.volumegroupsnapshot{classes,contents,snapshots}

3.3 kubectl 短名陷阱(实测踩过)

bash
# ✗ 短名 vsc 在本集群被解析为 volumesnapshotcontents(与 classes 短名冲突)
kubectl get vsc -A
# ✓ 排查快照类务必用全名
kubectl get volumesnapshotclasses.snapshot.storage.k8s.io
kubectl get virtualmachinesnapshots.snapshot.kubevirt.io -A
kubectl get volumes.longhorn.io -n longhorn-system

4. VM 生命周期状态机

4.1 VirtualMachine 的 printableStatus

                       ┌──────────────► DataVolumeError(导入失败,看 DV conditions)

(创建)──► Provisioning ──► Starting ──► Running ──► Stopping ──► Stopped
              (DV 创建/导入中)  (VMI 调度中)      │        ▲           │
                       ▲                            │        │           │
                       │                            ▼        │           ▼
                       └──────────────────── Scheduling ◄──────┘   (runStrategy=Always 再启动)
                                        (卷无法 attach / 资源不足)
状态含义第一反应查什么
ProvisioningDataVolume 创建/导入中kubectl get dv 的 phase 与 progress;importer Pod 日志
DataVolumeError导入失败kubectl get dv -o yaml 的 conditions/message
StartingVMI 调度中kubectl describe vm 事件;VMI conditions
Running正常
长期 Scheduling卷 attach 失败或资源不足Longhorn 卷 state/robustness/cloneStatus、节点容量、nodeSelector
Stopped/Halted已停机runStrategy=Always 启动
Migrating热迁移中VirtualMachineInstanceMigration 状态
Unknown/ErrorUnschedulable调度被拒污点/容忍、节点 cordon 状态

4.2 VMI 与 DataVolume 的对应状态

VMI:  Scheduling → Scheduled → Running
DV :  ImportScheduled → ImportInProgress(2.5%→99.6%) → Succeeded 100%
PVC:  Pending → Bound

⚠️ Succeeded / Bound / readyToUse=true 都只是控制面信号。 实测中出现过 DV Succeeded、PVC Bound、CSI readyToUse=trueVirtualMachineRestore complete=true、 甚至 DataVolumesReady=True 全部正常,而 Longhorn 卷 robustness=degradedcloneStatusinitiated、副本 mode=<none> → VM 起不来。 详见 06 存储实战 与 12 实战案例集 场景三。

4.3 RunStrategy 五值

RunStrategy含义
Always保持运行(VMI 异常退出自动重建)
Halted停止(回收 VMI;不存在 Stopped 这个值)
RerunOnFailure失败时重跑,正常关机后不重启
Manual由 start/stop 子资源显式控制
Once只运行一次,退出后不再拉起

5. 三种部署形态(+ 两种「非 Harvester」参照系)

形态节点 OSK8s 来源存储入口装机配置适用
Harvester ISO 一体机Harvester OS(Elemental 不可变系统)装机自带 RKE2自带 Longhorn(data_disk 自动纳管)VIP + kube-vipconfig.yamlscheme_version: 1,HTTP/PXE 托管)全新裸金属虚拟化集群、交付型项目
Harvester 容器化既有集群节点的任意 Linux既有 RKE2/K8s子 chart Longhorn(或复用既有 CSI)Service NodePort + SNI(或 Ingress/LB)Helm values.yaml + promote已有 K8s,叠加虚拟化能力
裸 KubeVirt任意任意任意 CSI(需自己配 RWX 才能热迁移)自己解决kubectl apply -f kubevirt-cr.yaml只要 VM 能力、不要产品化外壳
参照:公有云 IaaS云托管无(VM 与 K8s 分离,或用托管 K8s)云盘(EBS/ESSD/PD)云 API/控制台云 SDK/Terraform弹性、免运维、数据可出域
参照:vSphere/OpenStack宿主 OSvSAN/Ceph自有 API自有编排传统企业虚拟化存量

5.1 两种 Harvester 形态的关键差异(别把结论互相套用)

维度ISO 一体机容器化(Helm on 既有 RKE2)
节点 OS 可控性不可变系统,改动走 oem 挂载/ Elemental 机制完全可控(就是普通 Linux)
与既有集群共存不存在(它自己就是集群)必须处理冲突:snapshot-controller 双装、双默认 StorageClass、ingress/Rancher 缺失噪声
首登密码装机配置无法指定 → 引导密码 xxx + `mustChangePassword=xxx由 chart/Rancher 逻辑决定
节点角色join 节点被 harvester-promote-node-controller 自动提升为 control-plane+etcd取决于既有集群拓扑
典型坑nm-online 亚秒竞态、镜像预加载 >30min 卡死、CoreDNS 随机上游gate Snapshot 单数、helm upgrade 覆盖 CR、Longhorn RWX 数据面
排障层数宿主 → 引导 → 安装器 → 集群 → 应用(5 层集群 → 应用(2 层

5.2 Harvester OS(Elemental)到底特殊在哪

特性说明运维含义
不可变根文件系统系统分区只读,A/B 双状态分区(COS_STATE/COS_RECOVERY升级=换分区,失败可回滚;但别指望改 /usr 下的东西能持久
/oem/var/lib/rancher 可写配置与数据落在持久分区装机配置里的 os.* 最终写到这里
内置二进制不在 PATHkubectl/crictl/ctr 位于 /var/lib/rancher/rke2/bin/必须用绝对路径sudo /var/lib/rancher/rke2/bin/kubectl --kubeconfig /etc/rancher/rke2/rke2.yaml
registries.yaml 由控制器渲染声明源是 containerd-registry 设置手写该文件会被回收(实测 167B → 0B)
安装期是 live 内存 overlayroot=live:http://…squashfs安装期对 live 环境的任何修改重启即失效(自愈脚本要重新注入)

6. 与 Kubernetes 的关系(为什么这是「云原生虚拟化」)

K8s 机制在 Harvester 里如何作用于 VM
调度器VM 的落点由 virt-launcher Pod 的调度决定;可用 nodeSelector、亲和性、污点/容忍控制
资源模型domain.resources.requests/limits = Pod requests/limits;超分靠 requests < 实际用量
命名空间 + RBAC租户隔离用 namespace;权限用 K8s RBAC(Harvester 再包一层「项目」概念)
ResourceQuota / LimitRange直接限制某租户能开多少 VM、多少 CPU/内存
声明式 + 控制器改 YAML 即改 VM;kubectl apply 可进 Git,走 ArgoCD/Fleet
可观测性VM 指标就是 Pod 指标(cAdvisor)+ KubeVirt 的 kubevirt_* 指标,Prometheus 直接抓
准入控制KubeVirt 的 virt-api + Harvester 的 harvester-webhook 两级校验——大量「明明 YAML 没错却建不起来」都发生在这里
CRD 生态快照走 KubeVirt 原生 snapshot.kubevirt.io;卷走 CSI + Longhorn;网络走 NetworkAttachmentDefinition(Multus)

这条关系链解释了 Harvester 的两个最大红利(GitOps、统一可观测)与两个最大约束 (一切受 K8s 准入与调度语义约束存储必须走 CSI——而 CSI 的 accessModes 直接决定了热迁移能不能做,见 08)。


7. 术语表

术语全称/含义
HCIHyper-Converged Infrastructure,超融合:计算+存储+网络+管理同节点
KubeVirtCNCF 项目,用 CRD + Pod 把 KVM 虚拟机跑进 K8s
CDIContainerized Data Importer,KubeVirt 的镜像导入/克隆/上传组件
VMIVirtualMachineInstance,VM 的运行实例(停机即消失)
virt-launcher承载单个 VMI 的 Pod,内含 qemu-kvm
LonghornCNCF 分布式块存储,Harvester 默认存储后端
RWO/RWXReadWriteOnce / ReadWriteMany,PVC 的访问模式;★ 热迁移要求全部 RWX
DataVolume(DV)CDI 对象,声明「从哪来、放哪、多大」
VolumeSnapshotClassCSI 快照类;Longhorn 的 parameters.typesnap(卷内快照)或 bak(备份)
backup targetLonghorn 备份目标(NFS/S3);不配则 type: bak 失败
masqueradeKubeVirt 默认网络绑定模式:VM 出网走 Pod 网络 SNAT
bridgeKubeVirt 二层桥接模式;配合 Multus + VLAN 用
Multus / NAD多网卡 CNI 元插件 / NetworkAttachmentDefinition
whereabouts集群级 IPAM,为二层网络分配 IP
kube-vip提供 VIP 与 Service LoadBalancer 实现
ElementalSUSE 的不可变 OS 框架,Harvester OS 的底座
promote容器化形态下,把既有集群真实 CIDR/DNS 告知 Harvester 的配置段
SteveRancher 的 API 聚合/代理层,Harvester 的 /v1 API 由它提供
v2vVirt-to-Virt,从 VMware 等平台迁移 VM(vm-import-controller
cloud-initGuest OS 首启初始化(用户/密钥/网络/包)
qemu-guest-agentGuest 内代理,让宿主能做优雅关机、冻结文件系统做一致性快照
quorumetcd 多数派(3 成员需 ≥2 存活)
VIP虚拟 IP,ISO 形态的 Dashboard/API 入口
SNITLS Server Name Indication;容器化形态入口会校验 Host/SNI

8. 下一步

目标
30 分钟跑出第一台 VM02 快速上手
直接看部署03 ISO 一体机 / 04 容器化
想知道「该选哪个」10 五方对比