ImageApparate(幻影)镜像加速服务让镜像分发效率提高 5-10 倍

做者介绍

李昂,腾讯高级开发工程师,主要关注容器存储和镜像存储相关领域,目前主要负责腾讯容器镜像服务和镜像存储加速系统的研发和设计工做。node

李志宇,腾讯云后台开发工程师。负责腾讯云 TKE 集群节点和运行时相关的工做,包括 containerd、docker 等容器运行时组件的定制开发和问题排查。python

洪志国,腾讯云架构师,负责 TKE 产品容器运行时,K8s,容器网络,mesh 数据面等基础组件研发。nginx

背景

在业务广泛已经完成容器化的大环境下,不一样的业务场景对于容器启动需求也是不一样的,在离线计算和一些须要快速增长计算资源(伸缩组)的在线服务场景下,每每对于容器的启动速度有较高的要求。算法

在容器启动的整个周期中镜像拉取的时间每每占据 70% 甚至更多。据统计,某离线计算业务因容器镜像较大,每次扩容上千 Pod 耗时高达 40 分钟。镜像分发成为容器快速弹性伸缩的主要障碍。docker

ImageApparate(幻影)

为了解决这个问题,腾讯云容器服务 TKE 团队开发了下一代镜像分发方案 ImageApparate(幻影), 将大规模大镜像分发的速度提高 5-10倍
benchmark.png后端

应对既有 Docker 下载镜像模式带来的问题,社区新方案的讨论主要在镜像数据的延迟加载(Lazy-Pull)和新镜像格式的设计再也不以层为最小单位,而是 chuck 或者镜像内文件自己。缓存

不过,目前看OCI V2离咱们依然还很远,当前咱们经过何种方式来应对这类场景呢?网络

回到问题自己,当前OCI V1和容器运行时交互逻辑须要先下载完整镜像才能运行容器,可是容器启动和运行时到底会使用镜像内的多少内容,这篇论文 FAST '16 统计了 DockerHub 中一些常见的官方镜像在其使用启动后须要读取的数据量,得出的结论是仅有平均 6.4% 的内容须要读取。也就是说镜像中的大部份内容可能在容器的整个生命周期内根本不须要,那么若是咱们只加载 6% 的数据就能够大幅减小镜像拉取时间,从而加速容器启动速度,这也就为后续的优化提供了理论前提。session

所以减小容器启动时间的重点就在容器的 rootfs 即容器镜像的获取上。架构

基于此前提,在兼容OCI V1的框架下,TCR 推出了 ImageApparate(幻影) 容器镜像加速服务。首先直接放结论,在 200 节点且镜像内容占镜像总大小的 5% 到 10%。如上所述,相比于传统的下载所有镜像的方式,ImageApparate 在容器所有启动时间上都有 5-10倍 的提高。并且本测试主要并不仅是关注容器建立时间,而是继续测试了从容器启动到业务进程能够提供服务后的整体时间:

  • 顺序读取 500MB 大文件测试了包括从容器启动后到顺序读取 500MB 文件完成后的时间
  • 随机读取 1000 小文件测试了包括从容器启动后到随即读取 1000个 4k-16k 完成后的时间
  • 执行 python 程序测试了包括从容器启动后加载 Python 解释器执行一段简单的 python 代码完成后的时间
  • 执行 gcc 编译测试了包括从容器启动后执行 gcc 编译一段简单 C 代码并运行完成后的时间

ImageApparate 方案设计

传统模式的问题

自 Docker 发布以来云计算领域发生了巨大的变革,传统虚拟机逐步被容器替代。Docker 秉持 Build, Ship And Run 的理念出色的完成了容器运行时和容器镜像的设计,引领整个容器行业。可是随着时间的推移容器的 Ship And Run 在面对普遍的用户需求场景中也逐渐暴露出一些问题。

传统容器启动和镜像下载方式为:

  1. 访问镜像仓库服务获取权限认证以及获取镜像存储地址
  2. 经过网络访问镜像存储地址下载所有镜像层并解压
  3. 根据镜像的层信息使用联合文件系统挂载所有层做为rootfs,在此文件系统上建立并启动容器

traditional1.png

  1. 容器镜像的设计从 Docker 发布至今一直沿用下来,并已经成为事实标准也就是咱们如今使用的OCI V1,使用分层的设计大大减小空间占用,利用各种联合文件系统(Aufs、Overlayfs)将每层联合挂载起来造成一个完整的RootFS只读根文件系统,容器运行时的写入操做会在联合文件系统的最上层的读写层,很是精巧的设计。

    可是,开发者和用户对于速度追求是永无止境的,随着业务上云的普遍普及,为了充分发挥云上资源的弹性能力,用户每每须要新扩出来的计算节点能够用最快的速度使用容器化的计算能力(容器启动服务能够接受流量),而此时这个全新节点就须要下载容器镜像所有的层,大大拖慢容器启动速度,在这个场景下容器镜像的分层设计没有获得充分的利用,彻底失效了。

    针对OCI V1容器镜像格式的一些问题社区也开始有集中的讨论,当前tar包做为OCI V1的镜像层分发格式主要有如下问题:

    1. 不一样层之间的内容冗余
    2. 没有基于文件的寻址访问能力,须要所有解包后才能访问
    3. 没有并发解包能力
    4. 使用 whiteout 处理文件删除在不一样存储类型中转换致使解压效率低下

TCR-Apparate OCI制品

咱们设计的目标是面向生产级别,在节点上同时支持镜像加速模式和普通模式,为了和正常OCI V1镜像存储解耦,咱们开发了镜像附加存储IAS(ImageAttachStorage)结合镜像Manifest中的外部层类型(Foreign Layer),能够在契合OCI V1语义下完成加速镜像的制做、上传和下载,继承原有镜像权限的同时,加速后的镜像Manifest索引以 OCI 制品形式存储在镜像仓库自己的存储中。

在镜像格式方面为了支持按需加载和克服tar格式以前的一些缺点,ImageApparate 使用了只读文件系统代替了 tar 格式。只读文件系统解决了镜像层内文件寻址能力同时又具有成为Rootfs可靠的性能。ImageApparate 仍然使用分层的设计在Manifest外部层中直接指定附件存储地址,附加存储层IAS在下载镜像时就能够按需挂载。

用户开启镜像加速功能并设置相关规则后,push 镜像后 ImageApparate 会在后台运行以下流程:

  1. 用户以任意符合OCI V1接口标准的客户端(包括 Docker)Push 镜像到 TCR 仓库
  2. TCR 的镜像服务会将用户数据写入到镜像仓库自己的后端存储中,通常为 COS 对象存储。
  3. TCR 的镜像服务会检查镜像加速规则,若是符合规则会给 Apparate-client 组件发出 Webhook 通知,请求转换镜像格式。
  4. Apparate-client 组件收到通知后会把 COS 数据写入到IAS中,使用特定算法把此镜像的每一个 Layer 逐个转换为支持 ImageApparate 挂载的 Layer 格式。

所以,对于 TCR 用户来讲只须要定义规则标记哪些镜像须要加速,而 CI/CD 的使用方式上没有任何变化,原来的开发模式瓜熟蒂落地继承下来。

appa-flow.png

镜像附加存储 IAS(ImageAttachStorage)

顾名思义,狭义的镜像附加存储IAS是除了自己的镜像后端存储以外的数据存储地址,IAS既能够和镜像仓库的使用相同的对象存储,也可使用 NFS 或者 Lustre。Apparate 中的镜像附加存储除了存储地址外,还包含一套插件化的接口(兼容Posix)和镜像层IAS中的布局(Layout)。IAS中每一个目录表明一个 Layer,这里依然会使用基于内容寻址(Content Addressable)复用内容相同层, 只读文件系统文件包含了这个原始层中的所有内容,随时能够经过加载元数据索引获取整个目录树。目前 Apparate 使用了腾讯云 CFS 高性能版做为IAS的一种实现,高吞吐低延迟 CFS 目前和镜像下载场景很是契合。

镜像本地缓存由不一样的IAS附加存储插件自身实现,目前 CFS 实现使用了 FScache 框架做为本地缓存能够自动按页缓存访问过的在远端存储上的部分数据,根据当前磁盘经过本地缓存能力,有效提高镜像数据重复访问的性能和稳定性。

IAS.png

运行时实现

当前 ImageApparate 在节点上使用的IAS附加存储插件被称之为 Apparate-snapshotter,是经过 containerd 的 proxy-snapshotter 能力实现的。

Apparate-snapshotter 主要负责解析记录在镜像层中的IAS信息,从而拿到另外数据存储地址,接下来 Apparate-snapshotter 会去数据存储服务中加载远程数据,并在本地提供访问的 Posix 入口。

好比在 CFS 场景下,会把远端数据 mount 到本地,并把挂载点做为接下来本地访问的入口。当须要使用远端数据时便由 snapshotter 或内核来提供按需加载的能力。

只读镜像格式

对于支持 Lazy-Pull 的镜像文件系统来讲,只读是很是关键的属性,由于只读文件系统不须要考虑数据写入和删除形成的碎片和垃圾回收,能够提早在制做文件系统的时候优化数据块和索引的分布,这样能够大幅提升文件系统的读取性能。

当前 IAS 支持的只读文件系统还增长了基于字母顺序排序的目录项索引(directory index),能够大大加速目录项的Lookup操做。

rofs.png

ImageApparate在TCR中使用方式

建立加速组件

当前 ImageApparate 在 TCR 中为 alpha 功能须要白名单开启。开启加速组件须要选择对应 CFS 的高性能版,请确认所在地域有此版本 CFS。
use1.png
use2.png

建立加速规则

建立加速规则,只有规则中匹配的镜像或者 Tag 才会自动加速。以后再向 TCR 推送镜像后能够看到匹配加速规则的镜像会生成后缀为-apparateOCI制品。
use3.png
use5.png

TKE 集群侧开启加速功能

在 TKE 集群中建立 TCR 插件时开启镜像加速配置,以后能够给须要加速的集群中节点打标签kubectl label node xxx cloud.tencent.com/apparate=true,集群中 Pod 的镜像能够仍然使用原镜像名字(例如上述test/nginx:1.9),加速插件支持自动选取已加速的镜像来进行挂载。若是镜像已被加速,那么观察 TKE 集群中 Pod 的 image 字段能够看到已被替换为 test/nginx:1.9-apparate。
use4.png

后续工做

当容器镜像是按需加载后,Layer(层)可能已经再也不是复用的最小单位了, ImageApparate 后续也会探索基于文件或者块镜像格式以及转换工具以得到更高的性能和效率。在接口侧镜像附加存储IAS也会支持更多数据源,包括和 TKE P2P 组件的集成,按需加载与 P2P 结合能够更好的应对超大规模镜像加载场景,大大减轻源站压力。

内测邀请

ImageApparate(幻影)镜像加速服务现已开启内测,咱们诚挚邀请您参与内测申请 ~ 名额有限,快快 点击这里 直达内测申请页面进行信息提交。

参考

相关文章
相关标签/搜索