写点什么

部署太慢,我们用 Warm Docker 容器将速度提高了 5 倍

  • 2023-03-29
    北京
  • 本文字数:4012 字

    阅读完需:约 13 分钟

部署太慢,我们用 Warm Docker 容器将速度提高了 5 倍

背景

 

我们使用 Serverless Dagster Cloud 来开发和部署 Dagster 代码,无需设置本地开发环境或任何云基础架构。当提交更改到 GitHub 时,GitHub Action 会直接构建和部署代码到 Dagster Cloud,然后可以在界面上查看并与 Dagster 对象进行交互。 Dagster Cloud 可以利用一个远程环境来共享部署,并且可以利用自动创建的临时环境与合作者协作,实现了个人本地开发和共享远程环境的结合。

 

最初,我们在 Dagster Cloud Serverless 中使用了标准的基于 Docker 的构建流程,但很快发现这个流程会使“编辑-部署-运行”的循环变得非常缓慢。为了将过程加速,我们实现了一个在 Docker 镜像之外运送代码的系统。本文将描述我们分析的问题、选择的解决方案以及在此过程中做出的各种权衡。


Docker 镜像存在的问题

 

当我们在 GitHub 上构建 Docker 镜像并将其部署到 Dagster Cloud 时,每次提交需要 3~5 分钟才会在 Dagster UI 中显示。在每次迭代中,无服务器开发人员通常会对代码进行微小更改,但是必须等待 3 分钟以上才能看到该更改的效果,这很快就会变得非常烦人。我们分析了“当你更改一行代码并提交时会发生什么”,并发现以下问题:


你可以看到,有两样东西花了最多的时间:

 

  • 构建 Docker 镜像(60 ~ 90 多秒)

  • 部署 Docker 容器(90 秒)

 

让我们分别看一下这两个问题。

 

构建 Docker 镜像

 

有一些需要注意的关于构建 Docker 镜像的事情:

 

  1. Docker 镜像由堆栈中的多个层构成,每层由 Dockerfile 中的一部分命令构建。

  2. 每个层有一个哈希标识。

  3. 上传镜像到注册表时,只上传注册表中不存在的层(由哈希标识确定)。

  4. 在 GitHub 构建机上使用 GitHub Actions 缓存重新构建镜像会将所有未受影响的层从缓存中拉取到构建机上。请注意,如果你的项目中有大量不会更改的依赖项,它们仍将在构建过程中从缓存中复制到构建机上。

  5. Docker 构建不是确定性的。如果使用完全相同的内容构建两个镜像,可能每次都会产生不同的哈希值。(虽然与本文直接相关性不强,但我们想观察这个意外的结果。作为一个极端情况,请考虑,一个刚构建的大层与已存在于注册表中的层完全相同,但仍然会作为一个新的层被上传。)

 

启动 Docker 容器

 

关于启动 Docker 容器,我们使用亚马逊云科技 Fargate,需要 45~90 秒的时间来提供和启动一个镜像。它不提供任何镜像缓存。启动一个新的容器会将所有层从注册表下载到已提供的容器中。

 

其他限制

 

在 Docker 镜像构建和启动后,我们运行用户的代码来提取元数据,并在 UI 中显示。这是不可避免的,并且可能需要几秒钟、30 秒或更多时间,具体取决于如何计算元数据(例如可能会连接数据库以读取模式)。此代码服务器保持活动状态并服务元数据请求,直到推送代码的新版本,然后启动一个新的容器。

 

我们有一个关键要求是可重复性:我们需要能够多次重新部署完全相同的代码和环境。使用 Docker 镜像哈希作为代码和环境的标识符非常适合这个要求。

 

我们的备选方案

 

下面是我们探索和讨论过的一些备选方案:

 

  1. 切换到 EC2 以加快容器启动速度。这会增加我们的运营负担,需要我们预先预配、监控和扩展集群。我们仍然会面临 Docker 构建速度慢的问题。

  2. 切换到其他的 Docker 构建系统,例如 AWS CodeBuild。这需要更多的实现工作,并与 GitHub 进行更深入的集成。不确定收益是否值得。

  3. 切换到 AWS Lambda,启动时间更快。Lambda 环境附带其自己的基础镜像,如果需要进行定制则更加困难。它还对执行时间施加了 15 分钟的限制,这将需要为运行时间更长的服务器实施复杂的解决方案。

  4. 通过仅构建和上传更改的代码到相同的服务器,来重复使用长时间运行的代码服务器。这里的挑战是实现打包和运行时机制,以确保可靠和可重复的执行环境。我们研究了各种打包和分发 Python 环境的方法,包括 rsync、poetrynixshivpex。我们还考虑使用 EFS 卷以及这些工具来挂载 Python 环境。

 

做出这个决定的关键因素是因为我们意识到,虽然 Docker 镜像是行业标准,但在只需要同步一个小改变时,传输数百兆字节的镜像似乎是不必要的。考虑 git——它只传输差异,但却产生了完整且一致的代码库。

 

这让我们倾向于选择方案 4……如果我们能找到一个适合我们大部分工作工具的话。经过一些实验,我们发现 PEX 具有许多特性,非常适合我们的使用情况——在下一节中会详细介绍。

 

什么是 PEX?

 

PEX 是 Python 可执行文件的缩写,是一个将 Python 包打包成名为 pex 文件的工具。这些可执行文件包含 Python 包和一些引导代码。例如,我们可以将 dagster 包和其依赖项打包成单个文件,然后运行它:

 

% pex dagster --python=python3.8 -o dagster.pex% ./dagster.pexPython 3.8.16 (default, Dec  7 2022, 01:24:57)[Clang 14.0.0 (clang-1400.0.29.202)] on darwinType "help", "copyright", "credits" or "license" for more information.(InteractiveConsole)>>> import dagster>>>
复制代码

 

将整个环境存储在单个文件中非常方便,可以轻松地将其传输到 S3 中进行存储。PEX 提供了更多功能,不仅仅是“文件中的虚拟环境” - 这里是我们使用的其他功能:

 

  • 隔离性

 

在运行时,pex 环境与其他全局包完全隔离。在环境中只有捆绑在 pex 文件中的包。我们将多个 pex 文件一起发送到同一台机器上,而不必担心环境隔离问题。

 

  • 确定性

 

使用相同的输入包会生成完全相同的 pex 文件:

$ pex dagster pandas -o out.pex | sha256sume3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855  -$ pex dagster pandas -o out.pex | sha256sume3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855  -
复制代码

 

这让我们可以使用内容寻址来识别这些 pex 文件,从而对实现可重复性更有信心。为了实现可重复性,除了使用 Docker 镜像哈希之外,我们还使用 pex 文件哈希。

 

  • 组合

 

多个 pex 文件可以在运行时合并,有效地将多个环境合并为一个环境。

 

% pex pandas -o pandas.pex% pex dagster -o dagster.pex% PEX_PATH=pandas.pex ./dagster.pexPython 3.8.16 (default, Dec  7 2022, 01:24:57)[Clang 14.0.0 (clang-1400.0.29.202)] on darwinType "help", "copyright", "credits" or "license" for more information.(InteractiveConsole)>>> import pandas>>> import dagster>>>
复制代码

 

我们使用这个功能将代码分成两个部分,在运行时合并起来:一个包含所有依赖项的 deps.pex 文件,和一个仅包含用户代码的 source.pex 文件。

 

  • 跨平台构建

 

我们在 Serverless Cloud 中使用 Linux python:* -slim 衍生的基础镜像。只要有包的 wheelpex 工具就可以在任何平台上为 Linux 构建 pex 文件。

 

快速部署

 

使用 pex 和 S3 存储 pex 文件,我们构建了一个系统,其中快速路径避免了构建和启动 Docker 镜像的开销。

 

我们的系统工作方式如下:当你将代码提交到 GitHub 时,GitHub 操作根据你的依赖关系是否与上一次部署不同,执行全量构建或快速构建。我们跟踪在 setup.pyrequirements.txt 中指定的依赖关系集。

 

对于全量构建,我们将你的项目依赖项构建为 deps.pex 文件,将你的代码构建为 source.pex 文件。这两个文件都会上传到 Dagster Cloud。对于快速构建,我们只构建并上传 source.pex 文件。

 

在 Dagster Cloud 中,我们可能会重复使用现有容器或为代码服务器提供新的容器。我们将 deps.pexsource.pex 文件下载到此代码服务器上,并在隔离环境中使用它们运行你的代码。我们从不跨用户共享容器,容器上的所有环境都属于同一用户。快速部署的最佳时间和最差时间如下所示:

 

这里的要点是,在快速路径中——当我们进行快速构建并重用现有容器时——整个过程只需要大约 40 秒,而不是之前的 3 分钟多。我们称这个功能为快速部署,现在已经默认开启了所有新的无服务器注册。


权衡和问题

 

这种方式可以显著提高部署速度(4~5 倍),但也带来了一些权衡和其他需要调整的因素:

 

  1. 虽然现在我们可以在一个代码服务器上运行多个环境,并且在代码方面是隔离的,但它们仍然共享相同的 RAM 和 CPU。如果我们将太多的环境放在一个容器中,而一个环境占用了太多的内存,就可能对在同一个容器中运行的其他环境产生不利影响。

  2. Docker 可以在任何操作系统上为 Linux 构建 Python 包,因为在构建过程中目标 Linux 操作系统和 Python 解释器都可用。pex 仅为提供 wheel 的包构建 Linux 的 pex 文件。如果出现问题,我们在构建过程中使用 Docker 容器来处理源分发。未来,这一步骤可以移动到单独的共享服务中。

  3. 在构建 Docker 镜像时可以进行深度定制,例如,你可以指定自定义基础镜像而不是默认的 python:*-slim 镜像之一。为了实现功能的平等,我们实现了一种方法,允许用户指定他们自己的基础 Docker 镜像,我们将其用于快速部署。

 

GitHub 工作流和 PEX

 

你可能已经注意到,在最初的图表中,Download Docker based action 的操作大约需要 10 秒钟。我们是如何完全消除这个步骤的呢?

 

我们曾经将 GitHub action 代码打包成 Docker 镜像,并使用 Docker container action。现在,我们将我们的 action 代码打包为 pex 文件,将其检入我们的 action 存储库并直接在 GitHub runner 上运行。这消除了下载和启动 Docker action 镜像所花费的时间,同时仍允许我们打包所有依赖项。

 

我们做出的另一个小优化是只使用一个 GitHub 工作流作业。在 GitHub 中,每次作业启动需要大约 10 秒钟来准备一个新的 runner。

 

总结

 

将部署时间从超过 3 分钟缩短到 40 秒是一个显著的加速,我们对这个结果非常满意,特别是在测试自己的服务时。使用 pex 使我们能够在 Docker 之上构建一个可重复、一致的环境,我们很高兴能够探索使用 pex-on-docker 组合的其他可能性。

 

如果有兴趣,可以看 PEX 团另一篇关于使用 Docker 进行部署的博客文章,它描述了如何使用 pex 文件作为中间目标来加速 Docker 镜像构建。

 

原文链接:

 

https://dagster.io/blog/fast-deploys-with-pex-and-docker

2023-03-29 12:085894

评论

发布
暂无评论
发现更多内容

PCB生产工艺 | 第九道主流程之表面处理

华秋电子

上传iOS应用变得更加容易 - 在Windows上架iOS APP的工具介绍

雪奈椰子

熟悉的测试用例设计方法都有哪些?

测吧(北京)科技有限公司

测试

测试策略与测试手段

测吧(北京)科技有限公司

测试

ChatGPT编程秀-3:适合面向ChatGPT编程的架构

仝键

JavaScript 架构 java ChatGPT

ZBC新一轮流动性收益计划迎来新通缩,APR高达100%

股市老人

开源工具系列6:Grype

HummerCloud

某头部零售集团的数据云平台“多租户安全”实践 | 奇点云技术分享

奇点云

数据安全 多租户技术 奇点云

入选Gartner低代码魔力象限 |『华为云Astro』低调的背后

路过的憨憨

软件测试 |全局变量和局部变量有什么区别?

测吧(北京)科技有限公司

测试

旺链科技荣获“高新技术企业证书”殊荣

旺链科技

区块链 区块链+ 高新技术企业

DPU 厂商北中网芯加入龙蜥社区,共建网络通信与安全

OpenAnolis小助手

开源 龙蜥社区 DPU CLA 北中网芯

九科企业级超级自动化平台引入ChatGPT,新技术助推产品能力全面提升

九科Ninetech

安如泰山 华为云发布制品仓库CodeArts Artifact

路过的憨憨

OpenHarmony关系型数据库[1]

白晓明

关系型数据库 OpenHarmony

网心科技荣获“深圳市自主创新百强中小企业”称号

网心科技

专精特新

华为云低代码平台Astro|通过零代码快速搭建打卡小程序

路过的憨憨

【3ds MAX 插件】近期发布的几个小插件,总有一款适合你

Finovy Cloud

插件 3ds Max

智慧公厕管理系统哪家好?

光明源智慧厕所

智慧城市

开心档之Go 语言环境安装

雪奈椰子

SRE是什么,与传统运维有什么不同?

不思jo

SRE #运维

机器学习算法(四): 基于支持向量机的分类预测

汀丶人工智能

数据挖掘 机器学习 SVM

通信系统综合仿真

timerring

通信系统 通信系统仿真

软件测试 | 白盒的测试方法

测吧(北京)科技有限公司

测试

软件测试/测试开发丨app自动化测试之Andriod微信小程序的自动化测试

测试人

微信小程序 软件测试 自动化测试 测试开发

Moblink节省开发者时间精力和公司成本

MobTech袤博科技

性能最大提升60%,阿里云第八代企业级实例ECSg8i正式上线

云布道师

阿里云 ECS

软件缺陷是什么?

测吧(北京)科技有限公司

测试

ChatGPT王炸更新!能联网获取新知识,可与5000+个应用交互,网友:太疯狂了

Openlab_cosmoplat

工业互联网 开源社区 智能制造 ChatGPT

强大的克隆备份软件:EaseUS Todo Backup直装激活版

真大的脸盆

Mac Mac 软件 备份软件 克隆工具

部署太慢,我们用 Warm Docker 容器将速度提高了 5 倍_文化 & 方法_Shalabh Chaturvedi_InfoQ精选文章