构建 CI/CD 构建管道

Constructing a CI/CD Build Pipeline

到目前为止,在我们CI/CD 系列中,我们已经讨论了一些高级概念和术语。在本期中,我们将深入构建管道的实际阶段,展示其在实现中的样子。

我们将深入探讨烘焙和油炸,展示它在 MinIO 分布式集群构建过程的不同阶段中的外观。在此过程中,我们将使用基础设施即代码来确保所有内容都使用 Packer 和 Jenkins 进行版本控制和自动化。

为了让开发人员能够轻松使用我们的分布式 MinIO 设置,而无需在云中启动资源,我们将使用 Vagrant 对其进行测试。我们大多数笔记本电脑都足够强大,可以尝试一些东西,但我们已经习惯了云,因此我们倾向于首先查看那里。但我们将改变这种看法,向您展示在本地创建类似云的环境是多么容易,该环境配备了 MinIO 对象存储,只需使用您的笔记本电脑即可。

MinIO 镜像

这是烘焙阶段。为了尽可能地自动化此过程,我们将使用构建工具来创建 MinIO 的 L2 镜像,该镜像可用于启动任何类型的 MinIO 配置。这不仅使我们能够遵循基础设施即代码的最佳实践,而且还为任何未来的更改提供版本控制。

MinIO 构建模板

我们将使用 Packer 以一致的方式构建机器可读的镜像。Packer 允许您从多个输入(如 ISO、Docker 镜像和 AMI 等)中获取源代码,并通过将构建的镜像上传到 Amazon Elastic Container Registry (ECR)、Google Container Registry (GCR)、Docker Hub、Vagrant Cloud 和其他几个输出(甚至本地磁盘)来对构建的镜像进行后处理。

安装非常简单;您可以使用 brew

$ brew install packer

或者,如果您正在寻找其他发行版,请访问 Packer 下载 页面。

Packer 最初推出时,它只使用 JSON 作为模板语言,但如您所知,JSON 不是最适合人类编写的语言。机器很容易使用 JSON,但如果您必须编写一个巨大的 JSON 块,则此过程容易出错。即使省略单个命令也会导致错误,更不用说您无法在 JSON 中添加注释了。

由于上述问题,Packer 转向 HashiCorp 配置语言或 HCL(也由 Terraform 使用)作为首选模板语言。我们编写了一个 HCL Packer 模板 来构建 MinIO 镜像,让我们详细了解一下。

对于我们所有的代码示例,我们将在此处粘贴代码的关键部分,并且我们提供了完整的端到端工作示例,可在 GitHub 上下载。主模板将放在 main.pkr.hcl 中,变量(以 var 开头的任何内容)将放在 variables.pkr.hcl 中。

将仓库克隆到您的本地设置中,您将在其中运行 Packer 构建

$ git clone https://github.com/minio/blog-assets.git
$ cd blog-assets/ci-cd-build/packer/

我们将使用 virtualbox 来构建 MinIO 镜像。安装 Virtualbox

$ brew install virtualbox

然后在 main.pkr.hcl 中将其定义为第一行的源代码

source "virtualbox-iso" "minio-vbox" {
...
}

main.pkr.hcl#L1

**注意:** 在文章中,我们将引用指向 GitHub 仓库中您可以在其中看到完整代码的特定行的链接,与上面类似。您可以单击这些链接以转到代码中的特定行。

让我们为将要构建的 MinIO 镜像设置一些基本参数。我们将定义名称、CPU、磁盘、内存以及与镜像配置相关的几个其他参数。

  vm_name = var.vm_name

  cpus      = var.cpus
  disk_size = var.disk_size
  memory    = var.memory

  hard_drive_interface = "sata"
  headless             = var.headless

main.pkr.hcl#L3-L10

为了构建自定义镜像,需要提供源。源可以是本地相对路径(相对于运行packer命令的路径)或在线URL。

源需要按照Packer尝试使用的顺序提供。在以下示例中,我们提供了一个本地源和一个在线源;如果本地源可用,则会跳过在线源。为了加快构建速度,我已经预先下载了ISO并将其添加到`${var.iso_path}`目录中。

  iso_checksum = "${var.iso_checksum_type}:${var.iso_checksum}"
  iso_urls     = [
        "${var.iso_path}/${var.iso_name}",
        var.iso_url
      ]

main.pkr.hcl#L12-L16

我们创建的镜像需要一些默认设置,例如在配置过程中设置主机名、SSH用户和密码。这些命令作为 preseed.cfg 启动过程的一部分执行,该过程通过http服务器提供。

        " hostname=${var.hostname}",
        " passwd/user-fullname=${var.ssh_fullname}",
        " passwd/username=${var.ssh_username}",
        " passwd/user-password=${var.ssh_password}",
        " passwd/user-password-again=${var.ssh_password}",

main.pkr.hcl#L30-L34

该镜像将使用我们编写的一些脚本进行自定义,这些脚本位于 scripts/ 目录中。我们将使用shell供应器来运行这些脚本。

provisioner "shell" {
...
}

main.pkr.hcl#L61

接下来,让我们运用我们在 上一篇博文中 学到的一些概念,特别是烘焙和煎炸镜像。在本教程中,我们将烘焙MinIO二进制文件和服务依赖项,例如MinIO所需的用户名和组。我们将其烘焙而不是煎炸,因为无论我们如何配置和启动镜像,这些都将保持不变。

我们将设置要安装的MinIO版本以及服务运行所在的用户名和组。

        "MINIO_VERSION=${var.minio_version}",
        "MINIO_SERVICE_USER=${var.minio_service_user}",
        "MINIO_SERVICE_GROUP=${var.minio_service_group}",

main.pkr.hcl#L67-L69

大多数安装步骤都隐藏在与模板分离的专用 bash 脚本中,但它们将从模板中调用。这使整体模板保持简洁易懂,更易于管理。以下是我们将使用的脚本列表

    scripts = [
        "scripts/setup.sh",
        "scripts/vagrant.sh",
        "scripts/minio.sh",
        "scripts/cleanup.sh"
      ]

main.pkr.hcl#L75-L80

我不会过多介绍每个脚本的具体功能,因为大多数脚本都是设置基本 Linux 镜像所需的简单样板代码——可以将其视为我们安装的 L1 阶段。

我想要重点介绍的文件是 minio.sh,我们在其中烘焙 MinIO 二进制文件。

MinIO 二进制文件是从上游下载的,MINO_VERSION 变量在之前的几个步骤中已设置为环境变量,在安装期间可用。

wget https://dl.min.io/server/minio/release/linux-amd64/archive/minio_${MINIO_VERSION}_amd64.deb -O minio.deb
dpkg -i minio.deb

minio.sh#L8-L9

安装二进制文件后,它需要用户和组,我们分别创建了它们,以便 MinIO 服务可以以它们的身份运行

groupadd -r ${MINIO_SERVICE_GROUP}
useradd -M -r -g ${MINIO_SERVICE_GROUP} ${MINIO_SERVICE_USER}

minio.sh#L12-L13

通常,对于每个新的 MinIO 版本,我们应该构建一个新的镜像,但在紧急情况下,您可以在不升级整个镜像的情况下升级二进制文件。我将在煎炸阶段向您展示如何操作。

构建镜像后,我们必须告诉 Packer 如何处理它。这就是后处理器发挥作用的地方。您可以定义 多个 后处理器,但这里我们将介绍其中的三个。

  • vagrant 后处理器构建一个可以被 Vagrant 使用的镜像。它创建 Vagrant VirtualBox,可以使用 Vagrantfile(稍后将详细介绍 Vagrantfile)启动它。.box 文件存储在 output 中定义的位置,可以本地导入。

    post-processor "vagrant" {
      output = "box/{{.Provider}}/${var.vm_name}-${var.box_version}.box"
      keep_input_artifact  = true
      provider_override    = "virtualbox"
      vagrantfile_template = var.vagrantfile_template
    }

main.pkr.hcl#L88-L93

  • shell-local 后处理器允许我们在本地运行 shell 命令,packer 命令执行的位置可以进行后清理和其他操作。在本例中,我们将删除输出目录,以避免与下一次 Packer 运行构建冲突。

    post-processor "shell-local" {
      inline = ["rm -rf output-${var.vm_name}-virtualbox-iso"]
    }

main.pkr.hcl#L101-L103

  • 在本地拥有镜像很棒,但如果您想与团队中的其他人甚至组织外部的开发人员分享您优秀的 MinIO 镜像怎么办?您可以手动分享之前生成的 box 镜像,但这可能很麻烦。相反,我们将镜像上传到 **Vagrant 云注册表**,任何想要使用您的 MinIO 镜像的人都可以从那里获取。

将镜像上传到注册表另一个好处是可以对镜像进行版本控制,即使将来升级了镜像,用户也可以将其固定到特定版本,并根据需要进行升级。

    post-processor "vagrant-cloud" {
      access_token = "${var.vagrant_cloud_token}"
      box_tag      = "${var.vagrant_cloud_username}/${var.vm_name}"
      version      = var.box_version
    }

main.pkr.hcl#L95-L99

为了将 MinIO 镜像上传到 Vagrant Cloud,我们需要一个访问令牌和用于创建 Vagrant Cloud 帐户的帐户用户名。在接下来的步骤中,我们将向您展示如何获取此信息。

MinIO 镜像注册表

访问 https://app.vagrantup.com 创建一个 Vagrant Cloud 帐户。请务必遵循以下说明。

为了使用 Vagrant Cloud,我们需要预先创建一个与 Packer 配置中 `vm_name` 相同的仓库。

variable "vm_name" {
  type = string
  default = "minio-ubuntu-20-04"
}

variables.pkr.hcl#L108-L111

按照以下步骤创建用于上传镜像的仓库。

在 Vagrant Cloud 中还需要创建令牌,以便在上传构建后的镜像之前进行身份验证。请遵循以下说明。

构建 MinIO 镜像

此时,您应该已经拥有一个 Packer 模板来构建自定义 MinIO 镜像,以及一个用于上传镜像的注册表。这些都是我们在实际开始构建之前所需的所有先决条件。

进入包含 `main.pkr.hcl` 模板文件所在的目录,您会看到我们在之前的步骤中讨论过的一些其他文件。

├── http
│   └── preseed.cfg
├── iso
│   └── ubuntu-20.04.1-legacy-server-amd64.iso
├── main.pkr.hcl
├── scripts
│   ├── cleanup.sh
│   ├── minio.sh
│   ├── setup.sh
│   └── vagrant.sh
└── variables.pkr.hcl

构建过程需要有效的变量值才能在构建过程中传递,否则会失败并尝试使用默认值。具体来说,在这种情况下,我们需要传递 Vagrant Cloud 的**令牌**和**用户名**。您现在可以在 variables.pkr.hcl 中直接编辑这些值,但由于安全原因,请勿将包含这些值的该文件提交到仓库。在后面的自动化阶段,我们将向您展示另一种设置这些变量的方法,这种方法不需要编辑任何文件,并且更安全。

这些变量的值之前是在创建 Vagrant Cloud 帐户时创建的。您可以将这些值添加到 `default` 键中。

变量 "vagrant_cloud_token" {
  类型 = 字符串
  敏感 =
  默认 = "abc123"
}

变量 "vagrant_cloud_username" {
  类型 = 字符串
  默认 = "minio"
}

variables.pkr.hcl#L113-L122

在构建镜像时,还需要升级镜像版本,这样每次构建镜像都会有唯一的版本。我们使用一种叫做 Semver 的格式系统,它允许我们根据发布的类型设置 主版本号.次版本号.修订版本号。首先,我们总是从 0.1.0 开始,每次发布都需要进行递增。

变量 "box_version" {
  类型 = 字符串
  默认 = "0.1.0"
}

variables.pkr.hcl#L124-L127

设置完变量和其他设置的有效值后,让我们确保我们的模板经过检查和验证以正常工作。

$ packer inspect .
$ packet validate .

配置有效。

确认一切正确后,在 Packer 中运行 build 命令

$ packer build .

这将启动构建过程,该过程可能需要 15-20 分钟,具体取决于您的机器和网络速度,以构建和上传整个镜像。

打开 VirtualBox 管理器查看 Packer 启动的 VM。它将具有分配给变量 vm_name 的名称。双击 VM 以打开 Java 控制台,其中包含实时预览屏幕截图,您可以在其中看到操作系统安装过程。

以下是开头和结尾的代码片段,其中间散布了一些 MinIO 部分。

+ packer build .


==>

virtualbox-iso.minio-vbox: 输出将以这种颜色显示。

==>

virtualbox-iso.minio-vbox: 正在获取 Guest additions
==>

virtualbox-iso.minio-vbox: 正在尝试 /Applications/VirtualBox.app/Contents/MacOS/VBoxGuestAdditions.iso
virtualbox-iso.minio-vbox: 正在尝试 /Applications/VirtualBox.app/Contents/MacOS/VBoxGuestAdditions.iso
==>

==>

virtualbox-iso.minio-vbox: /Applications/VirtualBox.app/Contents/MacOS/VBoxGuestAdditions.iso => /Applications/VirtualBox.app/Contents/MacOS/VBoxGuestAdditions.iso
virtualbox-iso.minio-vbox: 正在获取 ISO
==>

==>

virtualbox-iso.minio-vbox: 正在尝试 iso/ubuntu-20.04.1-legacy-server-amd64.iso
==>

==>

virtualbox-iso.minio-vbox: 正在尝试 iso/ubuntu-20.04.1-legacy-server-amd64.iso?


…TRUNCATED…


    virtualbox-iso.minio-vbox: ==> 正在下载 MinIO 版本 20221005145827.0.0

==> virtualbox-iso.minio-vbox: --2022-10-10 15:01:07--  https://dl.min.io/server/minio/release/linux-amd64/archive/minio_20221005145827.0.0_amd64.deb

==> virtualbox-iso.minio-vbox: 正在解析 dl.min.io (dl.min.io)... 178.128.69.202, 138.68.11.125

==> virtualbox-iso.minio-vbox: 连接到 dl.min.io (dl.min.io)|178.128.69.202|:443... 已连接。

==> virtualbox-iso.minio-vbox: HTTP 请求已发送,正在等待响应... 200 OK

==> virtualbox-iso.minio-vbox: 长度: 31806114 (30M) [application/vnd.debian.binary-package]

==> virtualbox-iso.minio-vbox: 保存到: ‘minio.deb’

==> virtualbox-iso.minio-vbox

==> virtualbox-iso.minio-vbox:      0K .......... .......... .......... .......... ..........  0% 98.5K 5m15s

==> virtualbox-iso.minio-vbox:     50K .......... .......... .......... .......... ..........  0%  199K 3m55s

==> virtualbox-iso.minio-vbox:    100K .......... .......... .......... .......... ..........  0% 15.2M 2m37s


…TRUNCATED…


构建 'virtualbox-iso.minio-vbox' 在 18 分钟 41 秒后完成。


==> 等待在 18 分钟 41 秒后完成


==> 构建已完成。成功构建的工件为

--> virtualbox-iso.minio-vbox: 虚拟机文件在目录中: output-minio-ubuntu-20-04-virtualbox-iso

--> virtualbox-iso.minio-vbox: 'virtualbox' 提供商盒子: box/virtualbox/minio-ubuntu-20-04-0.1.0.box

--> virtualbox-iso.minio-vbox: 'virtualbox': minioaj/minio-ubuntu-20-04

--> virtualbox-iso.minio-vbox: 'virtualbox': minioaj/minio-ubuntu-20-04

已完成: 成功

前往 https://app.vagrantup.com 仪表板查看新上传的镜像

MinIO 分布式集群

这是煎炸阶段。我们现在发布了一个可以被我们的团队和任何想要运行 MinIO 的人使用的镜像。但我们如何实际使用这个发布的镜像?我们将使用 Vagrant 在本地启动虚拟机,类似于我们如何使用 Terraform 启动云实例。

MinIO Vagrantfile

好消息是我们已经为你写了 Vagrantfile,我们将逐步讲解它,这样你就可以理解如何在 分布式 模式下部署 MinIO。你可以在裸机、Kubernetes、Docker 和其他环境的生产环境中使用这些相同的步骤。唯一的区别是你可能想使用类似 TerraformCDK 的东西来启动这些,因为它们管理的不仅仅是虚拟机或容器,还包括 DNS、CDN 和托管服务等其他云资源。

进入 vagrant 目录,该目录位于与 packer 相同的 ci-cd-build 目录中。如果你仍然在 packer 目录中,可以运行以下命令

$ cd ../vagrant


ci-cd-build
├── packer
│   ├── main.pkr.hcl
│   └── variables.pkr.hcl
└── vagrant
    └── Vagrantfile

使用以下命令安装 Vagrant,以及 vagrant-hosts 插件,该插件将允许我们使用主机名在虚拟机之间进行通信。

$ brew install vagrant

$ vagrant plugin install vagrant-hosts

DNS 的工作方式非常简单,因为该插件基本上在每个虚拟机的 /etc/hosts 文件中编辑了其他在 Vagrantfile 中启动的虚拟机的详细信息。这可以手动完成,但为什么我们要手动完成呢,我们可以自动化呢?请注意,所有虚拟机都必须使用相同的 Vagrantfile 启动,因为 vagrant-hosts 不会跟踪两个独立的 Vagrantfile 之间的主机。

为了理解 Vagrantfile,你必须对 Ruby 有点了解,但如果你不了解,也没关系——它非常类似于 Python,所以我们将带你逐步讲解它的每一个部分。下面你可以看到我们如何为启动 MinIO 集群所需的一些基本参数定义变量。

大多数这些可以保持默认设置,但我建议注意 BOX_IMAGE。盒子镜像用户名当前设置为 minioaj,应该使用你在构建 Packer 镜像时选择的用户名进行更新。

MINIO_SERVER_COUNT  = 4
MINIO_DRIVE_COUNT   = 4
MINIO_CPU_COUNT     = 2
MINIO_MEMORY_SIZE   = 4096 # MB
MINIO_DRIVE_SIZE    = 2 # GB
MINIO_ROOT_USER     = "minioadmin"
MINIO_ROOT_PASSWORD = "minioadmin"

BOX_IMAGE     = "minioaj/minio-ubuntu-20-04"
BOX_VERSION   = "0.1.0"
SUBNET_PREFIX = "192.168.60.1"
NAME_PREFIX   = "minio-"

Vagrantfile#L5-L16

除了上述变量外,你不需要编辑任何其他内容。它们非常容易理解,并严格遵循 MinIO 分布式设置指南。但是,无论如何,让我们一起浏览整个文件,以便我们更好地理解到目前为止我们学到的概念。

以下循环将根据MINIO_SERVER_COUNT中指定的数量创建虚拟机。在本例中,它将循环 4 次,同时定义虚拟机设置,例如 4 个虚拟机的主机名和 IP 地址,以及它们将使用的镜像。

  (1..MINIO_SERVER_COUNT).each do |i_node|

    config.vm.define (NAME_PREFIX + i_node.to_s) do |node|

      node.vm.box         = BOX_IMAGE
      node.vm.box_version = BOX_VERSION
      node.vm.hostname    = NAME_PREFIX + i_node.to_s

      node.vm.network :private_network, :ip => "#{SUBNET_PREFIX}#{i_node}"

Vagrantfile#L20-L28

接下来,我们需要使用MINIO_DRIVE_COUNT定义每个服务器集的驱动器数量。您可能已经注意到,我们不仅在数值上循环,而且还从b开始并递增(c、d、e...)驱动器字母。这样做的原因是,Linux 中的驱动器以字母命名,例如 sda、sdb、sdc 等等。我们从sdb开始,因为sda/根磁盘占用,其中安装了操作系统。

在本例中,这 4 个服务器中的每一个都将有 4 个磁盘,总共 16 个磁盘。将来,如果您更改设置,最简单的方法是将 MINIO_SERVER_COUNT x MINIO_DRIVE_COUNT 相乘即可得出磁盘总数。

      drive_letter = "b"

      (1..MINIO_DRIVE_COUNT).each do |i_drive|
        node.vm.disk :disk, size: "#{MINIO_DRIVE_SIZE}GB", name: "data-#{i_drive}"


…TRUNCATED…


        drive_letter.next!
      end

Vagrantfile#L30-L48

上一步只创建了一个虚拟驱动器,就像我们在裸机上添加了物理驱动器一样。您仍然需要配置磁盘分区并将其挂载,以便 Linux 可以使用它们。

使用parted为这 4 个磁盘(b、c、d、e)中的每一个创建一个 ext4 /dev/sd*1 分区。

node.vm.provision "shell", inline: <<-SHELL
  parted /dev/sd#{drive_letter} mklabel msdos
  parted -a opt /dev/sd#{drive_letter} mkpart primary ext4 0% 100%
SHELL

Vagrantfile#L35-L38

格式化已创建的分区并将它们添加到/etc/fstab中,以便每次重新启动虚拟机时,这 4 个磁盘都会自动挂载。

node.vm.provision "shell", inline: <<-SHELL
  mkfs.ext4 -L minio-data-#{i_drive} /dev/sd#{drive_letter}1
  mkdir -p /mnt/minio/data-#{i_drive}
  echo "LABEL=minio-data-#{i_drive} /mnt/minio/data-#{i_drive} ext4 defaults 0 2" >> /etc/fstab
SHELL

Vagrantfile#L40-L45

这时,我们将挂载我们创建的磁盘,并设置 MinIO 服务启动所需的适当权限。在配置完所有磁盘组件后,我们将添加卷和凭据设置/etc/default/minio。我们将启用 MinIO,但尚未启动它。在虚拟机启动后,我们将同时启动所有虚拟机,以避免 MinIO 在一定时间内找不到其他节点时发生的超时错误条件。

node.vm.provision "shell", inline: <<-SHELL
  mount -a
  chown minio-user:minio-user /mnt/minio/data-*
  echo "MINIO_VOLUMES=\"http://minio-{1...#{MINIO_SERVER_COUNT}}:9000/mnt/minio/data-{1...#{MINIO_DRIVE_COUNT}}\"" >> /etc/default/minio
  echo "MINIO_OPTS=\"--console-address :9001\"" >> /etc/default/minio
  echo "MINIO_ROOT_USER=\"#{MINIO_ROOT_USER}\"" >> /etc/default/minio
  echo "MINIO_ROOT_PASSWORD=\"#{MINIO_ROOT_PASSWORD}\"" >> /etc/default/minio


  systemctl enable minio.service
SHELL

Vagrantfile#L50-L60

我们设置了一些与虚拟机相关的设置,但最重要的是,此代码片段中的最后一行使用 `vagrant-hosts` 插件同步所有虚拟机上的 `/etc/hosts` 文件。

node.vm.provider "virtualbox" do |vb|
  vb.name   = NAME_PREFIX + i_node.to_s
  vb.cpus   = MINIO_CPU_COUNT
  vb.memory = MINIO_MEMORY_SIZE
end

node.vm.provision :hosts, :sync_hosts => true

Vagrantfile#L62-L68

到目前为止,您一定想知道为什么我们没有将所有这些 shell 命令直接烘焙到 Packer 构建过程中的 minio.sh 脚本中。为什么我们反而将这些设置作为 Vagrantfile 配置过程的一部分进行处理?

这是一个非常好的问题。原因是我们希望根据每个用例修改磁盘设置 - 有时候,您可能需要在 MinIO 集群中添加更多节点,而其他时候您可能不需要每个节点 4 个磁盘。您不希望为每个驱动配置创建唯一的镜像,因为这样会导致成千上万个类似的镜像,唯一的区别是驱动配置。

您也不想使用 MinIO 的默认 root 用户名和密码,因此我们构建了一个允许您在配置时修改这些信息的流程。

如果您想升级 MinIO 二进制版本,但又不想每次都构建新的 Packer 镜像怎么办?这很简单,只需添加一个包含下载和安装 MinIO 二进制文件的命令的 `shell` 块,就像我们在 Packer 的 minio.sh 脚本中所做的那样。以下示例伪代码可以帮助您入门

node.vm.provision "shell", inline: <<-SHELL


  # 下载 MinIO 二进制文件


  # 安装 MinIO 二进制文件


SHELL

这就是您作为 DevOps 工程师需要运用最佳判断,找到烘焙和处理之间的平衡的地方。您可以选择在 Packer 构建过程中烘焙所有配置,也可以选择在配置过程中灵活地处理配置。我们希望通过此思考,帮助您在开发自己的设置时获得启发。

启动 MinIO 集群

现在,我们已经非常了解集群的部署内部机制。现在剩下的就是使用 Vagrant 在 Virtualbox 上部署集群。

设置以下环境变量,以便虚拟机能够自动检测磁盘。

$ export VAGRANT_EXPERIMENTAL=disks

确保您位于与 `Vagrantfile` 相同的位置,并运行以下命令

$ vagrant status


当前机器状态


minio-1                   未创建 (virtualbox)

minio-2                   未创建 (virtualbox)

minio-3                   未创建 (virtualbox)

minio-4                   未创建 (virtualbox)

您的输出应该与上述内容类似,状态设置为 `未创建`。这是因为我们尚未配置节点。

最后,重头戏来了!配置我们 MinIO 集群中的 4 个节点。

$ vagrant up
==> vagrant: 您已请求启用包含以下功能的实验性标志:
==> vagrant:
==> vagrant: 功能:磁盘
==> vagrant:
==> vagrant: 请谨慎使用,因为某些功能可能尚未完全
==> vagrant: 可用。
启动虚拟机 'minio-1' 使用 'virtualbox' 提供程序…
启动虚拟机 'minio-2' 使用 'virtualbox' 提供程序…
启动虚拟机 'minio-3' 使用 'virtualbox' 提供程序…
启动虚拟机 'minio-4' 使用 'virtualbox' 提供程序…

确保您看到了以下输出 ==> vagrant: 功能:磁盘,因为这验证了环境变量 VAGRANT_EXPERIMENTAL=disks 已正确设置。随着每个 VM 启动,其输出将以主机名作为前缀。如果配置过程中出现任何问题,请查看此主机名前缀以查看哪个 VM 发出了消息。

==> minio-1: …

==> minio-2: …

==> minio-3: …

==> minio-4: …

命令执行完毕后,再次运行 vagrant status 以验证所有节点是否都处于 running 状态。

$ vagrant status

当前机器状态:

minio-1                   正在运行 (virtualbox)
minio-2                   正在运行 (virtualbox)
minio-3                   正在运行 (virtualbox)
minio-4                   正在运行 (virtualbox)

所有节点都应该处于running状态。这意味着节点正在运行,如果在配置过程中没有看到任何错误输出,那么我们Vagrantfile中的所有shell命令都已成功运行。

最后但并非最不重要的一点,让我们启动实际的MinIO服务。如果您还记得,我们启用了该服务,但没有启动它,因为我们希望所有节点首先启动。然后,我们将使用vagrant ssh命令几乎同时启动所有服务,该命令将使用此bash循环登录所有4个节点。

$ for i in {1..4}; do vagrant ssh "minio-${i}" -c "sudo systemctl start minio"; done

使用journalctl命令确认,查看日志并验证所有4个节点上的MinIO服务是否已正确启动。

$ for i in {1..4}; do vagrant ssh "minio-${i}" -c "sudo journalctl -u minio -n 10 --no-pager"; done

您应该在minio-4中看到类似以下示例的输出。16 Online意味着所有4个节点上的16个驱动器都在线。

Oct 17 09:34:47 minio-4 minio[1616]: Status:         16 Online, 0 Offline.
Oct 17 09:34:47 minio-4 minio[1616]: API: http://10.0.2.15:9000  http://192.168.60.14:9000  http://127.0.0.1:9000
Oct 17 09:34:47 minio-4 minio[1616]: Console: http://10.0.2.15:9001 http://192.168.60.14:9001 http://127.0.0.1:9001

将来,如果您想自己启动自定义的MinIO集群,您现在拥有所有必要的工具。

自动执行MinIO构建

从技术上讲,您可以在此停止并继续您的快乐旅程。但我们知道您总是想要更多MinIO,所以我们将更进一步,向您展示如何自动化此过程,这样您就不必每次都手动运行Packer构建命令。

安装Jenkins

使用以下命令安装并启动Jenkins

$ brew install jenkins-lts
$ brew services start jenkins-lts

Jenkins启动后,它会要求您设置一些凭据,这应该非常简单。设置好凭据后,您需要确保已安装git插件,请按照以下步骤进行。

配置 MinIO 构建

让我们创建一个构建配置来自动化 MinIO 镜像的 Packer 构建流程。但在此之前,我们前面提到过,还有其他方法可以设置 Packer 变量的值。使用环境变量,variables.pkr.hcl 中的值可以通过在变量名前添加前缀 PKR_VAR_varname 来覆盖。在下一步中,我们将使用环境变量来覆盖一些变量,而不是直接编辑文件。

请按照以下步骤配置构建。

在“构建步骤”部分,我们添加了一些命令。以下内容可以复制粘贴到您的配置中。

export PATH=$PATH:/usr/local/bin
export PKR_VAR_box_version="0.1.1"

cd ci-cd-build/packer/
packer inspect .
packer validate .
packer build .

执行 MinIO 构建

配置完构建作业后,就可以执行构建了。请按照以下步骤操作。

构建成功后,请访问 https://app.vagrantup.com 验证镜像是否已成功上传。

总结

在这篇博文中,我们展示了如何将 MinIO S3 兼容的对象存储在分布式模式下从构建到在笔记本电脑上配置的整个流程。这将帮助您和您的开发人员快速启动并运行生产级 MinIO 集群,并在本地使用整个功能集而不影响效率。

让我们简单回顾一下我们执行的操作。

  • 我们创建了一个 Packer 模板,用于从头开始创建 MinIO 镜像。
  • 我们使用 Vagrant 作为供应器,以便我们能够使用镜像在本地进行开发。
  • 我们利用 Jenkins 自动将镜像上传到 Vagrant 云,以便将来构建。

我们演示了您必须在“烘焙”和“油炸”之间取得平衡。每个组织的需求都不一样,所以我们不想划清界限来说明“烘焙”应该在哪里结束,“油炸”应该在哪里开始。作为 DevOps 工程师,您需要评估以确定最适合每个应用程序的方案。我们构建 MinIO 的目的是为了提供您运行自己的对象存储所需的灵活性和可扩展性。

如果您自己实现了这一点,或者在我们的流程中添加了其他功能,请在 Slack 上告诉我们!