构建和命名工件存储库的最佳实践
为您的组织设计正确的存储库命名约定至关重要。为任何产品开发创建正确的存储库结构,在促进一致的产品扩展战略方面发挥着至关重要的作用。它不仅减少了随机创建多个存储库的开销,而且帮助团队辨别使用存储库管理器的目的。
使用Artifactory 作为您的存储库管理器,结合了强大的通用二进制存储库的强大功能,该存储库将您所有不同类型的二进制文件托管在一个地方,以及完全集成到您的软件开发生命周期中的企业级功能。
软件开发涉及开放式和不断发展的过程。对于参与产品开发的各个团队,以最精确的方式维护存储库结构成为该过程的必要任务之一。挑战在于,对于命名约定或创建存储库结构,没有可遵循的硬编码准则。
JFrog 推荐一个由四部分组成的命名结构,其中包括:
- 项目、产品或团队名称作为项目的主要标识符
- 正在使用的技术、工具或包类型。
- 包成熟度级别,例如开发、登台和发布阶段。
- 定位器,您的工件的物理拓扑。
注意:使用JFrog 项目的组织有一个额外的好处——项目密钥将自动添加到命名结构中。
此结构生成以下 JFrog 推荐的存储库命名结构,
应该在整个组织中使用:<team/projectKey>-<technology>-<maturity>-<locator>。
附加指南适用于四种不同的 Artifactory 存储库类型,包括:本地、远程、虚拟和分发。本地存储库命名约定由两个用例组成。第一个是存储的工件是您自己的,第二个是它们是第三方的。远程存储库要么是 Artifactory 拓扑的一部分,并且它们的命名约定应与为本地存储库定义的命名约定一致,要么它们是中央存储库,使它们成为外部并赋予它们稍微不同的命名约定。虚拟存储库与拓扑无关,因此它们缺少定位器。最后但并非最不重要的一点是分发存储库支持多种技术类型,一般以“-dist”结尾。
在为存储库设置命名约定时,要考虑的三个主要类别是:安全性、性能和可操作性。
在 Artifactory 中组织存储库时,最佳实践是在存储库级别管理安全权限。这个安全因素将决定您应该管理的不同存储库,具体取决于您组织中工作的不同团队。
性能问题因技术而异,应实施清理策略以确保最高的存储库效率。此外,应根据业务价值(取决于您的组织使用 Artifactory 的方式)和团队结构,在存储库结构中应用可操作性考虑因素。尽管管理员首选的存储库较少,但有时最好创建具有不同读/写/删除权限的单独存储库,以防止团队干扰彼此的工作。
本白皮书中涵盖的所有这些考虑因素将使您能够跨全球拓扑扩展您的 Artifactory,并提供大型企业 JFrog Artifactory 安装所需的 DevOps 支持。
介绍
使用存储库管理器
JFrog Artifactory 是一个通用二进制存储库管理器,旨在加快开发周期。这意味着它不仅是一个存储库,而且还是一个功能强大的管理器,可以帮助组织多个存储库以简化分布式软件开发过程。
在为您的存储库定义指南和约定时,灵活性优于严格的规则。创建弹性指南为 Artifactory 管理员提供了足够的空间来根据需要定制规则。
命名约定和存储库结构齐头并进。选择合适的名称并决定您是需要单个存储库还是多个存储库始终是一个艰难的决定。您选择的组织结构必须与您的开发、测试、部署和分发流程在您的组织中的工作方式相匹配,这一点很重要。这里表示的命名约定和组织结构主要基于一些相当常见的流程,但可能并不适合所有组织。但是,希望您可以使用此处列出的组织和命名注意事项来使其适应您自己的命名约定。
image.png
创建命名约定
组织经常处理在多个存储库中产生的多个项目、技术、生命周期和产品。每当你有不止一个东西时,你需要命名它。作为开发人员,在过去的几十年里,我们已经了解到,一个名字可以说明你在做什么,也可以混淆它。
本白皮书讨论了存储库命名约定和管理。
有关工件命名约定的更多信息,请参阅存储库布局。
在我们深入细节之前,让我们回顾一下三个首要问题:
首先是定义生成可用 URL的存储库名称。例如,由于 Artifactory 区分大小写,因此最好使用小写字母。更重要的是,避免在您的环境中使用需要 URL 编码的字符,例如“_”字符。这将简化您的 Artifactory 实例的最终用户以及必须管理反向代理和负载均衡器的管理员的 URL,从而使事情变得更容易。
所有编码人员都应该熟悉第二个问题:自我记录代码!尽可能确保您的存储库名称是自记录的。尽管有一个描述字段,但当存储库名称清晰时,它会使事情变得更容易。第三个问题是基于Artifactory UI。识别您的存储库的最相关的信息应该放在第一位。通过这样做,在应用过滤器选项后,字母顺序将根据名称组件的重要性在 Artifactory 树浏览器中将相似的存储库彼此相邻放置。
第四个问题是基于某些隐含的限制,无论您如何设计约定。例如,有一些特殊字符('/'、'\'、':'、'|'、'?'、'*'、'"'、'''、'<'、'>' , '+', space) 是完全禁止的。该名称最多可包含 64 个字符,远程存储库最多可包含 58 个字符。还有一些保留和不推荐的名称,例如“repo”和“trash”。附加单词“-cache”也被认为是保留的,因为它主要用于为远程存储库自动创建缓存。
命名结构基础
JFrog 建议采用四部分命名结构,最好按以下顺序。
1. 团队或产品
projectKey 或团队名称是项目的主要标识符。您可以选择根据您的公司命名约定来定制缩写。JFrog Projects 会自动使用项目密钥,而不是使用整个产品名称。另一方面,存储库可以在项目之外创建并稍后分配给它,因此项目密钥不是强制性的,有些人更喜欢使用团队或产品名称。主要思想是选择一个相关且易于团队理解的名称。
例如:老虎
为命名约定的项目/团队/产品名称部分选择粒度级别是开发命名约定最困难的部分之一。这将在本白皮书稍后的存储库组织部分中进一步讨论。但是,由于虚拟存储库的存在,这也可以在以后根据需要很容易地更改,所以不要太担心,而是选择容易理解和一致的东西,看看它是否适合你。
2. 技术
技术主要是指工具或包的类型。Artifactory 是一个通用的二进制存储库管理器,其核心能力使其能够存储涵盖 Maven、NuGet 和 Docker 等技术的各种类型的包。每个存储库都应保存一种类型的二进制文件。
以我们的示例为基础: tiger-docker
高级用户
一般来说,任何存储库类型都可能具有任何所需的二进制文件,只要存储库类型响应单个工具或在某些情况下通过其 API 和索引响应工具系列。因此,当您选择存储库类型时,您反映的是您计划使用什么工具来检索工件。这会影响 Artifactory 将计算的索引类型。如果您没有使用 get/put rest API 命令之外的任何工具,您可能需要考虑通用存储库并完全避免索引计算的开销。
在命名约定中包含工具类型或包名称有助于开发人员识别工件,从而更容易根据它们的类型浏览它们。在大多数情况下,这将准确反映在存储库创建时选择的包类型,但您可以选择更具体。例如,如果您的通用存储库存储视频,您可以选择“视频”一词作为技术类型。其他示例是:使用 'centos' 代替 'rpm' 或 'rhel',以及使用 'ubuntu' 代替 'deb'。
3. 成熟度
成熟度是指包的成熟度级别,例如开发、登台和发布阶段。在 Artifactory 中可以通过多种不同的方式进行工件提升。从针对较小事件的简单属性标记(例如“通过测试 X”)到工件已通过的较大质量门。出于本次讨论的目的,我们对提升感兴趣,其中将工件从一个存储库移动或复制到另一个存储库。
那么我们为什么要这样做呢?通常这是在工件更改其控制状态时完成的。在传统的开发模型中,这可能代表在其生命周期的不同阶段拥有软件的实际团队。您可能有一个“沙箱”,而工件正在由开发人员在他们的办公桌上进行测试,并且“开发”或“快照”用于在初始构建提交时发生在 CI 系统之外的构建。然后,工件将移至“ qa ”、“ preprod ”或“ staging ”存储库,最后移至“ release ”或“ prod ”” 存储库。当一个工件退休,或者当它触发某些保留的监管要求时,工件和可能的所有依赖项都可以移动到“存档”。
在DevOps中呢?根据 DevOps 原则,不应将工件传递给新团队,而应在整个生命周期内由同一团队拥有。从自动化的角度来看,控制状态与公司内部的团队无关,而是基于具有不同权限模型的不同环境,以确保不会过早部署工件。
继续构建我们的示例:tiger-docker-release
虽然本白皮书的大部分内容都集中在命名约定上,但它实际上是关于工件的组织。没有比工件成熟度的概念更重要的考虑了。下图说明了一个典型的促销概念。如果满足质量要求,工件将从一个 DevOps 阶段进展到另一个阶段:
image.png
4.定位器
定位器本质上是指工件的****物理拓扑。拓扑中的每个存储库都必须是唯一的。真正本地的本地存储库,这意味着它们的内容是在本地管理/上传的,应该以“-local”结尾。作为在别处管理的内容的复制活动目标的本地和远程存储库应以其他服务的指示符结尾。
例如,“波士顿”可用于波士顿****数据中心中管理的工件。为了符合要求,访问外部位置的远程存储库应以“-remote”结尾。这通常被省略,特别是对于主要的中央存储库,假设用户熟悉“jcenter”和“npmjs”作为名称的中央存储库,但这样的假设可能会引起混淆。
使用以下存储库名称完成我们的示例: tiger-docker-release-boston
存储库类型
Artifactory 托管四种存储库类型:本地、远程和 虚拟。本地和远程存储库是真正的物理存储库,而虚拟存储库实际上是它们的聚合,用于创建用于搜索和解析工件的受控域。
JFrog Distribution 使您能够在整个 SDLC 中加速部署和大规模并发下载:从 CI 到 CD,再到设备管理——跨越远程站点、混合基础设施、云、边缘、嵌入式设备和 IoT 队列。 了解更多 >
本节提供有关如何应用上述命名结构的指南,特别是针对每种存储库类型。
命名约定的任何部分在不相关时都可以是可选的,并且四部分命名约定的一般概念可以适用于初始约定中未涉及的其他情况。
1. 本地存储库
使用上一节中描述的四部分命名结构,我们可以解决本地存储库命名约定所需的所有注意事项,包括:项目/组织(业务单位或产品)、技术、成熟度和定位器。正如所讨论的,顺序代表了重要性。JFrog 的建议是:<team>-<tech>-<maturity>-<locator>,尽管在某些用例中可能适用其他命令。
本地存储库有两个基本用例:第一个用例是当您引用与您自己的组织工件相关的工件时。在这种情况下,定位器纯粹是基于拓扑考虑,也是相当不言自明的。另一方面,团队和成熟度变得有点复杂,基本上取决于所需的存储库数量。团队依赖于业务逻辑和权限。成熟度取决于门和工件所有权/处置。如果 Artifactory 实例专注于部署而不是生成,那么考虑成熟度实际上比技术更重要是有好处的。但是,遵循统一的命名约定优先。
本地存储库
本地存储库是物理的、本地管理的存储库,您可以在其中部署工件。通常,这些用于部署内部和外部版本以及开发构建,但它们也可用于存储在公共存储库(例如 3rd 方商业组件)上未广泛使用的二进制文件。使用本地存储库,您的所有内部资源都可以通过一个通用 URL 从您组织内的单个访问点访问。了解更多 >
本地存储库的一个关键次要用例是它们用于存储第三方工件时。这通常涵盖无论出于何种原因您无法远程访问第三方工件的源(由于气隙或仅仅因为它没有 http 访问权限)的场景,或者您正在实现一个白色-列表方法。在这两种情况下,一般来说,技术保持不变,但团队名称应该是表明其来源位置的东西;例如,tomcat 或 centos。因为通常仍然存在这些拓扑,所以定位器的工作方式也与其他本地存储库相同。到期但是,现在不再是 release/dev 之类的东西,而是反映了工件的信任级别。所以它可能是“上传”或“白名单”。例如,“tomcat-mvn-upload-local”。如果您使用本地存储库对处于某个状态的远程进行快照,则这可能是一个日期。例如,“centos7-rpm-oct2017-local”。
2. 远程仓库
远程存储库分为两类:
那些是 Artifactory 拓扑的一部分,在这种情况下,它们的命名约定应与本地存储库和四个相关部分的命名约定一致,其中定位器指示源存储库被远程。
远程存储库
远程存储库充当在远程站点(如 ConanCenter)管理的存储库的缓存代理。根据控制缓存和代理行为的各种配置参数,工件在远程存储库中存储和更新。了解更多 >
那些是中央存储库。这些是您从中提取工件的外部存储库,可以通过它们的源 ID 引用,例如ConanCenter。为了严格遵守,您可以考虑以下模型<central_name>-<technology>-remote,其中默认 Artifactory 命名行为使用源。通常,这有助于轻松识别伪影。
中央存储库
ConanCenter是 C/C++柯南包的中央存储库。
3. 虚拟仓库
有两种类型的虚拟存储库名称。
大多数虚拟存储库不包含<locator>,并且由<team>-<tech>-<maturity>组成. 在很多情况下,用户不需要了解拓扑实现细节。一般来说,所有消费和写入都是通过虚拟存储库完成的,而不是本地/远程存储库,这是最佳实践。这样就可以省略尽可能多的实现细节,让用户使用单个众所周知的 URL。此外,虽然对于本地存储库而言,成熟度严格取决于工件阶段,但对于虚拟存储库,您可能会更多地考虑受众。例如,名称中包含“-dev”的虚拟存储库表示开发人员应该使用的虚拟存储库。最后,一个常见的用例是整个公司使用一个虚拟存储库,该存储库聚合了特定技术的所有存储库,例如 Docker, 用于解析和读取权限。虽然严格遵守命名约定将要求团队名称为“all”或类似的名称(例如 all-mvn-release),但更常见的是简单地省略团队名称并使用存储库名称,例如 docker-stage。
另一种主要类型的虚拟存储库名称是为一致性起别名,例如,符合外部工具或遗留自动化的要求。虚拟存储库允许您为单个或多个存储库创建别名。这可能是一个一致的名称,但如果您需要适应遗留的构建过程或使用特定名称的特定工具,它也非常有用。例如,对于自制软件,拥有一个名为“bottles”的虚拟存储库很有用。一般来说,这些名称不受标准实践的约束,尽管在可能的情况下尽量避免完全违反虚拟存储库似乎符合但不符合的情况。一个例子是调用虚拟存储库“ci-files-local”,因为自动化需要这个存储库名称;
虚拟存储库
虚拟存储库封装了任意数量的本地和远程存储库,并将它们表示为从单个 URL 访问的统一存储库。它为您提供了一种管理开发人员访问哪些存储库的方法,因为您可以自由混合、匹配和修改虚拟存储库中包含的实际存储库。您还可以通过定义底层存储库顺序来优化工件解析,这样 Artifactory 将首先查看本地存储库,然后是远程存储库缓存,然后 Artifactory 才会通过网络直接从远程资源请求工件。对于开发人员来说,这很简单。只需请求包,Artifactory 将根据您的组织政策安全且最佳地访问它。了解更多 >
存储库的组织和管理
现在我们已经建立了基本的存储库命名结构,让我们回顾一下在 JFrog Artifactory 中组织存储库时需要考虑的不同事项。本质上,存储库组织归结为三件事:安全性、性能和可操作性。大多数情况下,这些考虑因素将决定您设置“团队”的粒度,以及在较小程度上计算成熟度级别的粒度。
1. 安全
Artifactory 权限目标允许通过包含/排除模式在单个文件夹甚至文件级别管理权限。一般来说,这里的最佳实践是在存储库级别管理权限。对于具有高度结构化组织的存储库,如 Maven 和 RPM,可以在文件夹级别实现大量粒度。但是,这对于管理员来说仍然太复杂而无法跟踪(尽管有效的权限分析可以提供帮助)。对于 READ 权限尤其如此,尽管可以将其工作的那些技术的更精细粒度用于写入权限。
至少,当您的团队不协作或不共享数据时,您应该在相同的技术和成熟度级别内拥有单独的存储库,因此不需要/不需要对彼此软件的读取权限。您还可以根据写入权限选择提供不同的存储库,并假设它们聚合在虚拟存储库中以供读取。这种基于写入的存储库的选择对于没有按命名空间很好划分的存储库类型尤其重要,例如默认的 NuGet 行为或没有作用域的 npm 存储库。
2. 性能
另一个主要问题是性能。这因技术而异,但对于任何给定的技术,在该存储库中往往存在最大数量的有意义的包。在 Maven 中,这往往是数十万个,并且更多地是由 UI 考虑驱动的。而在 Yum/Debian 中,这往往更多,数以万计,并且更多地受到计算索引的整体方法和生成的索引文件的大小以及它们对客户端性能的影响的驱动。
另一方面是清理策略。一个完全没有清理策略的人工服务器将在存储使用方面增长得非常快,而且通常大部分不会是你真正需要存储的东西。实施清理政策的机制是一个不同的讨论。有些可以在这里找到。根据组织的业务需求,不同的项目可能有不同的策略。上面讨论的一个主要驱动因素往往是成熟度。例如,一个 dev-sandbox docker 注册表可能有一项政策规定应删除过去两周内未下载的任何 Docker 标签。另一方面,受监管的行业可能有监管要求,即任何已在受监管的生产环境中的对象必须保留十年。在生命周期的这些阶段到不同存储库之间建立可靠的升级模型至关重要。但这些政策对于正在开发的所有应用程序也可能并不相同。虽然在生产中处理股票交易的申请将受到监管,但同一家公司用于管理午餐点菜的工具可能会在其“生产”生命周期完成后不久被丢弃,但确实需要在实际运行时进行维护正在使用。
3. 可操作性
当涉及到在特定环境中为特定团队管理工件存储库时,需要考虑其他基本的可操作性。通常,这些策略将希望在存储库级别进行处理,因此这将是选择存储库结构的驱动决定。
第一个是相当简单的:确定业务价值。如果您管理的 Artifactory 跨越公司内的多个大型项目和业务单位,除了上述注意事项外,您还希望能够确定这些不同的项目/单位如何使用 Artifactory 服务。这可能是为了明确的拒付,或者只是为了跟踪哪些单位导致了哪些类型的成本。只要您想跟踪公司中给定组织单位的使用情况,与其他组织分开,它就应该有自己的存储库,并在命名约定中相应地进行分解,以便于识别。
此外,一旦超出业务可以成功协调命名约定和目录结构组织的界限,您至少必须拥有单独的存储库。也就是说,如果一个团队太大而无法在没有可怕的官僚流程的情况下成功管理诸如工件的组 ID/命名约定之类的东西,最好只给他们单独的存储库,并且总是存在这种限制的规模。一般来说,写权限,尤其是删除权限,应该合理具体,以防止团队干扰彼此的工作。一般来说,删除权限应该只提供给一个非常小的组,在基于策略的收割者之外(请参阅上面性能部分中关于清理策略的讨论)。
考虑到所有这些,通常管理员更喜欢更少的存储库。即使您的存储库管理过程自动化程度越高,它的重要性就越小。例如,在一个强大的 DevOps 环境中,您最终可能会遇到这样一种情况,即每一个测试都可以被视为一种提升。虽然为每个测试使用升级 API可能有意义,但为数十个测试中的每一个都拥有一个存储库可能没有意义,而是通过properties跟踪它,并为主要控制点保留单独的存储库
推荐的公约
下表总结了最佳实践命名约定以及每种存储库类型的示例。
1. 本地存储库
<项目密钥/团队>-<技术>-<成熟度>-<定位器>
例子:
- rtfact-docker-dev-local(其中 rtfact 是 Artifactory 的项目密钥)
- Tigerteam-码头工人-发布-本地
| 名称部分 | 推荐 |
| --------------- | :----------------------------------------------------------: |
| <项目密钥/团队> | 这是命名约定中最难的部分。它基于您想要管理权限/性能/可操作性问题的粒度。它也可以是产品名称,或引用第三方库的来源。对于 JFrog 项目,它是项目存储库的唯一标识符。Projects Key 会自动作为前缀添加到在项目中创建的资源。 |
| <技术> | 内容类型。这通常是包类型,例如:mvn、rpm、docker。它也可能更具体,例如 centos 或 ubuntu。 |
- 远程仓库
例子:
老虎 mvn 发布波士顿
rtfact-远程
存储库用例 | 推荐 |
---|---|
Artifactory 拓扑的一部分 | 对于远程处理另一个工件服务器,请使用与本地存储库相同的命名约定,具体取决于它正在远程处理的存储库。 <locator> 在这种情况下应该是远程工件的标识符。 |
中央资料库 | <中央名称>-远程“-remote”是可选的,但有助于避免与虚拟存储库命名约定混淆。即 jcenter-remote 或只是 'jcenter' |
- 虚拟仓库
<项目密钥/团队>-<技术>-<成熟度>
例子:
rtfact-docker-dev
老虎码头产品
名称部分 推荐
<项目密钥/团队> 共享读取权限的组。
如果您使用虚拟写入来控制写入,那么您可以在写入权限级别进行控制。
<技术> 包类型。
<成熟度> 这部分可以省略。但是,它通常用作写入控制功能的一部分和/或专门用于生产。
与本地存储库中的 <maturity> 不同,它更有可能从部署模型的角度而不是 CI 的角度进行控制。
结论
组织存储库和选择命名约定是 JFrog Artifactory 管理员需要做出的第一个也是最重要的决定之一。虽然充分利用虚拟存储库可以允许以后进行更改,但最好预先选择命名约定。
本白皮书介绍了存储库组织和命名约定的各种注意事项,应该可以帮助您回答以下问题:“我需要多少个存储库?”。它提供了一个由四部分组成的约定,<projectKey/team>-<tech>-<maturity>-<locator>,可用作命名和组织结构的基本最佳实践指南。使用这个建议的约定,大多数组织问题变得相当清楚。
尽管团队粒度可能有点挑战,但这种粒度通常是根据安全性、性能和可操作性问题决定的。虽然您可能必须随着时间的推移调整粒度,但良好的命名约定与使用虚拟存储库相结合可以使您的团队成为一个相对轻松的过程。此外,您可以使用虚拟存储库别名来避免在前进时破坏构建。
本白皮书中描述的约定将允许您跨全球拓扑扩展您的 Artifactory。它将为大型企业安装提供 DevOps 支持,为许多不同团队和项目的数千名开发人员提供服务。