大规模并发下如何加快 Pod 启动速度

技术

picture.image

来源 | 火山引擎云原生团队

容器化的应用在真正能够运行业务逻辑前,需要经过镜像拉取、镜像解压、为容器运行时提供联合文件系统、容器启动、业务初始化等多个步骤,其中 容器镜像拉取 是所有环节中最耗时的。

在大规模集群下,镜像拉取如果耗时过久,对于流量突发场景,会影响业务的弹性效率;对于大数据、AI 的场景,会影响任务的吞吐性能。为缓解对于弹性效率的影响,研发团队需要提前更多时间预置节点,扩容业务容器;针对吞吐性能影响,需要扩大集群的规模。 然而上述操作都会在无形中造成成本上升。 因此镜像拉取的优化一直是容器服务重点优化的方向之一。

火山引擎容器服务 VKE(Volcengine Kubernetes Engine)深度融合新一代云原生技术,可提供高性能、高可靠、极致弹性的企业级容器管理能力。 在服务企业客户的过程中,为了进一步提升镜像拉取效率,帮助以 AIGC 为代表的企业敏捷、高效地落地 AI 技术,容器服务 VKE

结合 对镜像拉取环节问题的分析,从三个不同角度对镜像拉取进行了一系列优化:

picture.image

P2P 加速

在大镜像场景下,火山引擎容器服务 VKE 基于开源项目 Dragonfly,推出了 P2P 加速方案,来规避镜像仓库 CR 带宽有限的问题。

P2P 加速原理

Dragonfly 有如下组件:

  • Manager: 维护每个 P2P 集群之间的关系,动态配置管理。
  • Scheduler: 为下载节点选择最优的下载父节点,控制 异常 Peer 的回源。
  • Peer: Dragonfly 网络中的一个节点,也就是用户提出文件下载请求的计算机或服务器。

火山引擎容器服务 VKE 实现了对 Manager 和 Scheduler 的托管化改造,无需用户额外管理。VKE 中 P2P 组件 的工作流程如下图所示:

picture.image

  • 当一个 Peer(例如,Peer A)需要拉取镜像时,它会首先与 Manager 节点进行通信。
  • Manager 会检查所有在线的 Peer 的列表,考虑到各种因素(如网络连通性等)。
  • 选择合适的 Peer 作为 Parent Peer。 如果没有可供选择的 Parent Peer,Manager 会带领 Peer 直接从源服务器获取镜像。
  • Manager 把找到的 Parent Peer 信息发送给发起请求的 Peer A,包括每个 Parent Peer 的地址和服务端口。
  • Peer A 根据从 Manager 接收到的 Parent Peer 信息,从其它的 Peer 中下载镜像数据。
  • Scheduler 模块会持续监控整个文件下载过程。 如果发现 Parent Peer 下载速度过慢或者出现错误的情况,它将重新从 Manager 获取新的 Parent Peer 进行下载。
  • 当获取整个镜像后,Peer A 就成为了该镜像的一个分发节点,所有的镜像数据都会直接从一个 Peer 传输到另一个 Peer。

如果此时有另一个 Peer(例如 Peer B)也需要同样的镜像,那么当 Dragonfly 收到 Peer B 的请求时,同样经过 Manager、 Scheduler 的处理,最后会从已经保存了该镜像的 Peer A 那里拉取数据,从而实现了 P2P 的镜像分发。

使用流程

在火山引擎上使用 P2P 的大致的流程如下 :

前置条件:

  • 有 可用的 VKE 集群
  • 有可用的标准版镜像仓库实例

操作步骤:

  • 在标准版镜像仓库实例内开启对应 VKE 集群的 P2P 分发能力
  • 在 VKE 集群内安装 p2p-accelerator 组件

下图展示了实际的加速效果:

picture.image

数据显示,使用 Dragonfly 后,拉取镜像的时间在不同程度上得到了缩短,效率提升了 6 倍以上,甚至在规模较大的情况下,可以达到 200 倍。 在普通的场景下,Pod 的拉取镜像时间基本上呈指数递 增的趋势, 但在 Dragonfly 的场景下 ,它有效地控制了增长趋势,用户 能在一分钟内完成一个 3G 镜像的拉取,即使并发拉取的规模达到了 500 量级,这个时间也几乎是恒定的。

容器镜像懒加载

根据研究分析(论文: https://www.usenix.org/conference/fast16/technical-sessions/presentation/harter ),容器镜像中的绝大部分文件内容在容器启动阶段都是不需要被读取的,因此这部分内容在容器启动阶段不需要预先下载。

容器镜像懒加载技术使得容器运行时在启动容器前, 不需要将整个容器镜像全量下载到计算节点的本地文件系统,尽可能地降低镜像下载对容器端到端启动时间的影响。当容器需要读取镜像中的文件内容的时候,懒加载技术才会从镜像中心下载对应的数据块并解压。

Dragonfly 社区曾对比过 OCI 镜像和 Nydus 镜像的容器启动耗时,发现 Nydus 镜像的性能显著优于 OCI 镜像,尤其是当 OCI 镜像大小增加时:

picture.image

基于上述数据,火山引擎容器服务 VKE 兼容了 Dragonfly 的开源子项目 Nydus 作为容器镜像懒加载方案的技术底座。 借助 VKE 内置的的容器镜像懒加载能力和火山引擎容器镜像中心服务 CR 的一键镜像转换服务,用户可以便捷地使用镜像懒加载技术快速启动容器。

使用镜像懒加载前,用户需要将 OCI 镜像转换成 Nydus 的镜像格式。用户可以使用 Nydus 社区的工具在本地转换后推送到任何满足 OCI 规范的镜像中心;或者使用火山引擎镜像中心服务 CR 内置针对 Nydus 镜像格式转换服务 —— 将托管在 CR 的 OCI 镜像一键转换成 Nydus 镜像。

具备 Nydus 格式的容器镜像后,用户在创建 VKE 集群的时候,只需要打开节点池支持“懒加载”的开关,VKE 集群便具备了使用懒加载格式镜像的全部配置。更加详细的使用步骤可以参阅: www.volcengine.com/docs/6460/1130434

自定义系统镜像+预热

如果容器镜像非常大,且镜像中的大部分 layer 都不会频繁变更,加之对镜像拉取的速度要求又比较高时,工程师可以考虑使用自定义系统镜像的方案。

自定义镜像原理

为了避免混淆,这里先明确两个“镜像”:

  • 自定义系统镜像 :云上 ECS 所使用的 OS 镜像,对一台运行中的 ECS ,可以将 ECS 中的内容导出为“自定义镜像”,方便后续再基于这个“自定义镜像”来创建新的 ECS。

自定义镜像是您自行创建或上传的镜像,是您的私有镜像。镜像中除操作系统外,您还可以预装公共应用或私有应用,具有更高的定制化性。适用于需要重新部署复杂初始化系统或多次部署同样配置服务器的场景。关于“系统镜像”的更多信息,请参考: www.volcengine.com/docs/6396/801453

  • 容器镜像 :创建 Pod 时所需要的 image,一般通过 Dockerfile 构建后推送到镜像仓库中,启动 Pod 时再从镜像仓库拉取到节点上。

如果容器镜像巨大,Pod 在启动时会消耗大量的时间在拉取容器镜像上。容器镜像的拉取耗时,取决于 layer 数、layer 的大小、镜像仓库的下载带宽、拉取 layer 的并发度、节点上磁盘的写入速度等因素。

我们可以将容器镜像的数据,提前预置到自定义系统镜像中,避免在 Pod 启动再花时间去拉取容器镜像。

picture.image

picture.image

使用流程

在火山引擎容器服务 VKE 中制作自定义镜像的大致流程如下:

  • 创建 ECS
  • 在 ECS 中安装、启动 Containerd
  • 利用 ctr 或者 crictl 命令拉取容器镜像
  • 卸载 containerd 和其他临时文件
  • 将 ECS 导出为自定义镜像

如果直接使用上述方式手动构建自定义系统镜像,会有以下问题:

  • 需要用户手动操作,流程较为繁琐且易出错
  • 制作出来的自定义系统镜像无法被 VKE 识别,VKE 只识别带有特定标签的自定义系统镜像
  • 首次使用自定义系统镜像创建 ECS 时,因系统镜像未预热,创建耗时较长

因此火山引擎提供了两种方式来构建自定义系统镜像:

【推荐】Docker CLI :在安装了 Docker 的节点上,执行一条 docker run 语句,自动完成 ECS 的创建、 ECS 中拉取容器镜像、导出这个自定义系统镜像并完成预热。具体使用方式可以参考: www.volcengine.com/docs/6460/357229

手动基于 ECS 来创建自定义镜像 :在某些场景下,除了期望能在系统镜像中预置容器镜像外,还期望能安装自己的软件包、安装特定的 GPU 驱动,此时我们可以使用这种方式,自己在 ECS 中执行操作,最后执行特定的脚本执行镜像的打包检查、导出自定义镜像。具体使用方式可以参考: www.volcengine.com/docs/6460/1159228

picture.image

通过自定义系统镜像,在大批量扩容时,可以规避拉取镜像的操作,从而提升了业务 Pod 的启动速度、减少节点上因拉取镜像而带来的磁盘写入和网络下载。不论容器镜像多大,Pod 在启动时的镜像拉取耗时,都可以收敛到 秒级 以内。但因容器镜像固化到系统镜像内,之后可能会需要不断重新制作自定义系统镜像以便更新容器镜像内容,因此需要合理取舍 Pod 的启动性能、制作频率和制作成本。

总结

为 了加快 Pod 启动速度,容器服务 VKE 提供了不同的方案进行优化。用户 可以根据场景采取合适的方法。

picture.image

综上所述,自定义节点镜像和预热在使用流程上多了镜像拆分和节点镜像预热的步骤。但在预热后,整体拉取镜像的时间和性能,不会受其他因素影响。镜像频繁变动场景,需要再次制作自定义节点镜像、重新进行镜像预热, 因此在镜像变动频繁的场景,可以使用 P2P 加速 或镜像懒加载方案,也可以结合使用该两个方案。

picture.image

扫码咨询

  • END -

相关链接

[1] 火山引擎: www.volcengine.com

[2] 火山引擎 VKE: www.volcengine.com/product/vke

火山引擎云原生团队

火山引擎云原生团队主要负责火山引擎公有云及私有化场景中 PaaS 类产品体系的构建,结合字节跳动多年的云原生技术栈经验和最佳实践沉淀,帮助企业加速数字化转型和创新。产品包括容器服务、镜像仓库、分布式云原生平台、函数服务、服务网格、持续交付、可观测服务等。

picture.image

picture.image

picture.image

0
0
0
0
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论