随着容器及 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 相干的介绍,这个就是腾讯对于这一畛域的解决方案和奉献。
【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!