在 Pinterest,我们的使命是帮助人们发现他们喜爱的事物,从而让他们能够过上更富创造力和成就感的生活。Pinterest 工程部门以惊人的速度运转,一些主要服务每天发布两次。我们努力在主干中构建和集成每一次提交,这转化为每天产生大量的构建工件。可靠地存储这些工件并以一致的性能高效地提供它们,对我们的增长速度构成了巨大的挑战。
Pinrepo 是我们应对这一挑战的答案。它是一个简单而可扩展的解决方案,用于在内部存储和提供构建工件,例如 Debian 软件包、Maven jar 包和 pypi 软件包。我们已经在生产环境中运行 Pinrepo 超过八个月,性能稳定,几乎无需维护。
现在我们将 Pinrepo 在 GitHub 上开源。在那里您可以找到所有的配置节和说明,以便您自己重新创建它。它还包括一个 pypi 发布工具,用于发布和维护 pypi 软件包。请查看并告诉我们您的想法!并且,欢迎贡献您的自定义和改进。
Pinrepo 功能
- 简单: 在 AWS S3 中发布和存储构建工件,并使用 Nginx 反向代理提供服务
- 可扩展: 轻松添加其他格式支持,例如 RPM
- 可靠: 高可用的 Nginx 集群和 AWS S3 服务
- 可伸缩: Nginx 层可以水平扩展,因为 AWS S3 后端具有高度可伸缩性
- DevOps 友好: 已在生产环境中运行八个月,几乎无需维护
克服扩展挑战
Pinrepo 帮助我们解决的最大挑战是可伸缩性——它使我们能够随着时间的推移有效地提供大量数据。例如,当每天构建 50 次一个 36MB 的大型 Python 软件包时(总共每天 1.8GB,每三个月 162GB),扩展成为一个问题。我们以前使用过不同的解决方案,但随着对象数量的增长,它们的性能通常会随着时间的推移而下降。
除了扩展之外,还存在服务可用性和数据持久性方面的担忧。我们之前使用的解决方案基于单台主机和磁盘,它们速度慢且经常崩溃。虽然有备份流程,但它们经常在没有通知的情况下中断。维护这些服务是一场噩梦,我们需要一个可靠的服务,它位于持久、高度可扩展的对象存储之上。
我们考虑过直接使用 Amazon S3,但我们发现我们无法使用它来存储和提供构建工件,因为如果存储桶未配置为公开访问,则存储库客户端无法与 S3 通信。这些类型的 AWS S3 请求需要首先“签名”,包括一个根据请求的某些元素计算和附加 HMAC 的过程。
这个问题可以通过简单地在 AWS S3 前面添加一个 Nginx 服务器集群来解决。理论上我们可以“修复”所有的存储库客户端,以便它们可以直接与 S3 通信,但这将需要大量的工作,并且难以维护和扩展到其他工件格式。另一方面,Nginx 层不仅可以签名并将请求转发到 AWS,还可以为工件提供本地缓存,从而大大提高性能。Nginx 层是无状态的,可以轻松地水平扩展,因此也解决了可用性问题。此外,不需要额外的备份流程。
我们的答案:Pinrepo,我们的内部工件存储库。
介绍 Pinrepo
我们创建了一个负载均衡器后面的 Nginx 服务器集群,将所有请求代理到后端 AWS S3 服务,并使用 Nginx 模块 ngx_set_misc 来创建 AWS 服务请求签名。
直接将工件发布到 S3
有很多方法可以在 Amazon S3 中上传和维护工件元数据和布局,包括使用 deb-s3 上传和维护 debian 软件包,以及使用 maven 插件 maven-s3-wagon 处理 maven 软件包。我们找不到任何现有的工具将 Python 软件包上传到 S3,因此我们编写了自己的 pypi-release 来上传和维护 pypi 软件包。
简单至上
通过直接将构建工件发布和存储到 Amazon S3,并使用 Nginx 集群作为前端,我们简化了技术堆栈,并在最大限度减少维护需求的同时实现了可伸缩性和持久性。
未来的改进
一个带有搜索支持的简单 UI 可以作为一个附加功能,尽管可以使用各种 S3 工具来查找存储库中可用的内容。在添加额外功能时要谨慎,不要让它们成为关键路径的一部分,以免危及现有简单解决方案的可靠性和可伸缩性。暂存存储库和软件包提升也很好,但如果您有暂存部署和预生产测试环境,则不是必需的。Pinrepo 还可以扩展以轻松支持更多软件包格式,例如 RPM。
致谢:感谢 Raj Patel,他帮助评估了各种现有解决方案并使流程规范化;感谢 Jayme Cox 审查了设计并就实施细节提供了建议;并感谢 Pinterest 云工程团队的所有成员,他们为网站驱动可靠性、速度和安全性,并为云基础设施和开发人员构建技术构建块。
本文基于 Pinterest 博客的公告。
评论已关闭。