KubeVirt 磁盘
KubeVirt 如何添加磁盘
KubeVirt 可以将多种资源挂载为磁盘:
- PersistenVolumeClaim:K8S 自带的存储资源,可以挂载给虚拟机做磁盘。
- DataVolume:部署 CDI 后添加的 CRD,可以通过 CDI 将虚拟机镜像导入到 PVC。
- containerDisk:利用容器存储磁盘,可以挂载给虚拟机做磁盘。
更多的可以查看官网:Filesystems, Disks and Volumes - KubeVirt user guide
下边是一个带有硬盘的虚拟机 YAML 文件:
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: vm-storage
namespace: default
spec:
runStrategy: Always
template:
spec:
architecture: amd64
domain:
devices:
disks:
- disk:
name: containerdisk
- disk:
name: dv-disk
- name: mypvcdisk
lun:
bus: scsi
interfaces:
- masquerade: {}
name: default
machine:
type: q35
resources:
requests:
memory: 512Mi
networks:
- name: default
pod: {}
volumes:
- containerDisk:
image: quay.io/kubevirt/cirros-container-disk-demo
name: containerdisk
- DataVolume:
name: fedora
name: dv-disk
- name: mypvcdisk
persistentVolumeClaim:
claimName: iscsi-pvc
PersistentVolumeClaim
PVC 自己有 Block 和 Filesystem 两种类型:
- Block:直接申请块存储做磁盘
- Filesystem:将磁盘存储在文件存储中使用
Filesystem 存储虚拟机磁盘时有如下要求:
-
磁盘必须放在文件系统的根路径,并且名字必须为
disk.img
-
文件所有者必须为
107
-
由于文件系统的原因,提供的磁盘大小在虚拟机内显示会有所减少,KubeVirt 最多会有 10% 的减少
可以通过编辑 KuveVirt 资源的
developerConfiguration.pvcTolerateLessSpaceUpToPercent
来做修改。
添加 PVC 磁盘:
volumes:
- name: mypvcdisk
persistentVolumeClaim:
claimName: iscsi-pvc
DataVolume(dv)
DataVolume 的意义
我们使用虚拟机多数时候是用一个模板的 qcow2 镜像来启动虚拟机。想想一下,如果只用 PVC 做虚拟机磁盘,那么每次创建虚拟机都需要先创建好 PVC,并且要将系统镜像导入到 PVC。先不讨论这套流程的复杂性,如何实现虚拟机镜像导入 PVC?为了解决这个问题,就产生了 DataVolume
。
DataVolume
是部署 CDI 后添加的 CRD,它可以在创建虚拟机时自动将虚拟机磁盘导入 PVC。
下边演示一个带有 DataVolumeTemplates 的 YAML:
apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
name: "fedora"
spec:
storage:
storageClassName: csi-rbd-sc
resources:
requests:
storage: 5Gi
source:
http:
url: "https://download.fedoraproject.org/pub/fedora/linux/releases/41/Cloud/x86_64/images/Fedora-Cloud-Base-Generic-41-1.4.x86_64.qcow2"
这个表示从网络下载 Fedora 的镜像,并导入名为 fedora 的 PVC。
DataVolume 模板
上边已经实现了 PVC 的自动导入,但是还有可以优化的点,能不能创建一个模板,然后在创建虚拟机的时候按照模板创建 DataVolume 来简化 dv 的创建流程?答案是可以的。
下边演示一个官网的 DataVolumeTemplates:
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: vm-dv-temp
namespace: default
spec:
runStrategy: Always
template:
spec:
domain:
cpu:
cores: 1
sockets: 1
threads: 1
memory:
guest: 1Gi
devices:
disks:
- disk:
name: rootdisk
- disk:
name: cloudinitdisk
interfaces:
- masquerade: {}
name: default
machine:
type: q35
networks:
- name: default
pod: {}
volumes:
- DataVolume:
name: vm-dv-temp
name: rootdisk
- name: cloudinitdisk
cloudInitNoCloud:
userData: |-
#cloud-config
chpasswd: { expire: False }
password: redhat
runcmd:
- 'sudo echo $(date "+%F %T") > /tmp/install.log'
DataVolumeTemplates:
- metadata:
name: vm-dv-temp
namespace: default
spec:
storage:
storageClassName: csi-rbd-sc
resources:
requests:
storage: 5Gi
source:
http:
url: "https://download.fedoraproject.org/pub/fedora/linux/releases/41/Cloud/x86_64/images/Fedora-Cloud-Base-Generic-41-1.4.x86_64.qcow2"
可以看到 VM 的 YAML 文件有一个 DataVolumeTemplates
,在创建虚拟机时会先创建 DataVolume
然后在创建虚拟机。
DataVolume
即支持 VM 也支持 VMI,VM 添加的话虚拟机整个生命周期都会使用 dv,VMI 添加的话虚拟机重启就需要重新添加。
containerDisk
containerDisk 的意义
containerDisk
的作用是利用容器提供一个不可变的系统磁盘,它适合会批量创建但不需要持久化保存数据的虚拟机。
下边是添加 containerDisk
的字段:
volumes:
- containerDisk:
image: quay.io/kubevirt/cirros-container-disk-demo
name: containerdisk
创建 containerDisk 容器镜像
创建 containerDisk 容器镜像有如下要求:
- 磁盘镜像建议放在容器内的
/disk
,也可以放在自定义目录 - 容器镜像建议基于
scratch
- 镜像格式只支持 Raw 和 qcow2,建议使用 qcow2
- containerDisk 需要对 UID 107(qemu)的用户可读。
- 在 kubevirt 0.20 之前,containerDisk 镜像需要以 kubevirt/container-disk-v1alpha 作为基础镜像
下边是容器磁盘的 Dockerfile
cat << END > Dockerfile
FROM scratch
ADD fedora25.qcow2 /custom-disk-path/fedora25.qcow2
END
然后 build
镜像:
docker build -t custom/fedora25:latest .
docker push custom/fedora25:latest
如果是自定义的目录,在使用时需要通过 path
字段来设置自定义目录:
volumes:
- containerDisk:
image: custom/fedora25:latest
path: /custom-disk-path/fedora25.qcow2
name: containerdisk
containerDisk
是基于文件的,因此不能作为lun
设备附加到虚拟机。
Cloud-init 磁盘
除了存储数据的磁盘,还有个很重要的磁盘 Cloud-init,利用 Cloud-init 可以对虚拟机做初始化。
KubeVirt 可以导入 Cloud-init 的两种数据源:
cloudInitNoCloud
cloudInitConfigDrive
cloudInitConfigDrive
可以使用 Ignition 配置虚拟机。只需用 Ignition 数据替换 cloud-init 数据即可。
下边展示两种 Cloud-init 添加方式。
volumes:
- name: mynoclouddisk
cloudInitNoCloud:
secretRef:
name: testsecret
volumes:
- name: myconfigdrivedisk
cloudInitConfigDrive:
secretRef:
name: testsecret
# cloudInitNoCloud 和 cloudInitConfigDrive 还支持下边这个写法
volumes:
- name: myconfigdrivedisk
cloudInitNoCloud:
userData: |-
#cloud-config
chpasswd: { expire: False }
hostname: vm-dv
fqdn: vm-dv.example.com
password: fedora
runcmd:
- 'sudo echo "The virtual machine initialization time is $(date "+%F %T")" > /tmp/install.log'
bootcmd:
- 'sudo echo "The virtual machine startup time is $(date "+%F %T")" > /tmp/boot.log'