TT Lab
博客

한국어 English 日本語 中文

开始
博客

博客

学生 VM 诞生记 3:磁盘即 PVC — DataVolume、访问模式与卷模式

状态:草案(2026-10-16),官方文档 + 部分实测。 于 2026-10-16 打开并查阅了 KubeVirt、CDI、Kubernetes 文档(KubeVirt v1.9.0、CDI v1.66.0、Kubernetes v1.34)。存储类的配置是在同一天以只读方式查询的,由于是公开文章,存储产品和驱动程序名称已泛化为“共享存储的 CSI 驱动程序”和“节点本地类”。编写规则:实测数据为基础,未能测量的数据标记为“未实测”,在文档中未找到的内容标记为“未确认”。

学生 VM 诞生记 3:磁盘即 PVC

目录

第 1 篇的第 ⑦ 项“挂载卷”。从结论来说,KubeVirt 的磁盘是**对客机可见的设备(disk)**与**承载其内容的 Kubernetes 卷(volume)**的配对。在清单中,两者通过名称相连。

domain:
  devices:
    disks:
      - name: root          # 게스트에게는 virtio 디스크(/dev/vda)
        disk: {bus: virtio}
volumes:
  - name: root              # 내용은 이 볼륨에서 온다
    containerDisk: {image: quay.io/containerdisks/ubuntu:24.04}

根据卷位置填入的内容,磁盘的属性会发生完全的变化。

1. 卷的类型

在 KubeVirt 用户指南列出的卷源中,实验 VM 使用的有五种。

源 内容 关闭时 在实验中
containerDisk 容器镜像的 /disk 内部包含的磁盘镜像 消失(临时) 默认根磁盘
emptyDisk 在节点上创建空的稀疏 qcow2 文件。必须指定容量 客机重启时保留,重新创建 VM 时消失 Docker / Kubernetes 实验的临时空间(Scratch)
persistentVolumeClaim 现有的 PVC 保留 —
dataVolume 由 CDI 获取并创建的 PVC 保留(若 VM 拥有它,则随 VM 一同删除) 持久磁盘选项
ephemeral 将 PVC 作为 只读基础层使用,写入操作则交由本地写入层 仅写入层消失 黄金磁盘(第 4 篇)
cloudInitNoCloud cloud-init 数据(来自 Secret) — 首次启动配置(第 1 篇 ③)
루트 디스크를 마련하는 세 갈래 A. 컨테이너 디스크 (기본) 레지스트리 이미지 노드가 한 번 받음 노드 캐시 바탕(읽기만) 쓰기 층 emptyDir · VM 마다 루트 2.4GiB · Running 20초(실측) · 끄면 초기화 B. DataVolume (VM 마다 PVC) 레지스트리 이미지 VM 마다 다시 CDI 가져오기 파드 + 스크래치 PVC PVC 하나 RWO · 10Gi 원하는 크기 · 첫 부팅 최대 195초(실측) C. 골든 + 쓰기 층 골든 PVC 운영자가 한 번 · RWX 읽기 전용 readOnly: true 쓰기 층 emptyDir · VM 마다 골든 크기(10·20Gi) · 부팅 시간 미실측 A 와 C 는 같은 원리다: 읽기 전용 바탕 + VM 마다 쓰기 층. 바탕이 노드 캐시냐 PVC 냐만 다르고, 바탕의 크기가 곧 게스트 루트의 크기다.
图:准备根磁盘的三条路径

2. 容器磁盘:快捷但娇小

容器磁盘像获取容器镜像一样从注册表中拉取 OS 镜像。一旦节点拉取过一次,后续的 VM 将直接使用,无需再次获取。由于磁盘是临时的,非常契合“创建、损坏、销毁”的实验场景,因此它是默认选项。正如第 1 篇实测的那样,状态在大约 20 秒内就会变为 Running。

所谓临时,是指 基础层是节点上预先获取的镜像文件,客机的写入会单独累积。查看已运行 9 天的操作员 VM 的 virt-launcher 内部,发现根目录是叠加在基础层(节点上拉取的磁盘镜像,分配约 596MiB)之上的 qcow2 写入层(分配约 1.10GiB)(实测,2026-10-14)。第四篇将要讨论的黄金磁盘,就是将该结构中的 仅基础层替换为 PVC。

缺点是容量。容器磁盘的根目录只有基础镜像的虚拟大小,对于我们使用的 Ubuntu 镜像而言,仅仅只有 2.4GiB (实测)。在制作实验的过程中,我们曾因此处而两次受阻。

3. DataVolume:宽敞但缓慢

为了支持需要大根目录的实验,我们有 persistent 这一选项。此时,后端会在 VM 清单中填入 dataVolumeTemplates ,而 CDI(Containerized Data Importer)会为每个 VM 创建 PVC 并获取镜像。

CDI 获取注册表镜像的流程如下(参考 CDI “Scratch space”文档):导入 Pod 获取镜像、解压镜像层、找到磁盘镜像,然后将其转换为 qemu-img 并写入目标 PVC。此过程需要一个 与目标大小相同的临时(Scratch)PVC ,并在结束后归还。因此,在获取一个 10Gi 磁盘的过程中,会产生两个 PVC。

由于 VM 拥有 DataVolume,删除 VM 时也会一并删除 PVC。问题在于时间。实验会话的架构是每次都重新创建一个新的 VM,因此 每次创建 VM 时都要重新获取镜像 ,首次启动时间甚至长达 最高 195 秒(实测,仅记录实验开发期间的最大值)。后端将容器磁盘(150 秒)和 DataVolume(300 秒)的 VM 准备就绪等待上限分开设置,也是出于这个原因。

容量上也有一个陷阱。在文件系统 PVC 中,KubeVirt 将磁盘放置在 PVC 根目录下名为 disk.img 的 raw 文件中,因此文件系统本身占用的空间会被空出来。根据 CDI 文档,只有在将 DataVolume 编写为 spec.pvc 而非 spec.storage 时,CDI 才会计算这部分份额(文件系统开销),并 请求一个更大的 PVC 。由于 TT Lab 的 CDI 配置中开销为 6%(2026-10-16 确认),如果将 10Gi 请求为 spec.storage ,客机磁盘将是 10Gi,而 PVC 则会比它稍微大一些(计算值, 未实测)。设计文档曾写道“10Gi 黄金镜像的客机根目录大约为 9.4GiB”,这与 CDI 文档不符。哪一方正确将在第 4 篇末尾的测量中进行确认。此外,KubeVirt 甚至能接受 disk.img 略小于请求值(默认最多差 10%)的情况(用户指南)。

4. 访问模式:多少节点可以同时挂载

PVC 的访问模式在 VM 中尤为重要。总结 Kubernetes 文档中的定义如下:

模式 含义 在 VM 中的表现
ReadWriteOnce (RWO) 单节点以读写方式挂载。同一节点上的多个 Pod 可以共同使用 VM 被绑定到该节点。无法进行实时迁移
ReadOnlyMany (ROX) 多节点以只读方式挂载 看似契合基础盘,但请注意下方说明
ReadWriteMany (RWX) 多节点以读写方式挂载 支持实时迁移,多节点共享同一基础盘
ReadWriteOncePod (RWOP) 整个集群仅允许一个 Pod 仅限 CSI 卷

在此明确两点。

访问模式不等同于写保护。 Kubernetes 文档明确指出,访问模式无法阻止挂载之后的写入操作,由 ROX 创建的卷也无法保证只读。真正的保护是将卷 以只读方式挂载。这就是为什么第 4 篇的黄金磁盘虽然创建为 RWX,但在挂载时却没有 readOnly: true 的原因。

实时迁移需要 RWX。 KubeVirt 用户指南指出,只有当使用 PVC 的 VM 的访问模式为 RWX 时,才能进行迁移。是否可迁移会在 VMI 启动时计算并作为 LiveMigratable 条件保留,其方法分为仅迁移内存的 LiveMigration 以及连同磁盘一起复制的 BlockMigration 。实际检查一个使用容器磁盘和 emptyDisk 的 VM 时,发现其状态为 LiveMigratable=True,方法是 BlockMigration (2026-10-16 查询)。这意味着如果要迁移节点本地磁盘,必须将其整体复制。TT Lab 的 DataVolume 选项创建出来是 RWO,因此该 VM 无法迁移。由于实验 VM 本身就不需要迁移,这是一个可以接受的选择。

5. 卷模式:文件系统还是块设备

模式 在 Pod 中的形态 KubeVirt 的磁盘
Filesystem(默认) 挂载为目录 其中的 disk.img(raw) 文件。所有者必须是 UID 107
Block 无文件系统的块设备 直接将设备作为磁盘使用

Kubernetes 文档将块设备模式描述为 Pod 与卷之间没有文件系统层的最快路径。不过,这要求使用方懂得如何处理块设备,而 QEMU 正好具备此能力。据报导,TT Lab 的共享存储类仅提供文件系统模式(见下文第 6 节)。因此,黄金磁盘也是文件系统 PVC 内的 disk.img 。

6. 绑定时机与 StorageProfile

是在创建 PVC 后立即分配卷(Immediate),还是推迟到使用该 PVC 的 Pod 降落在节点上时再分配(WaitForFirstConsumer),也会在 VM 中造成差异。节点本地类必须采用延迟绑定。因为卷是特定节点的磁盘,如果在 Pod 降落到何处尚不清楚之前就进行分配,它可能会在错误的节点上创建。

CDI 提供了尊崇此延迟特性的功能开关(HonorWaitForFirstConsumer)。这样一来,镜像获取也会推迟到首个使用者(VM)降落时。像黄金磁盘这样 在 VM 到来之前必须已经获取完毕 的卷,因此会带有“请立即绑定”的注解(cdi.kubevirt.io/storage.bind.immediate.requested)。

CDI 会为每个存储类创建一个 StorageProfile ,并在其中填入适合该类的访问模式、卷模式和克隆策略。它会为知名的 Provisioner 填入推荐值,而对未知的 Provisioner 则保持空白。如果在空白的类中创建未指定访问模式的 DataVolume,将会失败(CDI StorageProfile 文档)。在撰写本文当天读取 TT Lab 的类时,结果如下。

类 绑定 扩容 StorageProfile 提供的内容 克隆策略
共享存储(CSI 驱动程序) Immediate 支持 RWX · Filesystem copy
节点本地 WaitForFirstConsumer — 无 copy

只有共享存储类才能挂载到多个节点上。因此,黄金磁盘是用这个类创建的。没有克隆策略 copy 和快照类,正是第四篇中「为什么不是 PVC 克隆而是写入层」的依据。

7. 总结:三路权衡

容器磁盘 DataVolume 黄金 + 写入层(第四篇)
根大小 2.4GiB(实测) 期望大小 黄金大小(10Gi·20Gi 菜单)
创建 VM 时的操作 节点上有镜像时几乎没有 获取新镜像并写入 PVC 一个空的写入层
首次启动 约 20 秒(实测) 最多 195 秒(实测) 未实测
每个 VM 生成的 PVC 无 一个(+ 获取期间的一个 scratch) 无
关闭时 写入层消失 保留 PVC(删除 VM 时随之删除) 写入层消失

第四篇的黄金磁盘,就是将中间列的「为每个 VM 获取新镜像」改为了「获取一次并共享使用」。

TT 小贴士。 访问模式的意思是「可以在几个地方挂载」,而不是「阻止你写入」。如果你想保护基础磁盘,无论是 RWX 还是 ROX,请务必以只读方式挂载。而且当磁盘满时,错误信息可能会莫名其妙,如果觉得奇怪,请先检查 df -h !

参考

所有文档均于 2026-10-16 查阅。

登录后即可点赞

评论

还没有评论。

登录后即可发表评论