随着容器及K8s的宽泛应用,越来越多的容器平安与隔离问题被裸露进去,如:容器逃逸、程度攻打、DDos攻打等严重威胁了办公和生产环境的平安与稳固,影响了业务的失常运行。平安容器技术孕育而生,产生了kata、gVisor、unikernel等多种平安容器计划。本文旨在介绍各种平安容器计划,剖析各计划特点,联合腾讯在容器平安畛域的实际,帮忙读者抉择适宜本身个性的容器运行时。同时引入Rust-VMM我的项目,介绍 Rust-VMM 技术和生态,演示如何应用K8s调度和启用Rust-VMM平安容器运行时,瞻望以Rust语言实现的容器运行时的广大前景。
容器平安与隔离
一个基于K8s集群构建的基础设施中,外部存在不同档次的隔离,从容器到Pod再到节点最初到cluster,每一层隔离都有它的特点和个性,咱们尤其关注Pod级别的隔离个性。
相比其余档次的平安隔离,Pod及容器级别的隔离对咱们的挑战十分大。容器在运行时应用root运行过程,只管应用namespace技术为容器空间内的pid、uts、fib等进行了隔离,但因为各个容器共享零碎内核,容器与内核间不足隔离爱护,容易引发容器逃逸等平安问题,典型容器逃逸攻打如:CVE-2018-14634、CVE-2016-5195、CVE-2019-5736 及 CVE-2019-14271等。
docker.vh.neargle.com:8888/?command_exec=python3 -c "import docker;client = docker.DockerClient(base_url='unix:///var/run/docker.sock');data = client.containers.run('alpine:latest', r'''sh -c \"echo 'ssh-rsa xxxxx root@620e839e9b02' >> /tmp/root/root/.ssh/authorized_keys\" ''', remove=True, volumes={'/': {'bind': '/tmp/root', 'mode': 'rw'}})"
上述脚本是一个简略的例子,这段代码会向docker.sock的端口发动申请,拉起一个alpine的容器,容器内过程会向所在主机注入一段SSH的公钥。在容器里的歹意用户或者攻击者,就能够获轻松得这个容器所在host主机的SSH的登录权限,从而可能非法查看同主机其余容器空间的信息,篡改要害文件或记录,甚至以主机为跳板攻打整个集群。
还有一个就是Noisy Neighbor,就是吵闹街坊问题。对于Noisy Neighbor,容器方面曾经有了很多停顿,比方对于CPU、memory、bandwidth甚至是buffer IO,基于Cgroup对这些资源曾经有了一些隔离和限度,然而这些限度并不能齐全解决Noisy Neighbor的问题,还是有一些吵闹的过程会影响到失常的业务过程的运行。
# kubectl run --rm -it bb --image=busybox sh/ # f(){ f|f& };f # WARNING: Don't try this!
下面是一个简略的例子,启动一个busybox的容器,在外面执行一个嵌套循环的指令,会把这台主机上所有的file descriptor全副耗尽,造成这台主机上失常运行的业务过程工作不失常,这个是Noisy Neighbor的危险和问题。
对于上述问题,倡议用户关注官网的破绽报告,降级操作系统或docker的版本,依据平安指引配置容器环境,同时能够参考以下措施加强容器集群的平安防护级别。
- 在物理层面上隔离,为不同的租户之间划分不同的Hardware Isolation域,让不同的租户应用不同的硬件空间,从物理上、网络上以及存储上彻底的隔离,这也是最间接最无效的办法。
- 利用一些Security Tools,包含常常用的SElinux或者Cgroup隔离,划分不同的资源拜访和平安规定,然而这些平安规定须要编写大量的profile文件,实现起来难度颇大。
- 入侵检测机制,主机进攻的一种伎俩。入侵检测的软件或者过程会监控这台主机上有危险的过程或者有危险的文件,对于这些文件的读写操作都会有平安方面的记录,会即时预警,即时响应。比方对于containerd-shim/busybox/docker-runc的要害过程,比方docker-runc对于bash、init或者对于fd的拜访都能够做到即时的预警和标记。对于下面提到的容器逃离破绽,通过入侵检测的机制,就能够有一个比拟无效的进攻。
- 定制Linux Kernel Patch,一些非凡的资源隔离或者安全漏洞,也能够为kernel打一些本身特有的patch来加以防备,然而这里的patch面临的问题是多种多样的,所以这里就不再开展细讲了,如果有关注的同学能够参考一下腾讯对于Linux Kernel方面的一些文章和报道。
容器运行时
上述平安实际计划和措施可能很大水平的缩小对外提供服务时受攻打的范畴,进步容器服务的平安能力。但咱们依然想要寻找一种简略的、无效的、对立的runtime解决办法,咱们把眼光投入到CNCF runtime landscape,能够看到有多种解决方案。
简略梳理一下这些解决方案,都是依照两大规范划分的。一个就是CRI的规范,偏差于kubelet或者K8s这一侧的规范。还有一侧的规范就是OCI,就是偏差于容器底层根底实现。
能够看到OCI这边有很多种实现计划,简略梳理一下,划分了一个表格:
OCI Solution | OCI Compatible | Dedicated Docker Image | Implementation Language | Open source | Hot plug | Direct access to HW | Required Hypervisors | Backed by |
---|---|---|---|---|---|---|---|---|
Runc | yes | yes | golang | yes | no | yes | None | Docker |
gVisor + runsc | yes | yes | golang | yes | no | no | none or kvm | |
Kata + qemu | yes | yes | golang,C | yes | yes | yes | kvm | Hyper |
Firecracker + Firecracker containerd | no | yes | Rust,golang | yes | no | no | kvm | Amazon |
Nabla + runnc | yes | no | C,golang | yes | no | no | None | IBM |
简略介绍一下,比方有runc的计划,就是基于原生namespace的容器计划,docker应用的,containerd间接对接的runc的计划。GVisor是谷歌开源进去的一种基于用户态的内核过程的平安沙箱技术的计划。Kata和qemu的基于虚拟化实现平安容器,这个当初也是比拟热门,应用比拟宽泛的一种计划。Firecracker,由AWS开源进去的,Firecracker Containerd是对接OCI规范的组件,但当初还没有齐全对接OCI规范,所以这里是有所欠缺的。最初是Nabla, runnc是Nabla对接OCI实现的一个组件,Nabla是IBM开源的一套平安容器的计划,然而它跟上述的一些计划有所区别,它是一个基于unikernel的计划,把业务利用和内核齐全编译在了一起,间接运行在host下面,所以能够看到它跟其余的计划不一样的就是它不能间接应用容器的镜像,须要本人编译一个带着内核的非凡镜像,所以用起来不太合乎容器的规范。
比拟下来,典型的三种平安容器计划就是runc,kata-runtime,以及 gvisor 计划。
三种计划各有优缺点,从架构来说,runc的计划最简略,间接用原生的namespace的计划。kata是基于hypervisor的计划,就是基于虚拟化的计划,所以它的每一个容器或者它的容器是运行在一个一个guest kernel下面,就是guest的虚拟机里,而后会有一个kata agent负责runtime跟底层真正跑的container的进行通信。GVisor是介于runc和kata runtime之间,它不像Kata有一个虚拟化的Guest Kernel的存在,它是把Guest Kernel变成了一个运行于用户态的一个内核的过程叫做Sentry,Gofer是它IO的组件,外围的sentry负责的就是拦挡和劫持所有运行在它的沙箱外面容器的所有的Syscall,对系统调用进行过滤和爱护。
Solution | Typical Software | Bullet Point |
---|---|---|
Rule-based Sandbox | RunC | Needs to work with SELinux, AppArmor, Seccomp, cgroup |
VM-based Sandbox | Kata-container | BareMetal Only, Heavy control logic |
Application kernel based Sandbox | gVisor | Compatibility problem, Bottleneck in Sentry |
最初汇总比拟一下,runc的计划实现最简略,而且它的性能也是最好的。然而一大毛病就是平安隔离的个性不够平安,所以须要大量的内部Security Tools的爱护。
基于kata的虚拟化的沙箱计划,它只能运行在反对KVM虚拟化的环境下面,因为他的虚构层是基于KVM实现的。Kata的逻辑的链路很长,调用的门路也十分长,会造成一些性能上的损耗,也会有一些问题。
GVisor介于两者之间,然而GVisor当初的问题就是它的兼容性不够,300多个零碎调用只能兼容外面的一部分,并且Sentry的作为外围会有一些性能瓶颈。
腾讯云在平安容器上交融和上述计划的长处,联合腾讯云在虚拟化,存储和网络方面的劣势,
抉择应用mVMd + QEMU + EKLET的计划,实现一个弹性的Kubernetes的服务,即EKS,大家能够拜访一下腾讯云的官网,看一下EKS的介绍。
EKS是基于Hypervisor的虚拟化的解决方案,不同于Kata,EKS应用的containerd + mVMd组件更加轻量,调用门路更短。通过containrtd + mVMd来实现对于下层K8s调用的CRI的解析,并且把它转化成真正对于底层一个一个Guest VM或者QEMU的控制指令,在guest VM里会启动相应的containers容器。
在整个的架构中,在Runtime方面最大的瓶颈是QEMU,因为QEMU有几十年的历史了,所以存在着它比拟臃肿,反馈慢,占用的资源多等等问题。所以让QEMU作为底层Runtime还不够快,不够平安。为了加强QEMU的性能和平安个性,咱们很天然把眼光投向了Rust-Vmm。
Rust-Vmm 介绍
Rust-Vmm是一个开源工程,是一个能够自在定制的VMM(virtual machine monitor)虚拟机管理器,用户能够依照本人的形式订制它。它是基于Rust语言实现的VMM,有着Rust语言带来的长处和个性。
首先,Rust语言一个内存平安的语言,相比于用C或者C++会频繁遇到的各种内存的问题,比方内存的溢出、空指针、野指针、越界拜访等等,更进一步会造成平安的问题、性能的问题,以及各种解体的问题。Rust语言很好地解决了这一点,从它的语法、编译规定等杜绝了内存级别拜访的破绽以及危险,所以用Rust写的Rust-Vmm人造的就是内存平安的。
第二,Rust-Vmm是不易被攻打的,Rust-VMM是从零开始的,它是从最小的硬件虚拟化登程的,最小的硬件虚拟化意味着它有着最小的攻击面,被攻打的面就非常少,所以它会很平安。
第三,Rust-Vmm可能很灵便的定制。Rust-VMM能够灵便定制它的每一个组件,所有的对于设施的模仿或者要害个性的解决都是封装成了一个一个的Rust-Vmm crates包,比方有VCPU,有linuxloader,vm-virtIO等等。其中crates是Rust语言中的包管理工具,能够了解JAVA或golang外面的package,它是以发行不同的包或者库的模式对外公布它的feature。
第四,Rust-Vmm有十分高的性能,基于Rust语言的without garbage collection个性,它是没有GC回收查看机制的,不像JAVA或者其余更高级的语言会有一个runtime,Rust-Vmm的性能上会更好,同时基于KVM实现的虚拟化计划也是性能的保障。
简略介绍一下Rust-Vmm的一个历史,它是由谷歌首先实现的,谷歌首先实现一个Rust based的轻量级的VMM,它叫做crosVM,大家也能够从链接外面看到,它是一个为chrome浏览器做的一个微内核。而后AWS,亚马逊基于谷歌开源进去的crosVM,实现了本人的基于rust的VMM叫Firecracker。两个我的项目的开发人员会发现做这两个我的项目的时候,会有很多反复的重叠的通用的代码,很天然的把能够开源的、通用的局部联合到一块,就有了Rust-Vmm的我的项目。
从这个全景图外面能够看到,Rust-Vmm利用在多个我的项目和产品中。从最开始的谷歌开源的crosVM外面会有Rust-Vmm,比方AWS的Firecracker、以及其它CSP云服务器厂商,比方QEMU外面会把一些耗时的或者内存拜访的局部也用Rust-Vmm实现,还有开源的Cloud Hypervisor我的项目。
Cloud Hypervisor是Intel开源进去的一套框架,把Rust-Vmm的组件组合在一起,可能对外提供一个VMM的残缺服务。用户能够配置应用已公开公布的crates包,或集成本人的开发的crates包,通过将各种crates包组合在一起,就能够生成一个订制的平安的高性能的VMM。
基于 Rust-Vmm 实现 K8s Runtime
讲到这里,基于Rust-VMM的一个实现,组件、原料和所有的常识都曾经具备了,接下来就是如何对接K8s,基于Rust-VMM实现Kubernetes runtime,运行一个Kubernetes的Pod。
测试环境如图所示,用到了包含K8s, containerd, Kata, Rust-Vmm, Cloud Hypervisor等开源我的项目,首先咱们配置Kubernetes节点上的kubelet应用的runtime为containerd, 在containerd上配置了Kata-runtime作为容器的运行时,再配置了Kata-runtime应用的vmm为基于Rust-Vmm crates构建的Cloud Hypervisor,同时为了晋升性能,这里也是用了virtos-fs技术来承载物理机上的容器镜像到子机内容器的imagefs的共享,所以在物理机上须要额定开启virtiofsd的过程,在guest os的内核上也是应用最新的蕴含virtio-fs反对的内核版本。
在K8s上创立一个Pod后,调度器调度这个Pod到咱们这个环境上的一个worker节点,节点上的kubelet过程依据咱们的配置调用containerd,containerd的runtime插件kata来创立Cloud Hypervisor的vmm(virtual machine monitor),在子机内预置的Guest OS操作系统启动后,kata-agent也随之启动,胜利建设母机与子机的通道,后续cri协定中的createcontainer,startcontainer以及进行容器等接口也由这个通道传递到子机内的kata-agent,由其来调用子机内真正的容器运行时,从而实现整个pod的生命周期。
咱们来看一下最终咱们达到的一个成果,如图中第一条指令,咱们执行kubectl get pod命令能够看到pod的状态为运行中,同样的,咱们也能够通过crictl pods命令查问到这个Pod的状态。通过ps查问过程列表,能够看到蕴含这个pod id的kata shim过程,virtiofsd过程以及cloud-hypervisor这个vmm的过程。最初咱们也能够通过kubectl exec -it交互式的进入pod的container内,通过uname返回此容器应用的内核版本为5.6,物理机的内核版本为5.4。
总结与瞻望
最初是对将来的瞻望,基于Rust-Vmm咱们想要做得更多。比方心愿扩大一下Rust-Vmm在网络以及存储方面的一些个性,尤其是在腾讯云的环境外面,通过联合CBS和VPC,晋升Runtime的性能。
第二,会联合入侵检测、主机平安、平安工具等,把它们交融在一起,构建起一个多维的、多重防护的一套全维度平安的容器服务平台,Rust-VMM会实现外面的一部分。
第三,扩大Rust Runtime,尤其在边缘计算畛域,在边缘端可能实现K8s以下齐全由Rust接管,由Rust语言全副重写,比方底层的Containerd、 shim等组件,变成一个Full Stack Rust的实现。
最初,因为Rust-VMM也是基于hypervisor的一个实现,所以基于hypervisor的一些个性,比方热迁徙、备份、回滚这些机制,将来都能够在Rust-Vmm上有所实现,这个也是咱们的将来的一个构想。
最初大家如果想要理解更多对于我方才介绍的K8s Runtime,Rust-Vmm以及EKS方面的常识,大家能够扫描下方的二维码退出腾讯云容器团队的公众号。
或者点击下方的网址理解TKE的私有云产品。腾讯云对外也有一个开源进去的我的项目叫做TKEstack,大家能够从下方的github网址拜访失去,也心愿大家多多反对。
- Learn more about TKE:
https://cloud.tencent.com/pro...
https://github.com/tkestack/tke
- Join us:
https://careers.tencent.com/h...
最初如果大家有趣味,立志于开源事业,立志于CNCF的云原生事业,也欢送大家退出腾讯的团队。链接就在上方,欢送大家退出咱们。
Q&A
- 当初的Rust-VMM我的项目开源了,哪里能够看到我的项目相干的信息?
Rust-VMM是有谷歌,也有亚马逊、英特尔,也有业内的厂商独特开源进去的一个我的项目,相干的信息大家能够从github(https://github.com/rust-vmm)...,另外google一下就能够找到这个我的项目更多的信息。
- 基于Rust-Vmm成熟度如何,基于Rust-Vmm构建的平安容器次要解决了哪些难题。
大家能够比照一下AWS开源的Firecracker,它就是基于Rust-Vmm实现的一套亚马逊本人的计划,而且这套计划曾经利用在了亚马逊fargate以及lambda的我的项目,serverless的解决方案外面。所以基于Rust-Vmm这种我的项目的成熟度,亚马逊曾经把它做到商用了,这一点是有所保障的。
然而Rust-Vmm自身又是开源的我的项目,它是跟AWS的firecracker有不太一样的中央,成熟度方面必定是有所欠缺的,须要厂商本人保护和保证质量问题或者平安问题。
因而我想说基于Rust-Vmm实现的计划,亚马逊曾经帮咱们做了前驱的工作,曾经帮咱们做了一个商业上的试水,所以这个是没有问题的。
- 是否当初的私有云容器运行时都不偏向于应用runc。
不是不应用runc,应用runc有一些隔离的问题。比方两个租户共用一个物理资源池,或者两个租户的容器运行在一个物理节点上,这个时候就带来了容器逃离以及吵闹街坊的问题,多租户的场景下或者serverless的场景下就会有这种问题。
所以大部分的私有云厂商的解决方案其实就是物理隔离。一个租户所在的物理主机都是属于本人的,属于同一个租户的,所以你会发现某一个用户如果从一个容器外面逃离进来之后,逃离进来的这台主机还是本人的,所以这样逃出去,从物理下面还有平安防护的。
然而这种面对于serverless的场景,serverless人造的就是要脱离主机的治理、脱离主机的隔离,所以serverless场景下,跟私有云的容器服务就有所区别,它就不能简略靠物理隔离的形式实现的,它就要思考沙箱(平安容器)的技术,比方像方才我也介绍了多种多样的沙箱隔离的技术,咱们可能抉择的就是这种基于hypervisor的实现计划。
如果感兴趣,您能够拜访一下腾讯云的官网,看一下外面EKS相干的介绍,这个就是腾讯对于这一畛域的解决方案和奉献。
【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!