<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          kubevirt在360的探索之路(k8s接管虛擬化)

          共 20503字,需瀏覽 42分鐘

           ·

          2021-02-02 08:25

          來(lái)源:360云計(jì)算

          KubeVirt是一個(gè)Kubernetes插件,在調(diào)度容器之余也可以調(diào)度傳統(tǒng)的虛擬機(jī)。它通過使用自定義資源(CRD)和其它 Kubernetes 功能來(lái)無(wú)縫擴(kuò)展現(xiàn)有的集群,以提供一組可用于管理虛擬機(jī)的虛擬化的API。本文作者經(jīng)過長(zhǎng)時(shí)間對(duì)kubevirt的調(diào)研和實(shí)踐,總結(jié)了kubevirt的一些關(guān)鍵技術(shù)和使用經(jīng)驗(yàn),現(xiàn)在就跟隨作者一起探討下吧。


          背景簡(jiǎn)介

          當(dāng)前公司的虛擬化存在兩套調(diào)度平臺(tái),裸金屬和vm由openstack調(diào)度,容器肯定是k8s調(diào)度。兩套兩班人馬,人力和資源都存在著一定的重疊和浪費(fèi)。當(dāng)前vm和pod的比例在1:1,同時(shí)隨著業(yè)務(wù)的全面上云,大部分web無(wú)狀態(tài)業(yè)務(wù)都開始容器化,所以未來(lái)k8s+容器肯定是業(yè)務(wù)發(fā)布的主流選擇,業(yè)界也基本成型。


          而vm的使用場(chǎng)景會(huì)被壓縮,但是vm作為一個(gè)常用的運(yùn)行時(shí),未來(lái)也會(huì)長(zhǎng)期存在較長(zhǎng)時(shí)間,最后和容器達(dá)成一個(gè)三七開的比例。同時(shí)裸金屬物理機(jī),由于部分業(yè)務(wù)的特性獨(dú)占需求,也會(huì)在未來(lái)長(zhǎng)期存在。


          OpenStack轉(zhuǎn)型K8S

          所以未來(lái)可能會(huì)長(zhǎng)期存在openstack+k8s兩種虛擬化運(yùn)行時(shí)調(diào)度系統(tǒng),這個(gè)增加了團(tuán)隊(duì)的維護(hù)和學(xué)習(xí)成本,再加上現(xiàn)在openstack社區(qū)整體趨于平穩(wěn)和下滑,外加上openstack本身復(fù)雜和臃腫的調(diào)度架構(gòu),和python在大項(xiàng)目管理和維護(hù)方面天生的劣勢(shì),造成了相關(guān)的人員招聘難度較大,大家的學(xué)習(xí)和維護(hù)熱情也降低。


          于此相對(duì)的是k8s調(diào)度系統(tǒng)的全面優(yōu)越,簡(jiǎn)潔和更好的可擴(kuò)展性,go語(yǔ)言的大項(xiàng)目和易部署維護(hù)的天然優(yōu)勢(shì),業(yè)界不少公司都在考慮是否可以由k8s來(lái)接管vm和裸金屬等,因?yàn)楸举|(zhì)上vm底層干活的是libvirt,qemu-kvm等,裸金屬底層是物理機(jī)的ipmi,我們是否可以利用k8s的可擴(kuò)展性,實(shí)現(xiàn)一些新的operator來(lái)接管vm和裸金屬。

          ?

          基于上述考慮,最終的目標(biāo)是用k8s來(lái)管一切虛擬化運(yùn)行時(shí),包含裸金屬,vm,kata,容器,一套調(diào)度,多種運(yùn)行時(shí),用戶按需選擇。


          技術(shù)選型

          有了以上想法以后,就開始調(diào)研,發(fā)現(xiàn)業(yè)界在從openstack轉(zhuǎn)型k8s的過程中涌現(xiàn)了這么一部分比較好的項(xiàng)目,例如,kubevirt,virtlet,rancher/vm等,但是社區(qū)活躍度最高,設(shè)計(jì)最好的還是kubevirt。

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

          文章核心談了幾個(gè)點(diǎn):


          1. kubevirt是不是一個(gè)vm管理平臺(tái)的替代品,和OpenStack還有ovirt等虛擬化管理平臺(tái)的區(qū)別。


            簡(jiǎn)單來(lái)說(shuō):kubevirt只是用k8s管vm,其中會(huì)復(fù)用k8s的cni和csi,所以只是用operator的方式來(lái)操作vm,他不去管網(wǎng)絡(luò)和存儲(chǔ)等。所以和OpenStack中包含nova,neutron,cinder等不一樣,可以理解成kubevirt是一個(gè)k8s框架下的,用go寫的nova vm管理組件。


          2. kubevirt和kata的區(qū)別。


            簡(jiǎn)單來(lái)說(shuō):kata是有著vm的安全性和隔離性,以容器的方式運(yùn)行,有著容器的速度和特點(diǎn),但不是一個(gè)真正的vm,而kubevirt是借用k8s的擴(kuò)展性來(lái)管vm,你用到的是一個(gè)真正的vm。


          3. kubevirt和virtlet的區(qū)別。


            簡(jiǎn)單來(lái)說(shuō):virtlet是把vm當(dāng)成一個(gè)cri來(lái)跑了,是按pod api來(lái)定義一個(gè)vm,所以vm的很多功能比如熱遷移等,virtlet是沒法滿足vm的全部特性的,算是一個(gè)70%功能的vm。

            ?

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


            簡(jiǎn)單來(lái)說(shuō):k8s+容器是未來(lái)的主流方向,但是由于歷史和業(yè)務(wù)需要,vm也會(huì)存在很長(zhǎng)時(shí)間,所以我們一套支持vm的容器管理平臺(tái)k8s,而不是需要一套支持容器的vm管理平臺(tái)例如OpenStack管容器Magnum這種類似項(xiàng)目。


          選型插曲

          有個(gè)插曲:在驗(yàn)證kubevirt的這段時(shí)間,正好看到rancher也發(fā)布了基于 kubevirt 和 k8s 的超融合基礎(chǔ)架構(gòu)軟件 Harvester,從側(cè)面說(shuō)明,這個(gè)方向是有共性的。所有上了年紀(jì)的公司,都有OpenStack和k8s的包袱,而rancher的老總也是cloudstack的創(chuàng)始人,以前和OpenStack競(jìng)爭(zhēng)的時(shí)候落于下風(fēng),現(xiàn)在基于k8s和kubevirt又回到了iaas的地帶,所有技術(shù)圈好多也是輪回啊。


          所以kubevirt這種項(xiàng)目也是在很多從iaas OpenStack轉(zhuǎn)型paas k8s的人群中有更多共鳴,年輕k8s原住民可能對(duì)這個(gè)項(xiàng)目沒有太多感知。因?yàn)閗ubevirt的發(fā)起方redhat,和核心開發(fā)者以前也是OpenStack社區(qū)的項(xiàng)目owner等。所以kubevirt的一些測(cè)試公司和用戶也都是有此類共同轉(zhuǎn)型背景的人和公司。

          ?

          基于如上考慮,最終技術(shù)選型確定了kubevirt,接下來(lái)對(duì)kubevirt的一些概念和邏輯架構(gòu),還有在360的測(cè)試和驗(yàn)證之路做一個(gè)簡(jiǎn)單介紹。


          1

          Kubevirt 是什么

          Kubevirt 是 Redhat 開源一套以容器方式運(yùn)行虛擬機(jī)的項(xiàng)目,通過 kubernetes 云原生來(lái)管理虛擬機(jī)生命周期。


          2

          Kubevirt CRD

          在介紹kubevirt 前我們先了解一下CRD,在kubernetes里面有一個(gè)核心思想既一切都是資源,如同Puppet 里面一切都是資源思想。CRD 是kubernetes 1.7之后添加的自定義資源二次開發(fā)來(lái)擴(kuò)展kubernetes API,通過CRD 可以向API 中添加資源類型,該功能提升了 Kubernetes 的擴(kuò)展能力,那么KUBEVIRT 有哪些需要我們理解的CRD資源,這些資源會(huì)在我們的學(xué)習(xí)和理解過程中都是需要注意的,大概簡(jiǎn)介紹如下幾種:


          3

          Kubevirt 組件介紹

          與OpenStack 類似, kubevirt 每個(gè)組件負(fù)責(zé)不同的功能,不同點(diǎn)是資源調(diào)度策略由k8s 去管理,其中主要組件如下: virt-api,virt-controller,virt-handler,virt-launcher。


          4

          Kubevirt 常見操作

          type DomainManager interface { //SyncVMI 為創(chuàng)建虛擬機(jī)SyncVMI(*v1.VirtualMachineInstance, bool, *cmdv1.VirtualMachineOptions) (*api.DomainSpec, error)//暫停VMIPauseVMI(*v1.VirtualMachineInstance) error//恢復(fù)暫停的VMIUnpauseVMI(*v1.VirtualMachineInstance) errorKillVMI(*v1.VirtualMachineInstance) error//刪除VMIDeleteVMI(*v1.VirtualMachineInstance) errorSignalShutdownVMI(*v1.VirtualMachineInstance) errorMarkGracefulShutdownVMI(*v1.VirtualMachineInstance) errorListAllDomains() ([]*api.Domain, error)//遷移VMIMigrateVMI(*v1.VirtualMachineInstance, *cmdclient.MigrationOptions) errorPrepareMigrationTarget(*v1.VirtualMachineInstance, bool) errorGetDomainStats() ([]*stats.DomainStats, error)//取消遷移CancelVMIMigration(*v1.VirtualMachineInstance) error//如下需要啟用Qemu guest agent,沒啟用會(huì)包VMI does not have guest agent connectedGetGuestInfo() (v1.VirtualMachineInstanceGuestAgentInfo, error)GetUsers() ([]v1.VirtualMachineInstanceGuestOSUser, error)GetFilesystems() ([]v1.VirtualMachineInstanceFileSystem, error)SetGuestTime(*v1.VirtualMachineInstance) error}


          5

          kubevirt 虛機(jī)VMI

          [root@openstack825 ~]# kubectl get vmi -o wideNAME                          AGE     PHASE     IP             NODENAME        LIVE-MIGRATABLEtest100.foo.demo.example.com     8d   Running   192.168.10.30  10.10.67.244   Truetest200.foo.demo.example.com     8d   Running   192.168.10.31  10.10.67.245   True


          獲取已安裝的kubevirt pod[root@openstack825 ~]# kubectl  -n kubevirt get podNAME                               READY   STATUS    RESTARTS   AGEvirt-api-68c958dd-6sx4n            1/1     Running   0          14dvirt-api-68c958dd-sldgr            1/1     Running   0          14dvirt-controller-647d666bd5-gsnzf   1/1     Running   1          14dvirt-controller-647d666bd5-hshnz   1/1     Running   1          14dvirt-handler-4g7ck                 1/1     Running   3          14dvirt-handler-kzv86                 1/1     Running   0          14dvirt-handler-m2ppb                 1/1     Running   0          14dvirt-handler-v6fgt                 1/1     Running   0          14dvirt-operator-65ccf74f56-b82kz     1/1     Running   0          14dvirt-operator-65ccf74f56-zs2xq     1/1     Running   0          14dvirtvnc-947874d99-hn7k5            1/1     Running   0          6d19h


          總結(jié):同時(shí)我們?cè)谡{(diào)研過程遇到一些問題,比如重啟數(shù)據(jù)丟失、VMI 重啟和熱遷移后IP 改變、鏡像導(dǎo)入數(shù)據(jù)緩慢、VMI 啟動(dòng)調(diào)度緩慢、熱遷移網(wǎng)絡(luò)與存儲(chǔ)支持等等。Kubevirt 通過CRD 方式將 VM 管理接口接入到k8s集群,而 POD 使用 libvirtd 管理VMI,如容器一樣去管理VMI,最后通過標(biāo)準(zhǔn)化插件方式管理調(diào)度網(wǎng)絡(luò)和存儲(chǔ)資源對(duì)象,將其整合在一起形成一套 具有 K8s 管理虛擬化的技術(shù)棧。


          6

          kubevirt 存儲(chǔ)

          虛擬機(jī)鏡像(磁盤)是啟動(dòng)虛擬機(jī)必不可少的部分,目前 KubeVirt 中提供多種方式的虛擬機(jī)磁盤。
          • cloudInitNoCloud/cloudInitConfigDrive:用于提供 cloud-init 初始化所需要的 user-data,使用 configmap 作為數(shù)據(jù)源,此時(shí)VMI 內(nèi)部將出現(xiàn)第二塊大約為356KB的第二塊硬盤。


             devices:         disks:         - disk:             bus: virtio           name: cloudinit    - cloudInitNoCloud:         userData: |           #cloud-config           password: kubevirt[centos@xxxv ~]$ lsblkNAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTvda    253:0    0   47G  0 disk└─vda1 253:1    0   47G  0 part /vdb    253:16   0  366K  0 disk


          • dataVolume:虛擬機(jī)啟動(dòng)流程中自動(dòng)將虛擬機(jī)磁盤導(dǎo)入 pvc 的功能,在不使用 DataVolume 的情況下,用戶必須先準(zhǔn)備帶有磁盤映像的 PVC,然后再將其分配給 VM 或 VMI。dataVolume 拉取鏡像的來(lái)源可以是HTTP、PVC。


            spec:     pvc:       accessModes:       - ReadWriteMany       volumeMode: Block       resources:         requests:           storage: 55G       storageClassName:  csi-rbd-sc     source:       http:         url: http://127.0.0.1:8081/CentOS7.4_AMD64_2.1


          • PersistentVolumeClaim: PVC 做為后端存儲(chǔ),適用于數(shù)據(jù)持久化,即在虛擬機(jī)重啟或關(guān)機(jī)后數(shù)據(jù)依然存在。PV 類型可以是 block 和 filesystem,為 filesystem 時(shí),將使用 PVC 上的 disk.img,格式為 RAW 格式的文件作為硬盤。block 模式時(shí),使用 block volume 直接作為原始?jí)K設(shè)備提供給虛擬機(jī)。缺點(diǎn)在于僅支持RAW格式鏡像,若鏡像較大CDI 導(dǎo)入鏡像會(huì)比較慢(如果是QCW2 CDI 內(nèi)部機(jī)制qemu.go 會(huì)將其進(jìn)行格式轉(zhuǎn)換為RAW并導(dǎo)入PVC中),因此降低快速創(chuàng)建 VMI 體驗(yàn)感。當(dāng)然社區(qū)目前支持一種較smart-clone 方式導(dǎo)入,目前筆者還沒進(jìn)行測(cè)試。


            spec: pvc:   accessModes:   - ReadWriteMany   volumeMode: Block   resources:     requests:       storage: 55G   storageClassName:  csi-rbd-sc source:   pvc:     namespace: "default"     name: "q18989v.cloud.bjyt.qihoo.net"


          ephemeral、containerDisk: 數(shù)據(jù)是無(wú)法持久化,故在存儲(chǔ)選型上,我們采用 CEPH 作為后端存儲(chǔ),通過調(diào)用Ceph CSI 插件創(chuàng)建 PVC 卷方式管理虛機(jī)磁盤設(shè)備。Ceph CSI 插件實(shí)現(xiàn)了容器存儲(chǔ)編排與Ceph集群交互的接口,它可以為容器應(yīng)用分配 存儲(chǔ)集群中的存儲(chǔ)空間,同時(shí)在選擇 Ceph-CSI 版本需要考慮到當(dāng)前 K8S 版本、及 CEPH 版本號(hào)。


          當(dāng)前支持的版本列表:

          Dynamically provision, de-provision Block mode RWX volume

          ?

          支持RBD 塊 RWX 的模式,使用此模式主要涉及到Kubevirt 熱遷移場(chǎng)景,虛擬機(jī)調(diào)用 VirtualMachineInstanceMigration CRD 資源,熱遷移時(shí)會(huì)檢測(cè)Volume 模式,此時(shí)塊設(shè)備必須 RWX 模式,代碼如下. ?

          ?

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


          //主要通過調(diào)用磁盤、網(wǎng)絡(luò)相關(guān)函數(shù),來(lái)判斷當(dāng)前VMI 是否適合遷移func (d *VirtualMachineController) calculateLiveMigrationCondition(vmi *v1.VirtualMachineInstance, hasHotplug bool) (*v1.VirtualMachineInstanceCondition, bool) {liveMigrationCondition := v1.VirtualMachineInstanceCondition{Type:   v1.VirtualMachineInstanceIsMigratable,Status: k8sv1.ConditionTrue,}//調(diào)用 checkvolume 方法isBlockMigration, err := d.checkVolumesForMigration(vmi)if err != nil {//如果返回錯(cuò)誤信息則會(huì)限制遷移liveMigrationCondition.Status = k8sv1.ConditionFalseliveMigrationCondition.Message = err.Error()liveMigrationCondition.Reason = v1.VirtualMachineInstanceReasonDisksNotMigratablereturn &liveMigrationCondition, isBlockMigration}//調(diào)用網(wǎng)絡(luò)模式檢查方法err = d.checkNetworkInterfacesForMigration(vmi)if err != nil {liveMigrationCondition = v1.VirtualMachineInstanceCondition{Type:    v1.VirtualMachineInstanceIsMigratable,Status:  k8sv1.ConditionFalse,Message: err.Error(),Reason:  v1.VirtualMachineInstanceReasonInterfaceNotMigratable,}return &liveMigrationCondition, isBlockMigration}if hasHotplug {liveMigrationCondition = v1.VirtualMachineInstanceCondition{Type:    v1.VirtualMachineInstanceIsMigratable,Status:  k8sv1.ConditionFalse,Message: "VMI has hotplugged disks",Reason:  v1.VirtualMachineInstanceReasonHotplugNotMigratable,}return &liveMigrationCondition, isBlockMigration}return &liveMigrationCondition, isBlockMigration}


          //checkvolume 定義/檢查所有VMI卷共享可以在源和實(shí)時(shí)遷移的目的地之間熱遷移//當(dāng)所有卷均已共享且VMI沒有本地磁盤時(shí),blockMigrate才返回True//某些磁盤組合使VMI不適合實(shí)時(shí)遷移, 在這種情況下,將返回相關(guān)錯(cuò)誤func (d *VirtualMachineController) checkVolumesForMigration(vmi *v1.VirtualMachineInstance) (blockMigrate bool, err error) {for _, volume := range vmi.Spec.Volumes {volSrc := volume.VolumeSourceif volSrc.PersistentVolumeClaim != nil || volSrc.DataVolume != nil {var volName stringif volSrc.PersistentVolumeClaim != nil {volName = volSrc.PersistentVolumeClaim.ClaimName} else {volName = volSrc.DataVolume.Name}//pvcutils.IsSharedPVCFromClient_, shared, err := pvcutils.IsSharedPVCFromClient(d.clientset, vmi.Namespace, volName)if errors.IsNotFound(err) {return blockMigrate, fmt.Errorf("persistentvolumeclaim %v not found", volName)} else if err != nil {return blockMigrate, err}if !shared {return true, fmt.Errorf("cannot migrate VMI with non-shared PVCs")}} else if volSrc.HostDisk != nil {shared := volSrc.HostDisk.Shared != nil && *volSrc.HostDisk.Sharedif !shared {return true, fmt.Errorf("cannot migrate VMI with non-shared HostDisk")}} else {blockMigrate = true}}return}func IsSharedPVCFromClient(client kubecli.KubevirtClient, namespace string, claimName string) (pvc *k8sv1.PersistentVolumeClaim, isShared bool, err error) {pvc, err = client.CoreV1().PersistentVolumeClaims(namespace).Get(claimName, v1.GetOptions{})if err == nil {//IsPVCSharedisShared = IsPVCShared(pvc)}return}//IsPVCShared Shared 判斷,函數(shù)返回bool 類型,成功則返回truefunc IsPVCShared(pvc *k8sv1.PersistentVolumeClaim) bool {//循環(huán)PVC的accessModesfor _, accessMode := range pvc.Spec.AccessModes {if accessMode == k8sv1.ReadWriteMany {return true}}return false}


          Ceph CSi 啟動(dòng)的POD 進(jìn)程


          [root@kubevirt01 ~]# kubectl get podNAME                                               READY   STATUS    RESTARTS   AGEcsi-rbdplugin-7bprd                                3/3     Running   0          14dcsi-rbdplugin-fl5c9                                3/3     Running   0          14dcsi-rbdplugin-ggj9q                                3/3     Running   0          14dcsi-rbdplugin-provisioner-84bb9bdd56-7qtnh         6/6     Running   0          14dcsi-rbdplugin-provisioner-84bb9bdd56-sdscf         6/6     Running   0          14dcsi-rbdplugin-provisioner-84bb9bdd56-xjz2r         6/6     Running   0          14dcsi-rbdplugin-svfv2

          ? ? ? ??

          已創(chuàng)建的VMI 對(duì)應(yīng)的 PVC卷


          ---apiVersion: v1kind: PersistentVolumeClaimmetadata: name: testzhangsanlisispec: accessModes:   - ReadWriteMany volumeMode: Block resources:   requests:     storage: 10Gi storageClassName: csi-rbd-sckubectl apply -f pvc-test.yaml[root@kubevirt01 ~]# kubectl get pvcNAME                           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGEtestzhangsanlisi                       Bound    pvc-2c98391d-a2eb-4dd1-a1f0-2a8ef27d4ca3   10Gi       RWX            csi-rbd-sc     3s


          CEPH 架構(gòu)相關(guān),使用三副本策略,不同交換機(jī)下及高容量 SATA 盤 作為 OSD 數(shù)據(jù)載體,保證數(shù)據(jù)的可用性


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


          7

          kubevirt 網(wǎng)絡(luò)

          VMI 通信流程


          kubernetes是Kubevirt 底座,提供了管理容器和虛擬機(jī)的混合部署的方式,存儲(chǔ)和網(wǎng)絡(luò)也是通過集成到kubernetes中, VMI 使用了POD進(jìn)行通信。為了實(shí)現(xiàn)該目標(biāo),KubeVirt 的對(duì)網(wǎng)絡(luò)做了特殊實(shí)現(xiàn)。虛擬機(jī)具體的網(wǎng)絡(luò)如圖所示, virt-launcher Pod 網(wǎng)絡(luò)的網(wǎng)卡不再掛有 Pod IP,而是作為虛擬機(jī)的虛擬網(wǎng)卡的與外部網(wǎng)絡(luò)通信的交接物理網(wǎng)卡。


          在當(dāng)前的場(chǎng)景我們使用經(jīng)典的大二層網(wǎng)絡(luò)模型,用戶在一個(gè)地址空間下,VM 使用固定IP,在OpenStack社區(qū),虛擬網(wǎng)絡(luò)方案成熟,OVS 基本已經(jīng)成為網(wǎng)絡(luò)虛擬化的標(biāo)準(zhǔn)。所以我門選擇目前靈雀云(alauda) 開源的網(wǎng)絡(luò)方案:Kube-OVN,它是基于OVN的Kubernetes網(wǎng)絡(luò)組件,提供了大量目前Kubernetes不具備的網(wǎng)絡(luò)功能,并在原有基礎(chǔ)上進(jìn)行增強(qiáng)。通過將OpenStack領(lǐng)域成熟的網(wǎng)絡(luò)功能平移到Kubernetes,來(lái)應(yīng)對(duì)更加復(fù)雜的基礎(chǔ)環(huán)境和應(yīng)用合規(guī)性要求。?

          Kube-OVN 是一款基于 OVS/OVN 的 Kubernetes網(wǎng)絡(luò)項(xiàng)目


          網(wǎng)絡(luò) VLAN underlay


          在網(wǎng)絡(luò)平面,管理網(wǎng)和 VMI 虛擬機(jī)流量分開,其中使用Vlan 模式的 underlay 網(wǎng)絡(luò),容器網(wǎng)絡(luò)可以直接通過 vlan 接入物理交換機(jī)

          //Demo Yaml//IP 地址段來(lái)自源與網(wǎng)絡(luò)物理設(shè)備分配時(shí)spec: cidrBlock: 192.168.10.0/23 default: true excludeIps: - 192.168.10.1 gateway: 192.168.10.1 gatewayNode: "" gatewayType: distributed // 需要設(shè)置成false natOutgoing: false private: false protocol: IPv4 provider: ovn //需要設(shè)置成true,若為false,會(huì)在主機(jī)側(cè)加上route,導(dǎo)致net不通 underlayGateway: true vlan: ovn-vlan


          [root@kubevirt01 ~]# kubectl -n kube-system get podNAME                                   READY   STATUS    RESTARTS   AGEcoredns-65dbdb44db-8bxlr               1/1     Running   33         17dkube-ovn-cni-4v4xb                     1/1     Running   0          18dkube-ovn-cni-kvgrj                     1/1     Running   0          18dkube-ovn-cni-nj2pr                     1/1     Running   0          18dkube-ovn-cni-xv476                     1/1     Running   0          18dkube-ovn-controller-7f6db69b48-6c7w8   1/1     Running   0          18dkube-ovn-controller-7f6db69b48-82kjt   1/1     Running   0          18dkube-ovn-controller-7f6db69b48-mhkfc   1/1     Running   0          18dkube-ovn-pinger-n2rn4                  1/1     Running   0          18dkube-ovn-pinger-s4hrz                  1/1     Running   0          18dkube-ovn-pinger-tccz5                  1/1     Running   0          18dkube-ovn-pinger-x2tqq                  1/1     Running   0          18dovn-central-775c4ff46d-4nqjw           1/1     Running   1          18dovn-central-775c4ff46d-822v2           1/1     Running   0          18dovn-central-775c4ff46d-txkn8           1/1     Running   0          18dovs-ovn-mbpv2                          1/1     Running   0          18dovs-ovn-r9mvc                          1/1     Running   0          18dovs-ovn-wkxld                          1/1     Running   0          18dovs-ovn-z89hw                          1/1     Running   0          18d


          虛擬機(jī)固定IP


          k8s的資源是在運(yùn)行時(shí)才分配ip的,但是筆者希望能夠?qū)μ摂M機(jī)的ip進(jìn)行綁定從而實(shí)現(xiàn)固定ip的目的。為此,我們首先正常創(chuàng)建虛擬機(jī),在虛擬機(jī)運(yùn)行時(shí)k8s會(huì)為之分配ip,當(dāng)檢測(cè)到虛擬機(jī)的ip后,我們通過替換vmi的配置文件的方式將ip綁定改虛擬機(jī)中。但是在實(shí)際操作時(shí)會(huì)報(bào)出如下錯(cuò)誤:

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

          實(shí)際上 Kubernetes API Server是支持樂觀鎖(Optimistic concurrency control)的機(jī)制來(lái)防止并發(fā)寫造成的覆蓋寫問題,因此在修改的body中需要加入metadata.resourceVersion,筆者的做法是首選調(diào)用 read_namespaced_virtual_machine方法獲取metadata.resourceVersion,其次再修改body。具體方案可參考:

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


          8

          kubevirt SDK

          kubevirt sdk現(xiàn)狀 ? ?當(dāng)前kubevirt提供了Python版本以及Golang版本的SDK,具體的信息參考如下:

          https://github.com/kubevirt/client-pythonhttps://github.com/kubevirt/client-go

          筆者實(shí)際使用的是python的sdk,所以接下來(lái)重點(diǎn)敘述一下python版本的sdk的使用心得,使用時(shí)發(fā)現(xiàn)了一些問題,并加以解決也將在下面的內(nèi)容中記錄。


          sdk實(shí)現(xiàn)的功能本章筆者詳細(xì)介紹一下使用到的一些sdk中的功能,在初體驗(yàn)的過程中筆者只是用了部分功能,完整的功能可以詳見github。


          • 創(chuàng)建使用實(shí)例


            sdk主要使用的是kubevirt.apis.default_api中的DefaultApi對(duì)象,進(jìn)行接口調(diào)用個(gè)的。DefaultApi對(duì)象需要ApiClient對(duì)象,該對(duì)象實(shí)際上是連接k8s的實(shí)例。因此在使用之前,需要在底層的k8s中起一個(gè)proxy。通過創(chuàng)建DefaultApi對(duì)象即可調(diào)用后續(xù)的接口了,具體的創(chuàng)建方法如下:


            import kubevirt

            def get_api_client(host): api_client = kubevirt.ApiClient(host=host, header_name="Content-Type", header_value="application/json") return api_client

            api_client = get_api_client(host="http://127.0.0.1:8001")api_instance = kubevirt.DefaultApi(api_client)


          • kubvirt sdk 的本質(zhì)

            實(shí)際上我們知道,kubevirt是在k8s中定義了集中CRD,那么調(diào)用kubevirt的sdk實(shí)際上也是調(diào)用k8s中CRD相關(guān)接口,通過查看k8中CRD的接口我們知道,具體的url表示為:/apis/{group}/{version}/namespaces/{namespace}/{plural}/{name}因此重要的是找到group以及plural參數(shù)具體是什么。通過下圖可以看出group都是kubevirt.io,plural根據(jù)需要的不同可以定義不同的類型


          • sdk部分功能以及注意事項(xiàng)


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

          創(chuàng)建虛擬機(jī)( create_namespaced_virtual_machine)  注意:body是json格式,官方sdk的example有誤刪除虛擬機(jī)( delete_namespaced_virtual_machine)展示某個(gè)namespace下的vm資源( list_namespaced_virtual_machine)展示某個(gè)namespace下的vmi資源( list_namespaced_virtual_machine_instance)展示所有namespace下的vm資源( list_virtual_machine_for_all_namespaces)展示所有namespace下的vmi資源( list_virtual_machine_instance_for_all_namespaces)獲取某個(gè)namespace某個(gè)name下的vm資源( read_namespaced_virtual_machine)獲取某個(gè)namespace某個(gè)name下的vmi資源( read_namespaced_virtual_machine_instance) 注意:在獲取vm資源時(shí)無(wú)法獲取到node_name,uuid,ip的數(shù)據(jù),獲取vmi資源時(shí)無(wú)法獲取到disk以及image_url的數(shù)據(jù),筆者認(rèn)為vm是虛擬機(jī)資源,vmi是虛擬機(jī)實(shí)例資源,只有在running狀態(tài)下的vm才是vmi,由于k8s中ip是動(dòng)態(tài)分配的,因此才會(huì)出現(xiàn)node_name,uuid,ip數(shù)據(jù)在vm中獲取不到啟動(dòng)虛擬機(jī)( v1alpha3_start)停止虛擬機(jī)( v1alpha3_stop)重啟虛擬機(jī)( v1alpha3_restart) 注意: 重啟虛擬機(jī)只能在虛擬機(jī)狀態(tài)是running是才能調(diào)用,否則會(huì)失敗修改虛擬機(jī)名稱( v1alpha3_rename)替換虛擬機(jī)的配置文件( replace_namespaced_virtual_machine_instance)


          sdk使用注意事項(xiàng)

          • k8s版本問題


            官方給出的kubevirt sdk中對(duì)于創(chuàng)建刪除以及替換配置文件等部分接口,k8s版本是固定的穩(wěn)定版v1版本,這顯然不滿足于sdk的靈活使用,因此筆者在使用時(shí)對(duì)api版本進(jìn)行了兼容,保證用戶可以通過傳參的形式正確的使用。


          • 修改虛擬機(jī)名稱缺乏參數(shù)


            誠(chéng)如標(biāo)題所述,修改虛擬機(jī)名稱接口官方給出的參數(shù)有誤,缺乏新名稱參數(shù)


          筆者通過查看virtclt源碼找到了缺少的參數(shù)的具體名稱并添加至sdk中,具體代碼如下:


          def v1alpha3_rename_with_http_info(self, name, newName, namespace, **kwargs):   """   Rename a stopped VirtualMachine object.   This method makes a synchronous HTTP request by default. To make an   asynchronous HTTP request, please define a `callback` function   to be invoked when receiving the response.   >>> def callback_function(response):   >>>     pprint(response)   >>>   >>> thread = api.v1alpha3_rename_with_http_info(name, namespace, newName, callback=callback_function)   :param callback function: The callback function       for asynchronous request. (optional)   :param str name: Name of the resource (required)   :param str namespace: Object name and auth scope, such as for teams and projects (required)   :param str newName: NewName of the resource (required)   :return: str            If the method is called asynchronously,            returns the request thread.   """   all_params = ['name', 'namespace', 'newName']   all_params.append('callback')   all_params.append('_return_http_data_only')   all_params.append('_preload_content')   all_params.append('_request_timeout')   params = locals()   for key, val in iteritems(params['kwargs']):       if key not in all_params:           raise TypeError(               "Got an unexpected keyword argument '%s'"               " to method v1alpha3_rename" % key           )       params[key] = val   del params['kwargs']   # verify the required parameter 'name' is set   if ('name' not in params) or (params['name'] is None):       raise ValueError("Missing the required parameter `name` when calling `v1alpha3_rename`")   # verify the required parameter 'namespace' is set   if ('namespace' not in params) or (params['namespace'] is None):       raise ValueError("Missing the required parameter `namespace` when calling `v1alpha3_rename`")   collection_formats = {}   path_params = {}   # if 'name' in params:   #     path_params['name'] = params['name']   # if 'namespace' in params:   #     path_params['namespace'] = params['namespace']   query_params = []   header_params = {}   form_params = []   local_var_files = {}   body_params = {"newName": params["newName"]}   # Authentication setting   auth_settings = []   api_route = "/apis/subresources.kubevirt.io/v1alpha3/namespaces/{namespace}/virtualmachines/{name}/rename".format(namespace=params["namespace"], name=params["name"])   return self.api_client.call_api(api_route, 'PUT',                                   path_params,                                   query_params,                                   header_params,                                   body=body_params,                                   post_params=form_params,                                   files=local_var_files,                                   response_type='str',                                   auth_settings=auth_settings,                                   callback=params.get('callback'),                                   _return_http_data_only=params.get('_return_http_data_only'),                                   _preload_content=params.get('_preload_content', True),                                   _request_timeout=params.get('_request_timeout'),                                   collection_formats=collection_formats)


          9

          Ultron 平臺(tái)創(chuàng)建基于kubevirt 的虛擬機(jī)

          奧創(chuàng)平臺(tái)是公司內(nèi)的私有云管理平臺(tái)(類似horizon),可以通過其管理openstack VM,本次我們同時(shí)納入到對(duì)Kubevirt 虛擬機(jī)的支持,創(chuàng)建方式和OpenStack方式一樣。最后用戶體驗(yàn)和功能特性也和OpenStack一致,用戶本身也是不關(guān)注底層實(shí)現(xiàn),性能特性方面后續(xù)文章會(huì)有對(duì)比。


          10

          總結(jié)

          kubevirt作為一個(gè)兼容方案,當(dāng)前在cncf中孵化的也挺好,好像也要開始自己的KubeVirt Summit,主要是實(shí)際的解決了一些痛點(diǎn),但目前看,kubevirt還是適合在私有云,肯定滿足不了公有云,因?yàn)閗8s在iaas方面有先天劣勢(shì),所以kubevirt應(yīng)該是給大家在私有云領(lǐng)域落地虛擬化除了用OpenStack以外多了一種選擇方案。


          相關(guān)文章

          • https://kubevirt.io/

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





          關(guān)注「開源Linux」加星標(biāo),提升IT技能

          瀏覽 46
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄色视频电影 | 日韩性爱网址 | AV网站免费看 | 天天爽夜夜爽精品成人免费 | 三区视频在线播放 |