goodelephant 2020-06-10
本文的所有分析是基于Kata容器1.6.2版本。
在参加了2019年伦敦OpenInfra Days的Kata容器研讨会之后,我们对它们的启动时间印象比较深刻,与Kubernetes集群中的普通runC容器相比仅稍慢一些。我们自然而然的对它们的磁盘I/O绑定性能以及它们是否也符性能要求感到好奇。在本文中,我们将探讨这个主题,以了解在I/O绑定性能和安全性都是关键需求的环境中使用此技术的利弊。
什么是Kata容器?
Kata容器是轻量级vm,旨在与Docker和Kubernetes等容器编排软件无缝集成。设想的一个用例是运行不受信任的工作负载,利用不与主机共享操作系统内核所获得的额外隔离。然而,在最近一次对虚拟机和容器的调查中,使用宿主机内核导致额外安全性这一毫无疑问的假设受到了挑战。Kata源于Intel Clear Containers和Hyper runV技术。gVisor的目标是通过过滤和重定向系统调用到单独的用户空间内核来解决类似的问题。因此,gVisor会受到运行时性能损失。关于gVisor的进一步讨论超出了本博客的范围。
为Kata配置Kubernetes
Kata容器符合OCI,这意味着支持外部运行时类的容器运行时接口(CRI)可以使用Kata来运行工作负载。这些CRI的例子目前包括CRI-O和containerd,它们都默认使用runC,但这可以替换为kata qemu运行。从Kubernetes 1.14+开始,RuntimeClass特性标志已升级到beta,因此默认启用。因此,设置相对简单。
目前Kata支持qemu和firecracker hypervisor后端,但对后者的支持被认为是初步的,特别是缺乏主机到客户的文件共享。这让我们将kata qemu作为当前的选项,其中virtio-9p提供了基本的共享文件系统功能,这对分析至关重要(测试路径是安装在主机上的网络文件系统)。
没有这些先决条件,Kata启动将无声地失败(我们很难学到了这一点)。
这个示例要点展示了如何在Minikube集群中将runC替换为Kata运行时。注意,在编写本文时,Kata容器有额外的主机要求:
Kata将只在配置为支持嵌套虚拟化的计算机上运行。
Kata至少需要一个Westmere处理器架构。
如果没有这些先决条件,Kata的将悄无声息地失败(我们是从多次实践中得到的)。
为了进行此分析,部署了一个裸机Kubernetes集群,使用OpenStack Heat通过我们的appliances playbooks配置机器,并使用Kubespray将它们配置为Kubernetes集群。Kubespray支持除Docker之外的其他容器运行时规范,例如CRI-O和 containerd,这是支持Kata运行时所必需的。
设计I/O性能测试方案
为了对Kata容器的I/O性能进行基准测试,我们在裸机和runC容器的情况下提出了等效的场景来进行比较。在所有情况下,我们都使用fio(3.1版)作为I/O基准测试工具,调用方式如下,其中$SCRATCH_DIR是安装在主机上的BeeGFS(本节稍后将详细介绍)网络存储的路径:
fio fio_jobfile.fio --fallocate=none --runtime=30 --directory=$SCRATCH_DIR --output-format=json+ --blocksize=65536 --output=65536.json
该fio_jobfile.fio上述引用的文件内容如下:
[global]
; Parameters common to all test environments
; Ensure that jobs run for a specified time limit, not I/O quantity
time_based=1
; To model application load at greater scale, each test client will maintain
; a number of concurrent I/Os.
ioengine=libaio
iodepth=8
; Note: these two settings are mutually exclusive
; (and may not apply for Windows test clients)
direct=1
buffered=0
; Set a number of workers on this client
thread=0
numjobs=4
group_reporting=1
; Each file for each job thread is this size
filesize=32g
size=32g
filename_format=$jobnum.dat
[fio-job]
; FIO_RW is read, write, randread or randwrite
rw=${FIO_RW}
Scenario 客户端数量 磁盘I/O模式
裸机 1 顺序读取
runC容器 8 随机读取
Kata容器 64 顺序写
随机写
为I/O性能研究探索的参数空间涵盖了36种方案、客户机数量和磁盘I/O模式的组合。
结果
磁盘I/O吞吐量
在这些结果中,我们绘制了所有客户端上的总带宽,展示了单个客户端可以实现的向上扩展带宽以及许多客户端上实现的向外扩展吞吐量。
裸机,runC和Kata之间的磁盘I/O带宽比较。在所有情况下,使用runC容器实现的带宽都略低于裸机。但是,Kata容器的性能通常要差得多,当有64个客户端时,其获得的裸机读取带宽大约为15%,随机写入带宽的比例要小得多。唯一的例外是使用64个客户端的顺序写入情况,其中Kata容器的性能好于裸机方案约25%。
提交延迟累积分布函数(CDF)
在对延迟敏感的工作负载中,I/O延迟可能占主导地位。I/O操作提交延迟按对数比例绘制,以适应非常广泛的数据点。
分别针对1、8和64个客户端的裸机,runC和Kata容器环境之间的提交延迟CDF的比较。与将它们作为runC容器运行相比,在裸机中运行fio作业之间存在微小差异。但是,将裸机与Kata容器进行比较,在所有情况下的开销都非常大。
Number of clients > 1 8 64
Mode Scenario 50% 99% 50% 99% 50% 99%
sequential read bare 1581 2670 2416 3378 14532 47095
runC 2007 2506 2391 3907 15062 46022
Kata 4112 4620 12648 46464 86409 563806
random read bare 970 2342 2580 3305 14935 43884
runC 1155 2277 2506 3856 15378 42229
Kata 5472 6586 13517 31080 109805 314277
sequential write bare 1011 1728 2592 15023 3730 258834
runC 1011 1990 2547 14892 4308 233832
Kata 3948 4882 4102 6160 14821 190742
random write bare 1269 2023 3698 11616 19722 159285
runC 1286 1957 3928 11796 19374 151756
Kata 4358 5275 4566 14254 1780559 15343845
该表总结了与之前显示的数字相对应的50%和99%的提交延迟(以μs为单位)。*
展望未来
在这种I/O密集型方案中,Kata容器尚未达到传统容器的性能。
从结果可以明显看出,在裸机、runC容器和Kata容器之间进行选择时,需要权衡取舍。尽管runC容器为大多数用例提供了更完善的考量,但它们仍然使主机内核易于受到系统调用接口作为攻击面的利用。Kata容器提供了硬件支持的隔离,但是目前存在巨大的性能开销,尤其是对于磁盘I/O绑定操作。
Kata的发展路线图和发展速度拥有坚实的基础以及乐观的前景。Kata团队已经意识到使用virtio-9p作为存储驱动程序在主机和来宾VM之间共享路径的性能缺陷。