【CSDN编者按】使用pex使我们能够在Docker之上建立一个可重复的、一致的环境,我们很高兴使用这个pex-on-docker组合来探索其他的可能性。
原文链接:https://dagster.io/blog/fast-deploys-with-pex-and-docker
作者|ShalabhChaturvedi
(资料图片)
译者|邓晓娟责编|王子彧
出品|CSDN(ID:CSDNnews)
无服务器开发和反馈循环
Dagster是一个数据编排器。在无服务器Dagster云上,不需要建立本地开发环境或云基础设施,就可以开发和部署Dagster代码。当你向GitHub提交修改时,GitHubAction会直接构建和部署你的代码到Dagster云。你可以在用户界面中查看和互动你的Dagster对象。借助Dagster云,远程环境通常用于让使用自动创建的暂存环境与合作者共享部署。个人本地开发和共享远程环境相结合,形成了一个强大的开发周期。
最初,我们在这上面使用了基于Docker的标准构建流程。然而我们很快发现,这让编辑-部署-运行的周期变得非常繁琐缓慢。为了加快速度,我们构建了一个系统,实现在Docker镜像之外运送代码。这篇文章描述了我们分析的问题、确定的解决方案,以及在这个过程中做出的各种权衡。
ShalabhChaturvedi分享了DagsterCloud新的快速部署能力的高水平概述,详情请观看视频:https://youtu.be/mPT3FBFSw6g
Docker镜像的问题
当我们在GitHub上构建Docker镜像并将其部署到Dagster云时,每次提交都需要3到5分钟才能在Dagster用户界面上显示出来。无服务器开发人员通常会在每次迭代中对代码进行小的改动,但却每次都要等待3分钟以上才能看到改动的效果,这种无意义的等待很容易让人厌烦。我们分析了一个问题:“当你修改一行代码并提交后,会发生什么?”发现了以下的情况。
我们分析了"当你改变一行代码并提交时会发生什么",发现了以下情况。
20s>提供GitHub运行器并下载动作10s>下载基于Docker的行动60s>建立并上传用户的Docker镜像*。90s>在AWS中运行用户的Docker镜像180s的运行时间
*在启用缓存的情况下需要60秒(如果没有改变依赖关系的话);如果依赖关系有变化,则需要90秒以上。
如你所见,花费时间最长的两件事是:构建一个Docker镜像(60-90多秒)部署Docker容器(90秒)
那就让我们来看看这两件事都做了些什么。
构建Docker镜像
关于构建Docker镜像需要注意的一些事情。Docker镜像是由堆栈中的多个层堆叠而成的,其中每一层都是由Docker文件中的一个命令子集构建的;使用GitHubActions缓存在GitHub构建机上重建镜像时,会将所有未受影响的层从缓存中拉到构建机上。请注意,如果你的项目中有大量的依赖关系没有改变,它们会在构建过程中从缓存中一起被复制到构建机器上;Docker的构建不是确定性的。如果你用完全相同的内容构建一个镜像两次,每次都可能产生不同的哈希值。(虽然不直接相关,但我们想记录一下这个意外的观察结果。作为一个极端案例,考虑到一个新构建的大层与已经在注册表中的层相同,仍然可能作为一个新的层被上传)。
启动Docker容器
关于启动Docker容器需要注意的是,我们使用AWSFargate,它需要45到90秒的时间来配置和启动一个镜像。且不提供任何图像缓存。启动一个新的容器会从注册表中下载所有的层到配置的容器上。
其他限制
在Docker镜像建立和启动后,我们运行用户的代码来提取元数据,显示在用户界面上。这一步无法避免,可能需要几秒钟到30秒,甚至更久,这取决于元数据的计算方式(比如它可以连接到数据库来读取模式)。这个代码服务器保持活动状态,为元数据请求提供服务,直到推送新版本的代码,然后启动一个新的容器。
我们的一个关键要求是可重复性:我们需要能够多次重新部署完全相同的代码和环境。使用Docker镜像的哈希值作为代码和环境的标识符,可以很好地满足这一要求。
备选方案综述
除了上述的方案以外,我们还探索和讨论了一些替代方案。从Fargate切换到EC2,以加快容器的启动。这将增加我们的运营负担,要求我们预先提供、监控和扩展我们的集群。我们仍然会遇到Docker构建缓慢的问题;换成不同的Docker构建系统,如AWSCodeBuild。这将需要更多的部署工作,并与GitHub进行更深入的整合。目前还不清楚这样做的回报是否值得;切换到AWSLambda,启动时间快得多。Lambda环境有自己的基础镜像,对于自定义需求来说不太友好。而且它的执行时间还有15分钟的限制,这对运行时间较长的服务器来说,需要复杂的变通方法;通过构建并只上传修改后的代码到同一服务器,重新使用长期运行的代码服务器。这里的挑战是实现打包和运行机制,以确保一个可靠和可重复的执行环境。我们研究了各种打包和分发Python环境的方法,包括rsync、poetry、nix、shiv和pex。还考虑了使用EFS卷来挂载Python环境,与这些工具相结合。
我们作出最终决定背后的有一个关键因素,是意识到虽然Docker镜像是行业标准,但如果我们只需要同步一个小的变化时,就去移动100多兆的镜像,是很不必要的繁重操作。考虑到Git只提供差异,但却能产生完整而一致的存储库。因此我们倾向于方案4,只需要能找到一个合适的工具来做大部分的工作。经过一些实验,我们发现pex的许多功能对我们的用例非常有效。
什么是PEX?
pex是PythonExecutable的缩写,它是一种将Python包捆绑到称为pex文件的工具。这些是可执行文件,其中包含Python包和一些引导代码。例如,我们可以把dagster包和它的依赖项捆绑成一个文件,然后运行它。%pexdagster--python=python3.8-odagster.pex%./dagster.pexPython3.8.16(default,Dec72022,01:24:57)[Clang14.0.0(clang-1400.0.29.202)]ondarwinType"help","copyright","credits"or"license"formoreinformation.(InteractiveConsole)>>>importdagster>>>
将整个环境放在一个文件中,便于运输和存储在S3中。pex提供的不仅仅是一个"文件中的虚拟环境",以下是我们使用的其他功能。隔离
在运行时,pex环境与其他网站范围内的包完全隔离。环境中唯一存在的包是那些捆绑在pex文件中的包。我们将多个pex文件运送到同一台机器上,而不必担心环境隔离问题。确定性
使用相同的输入包会产生位对位的相同的pex文件。$pexdagsterpandas-oout.pex|sha256sume3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855-$pexdagsterpandas-oout.pex|sha256sume3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855-组成
多个pex文件可以在运行时合并,有效地将环境合并成一个。%pexpandas-opandas.pex%pexdagster-odagster.pex%PEX_PATH=pandas.pex./dagster.pexPython3.8.16(default,Dec72022,01:24:57)[Clang14.0.0(clang-1400.0.29.202)]ondarwinType"help","copyright","credits"or"license"formoreinformation.(InteractiveConsole)>>>importpandas>>>importdagster>>>
我们用它把代码分成两部分,在运行时合并:一个包含所有依赖关系的deps.pex文件和一个只包含用户代码的source.pex文件。跨平台的构建
我们在无服务器云中使用Linuxpython:*-slim衍生的基础镜像。只要软件包的轮子可用,pex工具可以在任何平台上为Linux构建pex文件。
快速部署
我们使用pex与S3相结合来存储pex文件,建立了一个系统,其中快速路径避免了构建和启动Docker镜像的开销。
我们的系统是这样工作的:当你向GitHub提交代码时,GitHubAction要么进行完全构建,要么进行快速构建,这取决于你的依赖关系自上次部署后是否有变化。我们跟踪setup.py和requirements.txt中指定的依赖项。
对于一个完整的构建,将项目依赖性构建到deps.pex文件,将代码构建到source.pex文件。两者都被上传到Dagster云端。对于快速构建,只构建和上传source.pex文件。
在Dagster云中,可以重新使用一个现有的容器或提供一个新的容器作为代码服务器。将deps.pex和source.pex文件下载到这个代码服务器上,并使用它们在一个隔离的环境中运行代码。我们从不在用户之间共享一个容器,一个容器上的所有环境都属于同一个用户。快速部署的最佳情况和最坏情况的时间线如下。
其结果是,在快速构建(FastBuild)的路径中,当我们进行快速构建并重用现有容器时,整个过程只需40秒,而不像以前一样需要3分钟以上。
我们将这一功能称为【快速部署】,现在所有新注册的无服务器用户都默认开启这一功能。
权衡与问题
快速部署极大地提高了部署速度(4-5倍),但它伴随着一些需要权衡的问题和其他因素,我们已经进行了调整:虽然我们现在可以在一个代码服务器上运行多个环境,并且它们在代码上是隔离的,但它们仍然共享相同的内存和CPU。如果我们在一个容器上放了太多的环境,而且一个环境占用了太多的内存,就会对同一容器中的其他运行环境产生不利的影响;Docker可以在任何操作系统上为Linux构建Python包,因为目标Linux操作系统和Python解释器在构建过程中是可用的。pex只能为Linux构建提供轮子的包的pex文件。作为退路,我们在构建过程中使用Docker容器来处理源码分发。这个步骤可以在未来被移到一个单独的共享服务中;在构建Docker镜像时,可以进行深度定制,例如,你可以指定一个自定义的基础镜像,而不是默认的python:*-slim镜像之一。为了实现功能上的平等,我们必须实施一种方法,让用户指定他们自己的基础Docker镜像,我们在快速部署时使用这种镜像。
GitHub工作流程和pex
很多人可能已经注意到,原图中,过去基于Docker的下载操作需要10秒左右。那么我们是如何完全消除这个步骤的呢?
以前我们把GitHubAction代码打包成Docker镜像,然后使用Docker容器操作。而现在,我们把动作代码打包成一个pex文件,将其检入动作仓库,直接在GitHub运行器上运行。这就省去了下载和启动Docker动作镜像的时间,同时仍然允许我们打包所有的依赖项。
我们做的另一个小优化是,只使用一个GitHub工作流作业。在GitHub中的每一个工作启动都需要10秒钟来配置一个新的运行器。
结论
将部署时间从3分钟以上减少到40秒,是一个显著的加速,我们对这个结果非常满意,特别是当测试自己的服务时。使用pex使我们能够在Docker之上建立一个可重复的、一致的环境,我们很高兴使用这个pex-on-docker组合来探索其他的可能性。
☞奇瑞汽车回应要求员工周六上班:本意不是压榨员工;Google发布史上最大通才模型PaLM-E;Chrome111发布|极客头条
☞创业5年暂未发布任何新品,由苹果前高管打造的初创公司,拥抱AI后,再获1亿美元融资!
☞“我们聘请ChatGPT,让它当了一天ML工程师”返回搜狐,查看更多
责任编辑:
关键词: