主题
KubeVirt 虚拟机使用商用 NAS 存储:方案与落地
日期: 2026-09-03 环境: RKE2 v1.35.6(6 节点)+ KubeVirt v1.9.0 + CDI v1.60.4 入口节点:
root@192.168.122.31关联文档:cdi-offline-deployment-guide.md、kubevirt-storage-ha-guide.md、rke2-kubevirt-deployment-guide.md
目录
- 结论与现网证据
- 三种接入方式对比
- qcow2 放哪里:镜像库与活动磁盘分离
- 镜像库 → 导入 → 金盘克隆
- NAS 容量与虚拟机数量限制
- NFS 关键注意事项
- 落地实施:vm-nas StorageClass
- 验证清单
1. 结论与现网证据
结论:完全可行,且是生产环境最常见方案之一。 KubeVirt 的虚拟机磁盘本质是一个 PVC(RWO 即可),任何能通过 StorageClass/CSI 供应 PVC 的存储后端都可以承载,商用 NAS 提供的 NFS / iSCSI 天然符合。
现网集群(192.168.122.31)已有的证据:
- 已存在基于 NFS 的 VM 磁盘 PVC:
sza001-rootdisk(SC=nfs)、vm1-rootdisk(SC=nfs-nvme) - NFS 由
nfs-subdir-external-provisioner供应,服务端当前是实验机192.168.122.1(/mnt/xfs/rancher/*、/srv/nfs-nvme/*)——换成商用 NAS 只需把NFS_SERVER/NFS_PATH指向 NAS 导出目录,架构不用变
2. 三种接入方式对比
| 方式 | 适用 | 优点 | 限制 |
|---|---|---|---|
| NFS(推荐起步) | 所有商用 NAS(Synology/QNAP/NetApp/华为/新华三等) | 通用,nfs-subdir-external-provisioner 现成;天然 RWX,支持热迁移 | 延迟高于块存储;导出版本/权限要调对 |
| 厂商 CSI(NetApp Trident、Synology CSI、华为 OceanStor CSI 等) | 中高端商用 NAS | 快照、在线扩容、精简配置、QoS | 需装厂商组件,确认与 RKE2/K8s 版本兼容 |
| iSCSI | 对 IOPS/延迟敏感 | 块级性能最好 | 节点需配 initiator;RWO 单挂载 → 不能热迁移;配置复杂 |
一般建议:NFS 起步,有性能/快照诉求再上厂商 CSI。CDI 导入流程与后端无关, CDI 会为每个新 StorageClass 自动生成 StorageProfile(默认 Filesystem + RWO),无需额外配置。
3. qcow2 放哪里:镜像库与活动磁盘分离
"qcow2 存 NAS、容器直接跑"要先分清两个角色:
3.1 方案 A:qcow2 只做镜像库,活动磁盘走 PVC(推荐,已验证)
NAS/文件服务器上的 qcow2 → CDI DataVolume 导入 → PVC 上的 disk.img(raw) → VM 启动
镜像仓库 一次性转换 真正的虚拟机磁盘- 即现网已跑通链路(
cdi-offline-deployment-guide.md§6) - CDI 导入时会把 qcow2 转成 raw(Filesystem PVC 上固定为
disk.img) - 运行中的 VM 只依赖 PVC,镜像库只在创建新 VM 时被用到(导入完成后源镜像 所在服务宕机不影响任何存量 VM)
- 镜像库与活动磁盘可合并在同一台商用 NAS 上(两个目录而已)
3.2 方案 B:NAS 挂进 Pod,VM 直接读写 NAS 上的 qcow2 文件(不推荐)
KubeVirt 技术上能识别 PVC 里现成的 qcow2 文件(自动检测格式),但:
- qcow2 是元数据密集型格式(L1/L2 表、引用计数频繁小写),叠加 NFS 延迟性能差
- 绕开了平台的单写者保护,两个 Pod 指到同一文件 = 磁盘损坏
- 失去在线扩容、preallocation、StorageProfile 调优、克隆能力
3.3 方案 C:绕开 KubeVirt,普通容器跑 qemu(仅临时用途)
Deployment 里跑 qemu-kvm -drive file=/mnt/nas/vm.qcow2 可以工作,但要自己解决 /dev/kvm 暴露、网络接入、VNC、重启策略,等于放弃 KubeVirt/dashboard 全部平台能力。
4. 镜像库 → 导入 → 金盘克隆
4.1 导入源说明
CDI 支持的导入源:http/https、s3、registry、gcs、pvc(克隆)、upload、blank。 不支持 nfs:// 直接导入——商用 NAS 上的 qcow2 需要用 HTTP 暴露 (NAS 自带 Web 服务,或沿用文件服务器方式)。
4.2 golden image + 克隆(批量建同类 VM)
让源 qcow2 只被导入一次,之后全部从"金盘"派生:
yaml
# ① 金盘:导入一次
apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
name: golden-rocky9
spec:
source:
http:
url: "http://<nas-or-fileserver>/images/rocky9-server-root.qcow2"
pvc:
storageClassName: vm-nas
accessModes: [ReadWriteMany] # 需要热迁移时用 RWX
resources:
requests:
storage: 20Gi
---
# ② 每台新 VM:从金盘克隆(不再碰镜像库)
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- 商用 NAS 配了厂商 CSI 时,克隆可走 CSI 快照,秒级开盘
- 也可用
DataSource+DataImportCron做定时刷新的金盘(适合镜像版本管理)
4.3 故障域视角
| 故障 | 影响 |
|---|---|
| 镜像库服务宕机 | 不能导入/新建,存量 VM 无感 |
| VM 盘所在存储宕机 | 挂在该盘上的 VM 受影响(这是需要保 HA 的一侧,见 kubevirt-storage-ha-guide.md) |
5. NAS 容量与虚拟机数量限制
NAS 没有显式的"虚拟机数量"配额——NAS 眼里只有 NFS 导出目录里的磁盘文件。 真正的限制全部是性能型约束,取决于 NAS 档次:
| 约束 | 说明 | 谁先撑爆 |
|---|---|---|
| 随机 IOPS | VM 磁盘典型 4K 随机读写;HDD 单盘 ~100-150 IOPS,RAID 后线性叠加 | 机械盘 NAS |
| 带宽 | 1GbE ≈ 110MB/s,10GbE ≈ 1GB/s,所有 VM 共享 | 大吞吐负载 |
| 协议栈 CPU/内存 | NFSv4 会话/锁处理消耗控制器 CPU | 入门级弱 CPU |
| 挂载连接数 | K8s 每节点每个在用 PV 各挂一次;企业级支持数千连接 | SOHO 机型 |
| Boot storm | 多 VM 同时开机的瞬时随机读风暴 | 无 SSD 缓存的 NAS |
部分厂商对 iSCSI 有显式限制(最大 LUN 数、并发连接数,如 Synology 按型号 10~128 LUN / 512 连接),走 NFS 基本不触碰此类硬限制。
各档次实际承载经验值(NFS + 通用型 VM):
| NAS 档次 | 典型配置 | 能撑的 VM 量级 |
|---|---|---|
| SOHO/入门(4 盘位,HDD,1GbE) | 无 SSD 缓存 | 5~15 台轻量级 |
| 中端(8~24 盘位,SSD 缓存,10GbE) | Synology SA/UC、QNAP TS-h 等 | 几十到一两百台 |
| 企业级(NetApp/华为 OceanStor/Dell Unity/PowerScale) | 全闪或混合多控 | 数百到数千台 |
判断方法:看规格书的 IOPS 和延迟,不看"支持多少虚拟机"。
估算步骤:
bash
# ① 从任一 K8s 节点对 NAS 导出实测
fio --name=nas --rw=randrw --bs=4k --iodepth=16 --numjobs=4 \
--runtime=60 --time_based --filename=/挂载点/fio.dat --size=4G --direct=1
# ② 算需求:普通业务 VM 稳态约 1~10 IOPS/台,开机瞬间 100~500 IOPS
# 总 IOPS ÷ 开机峰值 ≈ 可承载台数上限
# ③ 上线后盯延迟:NFS 读写延迟 <2ms 健康,>10ms 已过载(nfsiostat / NAS 面板)抗 boot storm:VM 分批启动 + NAS 加 SSD 缓存/SSD 分层。
6. NFS 关键注意事项
- 权限/uid 映射:virt-launcher 里 qemu 以非 root(uid 107)运行。 NAS 导出若开
root_squash且anonuid不匹配,会出现 VM 启动时磁盘写失败 (Permission denied)。K8s 专用导出目录建议no_root_squash。 - NFS 版本:用 4.1+(挂载
nfsvers=4.1),v3 文件锁问题可能影响磁盘一致性。 - 热迁移:需要磁盘可共享 → DV 用
accessModes: [ReadWriteMany](NFS 天然支持); iSCSI/RWO 无法热迁移。 - 文件格式:CDI 导入产物是 raw(性能优于 qcow2);不要手工往 PVC 里塞 qcow2。
- 容量开销:Filesystem 模式 CDI 默认预留 5.5%(
CDIConfig.filesystemOverhead)。 - 挂载健壮性:VM 盘必须
hard挂载(NAS 故障时 IO 挂起等待恢复,不产生静默错误), 详见kubevirt-storage-ha-guide.md。
7. 落地实施:vm-nas StorageClass
沿用现网已验证的 nfs-subdir-external-provisioner,指向商用 NAS:
yaml
# provisioner Deployment 关键环境变量(其余沿用现有部署)
env:
- name: NFS_SERVER
value: "<商用NAS IP>"
- name: NFS_PATH
value: "/exports/kubevirt"
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: vm-nas
provisioner: cluster.local/nfs-subdir-external-provisioner # 与 Deployment 的 PROVISIONER_NAME 一致
reclaimPolicy: Retain # VM 盘建议 Retain,防误删
allowVolumeExpansion: true
mountOptions:
- nfsvers=4.1
- hard
- timeo=600
- retrans=5
- noatimeNAS 侧配置:创建导出 /exports/kubevirt,选项 rw,sync,no_root_squash,no_subtree_check。
两个集群的落地建议:
| 集群 | 建议 |
|---|---|
| 现网 122.31 | 复制现有 provisioner 部署指向商用 NAS,建 vm-nas SC;新 VM 磁盘与 CDI 导入目标都用它 |
| 目标 RKE2(uat1) | 当前无动态存储(只能手工 hostPath PV);装好 vm-nas SC 后 KubeVirt + CDI 直接可用,可不再依赖 local-path |
8. 验证清单
- [ ] 各节点手动挂载 NAS 导出成功:
mount -t nfs4 <nas>:/exports/kubevirt /mnt/t - [ ]
vm-nasSC 创建 PVC 秒级 Bound,写文件无 Permission denied - [ ] 小镜像 DataVolume 导入 Succeeded(先小后大)
- [ ] VM 从 NAS PVC 启动,重启后数据保留
- [ ] (如需热迁移)DV 用 RWX,
kubectl virt migrate成功且业务不中断 - [ ]
fio实测结果记录存档,作为容量规划基线