关于kubernetes:如何进行容器镜像加速-深度揭秘阿里云-Serverless-Kubernetes3

28次阅读

共计 3496 个字符,预计需要花费 9 分钟才能阅读完成。

容器相比虚拟机最突出的特点之一便是轻量化和疾速启动。相比虚拟机动辄十几个 G 的镜像,容器镜像只蕴含利用以及利用所需的依赖库,所以能够做到几百 M 甚至更少。但即便如此,几十秒的镜像拉取还是在劫难逃,如果镜像更大,则消耗工夫更长。

咱们团队(阿里云弹性容器 ECI)剖析了 3000 个不同业务 Pod 的启动工夫,具体如下图。能够看出,在 Pod 启动过程中,镜像拉取局部耗时最长。大部分 Pod 须要 30s 能力将镜像拉下来,这极大减少了容器的启动工夫。

如果是大规模启动,这个问题则会变得更蹩脚。镜像仓库会因为镜像并发拉取导致带宽打满或者服务端压力过大而间接解体。

咱们屡次遇到过这个问题。因为一个服务的正本数达到 1000+,在迅速扩容 1000+ 多个实例的时候,很多 Pod 都处于 Pending 状态,期待镜像拉取。

尽管 kubernetes 在调度的时候曾经反对镜像的亲和性,但只针对老镜像,如果并发启动的新镜像的话,还是须要从镜像仓库外面拉取。上面提供几种罕用的解决思路。

办法一:多镜像仓库

多镜像仓库可能很好升高单个仓库的压力,在并发拉取镜像的时候,能够通过域名解析负载平衡的办法,将镜像仓库地址映射到不同的镜像仓库,从而升高单个仓库的压力。

不过,这里有个技术挑战点:镜像仓库之间的镜像同步。

为了确保 Docker 客户端无论从哪个仓库都能够获取到最新的镜像,须要保障镜像曾经胜利复制到了每个镜像仓库。开源的镜像仓库 Harbor 曾经反对镜像复制性能,能够帮忙咱们将镜像散发到不同的仓库中。

办法二:P2P 镜像散发

多镜像仓库尽管可能缓解单个仓库的压力,但依然不能完全避免单个仓库被打爆的问题,而且多个仓库的运维老本也比拟高。相比而论 P2P 的计划则更加优雅。

说起 P2P 大家可能都不生疏,咱们罕用的迅雷下载就是应用了 P2P 的原理,还有最近比拟火的区块链技术底层也是基于 P2P 技术。

P2P 镜像散发的原理比较简单。首先将镜像分成很多的“块(block)”,如果某个 Docker 客户端拉取了这个块,那么其余的 Docker 客户端就能够从这个客户端拉数据,从而防止所有的申请都打到镜像仓库。Dragonfly 是阿里开源的 P2P 散发工具。原理如下图所示:

其中的 SuperNode 是大脑,负责存储“块”和客户端的关系,客户端第一次申请会被打到 SuperNode 节点,而后 SuperNode 回源去镜像仓库拉取数据转发给客户端,并且会记录这些块和客户端的对应关系。后续其余客户端申请这些块的时候,SuperNode 会通知客户端应该去方才胜利拉取的节点上获取数据,从而升高 registry 的负载。上面是咱们生产环境并发拉取 Tensorflow 镜像的实测的数据:

能够看到,当并启动数比拟低的时候,是否应用 P2P 影响不大,但随着并发数的减少,P2P 能够保障镜像拉取工夫稳固在 50s。而间接应用镜像仓库的话,拉取工夫会随着并发数一直减少,在 1000 并发的时候,曾经达到 180s 了。

办法三:镜像提早加载

OCI 分层的镜像格局是一把双刃剑。一方面,通过分层能够晋升镜像的复用,每次镜像拉取只须要拉增量的局部,另一方面分层的镜像也存在很多问题:

  • 数据冗余:不同层之间雷同数据在传输和存储时存在冗余内容,每次针对文件的一个小批改就须要复制整个文件;
  • 无奈针对小块数据的进行校验,只有残缺的层下载实现之后,能力对整个层的数据做完整性校验;
  • 难以实现跨层的删除,以后 OCI 设计中,删除一个文件只能通过 Whiteouts 文件玩了一个障眼法让用户看不到,实在的文件并没有删除。

那么,有没有一种不须要下载残缺镜像,只在读数据的时候长期加载镜像的计划呢?

依据统计显示,在镜像启动的时候,均匀只有 6.4% 的数据被真正应用到,其余 90% 多的数据都属于提早被应用或者压根用不到。就像手机外面的 App,咱们每天罕用的也就几个。于是诞生了一种新的镜像减速计划:提早加载。比拟风行的开源我的项目包含 stargz、dadi 以及 nydus。

这里还有一个技术细节,在 OCI 分层的镜像格局中,如何疾速找到一个文件呢?如果每次按需加载的时候都须要逐层查找效率就太低了。所以,为了实现镜像数据的低提早按需加载,咱们不能再应用传统的 OCI 镜像格局了,无论是 nydus、dadi 还是 stargz 都从新定义了一种新的镜像格局。

其中,Nydus 采纳了一种“拍平”的计划,将多个分层“拍平”成一层。元数据是一个目录树,每个叶子节点外面存储了数据块是索引,能够疾速定位到一个或者多个数据块。如下图所示,能够看到 Nydus 能够实现不同镜像之间块级别的共享。

回忆方才传统 OCI 镜像格局的弊病,应用 Nydus 格局不仅能够去重文件,而且能够实现块级别的按需加载。下图是 Nydus 按需加载的原理图:

通过用户态文件系统为 Pod 外面的容器提供 rootfs,当程序启动须要拜访某个数据的时候,如果发现本地没有,于是 nydusd 守护过程,便会回源到后端,将数据加载回来。和内核外面的缺页原理十分类似,只不过缺页用于内存懒加载,而 Nydus 利用于镜像文件的懒加载。

上面是 Nydus 镜像减速比照原生 OCI 镜像,在拉取工夫上的比照效果图,能够看到极大的缩短了镜像拉取工夫。(注:统计从镜像开始拉取到镜像拉取胜利的耗时)

镜像的按需加载不仅能够在文件系统层面实现,还能够下移到更底层的块设施实现,DADI 便是一种基于块设施提早加载计划。

容器应用层 I/O 通过文件系统转换为简略的 Block I/O request,传递给内核虚构块设施 overlayBD 并转发到用户态过程 lsmd。lsmd 负责对申请进行数据定位,读申请将从不同的上游数据源获取(registry/p2pagent/nas/localfile),写申请将间接写入本地文件系统。

下面的 Nydus 测试的是镜像拉取工夫,很多人会放心提早加载解决了镜像拉取耗时,那后续会不会影响利用启动呢?所以这次针对 DADI 的测试,咱们实测利用执行的耗时。比方,上面第一个 demo 是运行一个辨认猫狗图片的 AI 学习工作,排除 ECI 自身启动耗时之外,如果采纳 OCI 镜像须要 62s,而应用 DADI 镜像则只须要 14 秒。

最初,仔细的你可能曾经发现,无论是 Nydus 还是 DADI,不仅能够从 registry 加载数据,也能够从 dragonfly 加载,这就和下面计划二完满联合了。

办法四:镜像缓存

下面说的几种计划,最终还是须要拉取镜像。传统观念里,咱们必定是须要先把镜像拉到本地,而后启动容器的,但这并不一定是对的。咱们能不能不拉镜像,间接将镜像提前加载到一个存储外面,而后在启动容器的时候,间接将这个存储挂载到宿主机上,那么这台机器下面就人造具备这个镜像了,真正做到镜像仓库零压力和镜像拉取零耗时呢?

在 ECI 场景中,咱们设计了镜像缓存。事后将镜像下载并且解压到云盘,而后制作成云盘快照,等到用户启动容器的时候,先通过快照创立一个云盘,再将云盘挂载到 ECI 下面,从而省去了容器拉取工夫。无论是一个几百 M 的镜像还是几百 G 的镜像,在 ECI 上都能够 Pod 都能够实现端到端 10s 启动。

下面的介绍的这些镜像减速的计划,无论是 P2P、Nydus、DADI 还是镜像缓存,目前 ECI 曾经全副反对。ECI 的指标之一就是实现容器的极致弹性能力,所以咱们会一直优化容器的启动过程,缩短启动耗时,更用户带来更好的体验。

这篇文章次要介绍容器镜像减速的几种罕用计划。总结说来,次要是通过 P2P 升高镜像仓库压力,通过提早加载晋升容器和利用启动速度,还有通过云盘挂载的形式间接加载镜像,用户能够依据本人的场景抉择适合的减速计划。

容器启动的全链路中,除了镜像下载认为,还须要 Kubernetes 和 ECI 底层多个方面优化,后续文章会逐步为大家解密阿里云 ASK 设计过程中各种技术细节,请大家持续关注。

本文节选自阿里云技术专家陈晓宇的《深度揭秘阿里云 Serverless Kubernetes》系列专题。本专栏将次要围绕如何在 Serverless Kubernetes 场景中实现秒级扩容,以及在大规模并发启动中遇到的各种技术挑战、难点以及解决方案,系统地揭秘阿里云 Serverless Kubernetes 的倒退、架构以及核心技术。

(文章首发于 InfoQ 平台,原文链接)

作者简介

陈晓宇,阿里云技术专家,负责阿里云弹性容器(ECI)底层研发工作,曾出版《深入浅出 Prometheus》和《云计算那些事儿》。

相干浏览

故事,从 Docker 讲起 | 深度揭秘阿里云 Serverless Kubernetes(1)
如何进行架构设计 | 深度揭秘阿里云 Serverless Kubernetes(2)

正文完
 0