《Docker容器5倍速度部署实战.docx》由会员分享,可在线阅读,更多相关《Docker容器5倍速度部署实战.docx(8页珍藏版)》请在第一文库网上搜索。
1、Docker容器5倍速度部署实战L无服务器开发和反馈循环Dagster是一个数据编排器。在无服务器Dagster云上,不需 要建立本地开发环境或云基础设施,就可以开发和部署Dagster代 码。当你向GitHub提交修改时,GitHub Action 会直接构建和部 署你的代码到Dagster云。你可以在用户界面中查看和互动你的 Dagster对象。借助Dagster云,远程环境通常用于让使用自动创 建的暂存环境与合作者共享部署。个人本地开发和共享远程环境相结 合,形成了一个强大的开发周期。最初,我们在这上面使用了基于Docker的标准构建流程。然而 我们很快发现,这让编辑-部署-运行的周期变
2、得非常繁琐缓慢。为了 加快速度,我们构建了一个系统,实现在Docker镜像之外运送代码。 这篇文章描述了我们分析的问题、确定的解决方案,以及在这个过程 中做出的各种权衡。2. Docker镜像的问题当我们在GitHub上构建Docker镜像并将其部署到Dagster 云时,每次提交都需要3到5分钟才能在Dagster用户界面上显示 出来。无服务器开发人员通常会在每次迭代中对代码进行小的改动, 但却每次都要等待3分钟以上才能看到改动的效果,这种无意义的等 待很容易让人厌烦。我们分析了一个问题:“当你修改一行代码并提 交后,会发生什么?”发现了以下的情况。我们分析了 当你改变一行代码并提交时会发生
3、什么,发现了以下 情况。20s T Provision GitHub runner and download actions10s - Download Docker based action60s T Build and upload user*s Docker image*90s T Run user,s Docker image in AWS180s run time, Takes 60s with caching enabled, if no dependencies have changed.Takes 90s+ if dependencies have changed. 20s 提
4、供GitHub运行器并下载动作 IOs 下载基于DoCker的行动 60s 建立并上传用户的Docker镜像*。 90s 在AWS中运行用户的Docker镜像 180s的运行时间*在启用缓存的情况下需要60秒(如果没有改变依赖关系的话); 如果依赖关系有变化,则需要90秒以上。如你所见,花费时间最长的两件事是:构建一个Docker镜像(60-90多秒)部署Docker容器(90秒)那就让我们来看看这两件事都做了些什么。3 .构建Docker镜像关于构建Docker镜像需要注意的一些事情。1 . Docker镜像是由堆栈中的多个层堆叠而成的,其中每一 层都是由Docker文件中的一个命令子集构建
5、的;2 .每一层都由一个哈希值来识别;3 .当上传镜像到注册表时,只有不存在于注册表中的层(由 哈希值识别)被上传;4,使用GitHub Actions缓存在GitHub构建机上重建镜像 时,会将所有未受影响的层从缓存中拉到构建机上。请注 意,如果你的项目中有大量的依赖关系没有改变,它们会 在构建过程中从缓存中一起被复制到构建机器上;5 . Docker的构建不是确定性的。如果你用完全相同的内容 构建一个镜像两次,每次都可能产生不同的哈希值。(虽 然不直接相关,但我们想记录一下这个意外的观察结果。 作为一个极端案例,考虑到一个新构建的大层与已经在注 册表中的层相同,仍然可能作为一个新的层被上传
6、)。4 .启动DoCker容器关于启动Docker容器需要注意的是,我们使用 AWS Fargate, 它需要45到90秒的时间来配置和启动一个镜像。且不提供任何图像缓 存。启动一个新的容器会从注册表中下载所有的层到配置的容器上。5 .其他限制在Docker镜像建立和启动后,我们运行用户的代码来提取元数 据,显示在用户界面上。这一步无法避免,可能需要几秒钟到30秒, 甚至更久,这取决于元数据的计算方式(比如它可以连接到数据库来 读取模式)。这个代码服务器保持活动状态,为元数据请求提供服务, 直到推送新版本的代码,然后启动一个新的容器。我们的一个关键要求是可重复性:我们需要能够多次重新部署完 全
7、相同的代码和环境。使用Docker镜像的哈希值作为代码和环境的 标识符,可以很好地满足这一要求。6 .备选方案综述除了上述的方案以外,我们还探索和讨论了一些替代方案。1 .从Fargate切换到EC2,以加快容器的启动。这将增加 我们的运营负担,要求我们预先提供、监控和扩展我们的 集群。我们仍然会遇到Docker构建缓慢的问题;2 .换成不同的Docker构建系统,如AWS CodeBuildo这将 需要更多的部署工作,并与GitHub进行更深入的整合。 目前还不清楚这样做的回报是否值得;3 .切换到AWS Lambda,启动时间快得多。Lambda环境有自 己的基础镜像,对于自定义需求来说不
8、太友好。而且它的 执行时间还有15分钟的限制,这对运行时间较长的服务 器来说,需要复杂的变通方法;4 .通过构建并只上传修改后的代码到同一服务器,重新使用 长期运行的代码服务器。这里的挑战是实现打包和运行机 制,以确保一个可靠和可重复的执行环境。我们研究了各 种打包和分发Python环境的方法,包括rsync poetry、nix、shiv和peo还考虑了使用EFS卷来挂 载PythOn环境,与这些工具相结合。我们作出最终决定背后的有一个关键因素,是意识到虽然 Docker镜像是行业标准,但如果我们只需要同步一个小的变化时, 就去移动100多兆的镜像,是很不必要的繁重操作。考虑到Git只 提供
9、差异,但却能产生完整而一致的存储库。因此我们倾向于方案4, 只需要能找到一个合适的工具来做大部分的工作。经过一些实验,我 们发现pex的许多功能对我们的用例非常有效。7 .什么是PEX?pex 是Python Executable的缩写,它是一种将Python包捆 绑到称为pex文件的工具。这些是可执行文件,其中包含Python 包和一些引导代码。例如,我们可以把dagster包和它的依赖项捆 绑成一个文件,然后运行它。% pex dagster -python=python3.8 -o dagster.pex% ./dagster.pexPython 3.8.16 (default, Dec
10、 7 2022, 01:24:57) Clang 14.0.0 (clang-1400.0.29,202) on darwin Type help, copyright, credits or license for more information. (InteractiveConsole) import dagster 将整个环境放在一个文件中,便于运输和存储在S3中。PeX提供的 不仅仅是一个文件中的虚拟环境,以下是我们使用的其他功能。1 .隔离在运行时,pex环境与其他网站范围内的包完全隔离。环境中唯一存 在的包是那些捆绑在pex文件中的包。我们将多个pex文件运送 到同一台机器上,而
11、不必担心环境隔离问题。2 .确定性 使用相同的输入包会产生位对位的相同的pex文件。$ pex dagster pandas -o out.pex sha256sum e3b0c44298fclcl49afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - $ pex dagster pandas -o out.pex sha256sum e3b0c44298fclcl49afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -这让我们有信心用内容寻址来识别这些pex文件。为了实现可重复 性,除了 DOCke
12、r镜像的哈希值,还使用PeX文件哈希值。3 .组成多个pex文件可以在运行时合并,有效地将环境合并成一个。% pex pandas -o pandas.pex % pex dagster -o dagster.pex % PEX_PATH=pandas.pex ./dagster.pex Python 3.8.16 (default, Dec 7 2022y 01:24:57) Clang 14.0.0 (clang-1400.0.29.202) on darwinType help, copyright, credits or nIicense for more information. (
13、InteractiveConsole) import pandas import dagster 我们用它把代码分成两部分,在运行时合并:一个包含所有依赖关系 的deps. pex文件和一个只包含用户代码的source. pex文件。4 .跨平台的构建我们在无服务器云中使用Linux python :*-SIiin衍生的基础镜像。 只要软件包的轮子可用,pex工具可以在任何平台上为Linux构 建pex文件。8 .快速部署我们使用pex与S3相结合来存储pex文件,建立了一个系 统,其中快速路径避免了构建和启动Docker镜像的开销。我们的系统是这样工作的:当你向GitHub提交代码时,Git
14、Hub Action要么进行完全构建,要么进行快速构建,这取决于你的依赖 关系自上次部署后是否有变化。我们跟踪 setup. py和 requirements. txt中指定的依赖项。对于一个完整的构建,将项目依赖性构建到deps.pex文件,将 代码构建到source. pex文件。两者都被上传到Dagster云端。对于快速构建,只构建和上传SOUrCe. pex文件。在Dagster云中,可以重新使用一个现有的容器或提供一个新 的容器作为代码服务器。将deps. pex和source. pex文件下载到 这个代码服务器上,并使用它们在一个隔离的环境中运行代码。我们从不在用户之间共享一个容器
15、,一个容器上的所有环境都属于同一个 用户。快速部署的最佳情况和最坏情况的时间线如下。depn Run users source.pe on a container that has deps.pex35s run timeno existing container foundFull Build10s - Provision GitHub runner and download actionsBuild and upload the source.pe file 60s - with users code and the deps.pex with dependencies90s - RUn a base docker image in AWS and run the user(s source.pe and deps.pex on it.160s run time其结果是,在快速构建(FaStBUiI