想象一下,您已经花费了无数小时来完善 Docker Swarm 设置,精心设计每项服务,并调整 CI/CD 管道以实现无缝自动化。现在,想象一下这个经过微调的系统被重置为原点,不是因为严重的故障或安全漏洞,而是因为数据中心工程师在硬件上按下神奇的“恢复出厂设置”的天真好奇心。这不是DevOps恐怖故事的开端,而是证明了精心设计的存储库和GitOps原则所实现的弹性和快速恢复。
在本文中,我们将深入探讨作为DevOps核心的自动化和冗余如何在重置可能带来灾难的情况下被证明是救星。我将分享 Docker、GitHub Actions 和 MinIO 的组合,以及意想不到的真实世界试验,强调了可靠且可重复的构建和部署过程的重要性。
通过这次体验,我们将探索版本控制配置的强大功能以及将映像推送到多个注册表的远见卓识,确保即使面对完整的系统擦除,恢复也只需几个命令即可完成。和我一起探索DevOps中弹性的深度,说明你如何保护你的系统,以应对生活可能给你带来的意外。
冗余和自动化的重要性
冗余和自动化是现代 DevOps 实践的基本支柱,对于保持连续性和确保高可用性至关重要。将 Docker 映像双重推送到 Docker Hub 和 GitHub Container Registry (GHCR.io) 的战略决策是由经过计算的风险管理和可访问性方法驱动的。
Docker Hub 作为主要的工件注册表,提供广泛的集成和公共可见性,用于广泛的分发和协作。它是即时项目检索和部署的首选注册表。但是,依赖单个注册表是一个漏洞;任何服务中断都可能停止部署和更新,从而导致潜在的停机。
相比之下,GHCR.io 默认情况下为 Docker 映像提供安全的专用存储解决方案,这与对某些部署工件的受控访问需求相一致。此注册表成为战略备份,确保即使 Docker Hub 遭到入侵或不可用,也有一个即时回退选项,而不会对 CI/CD 管道造成任何中断。
映像的自动化通过 GitHub Actions 推送到两个注册表。它确保最新版本始终可以从任一来源进行部署,从而有效地防止服务中断。这种有条不紊的冗余不是创建不必要的副本,而是以最短的恢复时间为突发事件做好准备。
在存储库所在的 GitHub 上构建,同时推送到两个注册表背后的逻辑很简单:它提供了一种无缝、自动化的方式来维护所有映像的专用备份,同时使公共注册表保持最新状态。这种双重方法是一种主动措施——精心设计的 DevOps 流程必须以战略冗余为核心。
针对复原能力的存储库增强功能
在追求弹性 DevOps 环境的过程中,持续改进至关重要。对原始存储库所做的增强既是反思性的,也是先发制人的,不仅旨在满足恢复需求,还旨在简化流程以满足任何未来的部署需求。
首先,对工作流程配置进行了细化,定义了每个作业和步骤,以确保效率和可靠性。为此,该 .github/workflows
目录丰富了用于多平台构建的新工作流,从而扩展了存储库的自动化功能。此设置不仅有助于一致的部署,还可以确保最新版本的应用程序已准备好从 Docker Hub 或 GHCR.io 中拉取。
在 cda-deploy-to-swarm 存储库中,该结构经过精心设计,以实现快速导航和易用性。该目录包括:
-
.github/workflows 文件夹,其中包含 CI/CD 自动化脚本。在这里,YAML 文件定义了在推送和拉取请求上运行的操作,包括生成和推送操作以及部署业务流程。
-
minio 目录包含为 MinIO 服务量身定制的自定义配置和 Docker Compose 文件,允许快速、标准化地设置对象存储功能。
-
nginx 目录设置了用于部署 NGINX Web 服务器的配置,有助于处理 HTTP 请求和充当反向代理。
-
weaviate 目录,其中包含部署 Weaviate 向量搜索引擎所需的元素,利用 Docker Compose 进行服务定义和部署。
-
存储库根的核心是 docker-compose.yaml 文件,它定义了多容器应用程序服务,并将各个组件绑定在一个有凝聚力的整体中。
每一项改进和结构决策都是为了创建一个存储库,该存储库不仅可以从中断中恢复过来,而且还可以作为在 Docker Swarm 环境中部署服务的模块化、可扩展的基础。存储库结构的清晰度和组织性有助于快速识别组件和配置,从而减少恢复时间并促进部署过程的有效管理。有关本文中提到的特定文件的详细信息,请访问 MinIO 博客资产存储库。
使用 GitHub Actions 和 Docker Compose 实现高效的 CI/CD
在我们的 DevOps 工作流程中,GitHub Actions 在自动化 Docker 映像的构建过程方面发挥着关键作用,包括我们的自定义 MinIO 和 Weaviate 服务。这些操作配置为在特定事件(例如推送到主分支)时触发,确保每个更改都无缝集成到我们的部署管道中。
以下是该过程的展开方式:
1 . **GitHub Actions 工作流:**提交到存储库后,将启动我们的 GitHub Actions 工作流。这些工作流包含使用自定义 Dockerfile 构建 Docker 映像并将其推送到注册表的作业。这些图像被适当地标记,例如, cdaprod/cda-minio:latest .
2 . **用于部署的 Docker Compose:**在构建和推送过程之后, docker-compose.yaml 文件开始用于部署。它配置为从注册表中提取最新映像,以便在 Docker Swarm 环境中进行服务部署。
docker-compose.yaml 文件包含如下服务定义:
version: '3.8'
services:
minio:
image: cdaprod/cda-minio:latest
# Other configurations ...
weaviate:
image: cdaprod/cda-weaviate:latest
# Other configurations ...
nginx:
image: cdaprod/cda-nginx:latest
# Other configurations ...
networks:
app_network:
driver: overlay
# Other definitions like volumes and secrets…
此方法通过分离映像构建和服务部署过程,大大简化了我们的部署策略。这也意味着我们不需要为不同的环境或场景提供多个 docker-compose 文件。
通过利用此 CI/CD 策略,我们能够为服务定义维护单一事实来源,并确保我们的部署过程尽可能简化和高效。我们的部署变成了一个自托管运行器,从我们的 GitHub Actions 工作流中执行一个docker-compose up command
,剩下的工作由 Docker Compose 处理——拉取最新的映像、启动服务,并确保它们完全按照我们的定义进行配置。
使用 MinIO 说明自定义映像构建
为了进一步阐明 CI/CD 管道的构建过程,让我们仔细看看 MinIO 服务映像的自定义。我们的 GitHub Actions 工作流负责根据官方 minio/minio:latest
构建此映像,并根据我们的要求定制其他配置。
下面是概述生成步骤的 /minio/Dockerfile:
# Start with the official MinIO image as a base
ARG BASE_IMAGE=minio/minio:latest
FROM $BASE_IMAGE
# Copy over the custom entrypoint script
COPY entrypoint.sh /entrypoint.sh
# Ensure the script is executable
RUN chmod +x /entrypoint.sh
# Expose the ports MinIO will use
EXPOSE 9000 9001
# Use the custom entrypoint script to start MinIO
ENTRYPOINT ["/entrypoint.sh"]
使用入口点脚本增强自定义
自定义过程不会以 Dockerfile
。为了完全根据我们的运营需求定制我们的 MinIO 服务,我们利用了一个 entrypoint.sh
脚本。此脚本在容器启动时充当命令中心,执行预定义的命令,以配置超出默认设置的 MinIO 实例。
使用 entrypoint.sh 脚本的美妙之处在于它能够执行运行时配置。这些对于动态设置我们的环境至关重要,确保我们的 MinIO 服务不仅仅是一个普通的部署,而是为我们的用例定制的部署。
这种将 Dockerfile
与 entrypoint.sh
脚本相结合的方法使我们能够构建容器,这些容器不仅在构建时考虑了我们的应用程序和服务,而且在部署它们时就可以在我们独特的生态系统中运行。
#!/bin/sh
set -e
# Start MinIO in the background
minio server /data --console-address ":9001" &
# Wait for the MinIO server to start
sleep 5
# Configure MinIO with the mc (MinIO Client) tool
mc alias set myminio http://localhost:9000 ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD}
# Before creating buckets, check if they already exist
if ! mc ls myminio/weaviate-backups; then
mc mb myminio/weaviate-backups
fi
if ! mc ls myminio/cda-datasets; then
mc mb myminio/cda-datasets
fi
# Keep the container running
tail -f /dev/null
将 Dockerfile
官方 MinIO 映像指定为基础,然后添加我们的自定义 entrypoint.sh
脚本。此脚本至关重要,因为它在启动后运行其他命令来配置 MinIO,例如使用 MinIO 客户端 ( mc
) 创建必要的存储桶。
在由我们的工作流程触发的图像构建阶段,我们使用它 Dockerfile
来创建 cdaprod/cda-minio:latest
图像。此映像封装了我们的自定义设置和脚本,该 docker-compose.yaml
文件稍后将使用这些设置和脚本在 Docker Swarm 中部署 MinIO 服务。
和 cdaprod/cda-minio:latest
之间的区别 minio/minio:latest
很小。前者是 MinIO 官方 Docker Hub 存储库中未更改的基础映像,而后者是我们的自定义版本,通过我们的 CI/CD 工作流构建和维护,确保任何特定配置和脚本都融入到我们部署的映像中。
深入了解工作流程
两个 GitHub Actions 工作流(构建和推送 Docker 映像和部署服务)构成了存储库中的核心自动化机制。以下是对每个方法的扩展解释。
构建和推送 Docker 映像工作流
此工作流在任何推送或 pull_request
分支 main
上触发,以确保最新的代码提交导致更新的 Docker 映像。
name: Build and Push Docker Images
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push custom MinIO image
uses: docker/build-push-action@v3
with:
context: ./minio
file: ./minio/Dockerfile
push: true
tags: cdaprod/cda-minio:latest
platforms: linux/amd64,linux/arm64
- name: Build and push custom Weaviate image
uses: docker/build-push-action@v3
with:
context: ./weaviate
file: ./weaviate/Dockerfile
push: true
tags: cdaprod/cda-weaviate:latest
platforms: linux/amd64,linux/arm64
作业生成和推送在 GitHub Actions 提供的最新 Ubuntu 运行器上执行。工作流包括以下步骤:
1 . **签出代码:**该 actions/checkout@v3 操作用于克隆存储库,以便工作流可以访问其内容。
2 . 设置 Docker Buildx: docker/setup-buildx-action@v2 用于安装和配置 Buildx,它扩展了 Docker,使其能够构建多平台映像、更高级的构建指标和不同的输出选项,同时利用 Docker 的 buildkit 库。
3 . **登录到 Docker Hub:**此步骤使用 docker/login-action@v2 、引用 DOCKERHUB_USERNAME 和 DOCKERHUB_TOKEN 机密登录到 Docker Hub 进行身份验证。这些机密安全地存储在存储库设置中,不会在工作流文件中公开。
4 . **构建并推送自定义 MinIO 映像:**用于 docker/build-push-action@v3 从 minio 上下文目录中指定的 Dockerfile 映像构建 MinIO 映像。它被标记,然后推送到 Docker Hub,确保映像可用于部署。platforms 参数指定映像应支持的 CPU 体系结构,以确保不同硬件设置之间的兼容性。
5 . **构建和推送自定义 Weaviate 映像:**同样,此步骤用于构建和推送具有适当标记和多架构支持的 Weaviate 映像。
部署服务工作流
此部署工作流是 CI/CD 管道的“持续部署”方面所必需的,当生成和推送 Docker 映像工作流在主分支上成功完成时,此工作流就会开始运行。
name: Deploy Services
on:
workflow_run:
workflows: ["Build and Push Docker Images"]
branches: [main]
types:
- completed
workflow_dispatch:
jobs:
deploy:
runs-on: self-hosted
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Deploy to Docker Swarm
run: |
docker stack deploy -c docker-compose.yaml cda_stack
1 . **签出存储库:**与生成工作流类似,它从签出代码开始。
2 . **设置 Docker Buildx:**尽管 Buildx 设置不用于部署,但如果堆栈部署过程中需要多节点构建,则将其包含在内,以便保持一致性和将来使用。
3 . **登录到 Docker Hub:**确保登录到 Docker Hub,以确保运行器可以毫无障碍地拉取部署所需的映像。
4 . **部署应用程序堆栈:**此关键步骤使用单个 docker-compose.yaml 应用程序堆栈来部署完整的应用程序堆栈。它将 MinIO、Weaviate 和 NGINX 的服务定义和配置组合到一个统一的部署命令中。环境变量和机密在 GitHub 机密中安全管理。
部署工作流将代码更改转换为实时服务,并通过 GitHub 机密处理敏感数据。它展示了部署复杂服务堆栈的能力,遵循基础架构即代码的原则,并且旨在随着应用程序基础架构的发展而发展。
DevOps 弹性的主动方法
在DevOps的世界里,系统的健壮性通常只在危机时期得到强调。最近的一次活动展示了我们实践中蕴含的力量;无意中启动了系统范围的重置,导致所有正在运行的服务中断。这远非一场灾难,而是验证我们在 MinIO 倡导的基础设施弹性的绝佳机会。
我们的存储库结构经过精心设计,利用 Docker Compose 和 GitHub Secrets 来编排我们的服务环境。这种战略设置简化了恢复过程,将原本复杂的恢复转变为一系列简单的自动化步骤:
1 . **初始化:**已针对此类突发事件配置的自托管运行器已启动,为恢复奠定了基础。
2 . **同步:**最新的服务代码是直接从我们的存储库中获取的,保证只有最新的配置在起作用。
3 . **配置:**安全存储为 GitHub 机密的环境变量无缝集成,无需手动设置。
4 . **编排:**服务的部署通过 Docker Compose 执行实现自动化,由 GitHub Actions 工作流主导,精确地恢复了整套服务。
在这次 IaC 演示中,我们的服务迅速恢复到其运行状态,突显了我们的 DevOps 方法的有效性。
构建弹性系统的关键见解
从意外的系统重置中快速恢复强调了现代软件开发和部署不可或缺的几个见解:
-
**自动化至关重要:**自动化恢复过程可最大限度地减少停机时间并消除人为错误,从而对系统故障做出快速而可靠的响应。
-
**统一事实来源:**GitOps 整合了基础架构和应用程序管理,简化了更改跟踪,并在必要时实现了轻松的回滚。
-
**持久性设计:**基础架构中的弹性是有意的,通过勤奋规划和实施 CI/CD 和 IaC 最佳实践来制定。
在MinIO,这些原则不仅仅是理论上的,而是嵌入到我们工作流程中的实用措施,确保我们的系统和服务在设计上具有弹性。对于开发人员和 DevOps 专业人员来说,信息很明确:投资于这些实践就是投资于基础架构未来的稳定性和成功。我们的集体经验充分说明了我们优雅而高效地管理中断的能力。
通过编纂我们的基础设施,并像对待我们的应用程序代码一样谨慎和关注它,我们可以大大减少在面对灾难时重建和重新部署我们的服务所需的时间和精力。此外,我们还强调了详尽的文档记录和定期自动备份的重要性。虽然强大的 CI/CD 管道可以促进快速恢复,但它不能替代维护代码、配置和数据的全面文档和可靠备份。