2 卷管理
-
磁盘(Disks): - 磁盘通常指的是物理存储设备,如机械硬盘(HDD)或固态硬盘(SSD),它们提供非易失性存储空间。磁盘有固定的容量,并且实际存在于服务器、个人计算机或其他计算设备中。
-
卷(Volumes): - 卷是逻辑存储资源,它建立在物理磁盘之上,通过分区或逻辑卷管理技术(LVM)来抽象物理存储。一个卷可以是一个分区,也可以是由多个磁盘的空间集合组成的一个逻辑单元。 卷对操作系统来说就像是一个独立的存储区域,可以格式化并挂载为文件系统,用于存储数据。
-
文件系统(Filesystems): - 文件系统是一种组织、管理和检索存储在磁盘上的数据的方法。它将物理存储空间转换成目录结构和文件层次,使得用户和应用程序能够以文件的形式读写数据。 每个卷都需要一个文件系统才能被操作系统识别和利用,比如XFS、NTFS、ext4等都是不同类型的文件系统。
总结起来: - 磁盘是硬件层面的物理存储介质。 - 卷是基于物理磁盘创建的逻辑存储容器,它可以跨越单个磁盘甚至多个磁盘。 - 文件系统则是应用在卷上的一套规则和数据结构,用来管理存储在卷中的文件和目录结构。
kubevirt是如何为虚拟机提供持久化存储的?先来看一段创建虚拟机的yaml
spec:
domain:
cpu:
cores: 1
model: host-passthrough
memory:
guest: 2Gi
devices:
disks:
- name: root-disk
disk:
bus: virtio
interfaces:
- name: default
masquerade: {}
resources:
requests:
memory: 2048M
networks:
- name: default
pod: {}
volumes:
- name: root-disk
persistentVolumeClaim:
claimName: pvc-centos01-bootdisk
-
定义卷(Volumes): 首先,在VirtualMachine的
spec.volumes部分指定所需的持久化存储卷。这可以是PersistentVolumeClaim(PVC)、HostPath等不同类型的卷。 -
添加磁盘到虚拟机(Disks): 接下来,在VirtualMachine的
spec.domain.devices.disks部分,为虚拟机添加相应的磁盘。这些磁盘将使用虚拟化技术(如 virtio 或 SCSI)模拟实际物理磁盘,并连接到虚拟机内。 -
引用已定义的卷: 最后,在上述磁盘配置中通过名称引用之前定义好的卷。这样,虚拟机内的操作系统就可以识别并挂载这个卷,从而访问和存储数据。例如,在磁盘规范中设置
volumeName字段以关联到对应的 volume 名称。
通过这三个步骤,KubeVirt就能够在k8s中将持久化存储卷与虚拟机内部的磁盘资源关联起来,使得虚拟机能够像物理服务器一样利用集群中的存储服务。
另外,VM中的磁盘名称spec.domain.devices.disks.name引用了spec.volumes.name,所以要保持一致。
为虚拟机添加磁盘,并且指定磁盘总线bus类型¶
spec:
domain:
cpu:
cores: 1
model: host-passthrough
memory:
guest: 2Gi
devices:
disks:
- name: root-disk
disk:
bus: virtio
interfaces:
- name: default
masquerade: {}
resources:
requests:
memory: 2048M
networks:
- name: default
pod: {}
volumes:
- name: root-disk
persistentVolumeClaim:
claimName: pvc-centos01-bootdisk
将磁盘以CDROM类型分配给虚拟机,默认只读¶
spec:
domain:
cpu:
cores: 1
model: host-passthrough
memory:
guest: 2Gi
devices:
disks:
- name: root-disk
disk:
bus: virtio
- name: cdrom
cdrom:
# 默认只读,可以设置为false,表示可写
readonly: false
# 设置总线类型
bus: sata
interfaces:
- name: default
masquerade: {}
resources:
requests:
memory: 2048M
networks:
- name: default
pod: {}
volumes:
- name: root-disk
persistentVolumeClaim:
claimName: pvc-centos01-bootdisk
- name: cdrom
- persistentVolumeClaim:
claimName: pvc-centos7-iso
为虚拟机添加一个filesystem类型的设备¶
filesystem设备会将存储卷作为文件系统添加到虚拟机。filesystem依赖virtiofs技术。 相较于disk,filesystem允许源端的变更能动态地反映到虚拟机内的卷中,比如,将一个configMap通过filesystem共享给虚拟机,对configMap做出的任何修改都会在虚拟机内得到实时反映。但是,虚拟机使用了filesystem后就不支持实时迁移了liveMigration了。此外,
filesystem设备必须在虚拟内部进行挂载,可通过cloudInitNoCloud自动完成挂载,或者进入到虚拟机中手动进行挂载。如若是手动挂载,则使用命令mount -t virtiofs [设备标签] [路径]完成挂载。 在虚拟机规格(VM spec)中的spec.domain.devices.filesystems.name字段会为文件系统分配一个标签。 例如,如果在某个虚拟机规格中设置了spec.domain.devices.filesystems.name: foo,则在虚拟机内将文件系统挂载到/tmp/foo路径所需的命令是mount -t virtiofs foo /tmp/foo。注意 设备为spec: domain: devices: filesystems: - name: foo virtiofs: {} disks: - name: containerdisk disk: bus: virtio - name: cloudinitdisk disk: bus: virtio volumes: - containerDisk: image: quay.io/containerdisks/fedora:latest name: containerdisk - cloudInitNoCloud: userData: |- #cloud-config chpasswd: expire: false password: fedora user: fedora bootcmd: - "sudo mkdir /tmp/foo" - "sudo mount -t virtiofs foo /tmp/foo" - persistentVolumeClaim: claimName: mypvc name: foofilesystem类型需要依赖virtiofs,而virtiofs需要内核支持才能在VM中工作,因此,要检查VM所使用的Linux镜像是否支持virtiofs,可以在制作镜像时执行命令modprobe virtiofs, 如果返回modprobe: FATAL: Module virtiofs not found,则表示该VM的Linux镜像不支持不支持virtiofs。 此外,可以检查Linux内核版本是否达到5.4及以上(针对任何Linux发行版)或者centos/rhel系统内核要达到4.18及以上,可以执行命令uname -r查看。
kubevirt支持的卷源包括:¶
- cloudInitNoCloud
允许将
cloudInitNoCloud数据源附加到虚拟机中。如果虚拟机配置了正确的cloud-init设置,它将会识别并使用这块磁盘作为用户数据源。简单示例如下:## 将一个Secret作为cloud-init disk数据源进行连接 spec: domain: resources: requests: memory: 64M devices: disks: - name: root-disk disk: bus: virtio - name: mynoclouddisk disk: {} volumes: - name: root-disk persistentVolumeClaim: claimName: pvc-centos01-bootdisk - name: mynoclouddisk cloudInitNoCloud: secretRef: name: testsecret
- cloudInitConfigDrive
允许将
cloudInitConfigDrive数据源附加到虚拟机中。若虚拟机中配置了正确的cloud-init设置,它将会识别并将该磁盘作为用户数据源。简单示例如下:## 将一个Secret作为cloud-init disk数据源进行连接 spec: domain: resources: requests: memory: 64M devices: disks: - name: root-disk disk: bus: virtio - name: myconfigdrivedisk disk: {} volumes: - name: root-disk persistentVolumeClaim: claimName: pvc-centos01-bootdisk - name: myconfigdrivedisk cloudInitConfigDrive: secretRef: name: testsecret
- persistentVolumeClaim(持久化卷声明)
允许将持久化卷声明
persistentVolumeClaim数据源附加到虚拟机中。 虚拟机需要在关机后磁盘仍然存在,就应该使用PVC,这样可以确保虚拟机的数据在重启时被持久化不会丢失。 持久化卷可以是文件系统filesystem或块设备block模式。filesystem模式:为了让KubeVirt能够消费位于持久化卷文件系统上的磁盘,磁盘必须命名为disk.img,并放置在文件系统的根路径下。 目前,磁盘还必须以raw格式存储。 注意:为了规避权限问题,disk.img镜像文件的所有者必须为用户ID是107。如果在启动虚拟机之前尚未手动创建disk.img镜像文件, 那么系统将在启动时根据持久化卷声明的大小自动创建。然而,由于并非所有的存储供应者都能提供精确等于请求量的可用空间(比如,可能因文件系统开销而导致), KubeVirt允许可用空间最多比请求量少10%。这一阈值可以通过编辑KubeVirt自定义资源(CR)中的developerConfiguration.pvcTolerateLessSpaceUpToPercent值来配置 可以使用命令kubectl edit kubevirt kubevirt -n kubevirt。 使用PVC作为虚拟机的数据源附加到虚拟机中,简单示例如下:
- dataVolume(数据卷)
允许将数据卷
dataVolume数据源附加到虚拟机中。在kubevirt中,dataVolume简化了虚拟机磁盘镜像的生命周期管理。当创建一个虚拟机实例时,可以通过dataVolume自动地将所需的磁盘镜像导入到PVC中, 也就是说,在虚拟机启动过程中,dataVolume会自动创建PVC,并从指定的源(PVC、HTTP、S3等)接取磁盘镜像文件填充到PVC中,从而省去了用户手动创建PVC并导入镜像来填充PVC的过程。dataVolume可以直接在VM spec中定义,通过将dataVolume添加致dataVolumeTemplates列表中实现,简单示例如下:apiVersion: kubevirt.io/v1 kind: VirtualMachine metadata: labels: kubevirt.io/vm: vm-alpine-datavolume name: vm-alpine-datavolume spec: running: false template: metadata: labels: kubevirt.io/vm: vm-alpine-datavolume spec: domain: devices: disks: - disk: bus: virtio name: datavolumedisk1 resources: requests: memory: 64M volumes: - dataVolume: name: alpine-dv name: datavolumedisk1 dataVolumeTemplates: - metadata: name: alpine-dv spec: pvc: accessModes: - ReadWriteOnce resources: requests: storage: 2Gi source: http: url: http://cdi-http-import-server.kubevirt/images/alpine.isodataVolumeTemplates部分定义了两部分内容:pvc和source。pvc部分则声明了应用于创建承载源数据的PVC的规格;source部分声明了存在一个位于HTTP服务器上的磁盘镜像。 当这份虚拟机配置文件提交到集群时,在启动流程中,会根据提供的规格自动创建一个PVC,并在虚拟机启动前将源数据自动导入到该PVC中。当虚拟机被删除时,由DataVolume配置的存储也会随之自动删除。
另外,dataVolume是由Containerized Data Importer(CDI)项目提供的一个自定义资源。Kubevirt与CDI进行了整合,目的是为用户提供一种能够动态创建PVC并在PVC中导入数据的工作流程。
为了在虚拟机(VM)或虚拟机实例(VMI)上利用DataVolume卷源,必须先安装CDI。
- ephemeral(临时卷)
临时卷是一种本地的COW(Copy-On-Write)镜像,它使用网络卷作为只读底层存储。在使用临时卷时,网络底层存储永远不会被修改。 相反,所有的写入操作都会存储在位于本地存储上的临时镜像上。当虚拟机(VM)启动时,KubeVirt会动态生成与其关联的临时镜像,并在虚拟机停止时丢弃这些临时镜像。 临时卷在无需硬盘持久化的场景中特别有用。当虚拟机达到最终状态(例如成功结束或失败)时,COW镜像会被丢弃。 当前,仅支持使用PVC作为临时卷的底层存储。 临时卷适合那些生命周期短暂且不需要持久化磁盘状态的虚拟机实例。这种情况下,网络底层存储作为只读源,而所有更改都在本地的临时COW镜像上发生,从而实现高效的资源利用和安全的数据管理。
- containerDisk(容器磁盘)
containerDisk曾被称为registryDisk。containerDisk功能提供了将虚拟机磁盘存储和分发在容器镜像仓库中的能力。containerDisks可以在VirtualMachineInstance规范的disks部分分配给虚拟机。containerDisks并不会使用网络共享存储设备。这些磁盘是从容器镜像仓库中拉取,并驻留托管在虚拟机所在节点的本地存储上。
何时使用 containerDisk?
当需要将临时存储设备分配给任意数量活跃的VirtualMachineInstances时,应使用containerDisk。
这使得它们成为理想工具,适用于希望复制大量不需要持久化数据的虚拟机工作负载的用户。containerDisks常常与VirtualMachineInstanceReplicaSets结合使用。
何时不应使用 containerDisk?
对于任何需要在虚拟机重启间持久化根磁盘的工作负载,containerDisks 并不是一个好的解决方案。
containerDisk 工作流示例
用户可以将 VirtualMachineInstance 磁盘以 KubeVirt 运行时可消耗的方式注入到容器镜像中。磁盘必须放置在容器内的/disk 目录下。
支持 Raw 和 qcow2 格式,推荐使用 qcow2 以减小容器镜像的大小。containerdisks 应该且可以基于scratch构建,除了镜像外,不需要任何其他内容。
注意:在 kubevirt 0.20 版本之前,containerDisk镜像需要以kubevirt/container-disk-v1alpha为基础镜像;containerDisk必须对用户 UID 为 107(qemu)的用户可读。
容器磁盘制作示例:
## 示例1
cat << END > Dockerfile
FROM scratch
ADD --chown=107:107 fedora25.qcow2 /disk/
END
docker build -t vmidisks/fedora25:latest .
cat << END > Dockerfile
FROM scratch
ADD --chown=107:107 https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2 /disk/
END
docker build -t vmidisks/centos7:latest .
- emptyDisk(空磁盘)
emptyDisk与k8s中的emptyDir类似,它会为虚拟机分配一个指定大小的qcow2格式的磁盘,该磁盘文件是稀疏的,这意味着仅在写入数据时才会实际占用存储空间,并且该磁盘是临时的,随着虚拟机的关闭数据会丢失。 但如果是在虚拟机内部执行重启reboot操作,数据不丢失。
何时使用 emptyDdisk?
当虚拟机需要一个临时磁盘来存放临时文件、日志等数据,这些数据需要在每次虚拟机关闭时自动被删除,可以使用emptyDisk。
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-cirros01-bootdisk
namespace: default
spec:
storageClassName: "ceph-hdd-block"
volumeMode: Block
accessModes:
- ReadWriteMany
dataSource:
kind: PersistentVolumeClaim
name: img-cirros
resources:
requests:
storage: 1Gi
---
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: vm-cirros01
spec:
instancetype:
kind: VirtualMachineInstancetype
name: p1-1
running: true
template:
metadata:
labels:
kubevirt.io/domain: vm-cirros01
spec:
architecture: amd64
domain:
devices:
disks:
- disk:
bus: virtio
name: root-disk
- disk:
bus: virtio
name: emptydisk
rng: {}
interfaces:
- name: default
masquerade: {}
networks:
- name: default
pod: {}
terminationGracePeriodSeconds: 0
volumes:
- name: root-disk
persistentVolumeClaim:
claimName: pvc-cirros01-bootdisk
- name: emptydisk
emptyDisk:
capacity: 2Gi
进入虚拟机查看,发现有一块2GB的vdb磁盘,格式化挂载并写入数据
注意 创建的# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 252:0 0 1G 0 disk |-vda1 252:1 0 1015M 0 part / `-vda15 252:15 0 8M 0 part vdb 252:16 0 2G 0 disk # mkfs.ext4 /dev/vdb mke2fs 1.44.5 (15-Dec-2018) Discarding device blocks: done Creating filesystem with 524288 4k blocks and 131072 inodes Filesystem UUID: b60be2d9-912a-4efd-95d1-7d70dfc4b223 Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912 Allocating group tables: done Writing inode tables: done Creating journal (16384 blocks): done Writing superblocks and filesystem accounting information: done # mount /dev/vdb /mnt ## 验证在虚拟机内部重启虚拟机,数据不丢失 # echo "hello" > /mnt/hello.txt # rebootemptydisk.qcow2文件位于/var/lib/kubelet/pods/<pod-id>/volumes/kubernetes.io~empty-dir/libvirt-runtime/empty-disks目录下`
- hostDisk(宿主机磁盘)
hostDisk卷类型提供了在宿主机节点上的某个位置创建或使用磁盘镜像的能力。其工作方式类似于k8s中的hostPath。相比emptyDisk,hostDisk允许持久化磁盘数据。使用
hostDisk需要先在kubevirt的featureGates中开启特性门控HostDiskhostDisk有两种使用类型: - DiskOrCreate:如果在指定的宿主机路径下没有找到磁盘镜像文件,会自动创建一个新的磁盘镜像文件;
- Disk:这种方式要求在指定的宿主机路径下已经存在一个磁盘镜像文件。以下给出具体示例:
手工创建
--- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-hostdisk01-bootdisk namespace: default spec: storageClassName: "ceph-hdd-block" volumeMode: Block accessModes: - ReadWriteMany dataSource: kind: PersistentVolumeClaim name: img-cirros resources: requests: storage: 1Gi --- apiVersion: kubevirt.io/v1 kind: VirtualMachine metadata: name: vm-hostdisk01 spec: instancetype: kind: VirtualMachineInstancetype name: p1-1 running: true template: metadata: labels: kubevirt.io/domain: vm-hostdisk01 spec: #nodeSelector: # kubernetes.io/hostname: k8s04 architecture: amd64 domain: devices: disks: - disk: bus: virtio name: root-disk - disk: bus: virtio name: host-disk rng: {} interfaces: - name: default masquerade: {} networks: - name: default pod: {} terminationGracePeriodSeconds: 0 volumes: - name: root-disk persistentVolumeClaim: claimName: pvc-hostdisk01-bootdisk - name: host-disk hostDisk: # 仅在type为DiskOrCreate时,需要指定容量,如果为Disk,则不需要指定容量,因为在要先创建,创建时就指定了容量 #capacity: 2Gi # 会在目标宿主机节点的指定路径下创建一个磁盘镜像文件 path: /var/lib/libvirt/images/hostdisk01-data.img #type: DiskOrCreate # 如果type: Disk,则需要事先在目标宿主机节点上创建一个磁盘镜像文件 type: Diskqcow2格式的磁盘文件注意 如果使用# qemu-img create -f qcow2 /var/lib/libvirt/images/hostdisk01-data.img 2G Formatting '/var/lib/libvirt/images/hostdisk01-data.img', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2147483648 lazy_refcounts=off refcount_bits=16 cache=writebackhostDisk,建议在VM定义中指定节点选择器(可以在"实例规格"中定义节点选择),以保证虚拟机始终运行在指定的节点上。虚拟机被删除时,对应宿主机节点上的磁盘文件不会被删除。
- configMap(配置映射)
configMap可以以磁盘形式或文件系统形式呈现给虚拟机。每种方法都有优缺点,例如:磁盘方式不支持动态变更传播;而文件系统方式则不支持实时迁移。 当configMap以磁盘形式呈现给虚拟机时,将会分配一个额外的ISO格式的磁盘,该磁盘需要在虚拟机(VM)上挂载。为了自动挂载configMap,可以利用cloudInit挂载。需要注意的是configMap的更新并不会传播到VMI中。当
configMap以文件系统形式呈现给虚拟机时,configMap是通过virtiofs进行共享,与通过磁盘方式共享configMap相比,使用文件系统方式允许将configMap上的动态变更实时传播到VMI(即虚拟机实例无需重启即可获取更改)。但使用了virtiofs后VM就不支持实时迁移了。
示例,以磁盘形式
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-cm01-bootdisk
namespace: default
spec:
storageClassName: "ceph-hdd-block"
volumeMode: Block
accessModes:
- ReadWriteMany
dataSource:
kind: PersistentVolumeClaim
name: img-cirros
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: ConfigMap
metadata:
name: cm01-config
namespace: default
data:
test.conf: |
testcm01
testcm02
---
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: vm-cm01
spec:
instancetype:
kind: VirtualMachineInstancetype
name: p1-1
running: true
template:
metadata:
labels:
kubevirt.io/domain: vm-cm01
spec:
#nodeSelector:
# kubernetes.io/hostname: k8s04
architecture: amd64
domain:
devices:
disks:
- disk:
bus: virtio
name: root-disk
- disk:
bus: virtio
name: cm01-disk
serial: "CM01"
rng: {}
interfaces:
- name: default
masquerade: {}
networks:
- name: default
pod: {}
terminationGracePeriodSeconds: 0
volumes:
- name: root-disk
persistentVolumeClaim:
claimName: pvc-cm01-bootdisk
- name: cm01-disk
configMap:
name: cm01-config
进入虚拟机查看,发现有一块vdb磁盘,不需要格式化,直接挂载。 注意 挂载的
configMap是只读的,不能写入。示例,以# mount /dev/vdb /mnt/ # cd /mnt/ # ls test.conf ## 不能往test.conf中写入文件,并且修改configMap cm01-config 不会传播到虚拟机中 # cat test.conf testcm01 testcm02virtiofs格式,注意,不能再使用cirros镜像,不支持virtiofs。注意 修改cm02-config 不会马上传播到虚拟机中,因为cm刷新到pod需要一定时间。kubelet通过apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-cm02-bootdisk namespace: default spec: storageClassName: "ceph-hdd-block" volumeMode: Block accessModes: - ReadWriteMany dataSource: kind: PersistentVolumeClaim # 不能用cirros镜像,因为不支持 virtiofs name: img-ubuntu2204 resources: requests: storage: 10Gi --- apiVersion: v1 kind: ConfigMap metadata: name: cm02-config namespace: default data: test.conf: | testcm01 testcm02 --- apiVersion: kubevirt.io/v1 kind: VirtualMachine metadata: name: vm-cm02 spec: instancetype: kind: VirtualMachineInstancetype name: p1-1 running: true template: metadata: labels: kubevirt.io/domain: vm-cm02 spec: #nodeSelector: # kubernetes.io/hostname: k8s04 architecture: amd64 domain: devices: disks: - disk: bus: virtio name: root-disk - disk: bus: virtio name: cloudinitdisk filesystems: - name: cm02-fs virtiofs: {} rng: {} interfaces: - name: default masquerade: {} networks: - name: default pod: {} terminationGracePeriodSeconds: 0 volumes: - name: root-disk persistentVolumeClaim: claimName: pvc-cm02-bootdisk - name: cm02-fs configMap: name: cm02-config - name: cloudinitdisk cloudInitConfigDrive: userData: |- #cloud-config hostname: vm-cm02 ssh_pwauth: True disable_root: False timezone: Asia/Shanghai password: 123456 chpasswd: {"list":"root:12345678",expire: False} bootcmd: - setenforce 0 - sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config - mount -t virtiofs cm02-fs /mnt runcmd: - sed -i "/PermitRootLogin/s/^.*$/PermitRootLogin yes/g" /etc/ssh/sshd_config - systemctl restart sshd.service #- echo root:12345678 |chpasswd--sync-frequency控制同步配置的时间间隔,默认是1min,所以更新configMap后,在容器中真正看到变化,需要0-1min之后。该值改得太小会导致kubelet占用过多资源,影响性能。 可通过修改:/var/lib/kubelet/config.yaml中的syncFrequency字段的值来并重启kubelet生效。 例如:syncFrequency: 10s
- secret(秘钥)
secret可以以磁盘形式或文件系统形式呈现给虚拟机。每种方法都有优缺点,例如:磁盘方式不支持动态变更传播;而文件系统方式则不支持实时迁移。 当secret以磁盘形式呈现给虚拟机时,将会分配一个额外的ISO格式的磁盘,该磁盘需要在虚拟机(VM)上挂载。为了自动挂载secret,可以利用cloudInit挂载。需要注意的是secret的更新并不会传播到VMI中。当
secret以文件系统形式呈现给虚拟机时,secret是通过virtiofs进行共享,与通过磁盘方式共享secret相比,使用文件系统方式允许将secret上的动态变更实时传播到VMI(即虚拟机实例无需重启即可获取更改)。但使用了virtiofs后VM就不支持实时迁移了。具体示例可参考
configMap,需要将configMap改成secret示例,以virtiofs格式,注意,不能再使用cirros镜像,不支持virtiofs。注意 同样,通过--- apiVersion: v1 kind: Secret data: secret-file: YWRtaW4K # admin base64后的值 metadata: name: secret02-config namespace: default type: Opaque --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-secret02-bootdisk namespace: default spec: storageClassName: "ceph-hdd-block" volumeMode: Block accessModes: - ReadWriteMany dataSource: kind: PersistentVolumeClaim # 不能用cirros镜像,因为不支持 virtiofs name: img-ubuntu2204 resources: requests: storage: 10Gi --- apiVersion: kubevirt.io/v1 kind: VirtualMachine metadata: name: vm-secret02 spec: instancetype: kind: VirtualMachineInstancetype name: p1-1 running: true template: metadata: labels: kubevirt.io/domain: vm-secret02 spec: #nodeSelector: # kubernetes.io/hostname: k8s04 architecture: amd64 domain: devices: disks: - disk: bus: virtio name: root-disk - disk: bus: virtio name: cloudinitdisk filesystems: - name: secret02-fs virtiofs: {} rng: {} interfaces: - name: default masquerade: {} networks: - name: default pod: {} terminationGracePeriodSeconds: 0 volumes: - name: root-disk persistentVolumeClaim: claimName: pvc-secret02-bootdisk - name: secret02-fs secret: secretName: secret02-config - name: cloudinitdisk cloudInitConfigDrive: userData: |- #cloud-config hostname: vm-secret02 ssh_pwauth: True disable_root: False timezone: Asia/Shanghai password: 123456 chpasswd: {"list":"root:12345678",expire: False} bootcmd: - setenforce 0 - sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config - mount -t virtiofs secret02-fs /mnt runcmd: - sed -i "/PermitRootLogin/s/^.*$/PermitRootLogin yes/g" /etc/ssh/sshd_config - systemctl restart sshd.service #- echo root:12345678 |chpasswdkubectl edit secret secret02-config修改secret不会马上传播到虚拟机中,因为secret刷新到pod需要一定时间。kubelet通过--sync-frequency控制同步配置的时间间隔,默认是1min,所以更新secret后,在容器中真正看到变化,需要0-1min之后。该值改得太小会导致kubelet占用过多资源,影响性能。 可通过修改:/var/lib/kubelet/config.yaml中的syncFrequency字段的值来并重启kubelet生效。 例如:syncFrequency: 10s
- serviceAccount(服务账户)
serviceAccount也可以以磁盘形式或文件系统形式呈现给虚拟机。每种方法都有优缺点,例如:磁盘方式不支持动态变更传播;而文件系统方式则不支持实时迁移。 当serviceAccount以磁盘形式呈现给虚拟机时,将会分配一个额外的ISO格式的磁盘,该磁盘需要在虚拟机(VM)上挂载。为了自动挂载serviceAccount,可以利用cloudInit挂载。需要注意的是serviceAccount的更新并不会传播到VMI中。当
serviceAccount以文件系统形式呈现给虚拟机时,serviceAccount是通过virtiofs进行共享,与通过磁盘方式共享serviceAccount相比,使用文件系统方式允许将serviceAccount上的动态变更实时传播到VMI(即虚拟机实例无需重启即可获取更改)。但使用了virtiofs后VM就不支持实时迁移了。
挂载
serviceAccount后,在挂载目录下会看到命名空间(namespace)、令牌(token)和 CA 证书(ca.crt)三个文件
具体示例可参考configMap,需要将configMap改成serviceAccount
示例,以virtiofs格式,注意,不能再使用cirros镜像,不支持virtiofs。
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: vm-acc02
# 默认会自动挂载API凭据
automountServiceAccountToken: true
---
# 手动为ServiceAccount创建长期有效的 API 令牌
apiVersion: v1
kind: Secret
metadata:
name: build-robot-secret
annotations:
kubernetes.io/service-account.name: vm-acc02
type: kubernetes.io/service-account-token
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-acc02-bootdisk
namespace: default
spec:
storageClassName: "ceph-hdd-block"
volumeMode: Block
accessModes:
- ReadWriteMany
dataSource:
kind: PersistentVolumeClaim
# 不能用cirros镜像,因为不支持 virtiofs
name: img-ubuntu2204
resources:
requests:
storage: 10Gi
---
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: vm-acc02
spec:
instancetype:
kind: VirtualMachineInstancetype
name: p1-1
running: true
template:
metadata:
labels:
kubevirt.io/domain: vm-acc02
spec:
#nodeSelector:
# kubernetes.io/hostname: k8s04
architecture: amd64
domain:
devices:
disks:
- disk:
bus: virtio
name: root-disk
- disk:
bus: virtio
name: cloudinitdisk
filesystems:
- name: serviceaccount-fs
virtiofs: {}
rng: {}
interfaces:
- name: default
masquerade: {}
networks:
- name: default
pod: {}
terminationGracePeriodSeconds: 0
volumes:
- name: root-disk
persistentVolumeClaim:
claimName: pvc-acc02-bootdisk
- name: serviceaccount-fs
serviceAccount:
serviceAccountName: vm-acc02
- name: cloudinitdisk
cloudInitConfigDrive:
userData: |-
#cloud-config
hostname: vm-acc02
ssh_pwauth: True
disable_root: False
timezone: Asia/Shanghai
password: 123456
chpasswd: {"list":"root:12345678",expire: False}
bootcmd:
- setenforce 0
- sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config
- mount -t virtiofs serviceaccount-fs /mnt
runcmd:
- sed -i "/PermitRootLogin/s/^.*$/PermitRootLogin yes/g" /etc/ssh/sshd_config
- systemctl restart sshd.service
#- echo root:12345678 |chpasswd
> 进入虚拟机查看,发现/mnt下有ca.crt、namespace、token文件
# ls -l /mnt/
total 0
lrwxrwxrwx 1 root root 13 Feb 24 15:00 ca.crt -> ..data/ca.crt
lrwxrwxrwx 1 root root 16 Feb 24 15:00 namespace -> ..data/namespace
lrwxrwxrwx 1 root root 12 Feb 24 15:00 token -> ..data/token
downwardMetrics允许将有限的虚拟机和主机指标暴露给虚拟机访问,其格式与vhostmd 兼容。 在某些情况下,允许虚拟机内的应用程序访问由宿主机收集的虚拟机和宿主机性能指标数据,这对于第三方诊断其应用设备上的性能问题是必要的。为了实现虚拟机访问
downwardMetrics的指标数据,KubeVirt 支持两种传输途径:一种是通过创建一个带有相关指标数据的disk磁盘文件;另一种是通过virtio-serial端口进行传输。当配置为
disk类型时,kubeVirt会为虚拟机创建并提供一个原始块存储设备,这个卷的内容可以是持久化存储或其他类型的数据源,并且kubeVirt会按照默认设定每隔5秒周期性地检查并更新这个卷的状态, 确保虚拟机与其关联的存储卷之间数据的一致性和实时性。这意味着虚拟机可以直接读取和写入这个卷,就像操作一个真实的硬件磁盘一样。当配置为
virtio-serial port类型时,kubeVirt在虚拟机内部创建一个名为/dev/virtio-ports/org.github.vhostmd.1的端口,该端口支持virtio传输协议。 可以通过这个端口获取downwardMetrics数据。另外,若要采用virtio-serial port方式对外提供downwardMetrics,需要在VM的domain设备部分显式声明一个downwardMetrics设备条目。 这样,kubeVirt将会自动将相应的指标数据通过virtio-serial port传递给虚拟机内部,便于虚拟机内部应用或服务能够访问和使用这些性能监控指标。使用
downwardMetrics需要先在kubevirt的featureGates中开启特性门控DownwardMetrics示例,以
disk磁盘文件方式--- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-dm01-bootdisk namespace: default spec: storageClassName: "ceph-hdd-block" volumeMode: Block accessModes: - ReadWriteMany dataSource: kind: PersistentVolumeClaim name: img-ubuntu2204 resources: requests: storage: 10Gi --- apiVersion: kubevirt.io/v1 kind: VirtualMachine metadata: name: vm-dm01 spec: instancetype: kind: VirtualMachineInstancetype name: p1-1 running: true template: metadata: labels: kubevirt.io/domain: vm-dm01 spec: #nodeSelector: # kubernetes.io/hostname: k8s04 architecture: amd64 domain: devices: disks: - disk: bus: virtio name: root-disk - disk: bus: virtio name: cloudinitdisk - disk: bus: virtio name: downwardmetrics rng: {} interfaces: - name: default masquerade: {} networks: - name: default pod: {} terminationGracePeriodSeconds: 0 volumes: - name: root-disk persistentVolumeClaim: claimName: pvc-dm01-bootdisk - name: downwardmetrics downwardMetrics: {} - name: cloudinitdisk cloudInitConfigDrive: userData: |- #cloud-config hostname: vm-dm01 ssh_pwauth: True disable_root: False timezone: Asia/Shanghai password: 123456 chpasswd: {"list":"root:12345678",expire: False} bootcmd: - setenforce 0 - sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config runcmd: - sed -i "/PermitRootLogin/s/^.*$/PermitRootLogin yes/g" /etc/ssh/sshd_config - systemctl restart sshd.service #- echo root:12345678 |chpasswd
示例,以Virtio-serial port方式(推荐)
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-dm02-bootdisk
namespace: default
spec:
storageClassName: "ceph-hdd-block"
volumeMode: Block
accessModes:
- ReadWriteMany
dataSource:
kind: PersistentVolumeClaim
name: img-ubuntu2204
resources:
requests:
storage: 10Gi
---
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: vm-dm02
spec:
instancetype:
kind: VirtualMachineInstancetype
name: p1-1
running: true
template:
metadata:
labels:
kubevirt.io/domain: vm-dm02
spec:
#nodeSelector:
# kubernetes.io/hostname: k8s04
architecture: amd64
domain:
devices:
# 暴露指标数据
downwardMetrics: {}
disks:
- disk:
bus: virtio
name: root-disk
- disk:
bus: virtio
name: cloudinitdisk
rng: {}
interfaces:
- name: default
masquerade: {}
networks:
- name: default
pod: {}
terminationGracePeriodSeconds: 0
volumes:
- name: root-disk
persistentVolumeClaim:
claimName: pvc-dm02-bootdisk
- name: cloudinitdisk
cloudInitConfigDrive:
userData: |-
#cloud-config
hostname: vm-dm02
ssh_pwauth: True
disable_root: False
timezone: Asia/Shanghai
password: 123456
chpasswd: {"list":"root:12345678",expire: False}
bootcmd:
- setenforce 0
- sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config
runcmd:
- sed -i "/PermitRootLogin/s/^.*$/PermitRootLogin yes/g" /etc/ssh/sshd_config
- systemctl restart sshd.service
#- echo root:12345678 |chpasswd
进入虚拟机,在/dev/vdc中个原始存储盘中查看到有类似如下指标数据
## 这里直接用cat命令查看了,可以在虚拟机中安装`vhostmd`,安装方式参照 https://github.com/vhostmd/vhostmd,安装成功后会生成`vm_dump_metrics`命令,也可以通过`vhostmd`命令查看指标数据
# cat /dev/vdc
mvbd <metrics>
<metric type="string" context="host">
<name>HostName</name>
<value>k8s04</value>
</metric>
<metric type="string" context="host">
<name>HostSystemInfo</name>
<value>linux</value>
</metric>
<metric type="string" context="host">
<name>VirtualizationVendor</name>
<value>kubevirt.io</value>
</metric>
<metric type="string" context="host">
<name>VirtProductInfo</name>
<value>QEMU 8.0.0</value>
</metric>
<metric type="real64" context="vm" unit="s">
<name>TotalCPUTime</name>
<value>96.370000</value>
</metric>
...
vm-dump-metrics
# wget https://github.com/vhostmd/vhostmd/archive/refs/tags/v1.1.zip
# apt -y install make unzip libtool pkg-config libxml2-dev libvirt-daemon libvirt-daemon-system libvirt-dev
# cd vhostmd-1.1
# sh autogen.sh
# ./configure --prefix=/usr --libdir=/usr/lib64 --disable-shared
# make
# make install
## 直接执行命令
# vm-dump-metrics
<metrics>
<metric type="string" context="host">
<name>HostName</name>
<value>k8s04</value>
</metric>
<metric type="string" context="host">
<name>HostSystemInfo</name>
<value>linux</value>
</metric>
<metric type="string" context="host">
<name>VirtualizationVendor</name>
<value>kubevirt.io</value>
</metric>
<metric type="string" context="host">
<name>VirtProductInfo</name>
<value>QEMU 8.0.0</value>
</metric>
<metric type="real64" context="vm" unit="s">
<name>TotalCPUTime</name>
<value>342.840000</value>
</metric>
<metric type="uint64" context="vm">
<name>ResourceProcessorLimit</name>
<value>1</value>
</metric>
<metric type="uint64" context="vm" unit="KiB">
<name>PhysicalMemoryAllocatedToVirtualSystem</name>
<value>1048576</value>
</metric>
<metric type="uint64" context="vm" unit="KiB">
<name>ResourceMemoryLimit</name>
<value>1048576</value>
</metric>
<metric type="int64" context="host">
<name>NumberOfPhysicalCPUs</name>
<value>1</value>
</metric>
<metric type="real64" context="host" unit="s">
<name>TotalCPUTime</name>
<value>2514.730000</value>
</metric>
<metric type="uint64" context="host" unit="KiB">
<name>FreePhysicalMemory</name>
<value>6735648</value>
</metric>
<metric type="uint64" context="host" unit="KiB">
<name>FreeVirtualMemory</name>
<value>6735648</value>
</metric>
<metric type="uint64" context="host" unit="KiB">
<name>MemoryAllocatedToVirtualServers</name>
<value>2968996</value>
</metric>
<metric type="uint64" context="host" unit="KiB">
<name>UsedVirtualMemory</name>
<value>2968996</value>
</metric>
<metric type="uint64" context="host" unit="KiB">
<name>PagedInMemory</name>
<value>0</value>
</metric>
<metric type="uint64" context="host" unit="KiB">
<name>PagedOutMemory</name>
<value>0</value>
</metric>
<metric type="int64" context="host" unit="s">
<name>Time</name>
<value>1708766512</value>
</metric>
</metrics>
Virtio-serial port方式,可以用命令vm-dump-metrics --virtio查看指标数据
如果是centos或者openeuler,可以直接用yum install vm-dump-metrics 进行安装。