来源:360云计算

KubeVirt是一个Kubernetes插件,在调度容器之余也可以调度传统的虚拟机。它通过使用自定义资源(CRD)和其它 Kubernetes 功能来无缝扩展现有的集群,以提供一组可用于管理虚拟机的虚拟化的API。本文作者经过长时间对kubevirt的调研和实践,总结了kubevirt的一些关键技术和使用经验,现在就跟随作者一起探讨下吧。

背景简介

当前公司的虚拟化存在两套调度平台,裸金属和vm由openstack调度,容器肯定是k8s调度。两套两班人马,人力和资源都存在着一定的重叠和浪费。当前vm和pod的比例在1:1,同时随着业务的全面上云,大部分web无状态业务都开始容器化,所以未来k8s+容器肯定是业务发布的主流选择,业界也基本成型。

而vm的使用场景会被压缩,但是vm作为一个常用的运行时,未来也会长期存在较长时间,最后和容器达成一个三七开的比例。同时裸金属物理机,由于部分业务的特性独占需求,也会在未来长期存在。

OpenStack转型K8S

所以未来可能会长期存在openstack+k8s两种虚拟化运行时调度系统,这个增加了团队的维护和学习成本,再加上现在openstack社区整体趋于平稳和下滑,外加上openstack本身复杂和臃肿的调度架构,和python在大项目管理和维护方面天生的劣势,造成了相关的人员招聘难度较大,大家的学习和维护热情也降低。

于此相对的是k8s调度系统的全面优越,简洁和更好的可扩展性,go语言的大项目和易部署维护的天然优势,业界不少公司都在考虑是否可以由k8s来接管vm和裸金属等,因为本质上vm底层干活的是libvirt,qemu-kvm等,裸金属底层是物理机的ipmi,我们是否可以利用k8s的可扩展性,实现一些新的operator来接管vm和裸金属。

基于上述考虑,最终的目标是用k8s来管一切虚拟化运行时,包含裸金属,vm,kata,容器,一套调度,多种运行时,用户按需选择。

技术选型

有了以上想法以后,就开始调研,发现业界在从openstack转型k8s的过程中涌现了这么一部分比较好的项目,例如,kubevirt,virtlet,rancher/vm等,但是社区活跃度最高,设计最好的还是kubevirt。

https://kubevirt.io/2017/technology-comparison.html

文章核心谈了几个点:

  1. kubevirt是不是一个vm管理平台的替代品,和OpenStack还有ovirt等虚拟化管理平台的区别。

    简单来说:kubevirt只是用k8s管vm,其中会复用k8s的cni和csi,所以只是用operator的方式来操作vm,他不去管网络和存储等。所以和OpenStack中包含nova,neutron,cinder等不一样,可以理解成kubevirt是一个k8s框架下的,用go写的nova vm管理组件。

  2. kubevirt和kata的区别。

    简单来说:kata是有着vm的安全性和隔离性,以容器的方式运行,有着容器的速度和特点,但不是一个真正的vm,而kubevirt是借用k8s的扩展性来管vm,你用到的是一个真正的vm。

  3. kubevirt和virtlet的区别。

    简单来说:virtlet是把vm当成一个cri来跑了,是按pod api来定义一个vm,所以vm的很多功能比如热迁移等,virtlet是没法满足vm的全部特性的,算是一个70%功能的vm。

  4. 为啥要用k8s管vm,而不是用OpenStack管容器。

    简单来说:k8s+容器是未来的主流方向,但是由于历史和业务需要,vm也会存在很长时间,所以我们一套支持vm的容器管理平台k8s,而不是需要一套支持容器的vm管理平台例如OpenStack管容器Magnum这种类似项目。

选型插曲

有个插曲:在验证kubevirt的这段时间,正好看到rancher也发布了基于 kubevirt 和 k8s 的超融合基础架构软件 Harvester,从侧面说明,这个方向是有共性的。所有上了年纪的公司,都有OpenStack和k8s的包袱,而rancher的老总也是cloudstack的创始人,以前和OpenStack竞争的时候落于下风,现在基于k8s和kubevirt又回到了iaas的地带,所有技术圈好多也是轮回啊。

所以kubevirt这种项目也是在很多从iaas OpenStack转型paas k8s的人群中有更多共鸣,年轻k8s原住民可能对这个项目没有太多感知。因为kubevirt的发起方redhat,和核心开发者以前也是OpenStack社区的项目owner等。所以kubevirt的一些测试公司和用户也都是有此类共同转型背景的人和公司。

基于如上考虑,最终技术选型确定了kubevirt,接下来对kubevirt的一些概念和逻辑架构,还有在360的测试和验证之路做一个简单介绍。

1

Kubevirt 是什么

Kubevirt 是 Redhat 开源一套以容器方式运行虚拟机的项目,通过 kubernetes 云原生来管理虚拟机生命周期。

2

Kubevirt CRD

在介绍kubevirt 前我们先了解一下CRD,在kubernetes里面有一个核心思想既一切都是资源,如同Puppet 里面一切都是资源思想。CRD 是kubernetes 1.7之后添加的自定义资源二次开发来扩展kubernetes API,通过CRD 可以向API 中添加资源类型,该功能提升了 Kubernetes 的扩展能力,那么KUBEVIRT 有哪些需要我们理解的CRD资源,这些资源会在我们的学习和理解过程中都是需要注意的,大概简介绍如下几种:

3

Kubevirt 组件介绍

与OpenStack 类似, kubevirt 每个组件负责不同的功能,不同点是资源调度策略由k8s 去管理,其中主要组件如下: virt-api,virt-controller,virt-handler,virt-launcher。

4

Kubevirt 常见操作

  1. type DomainManager interface {
  2. //SyncVMI 为创建虚拟机
  3. SyncVMI(*v1.VirtualMachineInstance, bool, *cmdv1.VirtualMachineOptions) (*api.DomainSpec, error)
  4. //暂停VMI
  5. PauseVMI(*v1.VirtualMachineInstance) error
  6. //恢复暂停的VMI
  7. UnpauseVMI(*v1.VirtualMachineInstance) error
  8. KillVMI(*v1.VirtualMachineInstance) error
  9. //删除VMI
  10. DeleteVMI(*v1.VirtualMachineInstance) error
  11. SignalShutdownVMI(*v1.VirtualMachineInstance) error
  12. MarkGracefulShutdownVMI(*v1.VirtualMachineInstance) error
  13. ListAllDomains() ([]*api.Domain, error)
  14. //迁移VMI
  15. MigrateVMI(*v1.VirtualMachineInstance, *cmdclient.MigrationOptions) error
  16. PrepareMigrationTarget(*v1.VirtualMachineInstance, bool) error
  17. GetDomainStats() ([]*stats.DomainStats, error)
  18. //取消迁移
  19. CancelVMIMigration(*v1.VirtualMachineInstance) error
  20. //如下需要启用Qemu guest agent,没启用会包VMI does not have guest agent connected
  21. GetGuestInfo() (v1.VirtualMachineInstanceGuestAgentInfo, error)
  22. GetUsers() ([]v1.VirtualMachineInstanceGuestOSUser, error)
  23. GetFilesystems() ([]v1.VirtualMachineInstanceFileSystem, error)
  24. SetGuestTime(*v1.VirtualMachineInstance) error
  25. }

5

kubevirt 虚机VMI

  1. [root@openstack825 ~]# kubectl get vmi -o wide
  2. NAME AGE PHASE IP NODENAME LIVE-MIGRATABLE
  3. test100.foo.demo.example.com 8d Running 192.168.10.30 10.10.67.244 True
  4. test200.foo.demo.example.com 8d Running 192.168.10.31 10.10.67.245 True
  1. 获取已安装的kubevirt pod
  2. [root@openstack825 ~]# kubectl -n kubevirt get pod
  3. NAME READY STATUS RESTARTS AGE
  4. virt-api-68c958dd-6sx4n 1/1 Running 0 14d
  5. virt-api-68c958dd-sldgr 1/1 Running 0 14d
  6. virt-controller-647d666bd5-gsnzf 1/1 Running 1 14d
  7. virt-controller-647d666bd5-hshnz 1/1 Running 1 14d
  8. virt-handler-4g7ck 1/1 Running 3 14d
  9. virt-handler-kzv86 1/1 Running 0 14d
  10. virt-handler-m2ppb 1/1 Running 0 14d
  11. virt-handler-v6fgt 1/1 Running 0 14d
  12. virt-operator-65ccf74f56-b82kz 1/1 Running 0 14d
  13. virt-operator-65ccf74f56-zs2xq 1/1 Running 0 14d
  14. virtvnc-947874d99-hn7k5 1/1 Running 0 6d19h

总结:同时我们在调研过程遇到一些问题,比如重启数据丢失、VMI 重启和热迁移后IP 改变、镜像导入数据缓慢、VMI 启动调度缓慢、热迁移网络与存储支持等等。Kubevirt 通过CRD 方式将 VM 管理接口接入到k8s集群,而 POD 使用 libvirtd 管理VMI,如容器一样去管理VMI,最后通过标准化插件方式管理调度网络和存储资源对象,将其整合在一起形成一套 具有 K8s 管理虚拟化的技术栈。

6

kubevirt 存储

虚拟机镜像(磁盘)是启动虚拟机必不可少的部分,目前 KubeVirt 中提供多种方式的虚拟机磁盘。

  • cloudInitNoCloud/cloudInitConfigDrive:用于提供 cloud-init 初始化所需要的 user-data,使用 configmap 作为数据源,此时VMI 内部将出现第二块大约为356KB的第二块硬盘。

    1. devices:
    2. disks:
    3. - disk:
    4. bus: virtio
    5. name: cloudinit
    6. - cloudInitNoCloud:
    7. userData: |
    8. #cloud-config
    9. password: kubevirt
    10. [centos@xxxv ~]$ lsblk
    11. NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
    12. vda 253:0 0 47G 0 disk
    13. └─vda1 253:1 0 47G 0 part /
    14. vdb 253:16 0 366K 0 disk
  • dataVolume:虚拟机启动流程中自动将虚拟机磁盘导入 pvc 的功能,在不使用 DataVolume 的情况下,用户必须先准备带有磁盘映像的 PVC,然后再将其分配给 VM 或 VMI。dataVolume 拉取镜像的来源可以是HTTP、PVC。

    1. spec:
    2. pvc:
    3. accessModes:
    4. - ReadWriteMany
    5. volumeMode: Block
    6. resources:
    7. requests:
    8. storage: 55G
    9. storageClassName: csi-rbd-sc
    10. source:
    11. http:
    12. url: http://127.0.0.1:8081/CentOS7.4_AMD64_2.1
  • PersistentVolumeClaim: PVC 做为后端存储,适用于数据持久化,即在虚拟机重启或关机后数据依然存在。PV 类型可以是 block 和 filesystem,为 filesystem 时,将使用 PVC 上的 disk.img,格式为 RAW 格式的文件作为硬盘。block 模式时,使用 block volume 直接作为原始块设备提供给虚拟机。缺点在于仅支持RAW格式镜像,若镜像较大CDI 导入镜像会比较慢(如果是QCW2 CDI 内部机制qemu.go 会将其进行格式转换为RAW并导入PVC中),因此降低快速创建 VMI 体验感。当然社区目前支持一种较smart-clone 方式导入,目前笔者还没进行测试。

    1. spec:
    2. pvc:
    3. accessModes:
    4. - ReadWriteMany
    5. volumeMode: Block
    6. resources:
    7. requests:
    8. storage: 55G
    9. storageClassName: csi-rbd-sc
    10. source:
    11. pvc:
    12. namespace: "default"
    13. name: "q18989v.cloud.bjyt.qihoo.net"

ephemeral、containerDisk: 数据是无法持久化,故在存储选型上,我们采用 CEPH 作为后端存储,通过调用Ceph CSI 插件创建 PVC 卷方式管理虚机磁盘设备。Ceph CSI 插件实现了容器存储编排与Ceph集群交互的接口,它可以为容器应用分配 存储集群中的存储空间,同时在选择 Ceph-CSI 版本需要考虑到当前 K8S 版本、及 CEPH 版本号。

当前支持的版本列表:

Dynamically provision, de-provision Block mode RWX volume

支持RBD 块 RWX 的模式,使用此模式主要涉及到Kubevirt 热迁移场景,虚拟机调用 VirtualMachineInstanceMigration CRD 资源,热迁移时会检测Volume 模式,此时块设备必须 RWX 模式,代码如下.

位置:pkg/vm-handler/vm.go

  1. //主要通过调用磁盘、网络相关函数,来判断当前VMI 是否适合迁移
  2. func (d *VirtualMachineController) calculateLiveMigrationCondition(vmi *v1.VirtualMachineInstance, hasHotplug bool) (*v1.VirtualMachineInstanceCondition, bool) {
  3. liveMigrationCondition := v1.VirtualMachineInstanceCondition{
  4. Type: v1.VirtualMachineInstanceIsMigratable,
  5. Status: k8sv1.ConditionTrue,
  6. }
  7. //调用 checkvolume 方法
  8. isBlockMigration, err := d.checkVolumesForMigration(vmi)
  9. if err != nil {
  10. //如果返回错误信息则会限制迁移
  11. liveMigrationCondition.Status = k8sv1.ConditionFalse
  12. liveMigrationCondition.Message = err.Error()
  13. liveMigrationCondition.Reason = v1.VirtualMachineInstanceReasonDisksNotMigratable
  14. return &liveMigrationCondition, isBlockMigration
  15. }
  16. //调用网络模式检查方法
  17. err = d.checkNetworkInterfacesForMigration(vmi)
  18. if err != nil {
  19. liveMigrationCondition = v1.VirtualMachineInstanceCondition{
  20. Type: v1.VirtualMachineInstanceIsMigratable,
  21. Status: k8sv1.ConditionFalse,
  22. Message: err.Error(),
  23. Reason: v1.VirtualMachineInstanceReasonInterfaceNotMigratable,
  24. }
  25. return &liveMigrationCondition, isBlockMigration
  26. }
  27. if hasHotplug {
  28. liveMigrationCondition = v1.VirtualMachineInstanceCondition{
  29. Type: v1.VirtualMachineInstanceIsMigratable,
  30. Status: k8sv1.ConditionFalse,
  31. Message: "VMI has hotplugged disks",
  32. Reason: v1.VirtualMachineInstanceReasonHotplugNotMigratable,
  33. }
  34. return &liveMigrationCondition, isBlockMigration
  35. }
  36. return &liveMigrationCondition, isBlockMigration
  37. }
  1. //checkvolume 定义
  2. /检查所有VMI卷共享可以在源和实时迁移的目的地之间热迁移
  3. //当所有卷均已共享且VMI没有本地磁盘时,blockMigrate才返回True
  4. //某些磁盘组合使VMI不适合实时迁移, 在这种情况下,将返回相关错误
  5. func (d *VirtualMachineController) checkVolumesForMigration(vmi *v1.VirtualMachineInstance) (blockMigrate bool, err error) {
  6. for _, volume := range vmi.Spec.Volumes {
  7. volSrc := volume.VolumeSource
  8. if volSrc.PersistentVolumeClaim != nil || volSrc.DataVolume != nil {
  9. var volName string
  10. if volSrc.PersistentVolumeClaim != nil {
  11. volName = volSrc.PersistentVolumeClaim.ClaimName
  12. } else {
  13. volName = volSrc.DataVolume.Name
  14. }
  15. //pvcutils.IsSharedPVCFromClient
  16. _, shared, err := pvcutils.IsSharedPVCFromClient(d.clientset, vmi.Namespace, volName)
  17. if errors.IsNotFound(err) {
  18. return blockMigrate, fmt.Errorf("persistentvolumeclaim %v not found", volName)
  19. } else if err != nil {
  20. return blockMigrate, err
  21. }
  22. if !shared {
  23. return true, fmt.Errorf("cannot migrate VMI with non-shared PVCs")
  24. }
  25. } else if volSrc.HostDisk != nil {
  26. shared := volSrc.HostDisk.Shared != nil && *volSrc.HostDisk.Shared
  27. if !shared {
  28. return true, fmt.Errorf("cannot migrate VMI with non-shared HostDisk")
  29. }
  30. } else {
  31. blockMigrate = true
  32. }
  33. }
  34. return
  35. }
  36. func IsSharedPVCFromClient(client kubecli.KubevirtClient, namespace string, claimName string) (pvc *k8sv1.PersistentVolumeClaim, isShared bool, err error) {
  37. pvc, err = client.CoreV1().PersistentVolumeClaims(namespace).Get(claimName, v1.GetOptions{})
  38. if err == nil {
  39. //IsPVCShared
  40. isShared = IsPVCShared(pvc)
  41. }
  42. return
  43. }
  44. //IsPVCShared Shared 判断,函数返回bool 类型,成功则返回true
  45. func IsPVCShared(pvc *k8sv1.PersistentVolumeClaim) bool {
  46. //循环PVC的accessModes
  47. for _, accessMode := range pvc.Spec.AccessModes {
  48. if accessMode == k8sv1.ReadWriteMany {
  49. return true
  50. }
  51. }
  52. return false
  53. }

Ceph CSi 启动的POD 进程

  1. [root@kubevirt01 ~]# kubectl get pod
  2. NAME READY STATUS RESTARTS AGE
  3. csi-rbdplugin-7bprd 3/3 Running 0 14d
  4. csi-rbdplugin-fl5c9 3/3 Running 0 14d
  5. csi-rbdplugin-ggj9q 3/3 Running 0 14d
  6. csi-rbdplugin-provisioner-84bb9bdd56-7qtnh 6/6 Running 0 14d
  7. csi-rbdplugin-provisioner-84bb9bdd56-sdscf 6/6 Running 0 14d
  8. csi-rbdplugin-provisioner-84bb9bdd56-xjz2r 6/6 Running 0 14d
  9. csi-rbdplugin-svfv2

已创建的VMI 对应的 PVC卷

  1. ---
  2. apiVersion: v1
  3. kind: PersistentVolumeClaim
  4. metadata:
  5. name: testzhangsanlisi
  6. spec:
  7. accessModes:
  8. - ReadWriteMany
  9. volumeMode: Block
  10. resources:
  11. requests:
  12. storage: 10Gi
  13. storageClassName: csi-rbd-sc
  14. kubectl apply -f pvc-test.yaml
  15. [root@kubevirt01 ~]# kubectl get pvc
  16. NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
  17. testzhangsanlisi Bound pvc-2c98391d-a2eb-4dd1-a1f0-2a8ef27d4ca3 10Gi RWX csi-rbd-sc 3s

CEPH 架构相关,使用三副本策略,不同交换机下及高容量 SATA 盘 作为 OSD 数据载体,保证数据的可用性

  1. (ceph-mon)[root@example100 /]# ceph -s
  2. cluster:
  3. id: d8ab2087-f55c-4b8f-913d-fc60d6fc455d
  4. health: HEALTH_OK
  5. services:
  6. mon: 3 daemons, quorum 192.168.10.100 192.168.20.100 192.168.30.100 (age 4d)
  7. mgr: ceph100(active, since 4d), standbys: ceph200 ceph300
  8. osd: 27 osds: 27 up (since 2w), 27 in (since 2w)
  9. data:
  10. pools: 1 pools, 1024 pgs
  11. objects: 55.91k objects, 218 GiB
  12. usage: 682 GiB used, 98 TiB / 98 TiB avail
  13. pgs: 1024 active+clean
  14. io:
  15. client: 2.2 KiB/s wr, 0 op/s rd, 0 op/s wr
  16. (ceph-mon)[root@example100 /]# ceph df
  17. RAW STORAGE:
  18. CLASS SIZE AVAIL USED RAW USED %RAW USED
  19. hdd 98 TiB 98 TiB 655 GiB 682 GiB 0.68
  20. TOTAL 98 TiB 98 TiB 655 GiB 682 GiB 0.68

7

kubevirt 网络

VMI 通信流程

kubernetes是Kubevirt 底座,提供了管理容器和虚拟机的混合部署的方式,存储和网络也是通过集成到kubernetes中, VMI 使用了POD进行通信。为了实现该目标,KubeVirt 的对网络做了特殊实现。虚拟机具体的网络如图所示, virt-launcher Pod 网络的网卡不再挂有 Pod IP,而是作为虚拟机的虚拟网卡的与外部网络通信的交接物理网卡。

在当前的场景我们使用经典的大二层网络模型,用户在一个地址空间下,VM 使用固定IP,在OpenStack社区,虚拟网络方案成熟,OVS 基本已经成为网络虚拟化的标准。所以我门选择目前灵雀云(alauda) 开源的网络方案:Kube-OVN,它是基于OVN的Kubernetes网络组件,提供了大量目前Kubernetes不具备的网络功能,并在原有基础上进行增强。通过将OpenStack领域成熟的网络功能平移到Kubernetes,来应对更加复杂的基础环境和应用合规性要求。

Kube-OVN 是一款基于 OVS/OVN 的 Kubernetes网络项目

网络 VLAN underlay

在网络平面,管理网和 VMI 虚拟机流量分开,其中使用Vlan 模式的 underlay 网络,容器网络可以直接通过 vlan 接入物理交换机

  1. //Demo Yaml
  2. //IP 地址段来自源与网络物理设备分配时
  3. spec:
  4. cidrBlock: 192.168.10.0/23
  5. default: true
  6. excludeIps:
  7. - 192.168.10.1
  8. gateway: 192.168.10.1
  9. gatewayNode: ""
  10. gatewayType: distributed
  11. // 需要设置成false
  12. natOutgoing: false
  13. private: false
  14. protocol: IPv4
  15. provider: ovn
  16. //需要设置成true,若为false,会在主机侧加上route,导致net不通
  17. underlayGateway: true
  18. vlan: ovn-vlan
  1. [root@kubevirt01 ~]# kubectl -n kube-system get pod
  2. NAME READY STATUS RESTARTS AGE
  3. coredns-65dbdb44db-8bxlr 1/1 Running 33 17d
  4. kube-ovn-cni-4v4xb 1/1 Running 0 18d
  5. kube-ovn-cni-kvgrj 1/1 Running 0 18d
  6. kube-ovn-cni-nj2pr 1/1 Running 0 18d
  7. kube-ovn-cni-xv476 1/1 Running 0 18d
  8. kube-ovn-controller-7f6db69b48-6c7w8 1/1 Running 0 18d
  9. kube-ovn-controller-7f6db69b48-82kjt 1/1 Running 0 18d
  10. kube-ovn-controller-7f6db69b48-mhkfc 1/1 Running 0 18d
  11. kube-ovn-pinger-n2rn4 1/1 Running 0 18d
  12. kube-ovn-pinger-s4hrz 1/1 Running 0 18d
  13. kube-ovn-pinger-tccz5 1/1 Running 0 18d
  14. kube-ovn-pinger-x2tqq 1/1 Running 0 18d
  15. ovn-central-775c4ff46d-4nqjw 1/1 Running 1 18d
  16. ovn-central-775c4ff46d-822v2 1/1 Running 0 18d
  17. ovn-central-775c4ff46d-txkn8 1/1 Running 0 18d
  18. ovs-ovn-mbpv2 1/1 Running 0 18d
  19. ovs-ovn-r9mvc 1/1 Running 0 18d
  20. ovs-ovn-wkxld 1/1 Running 0 18d
  21. ovs-ovn-z89hw 1/1 Running 0 18d

虚拟机固定IP

k8s的资源是在运行时才分配ip的,但是笔者希望能够对虚拟机的ip进行绑定从而实现固定ip的目的。为此,我们首先正常创建虚拟机,在虚拟机运行时k8s会为之分配ip,当检测到虚拟机的ip后,我们通过替换vmi的配置文件的方式将ip绑定改虚拟机中。但是在实际操作时会报出如下错误:

  1. Invalid value: 0x0: must be specified for an update

实际上 Kubernetes API Server是支持乐观锁(Optimistic concurrency control)的机制来防止并发写造成的覆盖写问题,因此在修改的body中需要加入metadata.resourceVersion,笔者的做法是首选调用 read_namespaced_virtual_machine方法获取metadata.resourceVersion,其次再修改body。具体方案可参考:

  1. https://www.codeleading.com/article/27252474726/

8

kubevirt SDK

kubevirt sdk现状    当前kubevirt提供了Python版本以及Golang版本的SDK,具体的信息参考如下:

  1. https://github.com/kubevirt/client-python
  2. https://github.com/kubevirt/client-go

笔者实际使用的是python的sdk,所以接下来重点叙述一下python版本的sdk的使用心得,使用时发现了一些问题,并加以解决也将在下面的内容中记录。

sdk实现的功能本章笔者详细介绍一下使用到的一些sdk中的功能,在初体验的过程中笔者只是用了部分功能,完整的功能可以详见github。

  • 创建使用实例

    sdk主要使用的是kubevirt.apis.default_api中的DefaultApi对象,进行接口调用个的。DefaultApi对象需要ApiClient对象,该对象实际上是连接k8s的实例。因此在使用之前,需要在底层的k8s中起一个proxy。通过创建DefaultApi对象即可调用后续的接口了,具体的创建方法如下:

    1. import kubevirt
    2. def get_api_client(host):
    3. api_client = kubevirt.ApiClient(host=host, header_name="Content-Type", header_value="application/json")
    4. return api_client
    5. api_client = get_api_client(host="http://127.0.0.1:8001")
    6. api_instance = kubevirt.DefaultApi(api_client)
  • kubvirt sdk 的本质

    实际上我们知道,kubevirt是在k8s中定义了集中CRD,那么调用kubevirt的sdk实际上也是调用k8s中CRD相关接口,通过查看k8中CRD的接口我们知道,具体的url表示为:/apis/{group}/{version}/namespaces/{namespace}/{plural}/{name}因此重要的是找到group以及plural参数具体是什么。通过下图可以看出group都是kubevirt.io,plural根据需要的不同可以定义不同的类型

  • sdk部分功能以及注意事项

    笔者主要使用了以下的功能:

  1. 创建虚拟机( create_namespaced_virtual_machine) 注意:bodyjson格式,官方sdkexample有误
  2. 删除虚拟机( delete_namespaced_virtual_machine)
  3. 展示某个namespace下的vm资源( list_namespaced_virtual_machine)
  4. 展示某个namespace下的vmi资源( list_namespaced_virtual_machine_instance)
  5. 展示所有namespace下的vm资源( list_virtual_machine_for_all_namespaces)
  6. 展示所有namespace下的vmi资源( list_virtual_machine_instance_for_all_namespaces)
  7. 获取某个namespace某个name下的vm资源( read_namespaced_virtual_machine)
  8. 获取某个namespace某个name下的vmi资源( read_namespaced_virtual_machine_instance) 注意:在获取vm资源时无法获取到node_name,uuid,ip的数据,获取vmi资源时无法获取到disk以及image_url的数据,笔者认为vm是虚拟机资源,vmi是虚拟机实例资源,只有在running状态下的vm才是vmi,由于k8sip是动态分配的,因此才会出现node_name,uuid,ip数据在vm中获取不到
  9. 启动虚拟机( v1alpha3_start)
  10. 停止虚拟机( v1alpha3_stop)
  11. 重启虚拟机( v1alpha3_restart) 注意: 重启虚拟机只能在虚拟机状态是running是才能调用,否则会失败
  12. 修改虚拟机名称( v1alpha3_rename)
  13. 替换虚拟机的配置文件( replace_namespaced_virtual_machine_instance)

sdk使用注意事项

  • k8s版本问题

    官方给出的kubevirt sdk中对于创建删除以及替换配置文件等部分接口,k8s版本是固定的稳定版v1版本,这显然不满足于sdk的灵活使用,因此笔者在使用时对api版本进行了兼容,保证用户可以通过传参的形式正确的使用。

  • 修改虚拟机名称缺乏参数

    诚如标题所述,修改虚拟机名称接口官方给出的参数有误,缺乏新名称参数

笔者通过查看virtclt源码找到了缺少的参数的具体名称并添加至sdk中,具体代码如下:

  1. def v1alpha3_rename_with_http_info(self, name, newName, namespace, **kwargs):
  2. """
  3. Rename a stopped VirtualMachine object.
  4. This method makes a synchronous HTTP request by default. To make an
  5. asynchronous HTTP request, please define a `callback` function
  6. to be invoked when receiving the response.
  7. >>> def callback_function(response):
  8. >>> pprint(response)
  9. >>>
  10. >>> thread = api.v1alpha3_rename_with_http_info(name, namespace, newName, callback=callback_function)
  11. :param callback function: The callback function
  12. for asynchronous request. (optional)
  13. :param str name: Name of the resource (required)
  14. :param str namespace: Object name and auth scope, such as for teams and projects (required)
  15. :param str newName: NewName of the resource (required)
  16. :return: str
  17. If the method is called asynchronously,
  18. returns the request thread.
  19. """
  20. all_params = ['name', 'namespace', 'newName']
  21. all_params.append('callback')
  22. all_params.append('_return_http_data_only')
  23. all_params.append('_preload_content')
  24. all_params.append('_request_timeout')
  25. params = locals()
  26. for key, val in iteritems(params['kwargs']):
  27. if key not in all_params:
  28. raise TypeError(
  29. "Got an unexpected keyword argument '%s'"
  30. " to method v1alpha3_rename" % key
  31. )
  32. params[key] = val
  33. del params['kwargs']
  34. # verify the required parameter 'name' is set
  35. if ('name' not in params) or (params['name'] is None):
  36. raise ValueError("Missing the required parameter `name` when calling `v1alpha3_rename`")
  37. # verify the required parameter 'namespace' is set
  38. if ('namespace' not in params) or (params['namespace'] is None):
  39. raise ValueError("Missing the required parameter `namespace` when calling `v1alpha3_rename`")
  40. collection_formats = {}
  41. path_params = {}
  42. # if 'name' in params:
  43. # path_params['name'] = params['name']
  44. # if 'namespace' in params:
  45. # path_params['namespace'] = params['namespace']
  46. query_params = []
  47. header_params = {}
  48. form_params = []
  49. local_var_files = {}
  50. body_params = {"newName": params["newName"]}
  51. # Authentication setting
  52. auth_settings = []
  53. api_route = "/apis/subresources.kubevirt.io/v1alpha3/namespaces/{namespace}/virtualmachines/{name}/rename".format(namespace=params["namespace"], name=params["name"])
  54. return self.api_client.call_api(api_route, 'PUT',
  55. path_params,
  56. query_params,
  57. header_params,
  58. body=body_params,
  59. post_params=form_params,
  60. files=local_var_files,
  61. response_type='str',
  62. auth_settings=auth_settings,
  63. callback=params.get('callback'),
  64. _return_http_data_only=params.get('_return_http_data_only'),
  65. _preload_content=params.get('_preload_content', True),
  66. _request_timeout=params.get('_request_timeout'),
  67. collection_formats=collection_formats)

9

Ultron 平台创建基于kubevirt 的虚拟机

奥创平台是公司内的私有云管理平台(类似horizon),可以通过其管理openstack VM,本次我们同时纳入到对Kubevirt 虚拟机的支持,创建方式和OpenStack方式一样。最后用户体验和功能特性也和OpenStack一致,用户本身也是不关注底层实现,性能特性方面后续文章会有对比。

10

总结

kubevirt作为一个兼容方案,当前在cncf中孵化的也挺好,好像也要开始自己的KubeVirt Summit,主要是实际的解决了一些痛点,但目前看,kubevirt还是适合在私有云,肯定满足不了公有云,因为k8s在iaas方面有先天劣势,所以kubevirt应该是给大家在私有云领域落地虚拟化除了用OpenStack以外多了一种选择方案。

相关文章

  • https://kubevirt.io/

  • https://xie.infoq.cn/article/9c911e195aa9b02a69f875489


  1. 关注「开源Linux」加星标,提升IT技能

kubevirt在360的探索之路(k8s接管虚拟化)的更多相关文章

  1. 全球首个开放应用模型 OAM 开源 | 云原生生态周报 Vol. 23

    作者 | 临石.元毅.冬岛.衷源.天元 业界要闻 全球首个开放应用模型 OAM 开源 2019 年 10 月 17 日,阿里巴巴合伙人.阿里云智能基础产品事业部总经理蒋江伟(花名:小邪)在 Qcon ...

  2. 全球首个开放应用模型 OAM 开源

    业界要闻 全球首个开放应用模型 OAM 开源 2019 年 10 月 17 日,阿里巴巴合伙人.阿里云智能基础产品事业部总经理蒋江伟(花名:小邪)在 Qcon 上海重磅宣布,阿里云与微软联合推出开放应 ...

  3. Flink 在又拍云日志批处理中的实践

    日前,由又拍云举办的大数据与 AI 技术实践|Open Talk 杭州站沙龙在杭州西溪科创园顺利举办.本次活动邀请了有赞.个推.方得智能.又拍云等公司核心技术开发者,现场分享各自领域的大数据技术经验和 ...

  4. 温故知新Docker概念及Docker Desktop For Windows v3.1.0安装

    Docker 简介 什么是Docker? Docker是一个开放源代码软件项目,项目主要代码在2013年开源于GitHub.它是云服务技术上的一次创新,让应用程序布署在软件容器下的工作可以自动化进行, ...

  5. [源码解析] 深度学习分布式训练框架 horovod (18) --- kubeflow tf-operator

    [源码解析] 深度学习分布式训练框架 horovod (18) --- kubeflow tf-operator 目录 [源码解析] 深度学习分布式训练框架 horovod (18) --- kube ...

  6. 虚拟化原理到K8s实践经验路线总结

    以下这些内容均为自行学习总结的内容,很多内容没有写概括介绍,看起来可能会有些突兀,但并不影响整体性,我自己的学习经验告诉我,这些内容还仅仅是最精简的核心部分,周边还有很多可扩展内容,主要是操作系统生态 ...

  7. VMware虚拟化与Kubernetes(K8s)类比阐述-适合VMware用户

    概述 容器技术是最近几年非常热门的技术,它似乎就是为云端的应用量身定制的,所以它也被贴上了云原生应用 (Cloud Native Application) 技术的标签.目前最为流行的容器管理调度平台是 ...

  8. 微服务探索之路02篇liunx ubuntu服务器部署k8s(kubernetes)-kubernetes/dashboard

    本章介绍所需环境:ubuntu18.04,建立在上一篇微服务探索之路01篇已经安装了docker的基础上. 1 替换k8s镜像源为国内镜像 进入目录 cd /etc/apt/sources.list. ...

  9. 微服务探索之路03篇-docker私有仓库Harbor搭建+Kubernetes(k8s)部署私有仓库的镜像

    ❝ 目录: 微服务探索之路01篇.net6.0项目本地win10系统docker到服务器liunx系统docker的贯通 微服务探索之路02篇liunx ubuntu服务器部署k8s(kubernet ...

随机推荐

  1. 什么是Spring IOC 容器?

    Spring IOC 负责创建对象,管理对象(通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期.

  2. Kafka创建Topic时如何将分区放置到不同的Broker中?

    副本因子不能大于 Broker 的个数: 第一个分区(编号为0)的第一个副本放置位置是随机从 brokerList 选择的: 其他分区的第一个副本放置位置相对于第0个分区依次往后移.也就是如果我们有5 ...

  3. 给定一个奇数n,比如n=3,生成1到n平方的数,如1到9,填入九宫格,使得横竖斜的和都相等。

    对于N阶幻方,从1开始把数字从小到大按以下规则依次写入: 一.在第一行中间一列写入1 二.依次向右上方写入2.3.4...... 三.如果某数字写在了表格的某个方向外面,那就把这个数字向相反方向移动N ...

  4. 经历了源码的痛苦,掌握DRF的核心序列化器

    目录 DRF的核心--序列化器 序列化器 什么是序列化和反序列化? 序列化 序列化demo 字段类型 字段参数 序列化自定制返回字段 方法一:在序列化类(serializers.py)中写 方法二:在 ...

  5. python学习笔记(九)——线程与进程

    一.线程 Python 中为我们提供了两个模块来创建线程. _thread threading thread 模块已被废弃.用户可以使用 threading 模块代替.所以,在 Python 中不能再 ...

  6. ROS机器人操作系统相关书籍、资料和学习路径

    作者:Top Liu链接:https://zhuanlan.zhihu.com/p/30391098来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 本文是易科机器人实验 ...

  7. 设计模式之:工厂方法模式FactoryMethodPattern的实现

    本例用到了配置文件.接口.反射.多态: 满足的设计原则: 通过工厂,实现创建对象和使用对象的分离,实现松耦合,满足迪米特法则: 通过配置文件指定创建对象类型,而不需更改源代码,满足开闭原则: 容易实现 ...

  8. 安装vue.js的方法

    一.安装nodejs环境,可以再nodejs官网下载相应的版本安装在自己电脑: 一般国内需要切换npm到国内淘宝环境,安装好nodejs之后切换国内淘宝镜像就能使用国内的npm包(npm instal ...

  9. DOCTYPE(⽂档类型) 的作⽤

    DOCTYPE是HTML5中一种标准通用标记语言的文档类型声明,它的目的是告诉浏览器(解析器)应该以什么样(html或xhtml)的文档类型定义来解析文档,不同的渲染模式会影响浏览器对 CSS 代码甚 ...

  10. Spring Boot配置druid监控页功能

    1.导入坐标 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http ...