当前位置: 首页 > 科技观察

容器与虚拟化的结合:浅谈“安全容器”技术的发展趋势

时间:2023-03-15 09:24:09 科技观察

众所周知,容器技术的出现有两个关键原因:1、软件运行过程中资源与环境的隔离。2、运行环境多种多样,软件打包配置复杂。至于软件运行环境的隔离要求,从计算机开始就已经有了。多任务分时操作系统和虚拟地址的引入,就是为了解决在同一台主机上运行多个任务,让任务自己认为自己是独占机器的。当然,这样的隔离是远远不够的。现在的软件,按照不同的层次,可以将隔离技术分为以下三类:1.进程级隔离2.操作系统级隔离3.虚拟化级隔离操作系统进程作为程序运行的抽象过程。进程有独立的地址空间,进程的执行依赖于操作系统的调度。但是进程共享文件系统、函数库等资源,程序之间相互干扰的可能性很大。这种隔离级别适合在同一台主机上运行单个用户的不同程序,用户保证程序之间的资源分配。在20世纪70年代,chroot出现以隔离文件系统。进入21世纪以来,随着计算硬件性能的提升,对软件隔离的需求也越来越强烈。这时jail、cgroup、namespace等各种资源开始出现。隔离技术。我们把这些技术分为操作系统的隔离技术。这种隔离技术可以实现软件在硬件资源、文件系统、网络、进程号等方面的隔离,但不同的应用程序仍然运行在同一个操作系统内核上。事实上,对于恶意利用漏洞的场景,这种隔离技术还是会捉襟见肘。但这种隔离级别带来的额外资源消耗相对较低,适合同一组织内不同用户的应用运行在同一台主机上。虚拟化技术的出现使得多个不同的操作系统可以运行在同一台物理机上。操作系统与硬件的接口由虚拟机管理程序(VMM)模拟。在不同系统上运行的程序具有不同的内核。硬件资源被各种硬件辅助手段分割,虚拟机上的程序很难突破虚拟化层的资源限制。并且因为内核的隔离,资源的可见性也实现了强隔离。即使是恶意用户,也很难突破这层虚拟化的限制,达到攻击物理机或同一主机上其他虚拟机的目的。以上三种隔离按层级逐层加强,其带来的理论损失也是逐步递增的。由于虚拟化需要模拟各种设备,因此虚拟化带来的资源消耗远大于其他两种隔离方式。什么是“安全容器”?系统调用等的限制和隔离。这种隔离方式效率更高,损失更小。但是随着容器的大规模使用,尤其是各种容器编排系统的深入使用,比如k8s,人们逐渐发现这样的隔离级别往往不能满足要求。在公有云场景下,如果同一台宿主机需要运行不同租户的应用,由于这种隔离级别还是采用了通用的内核机制,存在如此广泛的攻击面,容器的隔离级别根本无法满足要求.因此,公有云上最初的容器服务都是使用虚拟机来完成的。首先,用户需要创建一批虚拟机作为运行容器的节点,形成私有集群,然后在其上创建容器应用。.虚拟化层面的隔离已经被各种公有云证明,是一种安全的隔离技术。自从云计算概念提出以来,虚拟机一直是云平台的基础。无论是平台本身还是用户的使用,都是从在IaaS平台上创建通用虚拟机开始的。一般是创建一个相应规格的虚拟机,使用一个完整的操作系统镜像来启动一个完整的操作系统,然后在上面安装、配置和运行软件和服务。上一节提到的公有云容器服务的提供也是如此。虚拟化本身带来的隔离能力是公认的,但IaaS层希望提供的是一个完全独立于应用的基础设施层,它几乎完全不知道应用的任何信息。因此,从基础设施到应用运维,中间的巨大缺口由PaaS和用户自己来填补,仍然需要无数的人力和成本。通用的虚拟机服务当然有它的好处,比如一个完整的操作系统,非常适合程序调试,或者作为工作和办公环境等等。但对于大多数运行在云平台上的软件来说,它需要的是它独特的运行环境,而它的运行环境已经完全由它的形象来定义。如果除此之外再启动一个完整的操作系统,不仅会浪费资源,还会增加运维成本。为什么不能在容器技术中直接引入虚拟化级别的隔离?结合虚拟化的安全性和容器在软件生命周期管理方面的优势,能否为软件开发和运维带来极大的便利?也就是此时,docker和coreos共同成立了OCI组织,其目的是标准化容器运行时、镜像管理等流程。OCI标准为容器运行时定义了一组命令行界面和文件规范。Docker将其RunC捐赠给OCI作为运行时标准的参考实现。2015年,Hyper.sh开源了RunV,它是一个基于虚拟化的容器运行时接口的实现,它结合了虚拟化的安全性和容器的便利性。后来,RunV和ClearContainer合并形成了kata项目,提供了更完整的基于虚拟化的容器实现。我们将这种基于虚拟化的容器实现称为安全容器。除了kata,还有多种安全容器的实现,比如Google的gVisor、AWS的firecracker-containerd、IBM的Nabla、VMware的CRX等,原理各不相同,但都体现了一个趋势。就是将容器的便利性与虚拟化的安全隔离结合起来,让虚拟化可以直接与应用运维结合起来,这已经成为云原生技术的大势所趋。下面就这些“安全容器”的实现技术进行简要介绍和比较。谷歌gVisor与其他几个实现相比有很大的不同,它通过拦截应用在容器中的系统调用来模拟一个操作系统内核,所以gVisor并没有真正虚拟化,而是在用户态实现了一个操作系统。这种方法可以减少虚拟化带来的模拟设备的内存消耗。gVisor提供的runsc符合OCI标准,可以直接对接docker、containerd等容器平台。它还完全兼容docker图像格式。但由于不是标准的linux内核,应用兼容性存在较大问题。此外,拦截系统调用带来的巨大性能损失也是阻碍其广泛应用的障碍。图片来自https://gvisor.dev/docs/IBMnablanabla是继承自unikernel的一种隔离方式。应用程序使用rumprun打包成unikernel镜像,直接运行在专门为运行unikernel而设计的自定义虚拟机(ukvm)中。直接打包应用程序,首先可以减少很多内核态和用户态切换的开销。此外,通过ukvm暴露主机上非常有限的系统调用(仅剩7个)可以大大减少主机的攻击面。它是这些安全容器实现中最安全的。但是由于需要将应用打包成unikernel镜像,所以不兼容目前的docker镜像标准。此外,unikernel应用在支持创建子进程等一些常规操作上存在困难的问题。图片来自https://unit42.paloaltonetworks.com/making-containers-more-isolated-an-overview-of-sandboxed-container-technologies/AWSFirecracker最初的firecracker是为AWSLambda组件创建的高密度轻量级虚拟化。由于它以轻量化为目的从零开始构建虚拟化,因此将通用虚拟化组件qemu的大部分功能都扔掉了,只留下一些运行容器和功能所必需的模拟设备。因此,它的内存开销很小(小于5M),启动速度非常快(小于125ms),1秒可以在一个节点上运行150个轻量级虚拟机。为了让firecracker-microvm更好的运行容器,AWS推出了firecracker-containerd项目。firecracker-containerd是containerd-shim-v2的一个实现,不符合OCI标准,但是可以直接连接containerd启动容器,并且很容易通过containerd连接到k8s的CRI接口。containerd-shim-v2是containerd定义的一个新的运行时接口。它是对原始shim-v1的简化,可以大大简化运行时组件和内存使用。containerd是一个完全插件化的代码框架,具有很好的可扩展性。firecracker-containerd在这个框架下实现了一个snapshotter作为镜像插件,负责块设备镜像的生成;它实现了一个shim-v2运行时,负责容器的生命周期管理。另外还有一个fc-control-plugin作为虚拟机管理插件,提供grpc接口供运行时调用。在轻量级虚拟机内部,有一个agent负责监听runtime发送的vsock,接收runtime指令,在虚拟机内部进行真正的容器生命周期管理操作。它直接调用runc来管理容器。图片来自https://github.com/firecracker-microvm/firecracker-containerd/blob/master/docs/architecture.mdVMwareCRXVMware发布vSphere7和kubernetes,使用k8sCRD集成其集群虚拟机,所有功能k8s中集成了容器、函数等运行实体管理。VMware是一家以虚拟化起家的公司,所以虚拟化作为其老牌业务,有着非常深厚的积累。它将虚拟化集成到它的容器运行时CRX中,所以类似于firecracker-containerd和kata,它也是一种基于轻量级虚拟化的容器运行时的实现。通过简化其虚拟化组件和客户内核,CRX容器还实现了低内存消耗(20MB)、快速(100ms)启动和高密度部署(每个节点超过1000个pod)。图片来自https://cormachogan.com/2019/11/22/project-pacific-vmworld-2019-deep-dive-updates/vSphere对节点上的kubelet组件进行了比较大的改造,部分功能node上的Spherelet与kubelet重叠,负责pod的生命周期管理(他们称之为NativePod),运行在虚拟机中的SphereletAgent集成了符合OCI接口规范的libcontainer实现容器的生命周期管理,如以及容器的监控日志收集和容器登录的shell(kubectlexec)。Spherelet和SphereletAgent在虚拟机中的交互类似于kubelet使用CRI接口管理pod的效果。与上述类型的kata容器相比,kata容器最大的特点是专注于实现一个开放的符合OCI的安全容器运行时实现。它为它所连接的虚拟化解决方案类型抽象出一组管理程序接口。现在已经对接了多种虚拟化实现,如qemu、nemu、firecracker、cloud-hypervisor等。图片来自https://katacontainers.io/通过containerd-shim-v2和vsock技术,kata简化了大量组件。借助轻量级的管理程序和精简的内核,kata可以将额外的内存消耗减少到10MB以下。容器启动时间降至100毫秒以下。未来将通过重写rust语言的方式提供更低的内存消耗。图片来自https://github.com/kata-containers/documentation/blob/master/design/architecture.md现有安全容器技术对比及安全容器技术发展趋势随着Serverless等技术的兴起、应用部署和运维工作已经下沉到云平台,人们需要一个更高效的云原生技术平台。从近几年安全容器实现技术的出现可以看出,无论是公有云还是私有云厂商都已经意识到,将虚拟化的隔离性与容器的高效运维特性相结合是云原生平台发展的必然趋势.结合目前安全容器实现中遇到的一些问题,我们可以预见该技术未来发展的几个趋势:需要一个轻量级的安全容器hypervisor。目前,qemu+kvm是主流的虚拟化技术,但由于qemu是为通用虚拟机设计的,体积过大,而对于安全容器来说,模块化、可定制的虚拟化实现尤为重要。如果结合gVisor和nabla的实现,内核的可定制性也是安全容器场景的必然需求。rust-vmm就是这样一个模块化的虚拟化组件库。linux内核本身的模块化可以部分满足容器场景下的内核定制化需求,但是实现像gVisor这样专为容器设计的内核可能是未来的趋势。容器的启动时间是衡量云原生平台效率的重要指标。尤其是在serverless场景下,程序本身的运行时间可能会很短。这时候启动时间可能会占去大部分,所以这种低效率表现的尤为明显。明显的。安全容器的超轻量级可以将容器启动时间降低到100ms以内,但是拉取容器镜像的时间过长仍然是当前容器部署过程中的短板。由于目前容器镜像格式和镜像挂载方式的限制,需要在容器启动前将容器镜像拉取到本地,才能启动容器。容器启动本身所需的数据只占镜像的6%左右。因此,我们迫切需要一种高效的镜像挂载方法。目前已经有一些免费下载和延迟加载(Lazy-Loading)的技术雏形,我们需要尽快推出商用的图片下载加速方案。3、目前的公有云网络普遍采用原有的IaaS网络管理模式,在地址分配和网络配置效率上跟不上容器快速启停的需求。docker容器使用的veth方式在性能上也难以满足高效转发。要求。因此,需要专门为云原生设计的网管解决方案。4、我们看到云平台逐渐深化对应用的管理,从只管理基础设施的IaaS层,发展到管理应用整体部署和运维的PaaS层,现在ServiceMesh技术将平台管理融合在一起功能深入到应用程序内部的微服务级别。同时,我们也看到,以K8s容器、Istio服务网格为代表的云原生技术,逐渐与底层计算/网络虚拟化技术融合。例如,安全容器是容器与计算虚拟化的结合,而Istio服务网格也将与虚拟化网络深度融合,提供更高的性能和更精细的QoS控制。5、目前硬件加速技术在AI、大数据等领域大行其道。安全容器需要结合各种计算加速硬件技术,让AI、大数据、科学计算等批量计算领域的用户可以使用云平台直接下发海量计算任务,大大减轻用户的精神负担底层技术。硬件加速也是提高云平台自身效率、降低云平台运营成本的有效手段。例如,华为云架构在硬件加速方面的技术优势,在“安全容器”领域得到充分证明。CCETurbo裸机容器实现了安全容器的部分硬件卸载能力。综上所述,未来必然是云原生技术大行其道的时代。我们看到,很多传统行业已经逐渐意识到,云原生技术可以为传统企业的IT软件、工业自动化、在线运维、数据管理等带来显着的效率提升。.我们会看到,通过底层硬件和上层服务的全栈融合,打造一个高效智能的云计算技术平台,而容器将是连接整个技术栈的关键。