在构建服务器上重复使用Python虚拟环境

75次阅读
没有评论

问题描述

在使用Jenkins+Ansible进行构建时,每次都需要重新创建一个虚拟环境并重新安装requirements.txt文件中列出的所有依赖项。这种做法速度很慢,不利于扩展。用户希望优化和加速这个过程,能够重复使用虚拟环境,但不确定最佳解决方法是什么。

解决方案

请注意以下操作可能涉及版本差异,请确保备份好数据。

方案1

建议构建过程具有幂等性(idempotent),避免留下不必要的产物,这会导致依赖管理问题,解决这些问题正是使用构建服务器的原因。首先,建议检查Python构建为什么运行得这么慢,如果发现是每个项目中的包过多导致的,可以进行优化。如果发现是服务器性能问题,可以通过增加资源来解决。如果网络吞吐量是问题所在,可以考虑使用构件仓库来本地缓存包。但是构建持久性虚拟环境似乎是引发问题的风险,可能在迁移到另一台服务器时出现不可预测的问题,并且在排查问题时可能会非常麻烦。

方案2

将构建过程分解为中间步骤,创建可版本化的中间包,以便在工作区内部署,无需进行所有中间构建步骤。Docker是一种常见的打包解决方案,也可以使用.deb、.rpm、非Docker tarballs,或者制作CF“StemCells”甚至zip文件。此外,Python现在支持预构建的“wheel”包。
以下是一些问题:
1. 所有开发人员必须使用相同的build-deps包,以便其沙盒和CI工作区之间的差异不会引发问题。因此,该包必须支持开发笔记本沙盒和Jenkins工作区安装。
2. build-deps包必须有自己的CI构建/测试/打包/发布流程。然而,在它没有任何变更提交时,可以减少其循环频率(或其任何组件)。
3. 这是一个捆绑的示例。例如,如果要修补CVE,使用该捆绑包的所有内容都必须进行修补。这个过程不应该比其他任何东西更难部署,因此在CI构建速度很快时不要停止工作。CI需要CD,否则你可能会交付无法部署到生产环境的软件。
4. 如果要创建自己的预构建工件,需要基础架构来托管工件存储库,以及一个版本控制方案。

增量解决方案应该是解决那些在构建周期速度显著提升时解决最少数量问题的方案。因此,维护本地pypi存储库,并将Jenkins任务添加到构建和推送wheel包到该存储库中,可能是一个不错的方案。尽管听起来可能有点麻烦,但想象一下如果你必须为所有可以通过pip安装的东西都管理内部软件开发会是多么复杂。

方案3

考虑使用ShiningPanda插件来运行特定的Python虚拟环境。该插件会自动创建虚拟环境,如果不存在则创建,如果已经存在则复用。虚拟环境位于工作区之外,但可以通过在工作区内部显示一个相应名称的目录来访问。
要解决依赖关系,只需在拉取工作区之后插入一个执行所需的pip install -r requirements.txt变体的构建步骤,然后再进行任何需要使用虚拟环境的其他构建步骤。
同一个虚拟环境可以在同一个构建的多个步骤中使用(按名称),并且一个构建可以有多个虚拟环境(如果需要的话)。但据我所知,不能在不同的构建中重用同一个虚拟环境,每个构建将拥有自己的副本。
该插件具有在任何构建步骤中清除/擦除环境的配置,如果/当需要时。显然,你不希望始终启用这个功能,因为它会使可复用性失效。
根据我个人的经验,它最适用于具有固定包版本(例如,由pip-tools生成的那些)的requirements.txt文件。

更新:我最近在Windows上遇到了该插件的一个问题:我在不同的Jenkins文件夹中有几个作业,但作业名称相同,插件配置也相同(特别是Advanced部分中的Name字段不为空)。结果,所有作业实际上都共享一个环境(并相互干扰),我不得不对作业之间的Name字段使用唯一值。显然,这两个名称用于生成虚拟环境路径的两个哈希值,因此相同的名称->相同的路径。

正文完