虚拟化技术是云计算的根底,目前大量的私有云以及公有云环境都抉择 KVM 作为Hypervisor。KVM 作为 Type 2 型的零碎级硬件辅助虚拟化技术的典型计划,绝对于 Xen 的劣势有:
KVM 作为一个 Linux 内核模块形式实现,因而其硬件生态兼容性、扩展性较好;KVM 中没有实现调度等性能,而是依赖 Linux 内核的实现,如 Linux 的调度器,实现充分利用了 Linux 内核的成熟模块,实现绝对精简。
然而随着 FaaS、Serverless 等新场景的呈现,KVM 现有的实现就显得简单了。新的场景趋向于以容器为核心,虚拟化技术在新的场景中次要的作用是补救传统容器技术的隔离性有余的问题。因而对于 KVM 技术有进一步轻量化的需要。
Rust 作为内存平安语言曾经被业界宽泛认可。但 Rust 语言不只是谋求平安,而且在并发和性能方面也有很好的体现,因而 Rust 不仅被很多大公司如 AWS、微软、Google 等用于应用软件的开发,而且其曾经用于构建操作系统,比方 Redox OS。
Rust 也逐步成为将来底层软件开发的首选语言。目前 Rust 曾经被 Linux 内核开源社区承受作为开发语言,次要用于 Linux 内核驱动模块的开发。
一、Why LiKeX ?
LiKeX 是一个对 KVM 的 Rust 重构我的项目,但又不仅仅是简略的重构。
LiKeX 中的「Li」代表轻量,「K」代表 KVM,「e」代表 extension,「X」是一个对立的后缀对于下一代云原生 OS 我的项目。
LiKeX 我的项目开发的指标是针对 FaaS 场景,提供轻量化的 Hypervisor 解决方案。在架构设计上,思考到 FaaS 利用的特点:单实例短生命周期,单实例资源占用低,高实例密度,因而 LiKeX 在不少设计上与 KVM 有较大差别,局部比照项如下:
项 | KVM | 指标意义 |
---|---|---|
实现语言 | C | Rust |
lapic/ioapic/pic 模仿 | 多种实现形式组合 | lapic 内核模仿,ioapic/pic用户态模仿 |
PIT 模仿 | 内核或用户态都反对 | 不实现 |
KVM 设施文件 /vm/vcpu | 每个层面都是一个独立的文件句柄 | 共享一个文件句柄 |
指令模仿 | 内核态实现 | 用户态实现 |
mmio 解决 | 用 ept misconfig,通过 mmu 页表追踪 mmio 区域 | 不应用 ept misconfig |
同时 LiKeX 在设计上尽量放弃用户态接口与 KVM 兼容或者最小批改,这样对于基于 KVM 的设施模仿组件 VMM 能够较容易的迁徙到 LiKeX 上。
二、LiKeX 现状
目前,LiKeX 我的项目曾经开源到 OpenCloudOS 社区并在社区内进行继续演进,同时, LiKeX 我的项目曾经实现阶段性指标,能够加载一段用户态程序到 Guest 态运行,并反对多个 memslot。
测试程序(精简):
//Guest态运行的程序const unsigned char code[] = { 0xba, 0xf8, 0x03, /* mov $0x3f8, %dx */ 0x00, 0xd8, /* add %bl, %al */ 0x04, '0', /* add $'0', %al */ 0xee, /* out %al, (%dx) */ 0xb0, '\n', /* mov $'\n', %al */ 0xee, /* out %al, (%dx) */ 0xf4, /* hlt */ };//Guest内存区域struct kvm_userspace_memory_region region = { .slot = 0, .flags = 0, .guest_phys_addr = 0, .memory_size = 0x1000,};struct kvm_regs regs = { .rip = 0, .rax = 2, .rbx = 2, .rflags = 0x2,};void main(void){ fd = open("/dev/rust_kvm",O_RDWR); //关上rust_kvm设施 ret = ioctl(fd, KVM_CREATE_VM, 0);//创立虚拟机 mem = (unsigned long)mmap(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_ANONYMOUS, -1, 0); memset((char*)mem, 0, 4096); memcpy((char *)mem, code, sizeof(code));//拷贝Guest态代码到以后过程某段地址空间 region.userspace_addr = (uint64_t)mem; ret = ioctl(fd, KVM_SET_USER_MEMORY_REGION, ®ion);//传递Guest地址空间到内核局部到rust_kvm ret = ioctl(fd, KVM_CREATE_VCPU, 0); //创立VCPU run = (struct kvm_run *)mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); memset((char*)&sregs, 0, sizeof(sregs)); ioctl(fd, KVM_GET_SREGS, &sregs); sregs.cs.base = 0; sregs.cs.selector = 0; ioctl(fd, KVM_SET_SREGS, &sregs); ioctl(fd, KVM_SET_REGS, ®s); ioctl(fd, KVM_GET_REGS, ®s); while (loop0 < 8) { ioctl(fd, KVM_RUN, NULL); //进入Guest态运行 switch (run->exit_reason) {//从Guest态退出,依据退出起因在用户态调用对应处理函数 /* Handle exit */ case KVM_EXIT_HLT: return; case KVM_EXIT_IO: if (run->io.direction == KVM_EXIT_IO_OUT && run->io.size == 1 && run->io.port == 0x3f8 && run->io.count == 1) printf("exit io:%c \n", (*(((char *)run) + run->io.data_offset))); break; case KVM_EXIT_FAIL_ENTRY: printf(" fail entry\n"); memset((char*)®s, 0, sizeof(regs)); ioctl(fd, KVM_GET_REGS, ®s); return; case KVM_EXIT_INTERNAL_ERROR: printf(" internal error\n"); return; default: printf(" default:0x%x\n", run->exit_reason); return; } loop0++; }}
内核局部运行后果:
rust_kvm: Rust KVM Openrust_kvm: Rust kvm: vmcs=ffff888110f02000,revision=4rust_kvm: written new cr4 valuerust_kvm: Rust kvm: IOCTL_KVM_CREATE_VMrust_kvm: Rust kvm: IOCTL_KVM_SET_USER_MEMORY_REGIONrust_kvm: add_memory_region slot= 0,uaddr=7f531f3e5000, gpa = 0, npages=1rust_kvm: Rust kvm: IOCTL_KVM_CREATE_VCPUrust_kvm: RkvmMmu hpa(va) = ffff88811d6ed000rust_kvm: RkvmMmu hpa(phy) = 11d6ed000rust_kvm: ad_disabled = false, ecex_only = truerust_kvm: setup pin=17,cpu=a581e5f2, cpu2=82,exit=3fefff, entry=d1ffrust_kvm: pin_based = 17rust_kvm: cpu_based = a581e5f2rust_kvm: cpu_2nd_based = 82rust_kvm: vcpu_vmcs_initrust_kvm: init_mmu_rootrust_kvm: hpa= 11d6ed000, eptp = 11d6ed01erust_kvm: Rust kvm: IOCTL_KVM_CREATE_VCPU finishrust_kvm: Rust KVM mmaprust_kvm: Rust kvm: IOCTL_KVM_GET_SREGSrust_kvm: Rust kvm: IOCTL_KVM_VCPU_RUNrust_kvm: vcpu_run state guest rip = 0, read guest rip = 0rust_kvm: vmentry: launched = falserust_kvm: Enter handle EPT violationrust_kvm: pagefault: pfn=1999950rust_kvm: rkvm_tdp_map level=4, gfn=0, spte=14a55c907rust_kvm: rkvm_tdp_map level=3, gfn=0, spte=1567bf907rust_kvm: rkvm_tdp_map level=2, gfn=0, spte=11bcc5907rust_kvm: rkvm_tdp_map level=1, gfn=0, spte=6000001e844eb07rust_kvm: ret=Ok(1),after vcpu_exit_handlerrust_kvm: vmentry: launched = truerust_kvm: vmexit: guest_rip=7rust_kvm: handle_io port =3f8rust_kvm: ret=Ok(0), after vcpu_exit_handlerrust_kvm: vmentry: launched = truerust_kvm: vmexit: guest_rip=9rust_kvm: handle hltrust_kvm: ret=Ok(0), after vcpu_exit_handler
LiKeX 我的项目作为 OpenCloudOS 下一代云原生 OS 的一部分,其在整个零碎中的地位如下图:
从架构上看,分为 Guest 和 Host 两局部,作为 Host 局部的重要组成部分,LiKeX 为设施模仿组件 VMM 和容器编排引擎提供了更轻量、更平安的 Rust 根底,保障兼容原有协定,并依据用户需要扩大新协定,从而实现自主可控的下一代云原生操作操作系统。
三、小结
从整个 OpenCloudOS 云原生操作系统层面看,LiKeX 作为整个零碎虚拟化的底座,提供了轻量级平安的 Hypervisor,可能更好的反对下层 FaaS 等新场景。
总之,LiKeX 我的项目心愿从架构和性能两个方面以 Rust 语言从新开发出适宜 FaaS 等新场景的轻量、平安的 Hypervisor,以达到晋升容器部署密度、启停速率、隔离安全性的指标。
目前,LiKeX 我的项目已在 GitHub 开源,欢送对我的项目感兴趣的开发者,退出咱们,一起进行 LiKeX 的代码共建,我的项目地址:https://github.com/OpenCloudOS/LiKeX
欢送扫描下方二维码,退出社区用户群,理解 OpenCloudOS 最新动静,获取技术相干的反对,分享交换应用体验。