边缘云原生虚拟化研究报告 2024年1月 可信边缘计算推进计划 目次 前言III 1技术与需求概述1 1.1虚拟机和容器1 1.2OpenStack与Kubernetes1 1.3融合管理的演进:K8s环境下运行虚拟机3 1.4开源项目简介4 2技术实践9 2.1生命周期管理9 2.2镜像管理10 2.3存储管理13 2.4网络能力15 前言 参与单位(排名不分先后):中国联合网络通信有限公司研究院,中国联合网络通信有限公司智网创新中心、可信边缘计算推进计划 编写人:黄蓉庞博黄倩陈丹肖羽蔡超侯迎龙隗英英高沛李晓旭隋佳良王蕴婷李昂 1技术与需求概述 随着网络技术和云技术的发展,边缘计算得到了广泛的应用。边缘计算可以解决高可靠低延迟的设备接入和海量数据的实时计算问题,云技术有力的保障和推动了边缘计算的应用。 1.1虚拟机和容器 虚拟机和容器是云计算中最常用到的应用部署和运行方式。虚拟机是伴随着虚拟化的技术出现的,容器则云原生技术的典型特征之一,他们的架构对比如下图所示: 图1:虚拟机与容器架构对比图 如上图所示,虚拟化技术一般通过虚拟化层(hypervisor)来实现,通过虚拟化技术,虚拟机可以共享物理机的CPU、内存、IO等硬件资源,并在逻辑上实现相互隔离。每一个虚拟机都拥有独立的操作系统(客户机操作系统),所以虚拟机不依赖于宿主机操作系统,其安全性和隔离性更强。但是虚拟机占用的资源较多,而且由于要模拟硬件,虚拟化层本身也会占用部分资源,对宿主机性能有一定的消耗。比较而言,容器则是使用宿主机的内核系统加上自身的文件系统。运行容器时是在使用宿主机的内核情况下加载文件系统,一般可以将容器看作是在内核上运行的独立进程。而精简的文件系统可以小到100MB以内,因此容器比虚拟机占用资源的更少、启动速度更快。容器缺点是隔离性不如虚拟机,而且由于依赖宿主机内核,所以容器的操作系统选择一般会受到限制。 两种技术的特点对比如下表: 表1:虚拟机与容器技术特点对比 对比项 虚拟机技术 容器技术 安全隔离性 强,操作系统级别 弱,进程级别 对宿主机操作系统依赖 无 有,需要相同操作系统内核 启动时间 慢,分钟级 快,秒级 磁盘占用 大(GB) 小(MB) 虚拟化性能损耗 大1 小 1.2OpenStack与Kubernetes 从运行和管理平台来看,OpenStack2与Kubernetes(K8s)3分别是对虚拟机和容器进行运行和管理的典型开源项目。 OpenStack是开源的云计算平台,利用虚拟化技术和底层存储服务,提供了可扩展、灵活、适应性 强的云计算服务。OpenStack的服务分为核心功能和非核心功能。核心功能是指运行OpenStack系统必须的功能的组件,包括:Keystone(身份识别服务)、Glance(镜像服务)、Nova(计算机服务)、Neutron (网络服务)、Cinder(块存储服务)、Swift(对象存储服务)、Horizon(控制面板服务)。非核心功能指的是实现附加功能的组件,如Ceilometer(测量功能)、Heat(部署编排)、Trove(数据库服务)等。OpenStack的各个组件(服务)之间使用标准的API接口调用,减少了服务之间的依赖。 下图是OpenStack的逻辑架构图。 图2:OpenStack逻辑架构图 Kubernetes是容器管理编排引擎,可以自动完成容器的部署、管理和扩展等操作,部署Kubernetes的设备环境通常被成为Kubernetes集群。Kubernetes集群逻辑上可以分为两个部分:控制平面与计算设 备(或称为节点)。控制平面的包含:kube-apiserve(r接口程序,用于处理内部和外部请求)、kube-scheduler (调度程序)、kube-controller-manager(集群控制管理程序)、etcd(数据库)。计算设备包含容器运行时引擎、kubelet(节点代理程序)、kube-proxy(网络代理程序)。Kubernetes的设计原则包括:安全、易于使用和可扩展。Kubernetes同样遵循标准化API接口,而且Kubernetes实现了CNI(容器网络接口)、CRI(容器运行时接口)、CSI(容器存储接口)等接口和CRD(用户自定义资源)等,便于实现功能的扩展。 下图是Kubernetes的逻辑架构图。 图3:Kubernetes逻辑架构图 OpenStack的设计比较全面,组件众多,部署相对复杂,难于运维,使用成本较高,更适合作为大规模云的管理系统。相对而言,Kubernetes的设计更加简洁,其核心组件少,便于运维,同时K8s的生态很庞大,可以很方便地对其进行扩展或者定制,更适用于资源受限的边缘环境。 1.3融合管理的演进:K8s环境下运行虚拟机 当前,通过容器部署的应用越来越广泛。但是,通过虚拟机部署的应用也会存在相当长的时间。首先,有不少现存的应用程序是运行在虚拟机上的,其中一些程序无法轻松地进行容器化重构。其次,即便对程序进行容器化改造,之后的系统调试和问题定位又会带来很大的挑战,尤其是对于通信行业来说,多代通信设备并存,对设备和应用程序的稳定性要求又非常高,对原有的应用程序进行容器化改造的成本和风险都是较大的。最后,一些应用或者场景更加适合使用虚拟机来进行部署。比如下面这些场景更适合使用虚拟机来运行而不是容器: *NFV(networkfunctionvirtualization)网络功能虚拟化的场景:将传统的网元虚拟化,使用虚拟机会比使用容器更方便,因为容器在接入多网卡方面比起虚拟机的能力来说还有一定的差距; *大模型的研发测试:大模型在研发测试阶段进场需要使用多张GPU协同配合,同时要安装很多多软件依赖包来进行调试和使用,这时直接将多张GPU挂载到一个虚拟机里,然后在虚拟机里来实验开发要比在容器里方便很多; *数据库:不是所有的数据库都适合放在容器里运行,比如部分数据库的特定算法需要限制IP的变化,在虚拟机里部署可以有一个固定的IP,会更加方便; *很多进程的应用:在容器使用上,有个核心概念就是部署任务单一的进程,比如一个简单的api服务进程加一个日志收集的进程组合成为了一个容器,有些多进程的应用就不适合放在容器中运行了。 于是,随着时间推移,企业会遇到这样的情况,有些应用还是只能运行在虚拟机上,有些应用已经完成了容器化,企业管理员不得不同时运维管理多套平台,这大大增加了运维的难度: *计算资源:从管理角度来说计算资源的管理不同的平台的管理方法也是截然不同的,比如OpenStack是通过projectquota来管理,而K8s则通过request/limit来管理,管理人员必须完全了解2套机制才能完全很好的管理起来; *网络资源:同样,对于网络管理来说,不同的平台也是完全不同的,K8s使用CNI来管理网络,同时OpenStack通过neutron来管理网络,他们的使用理念上也是截然不同的,这样很大程度上增加了学习成本; *监控/日志:各种平台都有自己的完整的监控/日志收集系统,它们会占用大量的计算、存储和网络资源,同时部署这样2套平台,从资源使用的角度上来说也是一种很大的浪费; *存储资源:相同的存储资源对接K8s和OpenStack方式都是截然不同的,出现问题后找根因的思路和角度也都是不一样的,这样也大大加大了运维的成本和难度。 *安全风险:软件是由不同工程师编写的代码,运行在不同的操作系统上,每个环境都会遇到安全漏洞,越多组件则面临更多的安全漏洞,同时运维2套平台就意味着面临安全漏洞也会更多,企业面临的安全风险也就更大。 从各个方面来看,企业内部的虚拟机平台和容器平台合并成为同一套平台来进行管理是一个趋势。那么是将K8s合并到OpenStack呢?还是反过来呢? 业内也在研究虚拟机和容器的共平台的部署和管理,从OpenStack和K8s各自的发展来看,两个平台也在进行虚拟机和容器共同管理的探索,比如OpenStack的zun服务将容器作为一种OpenStack资源来进行管理,并通过集成OpenStack的其他服务,为用户呈现统一的、简化的API接口,用户可以通过这些接口来创建、管理容器;K8s也有多个相关的开源项目在研究如何实现对虚拟机的管理(见下文)。 从云技术的现状和发展来看,容器的应用越来越广泛,而且K8s在容器编排领域成为了业内事实上的标准。在边缘环境下,K8s的适用范围也更加广泛,因此,本文将进一步探讨在K8s环境下运行虚拟机的技术和实践范例。 1.4开源项目简介 本节介绍在K8s环境下运行虚拟机的相关开源项目。当前这些项目还在发展之中,功能还在不断地迭代和完善。 1.4.1KubeVirt KubeVirt4是一个K8s插件,由Redhat开源,云原生计算基金会(CNCF)赞助的开源项目。KubeVirt插件可以在K8s平台上调度传统的虚拟机。KubeVirt使用自定义资源(CRD)将VM管理接口接入到K8s中,通过一个Pod去使用libvirtd管理VM的方式,实现Pod与VM的一一对应,做到如同容器一般去管理虚拟机,并且做到与容器一样的资源管理、调度规划。KubeVirt的架构图如下。 图4:KubeVirt架构图 KubeVirt主要由下列五个部分组成: virt-api:kubevirt是以CRD形式去管理VMPod,virt-api就是所有虚拟化操作的入口,这里面包括常规的CDR更新验证、以及console、vmstart、stop等操作。 virt-controller:virt-controller会根据VMICRD,生成对应的virt-launcherPod,并且维护CRD的状态。与K8s的api-server通讯监控VMI资源的创建删除等状态。 virt-handler:virt-handler会以deamonset形式部署在每一个节点上,负责监控节点上的每个虚拟机实例状态变化,一旦检测到状态的变化,会进行响应并且确保相应的操作能够达到所需(理想)的状态。virt-handler还会保持集群级别VMISpec与相应libvirt域之间的同步;报告libvirt域状态和集群Spec的变化;调用以节点为中心的插件以满足VMISpec定义的网络和存储要求。 virt-launcher:每个virt-launcherPod对应着一个VMI,kubelet只负责virt-launcherPod运行状态,不会去关心VMI创建情况。virt-handler会根据CRD参数配置去通知virt-launcher去使用本地的libvirtd实例来启动VMI,随着Pod的生命周期结束,virt-lanuncher也会去通知VMI去执行终止操作;其次在每个virt-launcherPod中还对应着一个libvirtd,virt-launcher通过libvirtd去管理VM的生命周期,不再是以前的虚拟机架构那样一个libvirtd去管理多个VM。 virtctl:virtctl是kubevirt自带类似kubectl的命令行工具,它是越过virt-launcherPod这一层去直接管理VM虚拟机,可以控制VM的start、stop、restart。 KubeVirt利用CRD的功能定义了若干种资源对象。 VirtualMachineInstance(VMI):类似于KubernetesPod,是管理虚拟机的最小资源。一个VirtualMachineInstance对象即表示一台正在运行的虚拟机实例,包含一个虚拟机所需要的各种配置。 VirtualMachine(VM):为群集内的VirtualMachineInstance提供管理功能,例如开机/关机/重启虚拟机,确保虚拟机实例的启动状态,与虚拟机实例是1:1的关系,类似与spec.replica为1的StatefulSet。 VirtualMachineInstanc