构建 CI/CD 构建管道
到目前为止,在我们的CI/CD 系列中,我们已经讨论了一些高级概念和术语。在本期中,我们将进入构建管道的实际阶段,展示它在实施中的样子。
我们将更深入地研究 baking 和 frying,以展示它在 MinIO 分布式集群构建过程的不同阶段的样子。在此过程中,我们将使用基础架构即代码来确保一切都通过 Packer 和 Jenkins 进行版本控制和自动化。
为了使开发人员可以轻松使用我们的分布式 MinIO 设置而无需在云中启动资源,我们将使用 Vagrant 对其进行测试。我们的大多数笔记本电脑都足够强大,可以尝试一些东西,但我们已经习惯了云,所以我们倾向于先看看那里。但我们将改变这种看法,并向您展示在类似云的本地环境中进行开发是多么容易,只需在您的笔记本电脑上完成 MinIO 对象存储。
最小图像
这是烘烤阶段。为了尽可能自动化,我们将使用构建工具创建MinIO的 L2 映像,可用于启动任何类型的 MinIO 配置。这不仅使我们能够遵循基础架构即代码最佳实践,而且还为任何未来的更改提供版本控制。
MinIO 构建模板
我们将使用Packer以一致的方式构建机器可读的图像。Packer 允许您从多个输入(例如 ISO、Docker Image 和 AMI)以及其他输入中获取来源,并通过将构建的图像上传到 Amazon Elastic Container Registry (ECR)、Google Container Registry (GCR)、Docker Hub 来对构建的图像进行后处理、Vagrant Cloud 和其他几个输出,甚至本地到磁盘。
安装非常简单;你可以使用brew
或者,如果您正在寻找其他发行版,请前往 Packer下载页面。
最初推出 Packer 时,它仅使用 JSON 作为模板语言,但正如您可能知道的那样,JSON 并不是最适合人类编写的语言。机器使用 JSON 很容易,但是如果你必须编写一个巨大的 JSON blob,这个过程很容易出错。即使省略单个命令也可能导致错误,更不用说您不能在 JSON 中添加注释。
由于上述问题,Packer 过渡到 Hashicorp 配置语言或 HCL(Terraform 也使用它)作为选择的模板语言。我们编写了一个构建 MinIO 映像的HCL Packer 模板——让我们详细了解一下。
对于我们所有的代码示例,我们将在此处粘贴代码的关键,并且我们在GitHub上提供了完整的端到端工作示例可供下载。主模板将放在main.pkr.hcl中,变量(以 开头的任何内容var)将放在variables.pkr.hcl中。
Git 将存储库克隆到您的本地设置,您将在其中运行 Packer 构建
我们将使用它virtualbox来构建 MinIO 图像。安装虚拟机
然后将其定义为main.pkr.hcl中的源作为第一行
注意:在帖子中,我们将引用指向 GitHub 存储库中确切行的链接,您可以在其中查看完整代码,与上面类似。您可以单击这些链接转到代码中的确切行。
让我们为将要构建的 MinIO 图像设置一些基本参数。我们将定义名称、CPU、磁盘、内存,以及一些与图像配置相关的其他参数。
需要提供源以构建我们的自定义图像。来源可以是相对于您运行命令的路径packer或在线 URL 的本地。
需要按照 Packer 将尝试使用它们的顺序提供源。在下面的例子中,我们给出了一个本地资源和一个在线资源;如果本地源可用,它将跳过在线源。为了加快构建速度,我已经预先下载了 ISO 并将其添加到 `${var.iso_path}` 目录中。
我们创建的映像需要一些默认值,例如在配置过程中设置的主机名、SSH 用户和密码。这些命令作为通过 http 服务器提供的preseed.cfg kickstart 进程的一部分执行。
该图像将使用我们在scripts/目录中编写的一些脚本进行自定义。我们将使用shell配置器来运行这些脚本。
接下来,让我们展示一下我们在之前的博文中学到的一些概念,特别是烘焙和油炸图像。在本教程中,我们将烘焙 MinIO 二进制文件和服务依赖项,例如 MinIO 所需的用户名和组。我们正在烘烤它而不是油炸,因为无论我们如何配置和启动我们的图像,它们都将保持不变。
我们将设置 MinIO 版本与用户和组一起安装,服务将在其下运行。
大多数安装步骤都隐藏在独立于模板的专用 bash 脚本中,但它们将从模板中调用。这使整个模板保持干净和简单,使其更易于管理。下面是我们将要使用的脚本列表
我不打算详细介绍每个脚本的作用,因为它们中的大多数都是设置基本 Linux 映像所需的基本样板代码——将其视为我们安装的 L1 阶段。
我想谈的文件是minio.sh,我们在其中烘焙 MinIO 二进制文件。
MinIO 二进制文件是从上游下载的,“MINO_VERSION”变量在几步之前设置为安装期间可用的环境变量。
安装二进制文件后,它需要我们单独创建的用户和组,以便 MinIO 服务使用它来运行
通常,对于 MinIO 的每个新版本,我们都应该构建一个新镜像,但在紧要关头,您可以升级二进制文件而不升级整个镜像。我会告诉你如何在油炸阶段做到这一点。
构建镜像后,我们必须告诉 Packer 如何处理它。这就是后处理器发挥作用的地方。您可以定义其中的几个,但我们将在这里介绍其中的三个:
vagrant后处理器构建一个可供 vagrant 使用的图像。它创建了 vagrant VirtualBox,可以使用 Vagrantfile 启动它(稍后将详细介绍 Vagrantfile)。该.box文件存储在output可以在本地导入的定义位置。
shell-local后处理器允许我们在本地运行 shell 命令,其中packer执行命令以执行后清理和其他操作。在这种情况下,我们将删除输出目录,因此它不会与下一个打包程序运行构建冲突。
在本地拥有图像很棒,但是如果您想与团队的其他成员甚至组织外的开发人员分享您很棒的 MinIO 图像怎么办?您可以手动共享之前生成的框图像,但这可能很麻烦。相反,我们会将图像上传到Vagrant 云注册表,任何想要使用您的 MinIO 图像的人都可以拉取该图像。
将图像上传到注册表的另一个优点是您可以对图像进行版本控制,因此即使您将来升级它,人们也可以将其固定到特定版本并在闲暇时升级。
为了将您的 MinIO 图像上传到 Vagrant Cloud,我们需要一个访问令牌和用于创建 Vagrant Cloud 帐户的帐户的用户名。我们将在接下来的步骤中向您展示如何获取此信息。
MinIO 映像注册表
转到https://app.vagrantup.com创建一个 Vagrant Cloud 帐户。
为了让我们使用 Vagrant Cloud,我们需要事先创建一个与vm_namePacker 配置中名称相同的 repo。
按照以下步骤创建我们的图像将上传到的存储库。
我们需要在 Vagrant Cloud 中创建的另一件事是我们需要在上传构建的图像之前进行身份验证的令牌。按照以下说明进行操作。
构建 MinIO 镜像
此时,您应该有一个用于构建自定义 MinIO 映像的 Packer 模板和一个用于上传映像的注册表。这些是我们实际开始构建之前所需的所有先决条件。
进入main.pkr.hcl模板文件所在的目录,您将看到我们在前面的步骤中讨论过的一堆其他文件。
构建需要在构建过程中传递的变量的有效值,否则将无法尝试使用默认值。具体来说,在这种情况下,我们需要传递 Vagrant Cloud令牌和用户名。您现在可以直接在variables.pkr.hcl中编辑这些值,但出于安全原因,不要将包含这些值的文件提交到 repo。稍后在自动化阶段,我们将向您展示另一种设置这些变量的方法,该方法不涉及编辑任何文件并且是一种更安全的替代方法。
这些变量的值之前是在我们创建 Vagrant Cloud 帐户时作为步骤的一部分创建的。您可以将这些值添加到default键中。
在构建镜像时,还需要提升镜像的版本,因此每次构建镜像时,都会有一个唯一的版本。我们使用一个名为Semver的格式化系统,它允许我们根据我们正在制作的版本类型设置MAJOR.MINOR.PATCH编号。首先,我们总是0.1.0从每个版本需要增加的开始。
在为变量和其他设置设置有效值后,让我们确保我们的模板经过检查和验证以正常工作。
确认一切无误后,build在Packer中运行命令
这将启动构建过程,构建和上传整个图像可能需要 15-20 分钟,具体取决于您的机器和互联网速度。
打开 VirtualBox Manager 以查看 Packer 启动的 VM。它将具有分配给变量的名称vm_name。双击 VM 以打开带有实时版本预览屏幕截图的 Java 控制台,您可以在其中查看操作系统安装过程。

下面是开头和结尾的片段,中间有一些 MinIO 位。
前往https://app.vagrantup.com仪表板查看新上传的图片
MinIO分布式集群
这是油炸阶段。我们现在已经发布了一个镜像,我们的团队和任何想要运行 MinIO 的人都可以使用。但是我们如何实际使用这个发布的图像呢?我们将使用Vagrant在本地启动 VM,类似于我们将 Terraform 用于云实例的方式。
MinIO 流浪文件
好消息是我们已经为您编写了Vagrantfile,我们将逐步完成它,以便您了解如何在分布式模式下部署 MinIO。您可以在裸机、Kubernetes、Docker 等的生产环境中使用这些相同的步骤。唯一的区别是您可能希望使用Terraform或CDK之类的东西来启动它们,因为它们管理的不仅仅是 VM 或容器,如 DNS、CDN 和托管服务,以及其他云资源。
进入所在目录vagrant内的目录。如果您仍在该目录中,则可以运行以下命令ci-cd-buildpackerpacker
使用以下命令安装 Vagrant 以及vagrant-hosts允许我们使用主机名在 VM 之间进行通信的插件。
DNS 的工作方式非常简单,因为该插件基本上/etc/hosts使用 Vagrantfile 中启动的其他 VM 的详细信息编辑每个 VM 上的文件。这可以手动完成,但是当我们可以自动化时为什么还要这样做呢?请注意,所有 VM 都必须使用相同的 Vagrantfile 启动,因为 vagrant-hosts 不会跟踪两个离散 Vagrantfile 之间的主机。
您必须对 Ruby 有一点熟悉才能理解 Vagrantfile,但如果您不熟悉也没关系 – 它与 Python 非常相似,因此我们将带您了解它的每个部分。下面您可以看到我们如何为启动 MinIO 集群所需的一些基本参数定义变量。
其中大部分可以保持默认设置,但我建议注意BOX_IMAGE. 盒子图像用户名当前设置为minioaj并且应该更新为您在构建 Packer 图像时选择的用户名。
除了上述变量之外,您不需要编辑任何其他内容。它们是不言自明的,并且严格遵循 MinIO 分布式设置指南。但是,无论如何,让我们浏览整个文件,以便我们更好地理解到目前为止所学的概念。
以下循环将创建与我们在 中指定的一样多的 VM MINIO_SERVER_COUNT。在这种情况下,它将循环 4 次,同时定义 VM 设置,例如 4 个 VM 的主机名和 IP,以及它们将使用的图像。
接下来,我们必须使用 定义每个服务器集的驱动器数量MINIO_DRIVE_COUNT。你一定已经注意到下面我们不仅在数字上循环,而且在每个循环中drive_letter开始并递增 (c, d, e...)。b这是因为 Linux 中的驱动器是用 sda、sdb、sdc 等字母命名的。我们从安装操作系统的根磁盘sdb开始。sda/
在这种情况下,4 台服务器中的每台服务器将有 4 个磁盘,每个服务器总共有 16 个磁盘。将来,如果您更改设置,了解磁盘总数的最简单方法是乘以 MINIO_SERVER_COUNT x MINIO_DRIVE_COUNT。
上一步只是创建了一个虚拟驱动器,就好像我们在裸机上添加了一个物理驱动器一样。您仍然需要配置磁盘分区并挂载它们,以便 Linux 可以使用它们。
用于为 4 个磁盘(b、c、d、e)中的每一个parted创建一个 ext4分区。/dev/sd*1
格式化创建的分区并将它们添加到/etc/fstabVM 每次重新启动时自动安装 4 个磁盘。
这是当我们挂载我们创建的磁盘并设置 MinIO 服务启动所需的适当权限时。/etc/default/minio在配置所有磁盘组件后,我们添加卷和凭据设置 。我们将启用 MinIO 但尚未启动它。虚拟机启动后,我们将同时启动所有虚拟机,以避免在一定时间内找不到其他节点而导致 MinIO 超时的错误情况。
我们设置了更多与 VM 相关的设置,但最重要的是此代码段中的最后一行使用插件在所有 VM 之间vagrant-hosts同步文件。/etc/hosts
到目前为止,您一定想知道为什么我们不在minio.sh脚本中的 Packer 构建过程中烘焙所有这些 shell 命令。为什么我们将这些设置作为 Vagrantfile 配置过程的一部分?
这是一个很好的问题。原因是我们希望根据每个用例修改磁盘设置——有时,您希望 MinIO 集群中有更多节点,而其他时候您可能不希望每个节点有 4 个磁盘。您不想为每个驱动器配置创建一个唯一的图像,因为您最终可能会得到数千个相似的图像,唯一的区别是驱动器配置。
您也不想为 MinIO 使用默认的 root 用户名和密码,我们已经构建了一个流程,允许您在配置时修改它。
如果你想升级 MinIO 二进制版本但又不想每次都构建一个新的 Packer 镜像怎么办?这就像添加一个shell带有命令的块来下载和安装 MinIO 二进制文件一样简单,就像我们在minio.sh脚本中为 Packer 所做的那样。以下是帮助您入门的示例伪代码
这是您作为 DevOps 工程师需要使用您的最佳判断力在烘焙和煎炸之间找到适当平衡的地方。您可以在 Packer 构建过程中烘焙所有配置,也可以在供应过程中灵活地炸毁配置。我们希望在您开发自己的设置时留下一些思考的余地。
启动 MinIO 集群
到目前为止,我们对如何部署集群的内部结构有了很好的了解。现在剩下的就是使用 Vagrant 在 Virtualbox 上部署集群。
根据需要设置以下环境变量,让 VM 自动检测到我们的磁盘
确保您位于同一位置并Vagrantfile运行以下命令
您的输出应如上所示,状态设置为not created。这是有道理的,因为我们还没有配置节点。
终于是主打菜了!在我们的 MinIO 集群中提供 4 个节点
确保您看到此输出==> vagrant: Features: disks,因为这验证环境变量VAGRANT_EXPERIMENTAL=disks已正确设置。当每个 VM 出现时,其输出将以主机名为前缀。如果在配置过程中出现任何问题,请查看此主机名前缀以了解消息来自哪个虚拟机。
命令执行完毕后,vagrant status再次运行以验证所有节点是否正常running
所有节点都应该处于状态running。这意味着节点正在运行,如果您没有在供应过程的早期输出中看到任何错误,那么我们所有的 shell 命令都已Vagrantfile成功运行。
最后但同样重要的是,让我们启动实际的 MinIO 服务。如果您还记得,我们启用了该服务,但我们没有启动它,因为我们希望所有节点都先启动。然后我们将使用命令几乎同时启动所有服务vagrant ssh,这将使用此 bash 循环通过 SSH 连接到所有 4 个节点。
确认使用journalctl命令查看日志,验证所有4个节点上的MinIO服务是否正常启动
您应该会看到类似于下面示例的输出minio-4。这16 Online意味着我们 4 个节点上的所有 16 个驱动器都在线。
将来,如果你想启动自己的自定义 MinIO 集群,你现在拥有了所有必要的工具。
自动化 MinIO 构建
从技术上讲,你可以在这里停下来继续你的快乐之路。但我们知道您总是想要更多 MinIO,因此我们将更进一步向您展示如何自动执行此过程,这样您就不必每次都手动运行 Packer 构建命令。
安装詹金斯
使用以下命令安装并启动 Jenkins
Jenkins 启动后,它会要求您设置一些凭证,这应该非常简单。设置凭据后,您需要确保使用以下步骤安装了 git 插件。
配置 MinIO 构建
让我们创建一个构建配置来自动化我们的 MinIO 映像的 Packer 构建过程。但在开始之前,我们之前提到过还有其他方法可以设置 Packer 变量的值。使用环境变量,可以通过在变量名前加上前缀来覆盖variables.pkr.hcl中的值PKR_VAR_varname。我们将在下一步中使用环境变量覆盖一些变量,而不是直接编辑文件。
在“构建步骤”部分下,我们添加了一些命令。该文本如下,因此您可以将其复制并粘贴到您的配置中。
执行 MinIO 构建
一旦我们配置了作业,我们就可以执行构建。
一旦构建成功,请转到https://app.vagrantup.com以验证图像是否已成功上传。
最后的想法
在这篇博文中,我们向您展示了如何在笔记本电脑上从构建到配置的整个过程中以分布式模式采用 MinIO S3 兼容对象存储。这将帮助您和您的开发人员在本地快速启动并运行生产级 MinIO 集群,而不会影响使用整个功能集。MinIO 兼容 S3,轻量级,可以以云原生方式安装和部署在几乎任何平台上,例如 Bare Metal、VM、Kubernetes 和 Edge IoT 等。
让我们在下面简要回顾一下我们执行的操作:
我们创建了一个 Packer 模板来从头开始创建 MinIO 镜像。
我们使用 Vagrant 作为配置器,因此我们可以使用镜像在本地进行开发。
我们利用 Jenkins 自动将图像上传到 Vagrant 云以供将来构建。
我们证明了您必须在烘烤和油炸之间取得平衡。每个组织的要求都不同,所以我们不想一刀切地说什么地方应该停止烘烤,什么地方应该开始油炸。作为 DevOps 工程师,您需要进行评估以确定每个应用程序的最佳课程。我们构建 MinIO 是为了提供运行您自己的对象存储所需的灵活性和可扩展性。
如果您自己实施此功能或向我们的任何流程添加了其他功能,请在Slack上告知我们!