虚拟化简介
在云计算发展中,有两类虚拟化平台:
- openstack(iaas):关注于资源的利用,虚拟机的计算,网络和存储
- Kubernetes(pass):关注容器的编排调度,自动化部署,发布管理
Hypervisor(VMM)虚拟机监视器的分类
1、 Type-1,native or bare-metal hypervisors :硬件虚拟化
这些Hypervisor是直接安装并运行在宿主机上的硬件之上的,Hypervisor运行在硬件之上来控制和管理硬件资源。
比如:
- Microsoft Hyper-V
- VMware ESXI
- KVM
2、 Typer-2 or hosted hypervisors :
这些Hypervisor直接作为一种计算机程序运行在宿主机上的操作系统之上的。
- QEMU
- VirtualBox
- VMware Player
- VMware WorkStation
3、虚拟化主要就是虚拟CPU,MEM(内存),I/Odevices
其中Intel VT-x/AMD-X实现的是COU虚拟化
Intel EPT/AMD-NPT实现MEM的虚拟化
4、Qemu-Kvm的结合:
KVM只能进行CPU,MEM,的虚拟化,QEMU能进行硬件,比如:声卡,USE接口,…的虚拟化,因此通常将QEMU,KVM结合共同虚拟:QEMU-KVM。
Libvirt
是一个虚拟化管理平台的软件集合。它提供统一的API,守护进程libvirtd和一个默认命令行管理工具:virsh。
其实我们也可以使用kvm-qemu命令行的管理工具,但是其参数过多,不便使用。
所以我们通常使用libvirt的解决方案,来对虚拟换进行管理。
libvirt是Hypertvisor的管理方案,就是管理Hypervisor的。
我们通过libvirt命令行工具,来调动Hypervisor,从而使Hypervisor管理虚拟机。
KubeVirt介绍
参考文档:https://github.com/kubevirt/kubevirt
官方文档:https://kubernetes.io/blog/2018/05/22/getting-to-know-kubevirt/
有关卷和磁盘的介绍:http://kubevirt.io/user-guide/virtual_machines/disks_and_volumes/
KubeVirt是Red-Hat开源的,以容器方式运行的虚拟机项目。是基于Kubernetes运行的,具体的来说是基于Kubernetes的CRD(自定义资源)增加虚拟机的运行和管理相关的资源。特别是VM,VMI资源类型。也是说我们通过CRD进行增加关于虚拟机的资源类型,然后通过写YAML的形式来创建虚拟机等一系列的操作。
主要有两种资源类型:VM,VMI
- VM资源: 为群集内的
VirtualMachineInstance
提供管理功能,例如开机/关机/重启虚拟机,确保虚拟机实例的启动状态,与虚拟机实例是 1:1 的关系,类似与spec.replica
为 1 的 StatefulSet。 - VMI( VirtualMachineInstance )资源: 类似于 kubernetes Pod,是管理虚拟机的最小资源。一个
VirtualMachineInstance
对象即表示一台正在运行的虚拟机实例,包含一个虚拟机所需要的各种配置。
通过以上资源,可以在Kubernetes上管理虚拟机。
Kubevirt的架构
先看架构图:
KubeVirt以CRD的形式将VM管理接口接入到Kubernetes中,通过一个Pod去使用libvirt管理VM一样,实现Pod于VM的一一对应,就是说一个Pod中可以即可以运行VM同时也可以运行容器。做到如同容器般去管理虚拟机,并且做到与容器一样的资源管理,调度规划。
不同的是,普通Pod就叫做Pod,而包含VM的Pod就做virt-launcher Pod。
下面来介绍Master节点的组件:
- virt-api:KubeVirt是以CRD形式去管理virt-launcher Pod。virt-api就是所有管理虚拟机操作的入口,它只接收指令,比如:CRD更新,删除,增加,以及对虚拟机的start,stop,delete,console等等
- virt-controller: 管理和监控 VMI 对象及其关联的 Pod,对其状态进行更新。 virt-controller会根据你编写的VM资源清单 ,创建对应的VMI,然后在创建对应的virt-launcher Pod。并且和kuberneters的api-server通信,来监控和维护VMI资源的创建删除等。
下面来介绍node节点的组件:
- virt-handler:这个组件是以Pod的方式启动的,并且注意它是个DaemonSet的Pod,也就是守护进程是的Pod,那这就意味着,他需要守护进程的方式部署在每一个Node上,负责监控和操作节点上每个虚拟机实例。一旦检测到状态虚拟机实例变化,会进行响应并且确保响应的操作能够达到VMI CRD中你期望的状态。
- virt-launcher:每一个virt-launcher Pod对应这一个VMI。Kubernetes只负责virt-launcher Pod的运行状态,不会关心VMI创建的情况,所以virt-handler会根据创建资源清单的参数配置,去通知virt-launcher去使用本地的libvirtd来管理虚拟机的生命周期。 随着Pod的生命周期结束,virt-lanuncher也会去通知VMI去执行终止操作。
- virtctl:virtctl是kubevirt自带的命令行工具,和kubectl的性质一样,但不同于kubectl的是,virtctl和virt-api进行交互,从而进行虚拟机的删除,创建,更新等操作。
VM(虚拟机)的启动流程
参考文档:https://github.com/kubevirt/kubevirt
虚拟机相关资源简介
- virtualmachines(VM):为群集内的VirtualMachineInstance提供管理功能,例如开机/关机/重启虚拟机,确保虚拟机实例的启动状态。
- virtualmachineinstances (VMI) :类似于Kubernetes Pod,是管理虚拟机的最小资源。一个VirtualMachineInstance对象即表示台正在运行的虚拟机实例, 包含一个虚拟机所需要的各种配置。
- VirtualMachineInstanceReplicaSet:类似Kubernetes的ReplicaSet, 可以启动指定数量的VirtualMachineInstance,并且保证指定数量的VirtualMachineInstance运行,可以配置HPA。
- VirtualMachineInstanceMigrations:提供虚拟机迁移的能力。
虚拟机镜像,磁盘,卷
有关卷和磁盘的介绍:http://kubevirt.io/user-guide/virtual_machines/disks_and_volumes/
创建虚拟机镜像肯定是必须的,那既然需要镜像,就需要由存储来存放镜像。
在KubeVirt中有个子项目:CDI。
CDI是Kubernetes持久化存储管理的插件,CDI项目提供了用于使PVC作为KubeVirt VM磁盘的功能。
在spec.volumes下可以指定多种类型的卷:
- cloudInitNoCloud: Cloud-init相关的配置, 用于修改或者初始化虚拟机中的配置信息
- containerDisk:指定一个包含 qcow2或raw格式的docker镜像,重启vm数据会丢失
- dataVolume:动态创建一个PVC,并用指定的磁盘映像填充该PVC,重启vm数据不会丢失
- emptyDisk:从宿主机上分配固定容量的空间,映射到vm中的一块磁盘,emptyDisk 的生命周期与vm等同,重启mv数据会丢失
- ephemeral:在虚机启动时创建一一个临时卷,虚机关闭后自动销毁,临时卷在不需要磁盘持久性的任何情况下都很有用。
- hostDisk:在宿主机上创建一一个img镜像文件,挂给虚拟机使用。重启vm数据不会丢失。
- persistentVolumeClaim:指定一个PVC创建一个块设备。 重启vm数据不会丢失。
KubeVirt网络
前置环境
需要Kubernetes平台
可采用KubeKey部署
安装(v0.48.1)
官网地址:https://github.com/kubevirt/kubevirt
准备工作
1、先安装libvirt和qemu软件包
[root@master ~]# yum install -y qemu-kvm libvirt virt-install bridge-utils
2、查看节点是否支持kvm硬件虚拟化
[root@master ~]# virt-host-validate qemu
#以下就是虚拟化失败的情况
QEMU: Checking for hardware virtualization : FAIL (Only emulated CPUs are available, performance will be significantly limited)
QEMU: Checking if device /dev/vhost-net exists : PASS
QEMU: Checking if device /dev/net/tun exists : PASS
QEMU: Checking for cgroup 'memory' controller support : PASS
QEMU: Checking for cgroup 'memory' controller mount-point : PASS
QEMU: Checking for cgroup 'cpu' controller support : PASS
QEMU: Checking for cgroup 'cpu' controller mount-point : PASS
QEMU: Checking for cgroup 'cpuacct' controller support : PASS
QEMU: Checking for cgroup 'cpuacct' controller mount-point : PASS
QEMU: Checking for cgroup 'cpuset' controller support : PASS
QEMU: Checking for cgroup 'cpuset' controller mount-point : PASS
QEMU: Checking for cgroup 'devices' controller support : PASS
QEMU: Checking for cgroup 'devices' controller mount-point : PASS
QEMU: Checking for cgroup 'blkio' controller support : PASS
QEMU: Checking for cgroup 'blkio' controller mount-point : PASS
WARN (Unknown if this platform has IOMMU support)
3、如果不支持,则需要让kubevirt使用软件模拟虚拟化的配置:
kubectl create namespace kubevirt
kubectl create configmap -n kubevirt kubevirt-config \
--from-literal debug.useEmulation=true
安装KubeVirt
部署0.48.1版本
export VERSION=v0.48.1
kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-operator.yaml
kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-cr.yaml
检测结果:
[root@master ~]# kubectl get pods -n kubevirt
NAME READY STATUS RESTARTS AGE
virt-api-67699974c9-46h4p 1/1 Running 0 11m
virt-api-67699974c9-rxvzn 1/1 Running 0 11m
virt-controller-575dbb5b66-q2kps 1/1 Running 0 9m24s
virt-controller-575dbb5b66-xhv89 1/1 Running 0 9m24s
virt-handler-f9jlk 1/1 Running 0 9m24s
virt-handler-gtstv 1/1 Running 0 9m24s
virt-operator-574d595ffb-tlbcs 1/1 Running 0 12m
virt-operator-574d595ffb-w9s88 1/1 Running 0 12m
部署CDI(v1.47.1)
Containerized Data Importer
(CDI)项目提供了用于使 PVC 作为 KubeVirt VM 磁盘的功能。建议同时部署 CDI:
[root@master ~]# export VERSION=$(curl -s https://github.com/kubevirt/containerized-data-importer/releases/latest | grep -o "v[0-9]\.[0-9]*\.[0-9]*")
[root@controller ~]# kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-operator.yaml
[root@controller ~]# kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-cr.yaml
检测结果:
[root@master ~]# kubectl get pods -n cdi
NAME READY STATUS RESTARTS AGE
cdi-apiserver-67944db5c9-6bmpz 1/1 Running 0 2m53s
cdi-deployment-6fcc76f596-pfjqq 1/1 Running 0 2m45s
cdi-operator-5f57676b77-vq6rj 1/1 Running 0 5m39s
cdi-uploadproxy-66bd867c6f-5fl2r 1/1 Running 0 2m41s
安装virtctl客户端工具
KubeVirt提供了一个命令行工具:virtctl,我们直接下载使用。
[root@master ~]# wget https://github.com/kubevirt/kubevirt/releases/download/v0.48.1/virtctl-v0.48.1-linux-amd64
[root@master ~]# mv virtctl-v0.48.1-linux-amd64 /usr/local/bin/virtctl
[root@master ~]# chmod +x /usr/local/bin/virtctl
[root@master ~]# virtctl -h #help帮助命令
下载官方的vm.yaml文件(来生成官方的虚拟机)
1、下载官方VM.yaml文件。vm.yaml文件声明了,一个虚拟机所需要的所有配置,比如:网络,磁盘,镜像,…
[root@master ~]# wget https://kubevirt.io/labs/manifests/vm.yaml --no-check-certificate
#文件内容如下:
apiVersion: kubevirt.io/v1
kind: VirtualMachine #vm资源
metadata:
name: testvm
spec:
running: false #当此字段为"Running",开始创建vmi资源
template:
metadata:
labels:
kubevirt.io/size: small
kubevirt.io/domain: testvm
spec:
domain:
devices: #代表可以添加设备,比如:磁盘,网络...
disks: #硬盘设置。表示创建那种硬盘,这里表示有两块硬盘
- name: containerdisk
disk: #将卷作为磁盘连接到vmi(虚拟机实例)
bus: virtio #表示要模拟的磁盘设备的类型,比如有:sata,scsi,virtio
- name: cloudinitdisk
disk:
bus: virtio
interfaces: #选择定义的网络,下面的networks字段,就定义了一个"default"网络,这里就表示选择那个"default"网络
- name: default
masquerade: {} #开启masquerade,这个表示使用网络地址转换(NAT)来通过Linux网桥将虚拟机连接至Pod网络后端。
resources:
requests:
memory: 64M
networks: #网络的配置
- name: default #定义一个网络叫做"default",这里表示使用Kubernetes默认的CNI,也就是使用默认的网络
pod: {}
volumes:
- name: containerdisk
containerDisk:
image: quay.io/kubevirt/cirros-container-disk-demo #使用此镜像创建个虚拟机。
- name: cloudinitdisk
cloudInitNoCloud:
userDataBase64: SGkuXG4=
2、使用此模板文件创建虚拟机:
[root@master ~]# kubectl apply -f vm.yaml
virtualmachine.kubevirt.io/testvm created
#查看vm的状态,在上面的概念中也将到了,vm中的"running"字段默认是"false"的,我们需要用virtctl命令行去启动此vm,然后virt-controller就会把vm中的"running"字段由"false"改为"true",之后在创建vmi资源,创建虚拟机等操作。
[root@master ~]# kubectl get vm
NAME AGE STATUS READY
testvm 5s Stopped False
3、启动虚拟机,尽量开启虚拟化
#启动testvm这个虚拟机
[root@master ~]# virtctl start testvm
VM testvm was scheduled to start
#查看Pod,这个Pod里面就存放一个虚拟机
[root@master ~]# kubectl get pods
virt-launcher-testvm-c5gfc 2/2 Running 0 25s
#在查看vmi资源
[root@master ~]# kubectl get vmi
NAME AGE PHASE IP NODENAME READY
testvm 59s Running 10.244.1.26 node1 True
4、进入虚拟机控制台
virtctl console testvm
#Ctrl+]退出此虚拟机
Successfully connected to testvm console. The escape sequence is ^]
OK
GROWROOT: NOCHANGE: partition 1 is size 71647. it cannot be grown
/dev/root resized successfully [took 0.17s]
/run/cirros/datasource/data/user-data was not '#!' or executable
=== system information ===
Platform: KubeVirt None/RHEL-AV
Container: none
Arch: x86_64
CPU(s): 1 @ 2199.541 MHz
Cores/Sockets/Threads: 1/1/1
Virt-type: AMD-V
RAM Size: 43MB
Disks:
NAME MAJ:MIN SIZE LABEL MOUNTPOINT
vda 253:0 46137344
vda1 253:1 36683264 cirros-rootfs /
vda15 253:15 8388608
vdb 253:16 1048576 cidata
=== sshd host keys ===
-----BEGIN SSH HOST KEY KEYS-----
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCh4nXQS4nzbGRBMHw92aSBrSG1OPxbfp99vC2NHrYLtA6rMbi8sZ7H7Ys7A4RVC0vH1dcbVN/NFXRBfANXcD0rmr17HHX6nhXvFzWGBEEZEY2OYWErjxGAtAI/m+6OwOoYwYkHVIZTyAMejcN/JgW+yYqPAc8Md7zAfZ5c9xTqVnRASFxTpWwxGaf5p1pWq1RH2QHzKvEcbSqt0OIRyneqo25xn7we3rh2KcjCj16f4E0iL7qkum/ftv6bzgZ9mPKgRb2ja6W1LEek1GlHIwmvUuflL8Y6a4sk0RFTvyEUnNq8SdNBTqTUGZ9O8SSQx1bj733vr2WGLljDZkFB6Ver root@testvm
ssh-dss AAAAB3NzaC1kc3MAAACBAIlxV2kDXdGe3qapWXZ2qKoI3KCK9c6w80zSgfr0loLFwUaCWZax6NedlJDIXzoigjcgT0YWQT40aLxUrYQXlBUISnz8CkfKjfByzQK1WMP4OpZ0xjCWuuOdp0kqtGr76J8teq14RTRHdApUey0JHQCEkEU05AUqj3V3nmY8HcoRAAAAFQCmziUZA8vzBKHzc19KOpxnCsndUwAAAIBCPympZPf8EuY7miagP+vt6qFSW2Yv1X/xP0vTqd89BYCYmgoGHYKlU3B7gCq7EEF5kphzZ0CagjAPiHt50X3aL9vviqM9gJx721Dz+y5xvnicRs0OKfYMSDo7gg5bcsKM/BtKTR80gRq51IBWm+kO5NcIcCK75HIQX5cu5UK2DwAAAIBZPygbYSM7fetwf0qEvXInhbsvDtjFGXsHAh2M3n6DkbmDgTjwcnDBb2WPzkMzmnGz/mCsClMR/mZRjViZ7A5i3OKk2tpqBQbfP0drKPg4WaMuvtpkZ5drr8y6PHWlweekBmcuiK0mHlgRFCl0aoJ0KWXU0AH3llDxdZlVwl1U1Q== root@testvm
-----END SSH HOST KEY KEYS-----
=== network info ===
if-info: lo,up,127.0.0.1,8,,
if-info: eth0,up,10.0.2.2,24,fe80::5054:ff:feae:bce3/64,
ip-route:default via 10.0.2.1 dev eth0
ip-route:10.0.2.0/24 dev eth0 src 10.0.2.2
ip-route6:fe80::/64 dev eth0 metric 256
ip-route6:unreachable default dev lo metric -1 error -101
ip-route6:ff00::/8 dev eth0 metric 256
ip-route6:unreachable default dev lo metric -1 error -101
=== datasource: nocloud local ===
instance-id: testvm.default
name: N/A
availability-zone: N/A
local-hostname: testvm
launch-index: N/A
=== cirros: current=0.4.0 uptime=18.75 ===
____ ____ ____
/ __/ __ ____ ____ / __ \/ __/
/ /__ / // __// __// /_/ /\ \
\___//_//_/ /_/ \____/___/
http://cirros-cloud.net
login as 'cirros' user. default password: 'gocubsgo'. use 'sudo' for root.
#根据上面提供的用户/密码进行登录
testvm login:
Ctrl+]退出此虚拟机
5、相关命令
virtctl stop vm
virtctl start vm
virtctl restart vm
virtctl console vm
创建Win10操作系统的虚拟机
1、下载Win10镜像
下载地址:https://tb.rg-adguard.net/public.php
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D2Vd7Buo-1685428751730)(C:\Users\郑波\AppData\Roaming\Typora\typora-user-images\1650169936524.png)]
下载到Win在传至Linux,或者直接在Linux中:
wget https://tb.rg-adguard.net/dl.php?go=165b1d29
创建默认存储(StorageClass)
说明:由于等会我们需要上传镜像,需要使用PV,PVC,PVC它会给我们自动创建,但是PV,需要我们自己创建。
我们知道创建PV,PVC有两种方法,一个是静态,一个是动态。
静态就是:手动编写PV,PVC资源清单,然后在将他们进行绑定。
动态就是:我们创建一个存储类:StorageClass,然后我们只需要编写PVC的资源清单即可,它会给我们自动创建PV,然后和PVC进行绑定。
我们这里采用动态的方式:
1、部署NFS服务
# 在每个机器。
yum install -y nfs-utils
# 在master 执行以下命令
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
# 执行以下命令,启动 nfs 服务;创建共享目录
mkdir -p /nfs/data
# 在master执行
systemctl enable rpcbind
systemctl enable nfs-server
systemctl start rpcbind
systemctl start nfs-server
# 使配置生效
exportfs -r
#检查配置是否生效
exportfs
2、配置存储类
文件如下:
只需要修改两部分:就是把NFS服务端的IP修改为自己的即可。
## 创建了一个存储类
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storage
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
archiveOnDelete: "true" ## 删除pv的时候,pv的内容是否要备份
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/nfs-subdir-external-provisioner:v4.0.2
# resources:
# limits:
# cpu: 10m
# requests:
# cpu: 10m
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: k8s-sigs.io/nfs-subdir-external-provisioner
- name: NFS_SERVER
value: 172.31.0.4 ## 指定自己nfs服务器地址
- name: NFS_PATH
value: /nfs/data ## nfs服务器共享的目录
volumes:
- name: nfs-client-root
nfs:
server: 172.31.0.4
path: /nfs/data
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
3、应用,并查看StorageClass(sc)
kubectl apply -f sc.yaml
[root@master ~]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-storage (default) k8s-sigs.io/nfs-subdir-external-provisioner Delete Immediate false 11m
上传镜像
KubeVirt 可以使用 PVC 作为后端磁盘,使用 filesystem 类型的 PVC 时,默认使用的时 /disk.img 这个镜像,用户可以将镜像上传到 PVC,在创建 VMI 时使用此 PVC。使用这种方式需要注意下面几点:
一个 PVC 只允许存在一个镜像,只允许一个 VMI 使用,要创建多个 VMI,需要上传多次
/disk.img 的格式必须是 RAW 格式
CDI 提供了使用使用 PVC 作为虚拟机磁盘的方案,在虚拟机启动前通过下面方式填充 PVC:
通过 URL 导入虚拟机镜像到 PVC,URL 可以是 http 链接,s3 链接
Clone 一个已经存在的 PVC
通过 container registry 导入虚拟机磁盘到 PVC,需要结合 ContainerDisk 使用
通过客户端上传本地镜像到 PVC
通过命令行 virtctl,结合 CDI 项目,可以上传本地镜像到 PVC 上,支持的镜像格式有:
.img
.qcow2
.iso
压缩为 .tar,.gz,.xz 格式的上述镜像
我们的目标是安装 Windows 10 虚拟机,所以需要将上面下载好的 Windows 镜像上传到 PVC:
如下操作:
virtctl image-upload \
--image-path='Win10_20H2_Chinese(Simplified)_x64.iso' \
--pvc-name=iso-win10 \
--pvc-size=7G \
--uploadproxy-url=https://10.96.237.3 \
--insecure --wait-secs=240
#参数讲解:
--image-path='Win10_20H2_Chinese(Simplified)_x64.iso' #指定Win镜像的路径,我们是在/root目录下,因此就这个路径即可。
--pvc-name=iso-win10 #指定PVC的名字
--pvc-size=7G #指定PVC的大小,根据操作系统镜像大小来设定,一般略大一个G就行。
--uploadproxy-url=https://10.96.237.3 #cdi-uploadproxy 的 Service IP,可以通过命令 kubectl -n cdi get svc -l cdi.kubevirt.io=cdi-uploadproxy 来查看。
增加 hostDisk 支持
Kubevirt 默认没有开启对 hostDisk 的支持,需要手动开启,这里我们直接editKubeVirt1的ConfigMap
[root@master ~]# kubectl get cm -n kubevirt
NAME DATA AGE
kube-root-ca.crt 1 3h47m
kubevirt-ca 1 3h40m
kubevirt-config 2 3h47m #edit此ConfigMap
kubevirt-install-strategy-r6gd8 1 3h40m
[root@master ~]# kubectl edit cm kubevirt-config -n kubevirt
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
data:
debug.useEmulation: "true"
feature-gates: HostDisk #添加这一行即可
kind: ConfigMap
metadata:
creationTimestamp: "2022-04-17T01:19:05Z"
name: kubevirt-config
namespace: kubevirt
resourceVersion: "46074"
uid: 56ff5d51-1ce5-4c0e-bef2-7c2d24525306
创建虚拟机
1、同样我们需要自己写个vm.yaml文件
apiVersion: kubevirt.io/v1alpha3
kind: VirtualMachine
metadata:
name: win10
spec:
running: false
template:
metadata:
labels:
kubevirt.io/domain: win10
spec:
domain:
cpu:
cores: 4
devices:
disks:
- bootOrder: 1
cdrom:
bus: sata
name: cdromiso
- disk:
bus: virtio
name: harddrive
- cdrom:
bus: sata
name: virtiocontainerdisk
interfaces:
- masquerade: {}
model: e1000
name: default
machine:
type: q35
resources:
requests:
memory: 16G
networks:
- name: default
pod: {}
volumes:
- name: cdromiso
persistentVolumeClaim:
claimName: iso-win10
- name: harddrive
hostDisk:
capacity: 50Gi
path: /data/disk.img
type: DiskOrCreate
- containerDisk:
image: kubevirt/virtio-container-disk
name: virtiocontainerdisk
这里用到了 3 个 Volume:
cdromiso : 提供操作系统安装镜像,即上文上传镜像后生成的 PVC iso-win10。
harddrive : 虚拟机使用的磁盘,即操作系统就会安装在该磁盘上。这里选择 hostDisk 直接挂载到宿主机以提升性能,如果使用分布式存储则体验非常不好。
containerDisk : 由于 Windows 默认无法识别 raw 格式的磁盘,所以需要安装 virtio 驱动。containerDisk 可以将打包好 virtio 驱动的容器镜像挂载到虚拟机中。
关于网络部分,spec.template.spec.networks 定义了一个网络叫 default,这里表示使用 Kubernetes 默认的 CNI。spec.template.spec.domain.devices.interfaces 选择定义的网络 default,并开启 masquerade,以使用网络地址转换 (NAT) 来通过 Linux 网桥将虚拟机连接至 Pod 网络后端。
2、 使用模板文件创建虚拟机:
kubectl apply -f win10.yaml
virtctl start win10
#查看VM,VMI,Pod的状态
[root@master ~]# kubectl get vm
NAME AGE STATUS READY
testvm 3h30m Stopped False
win10 4m7s Running True
[root@master ~]# kubectl get vmi
NAME AGE PHASE IP NODENAME READY
win10 4m7s Running 10.244.2.12 node1 True
[root@master ~]# kubectl get pods
virt-launcher-win10-hwhcw 2/2 Running 0 4m16s