使用 GitOps 自动化驱动 AI/ML 工作流

Powering AI/ML workflows with GitOps Automation

作为一名深度沉浸于自动化和人工智能领域的开发者,我们逐渐认识到尖端工具和方法论之间非凡的协同效应,它们不断突破着可能的界限。在这个探索过程中,我们希望分享一个不仅彻底改变了我们软件开发和基础设施管理方法,也为无限创新打开了大门的概念:GitOps。这种范式将Git作为运营卓越的基石,已经成为我们工具包中的一个游戏规则改变者,并为无限的可能性奠定了基础。

MinIO 高性能对象存储、Weaviate 的 AI 增强元数据管理、Python 的动态脚本功能以及 GitOps 的系统化方法的融合,为任何渴望深入人工智能和机器学习的开发者构建了一个强大的基础。这些工具不仅简化了数据存储和管理的复杂性,还为快速开发和部署提供了灵活、强大的环境。通过将这些元素集成到我们的开发实践中,我们为建立在可扩展、高效和自动化基础设施上的项目奠定了基础。本文旨在指导您了解这些技术,轻松地将您的 AI 项目从概念转化为现实。

这种集成包括用于对象存储的MinIO、作为元数据管理器的WeaviatePython作为动态引擎以及用于简化基础设施管理的GitHub/GitOps,为开发本土 AI 解决方案创建了一个强大的基础。

  • MinIO—对象存储骨干:MinIO 提供高性能对象存储,对于高效管理海量数据集至关重要。它充当骨干,确保数据可用性、安全性及可扩展性。
  • Weaviate—基于 AI 的元数据管理:Weaviate 充当复杂的元数据管理器,利用 AI 提供语义搜索功能,增强数据可发现性和可用性。
  • Python—开发引擎:Python 以其简单性和丰富的 AI/ML 库生态系统,充当开发引擎,使 AI 应用程序能够快速原型设计和部署。
  • GitHub/GitOps—基础设施自动化:GitHub Actions 通过自动化基础设施管理赋能 GitOps,确保部署顺利且无错误。它简化了 GitHub 中的 CI/CD,提高了 DevOps 工作流的效率和可靠性。

释放 AI 潜力

通过这些组件,我们可以为开发应用程序以及在 AI 研究和开发的前沿进行创新建立框架。这种集成使开发人员能够将更多时间用于探索,而将更少时间用于构建和测试。特别是我们正在部署的服务组合,为任何有兴趣在强大的、可扩展的和自动化的基础设施支持下开发 AI 环境的人员提供了极佳的 AI/ML 起点。

MinIO Weaviate Python GitOps 和工作流

要创建用于测试的 GitOps 工作流,请使用下面提供的 docker-compose.yaml,其中包含应用程序、minioweaviate 服务的定义。我们将使用 CI/CD 管道方法,利用 GitHub Actions 进行自动化。

目标是自动化构建、测试和验证 Docker Compose 设置的过程,每次将更改推送到存储库时都会执行。成功的流程将选择为您生成一个“状态徽章”,该徽章放置在 Markdown 文档中时会提供实时更新。

通过状态徽章的屏幕截图

目录树结构

所有文件都可通过 GitHub minio/blog-assets/minio-weaviate-python-gitops 存储库文件夹获取

├── .github/workflows
│   └── docker-workflow.yml
├── README.md
├── app
│   ├── Dockerfile
│   ├── entrypoint.sh
│   └── python_initializer.py
├── docker-compose.yaml
└── minio
    ├── Dockerfile
    └── entrypoint.sh

目录树

从本质上讲,关闭此存储库并将这些文件添加到您自己的 GitHub 存储库中,如上图所示的目录树中所示。它将通过 GitHub 在特定存储库的“Actions”选项卡下自动运行。

什么是 GitOps?

GitOps 是一种现代的软件开发和基础设施管理方法,它植根于四个关键原则,这些原则简化并保护基础设施和应用程序的部署和管理。

  1. 声明式配置:使用代码定义系统及其所需状态,使配置易于维护和理解。
  2. 版本控制和不变性:所有更改和所需状态配置都存储在 Git 中,为可审计性和回滚功能提供不变的历史记录,从而确保一致性和可靠性。
  3. 自动化部署:自动化流程将实时状态与 Git 中定义的所需状态进行协调,增强部署一致性,减少人为错误并加快部署周期。
  4. 持续反馈和监控:系统会持续监控与 Git 中所需状态的差异,自动纠正差异或标记以进行人工干预,确保系统弹性和安全性。

通过围绕这些原则巩固基础设施和应用程序管理,GitOps 提供了一个强大的框架,可以为现代 DevOps 团队提高速度、可靠性、安全性以及协作效率。

.github/workflows/docker-workflow.yml 中定义的 GitHub 工作流旨在自动化根据提供的 docker-compose.yaml 构建和推送 Docker 镜像的整个过程。此 YAML 文件协调自定义 MinIO 和 Python 环境的部署,并使用最新的公共镜像部署 Weaviate;促进简化的开发过程。

GitHub:工作流目录路径

要通过 WebUI 在 GitHub 中创建嵌套目录,只需在添加新文件时在文件名之前键入所需的路径即可。此方法会自动将您的文件组织到指定的目录中,从而简化文件管理,而无需执行常规的文件夹创建步骤。

将 YAML 放置在 /.github/workflows/ 目录中,将告诉 GitHub 将其作为 Action 工作流运行。

Docker Compose 编排

当我们转向 Docker Compose 设置的细节时,我们的目录结构和 GitHub 工作流已经为我们奠定了所有基础。docker-compose.yaml 文件充当蓝图,详细说明了 MinIO、Weaviate 和我们的自定义 Python 应用程序等服务如何在我们的环境中容器化和交互。

此配置使您能够转向构建可扩展的自托管应用程序,从而挑战对 AWS 等传统云服务的需要。此蓝图使开发人员能够创建复杂的面向微服务的体系结构,利用容器化的效率和灵活性。

使用 Docker Compose 和一个用于自动模式创建和数据索引的 Python 脚本,此设置有助于开发能够在混合云环境中运行的可扩展自托管应用程序。

/docker-compose.yaml

版本: '3.8'

服务:
 minio:
   容器名称:minio_server
   构建:
     上下文:./minio

    depends_on:
      - weaviate
      - minio

基于docker-compose.yaml配置所构建的基础,您开发的Python脚本可用于自动化Weaviate数据库的初始化和管理。此脚本在您自托管的容器化架构中发挥着两个作用。

1. **模式创建:**您的Python脚本自动化了在Weaviate中定义模式的过程。模式充当数据的蓝图,指定数据库将保存的信息类型以及不同实体之间如何关联。

2. **数据索引:**模式就位后,您的脚本将继续将数据索引到Weaviate中。此过程涉及以符合预定义模式的方式将数据导入数据库,使其可搜索和检索。自动化数据索引有助于保持应用程序的流畅性,因为它允许对数据库进行持续的实时更新,而无需停机或手动数据处理。

以下是docker-compose.yaml的屏幕截图,以及使用GitHub UI提交时的样子。

提交更改的屏幕截图

Dockerfiles和入口脚本

docker-compose.yaml中的每个服务都有其自定义的Dockerfile和入口脚本,以确保正确设置环境。MinIO Dockerfile和入口脚本自定义了MinIO服务器,包括设置必要的环境变量并准备服务器以供运行。

构建MinIO容器

此Dockerfile使用上游的minio/minio镜像,并添加了一些在entrypoint.sh中实现的补充内容。

/minio/Dockerfile

FROM minio/minio
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENV MINIO_ROOT_USER=minio \
    MINIO_ROOT_PASSWORD=minio123
EXPOSE 9000 9001
ENTRYPOINT ["/entrypoint.sh"]

用于minio/Dockerfileentrypoint.sh执行以下几个操作。

  • 启动minio服务器。
  • 等待5秒。
  • 设置别名。
  • 为weaviate-backups创建存储桶。

/minio/entrypoint.sh

#!/bin/sh

set -e

# 在后台启动MinIO
minio server /data --console-address ":9001" &

# 等待for MinIO启动
sleep 5

# 设置别名并创建存储桶
mc alias set myminio http://minio:9000 ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD}
mc mb myminio/weaviate-backups

# 保持脚本运行以防止容器退出
tail -f /dev/null

MinIO Dockerfileentrypoint.sh文件应按如下屏幕截图所示创建(在/minio/目录中)。

minio目录的屏幕截图

构建Python容器

我们的Python应用程序的此app/Dockerfile执行以下几个操作。

  • 使用python:3.9-slim容器镜像。
  • /app/设置为工作目录。
  • 安装用于Python的weaviate-client库。
  • 将位于与Dockerfile相同的目录中的文件复制到容器中。
  • 设置entrypoint.sh脚本的权限。

设置Python环境,安装依赖项,并定义初始化Weaviate模式和数据的操作,然后备份到MinIO。

/app/Dockerfile

FROM python:3.9-slim

WORKDIR /app

RUN pip install weaviate-client

COPY . /app/

RUN chmod +x /app/entrypoint.sh

ENTRYPOINT ["/app/entrypoint.sh"]

entrypoint.sh用于我们的Python Dockerfile

  • 在发生错误时退出。
  • 运行python_initializer.py脚本。

/app/entrypoint.sh

#!/bin/bash


# 发生错误时退出脚本

set -e


echo "初始化Weaviate..."

python python_initializer.py


# 在脚本执行后保持容器运行

# 如果您希望在脚本完成后容器关闭,则可以注释或删除此行。

# 如果您的容器应该在执行后关闭,您可以注释或删除此行。

tail -f /dev/null

Python环境Dockerfileentrypoint.shpython_initializer.py文件应按如下屏幕截图所示创建(在/app/目录中)。

GitHub:python应用程序目录

用于Weaviate初始化的Python脚本

python_initializer.py脚本可以在blog-assets存储库的/app/目录中找到;它以编程方式与Weaviate交互以

  • 定义用于存储数据的模式。
  • 将示例数据索引到Weaviate中。
  • 查询已索引的数据并导出结果。
  • 使用backup-s3模块将Weaviate数据备份到MinIO中。

/app/python_initializer.py

import weaviate

import json


# 配置

WEAVIATE_ENDPOINT = "http://weaviate:8080"

OUTPUT_FILE = "data.json"


# 初始化客户端

client = weaviate.Client(WEAVIATE_ENDPOINT)

schema = {

    "classes": [

        {

            "class": "Article",

            "description": "用于存储文章的类",

            "properties": [

                {"name": "title", "dataType": ["string"], "description": "文章标题"},

                {"name": "content", "dataType": ["text"], "description": "文章内容"},

                {"name": "datePublished", "dataType": ["date"], "description": "文章发布日期"},

                {"name": "url", "dataType": ["string"], "description": "文章URL"}

            ]

        },

        {

        {

            "class": "Author",

            "properties": [

            "description": "用于存储作者的类",

            "properties": [

            ]

                {"name": "name", "dataType": ["string"], "description": "作者姓名"},

                {"name": "articles", "dataType": ["Article"], "description": "作者撰写的文章"}

}


            ]

        }

    ]

  }

# 刷新删除类

try


    client.schema.delete_class('Article')

        }

    client.schema.delete_class('Author')

# 刷新删除类

except Exception as e


    print(f"删除类时出错: {str(e)}")

# 创建新的 Schema

    client.schema.create(schema)

    print(f"创建 Schema 时出错: {str(e)}")

data = [

    {

        "class": "Article",

                {"name": "name", "dataType": ["string"], "description": "作者姓名"},

        "properties": {

# 创建新的 Schema

    client.schema.create(schema)

    print(f"创建 Schema 时出错: {str(e)}")

            "title": "LangChain: OpenAI + S3 Loader",

            "content": "本文讨论了 LangChain 与 OpenAI 和 S3 Loader 的集成...",

            "url": "https://blog.min-io.cn/langchain-openai-s3-loader/"

                {"name": "name", "dataType": ["string"], "description": "作者姓名"},

        "properties": {

# 创建新的 Schema

    client.schema.create(schema)

    print(f"创建 Schema 时出错: {str(e)}")

        },

        "properties": {

            "title": "MinIO Webhook 事件通知",

                {"name": "name", "dataType": ["string"], "description": "作者姓名"},

        "properties": {

# 创建新的 Schema

    client.schema.create(schema)

    print(f"创建 Schema 时出错: {str(e)}")

            "content": "探索 MinIO 中的 webhook 事件通知系统...",

            "url": "https://blog.min-io.cn/minio-webhook-event-notifications/"

        },

                {"name": "name", "dataType": ["string"], "description": "作者姓名"},

        "properties": {

]


            "title": "MinIO Postgres 事件通知",

            "content": "深入了解 MinIO 中的 Postgres 事件通知...",

            "url": "https://blog.min-io.cn/minio-postgres-event-notifications/"

        },

        "properties": {

            "title": "从 Docker 到本地主机",

            "content": "从 Docker 迁移到本地主机环境的指南...",

            "url": "https://blog.min-io.cn/from-docker-to-localhost/"


        }

        }

    }

for item in data

    try

        client.data_object.create(

            data_object=item["properties"],

            class_name=item["class"]

# 刷新删除类

        )


    except Exception as e

        }

        print(f"索引数据时出错: {str(e)}")

# 获取并导出对象

    query = '{ Get { Article { title content datePublished url } } }'

    result = client.query.raw(query)

    articles = result['data']['Get']['Article']

    with open(OUTPUT_FILE, 'w', encoding='utf-8') as f

        json.dump(articles, f, ensure_ascii=False, indent=4)

# 刷新删除类

    print(f"已导出 {len(articles)} 篇文章到 {OUTPUT_FILE}")

    print(f"发生错误: {str(e)}")

# 创建备份

  •     result = client.backup.create(
  •         backup_id="backup-id-2",
  •         backend="s3",
  •         include_classes=["Article", "Author"],
  •         wait_for_completion=True,
  •     )
  •     print("备份创建成功。")
  •     print(f"创建备份时出错: {str(e)}")

将容器镜像推送到 Docker Hub - Artifact Registry

  1. GitHub Actions 工作流自动化以下流程:
  2. 检出仓库代码。
  • 设置 Docker Buildx 用于构建多架构镜像。
  • 缓存 Docker 层以加快构建速度。
  • 登录 Docker Hub 以推送镜像。
  • 构建 docker-compose.yaml 中定义的 Docker 镜像。
  • 使用 docker-compose up 部署服务。

可选:将构建的镜像推送到 Docker Hub。

使用 docker-compose down 拆除部署。

要获取 Docker Hub 用户名并生成用于 Docker CLI 身份验证或将 Docker Hub 与其他工具集成的个人访问令牌 (PAT),请按照以下步骤操作

  1. 创建 Docker Hub 帐户:如果您还没有帐户,请在 Docker Hub 网站上注册以获取用户名。
  2. 生成个人访问令牌 (PAT)
登录您的 Docker Hub 帐户并导航到您的帐户设置。
  1. 在屏幕左侧菜单中找到“安全”部分。
单击“新建访问令牌”按钮以创建新令牌。
  1. 为您的令牌分配一个名称,这将帮助您识别其用途或其目标服务。
创建后,请务必复制令牌并安全存储,因为它只会显示一次。
  1. 个人访问令牌提供了一种比使用密码更安全的替代方案,尤其是在 CLI 操作或集成中。令牌可以通过 Docker Hub 用户界面进行管理(创建和撤销),提供一种安全灵活的方式来跨服务进行身份验证。
  • 如何使用 GitHub Secrets
  • 以下是将密钥添加到 GitHub 存储库的一般流程,您可以将其应用于添加您的 Docker Hub 凭据
  1. 导航到您的 GitHub 存储库:转到您要添加密钥的 GitHub 存储库。
访问存储库设置:单击存储库页面顶部的“设置”选项卡。

设置页面

转到密钥:在左侧边栏上,单击“密钥和变量”以展开该部分,然后选择“操作”以查看 GitHub Actions 的密钥页面。

密钥和变量页面

添加新密钥:单击“新建存储库密钥”按钮。

新建存储库密钥

输入密钥名称和值

对于 DOCKERHUB_USERNAME,请输入 DOCKERHUB_USERNAME 作为名称,并输入您的 Docker Hub 用户名作为值。

对于 DOCKERHUB_TOKEN,请输入 DOCKERHUB_TOKEN 作为名称,并输入您的 Docker Hub 令牌作为值。

保存每个密钥:输入每个密钥的名称和值后,单击“添加密钥”按钮将其保存到您的存储库。


密钥保存成功

这些密钥现在可用于您的 GitHub Actions 工作流中。您可以在工作流文件中使用语法 ${{ secrets.DOCKERHUB_USERNAME }}${{ secrets.DOCKERHUB_TOKEN }} 来引用它们。

此方法确保您的 Docker Hub 凭据安全存储,不会在您的存储库代码或日志中暴露。

使用 GitHub Actions 进行构建和测试

将 GitHub Actions 集成到开发和部署工作流中,代表着向自动化和效率转变的范式转变。GitHub Actions 是一个 CI/CD 平台,可自动化您的软件构建、测试和部署管道,使您可以自动化所有软件工作流,现在拥有世界一流的 CI/CD。

此方法确保您的 Docker Hub 凭据安全存储,不会在您的存储库代码或日志中暴露。

使用 GitHub Actions 进行构建和测试

为 Docker Compose 设置 GitHub Actions

要利用 GitHub Actions 自动化 Docker Compose 工作流,您可以从在存储库中创建工作流文件开始。此文件通常命名为 docker-workflow.yml,位于 .github/workflows/ 目录中,并指定 GitHub Actions 应执行的步骤。

1. **工作流定义**

保存每个密钥:输入每个密钥的名称和值后,单击“添加密钥”按钮将其保存到您的存储库。


docker-workflow.yml 文件以工作流名称和触发它的事件的定义开头。例如,您可能希望它在每次推送和拉取请求到主分支时运行


name: Docker Compose 测试构建和推送

on

  push


    branches

      - main


  pull_request

2. **作业和步骤**


在工作流中,您定义指定要执行的任务的作业。每个作业都在由 runs-on 指定的环境中运行,并包含执行命令、设置工具或使用 GitHub 社区创建的操作的步骤。

/.github/workflows/docker-workflow.yml

on: [push, pull_request]

jobs

  build-and-push

    runs-on: ubuntu-latest

    steps


    - uses: actions/checkout@v2

    - name: 设置 Docker Buildx

on: [push, pull_request]

      uses: docker/setup-buildx-action@v1

    - name: 缓存 Docker 层


      uses: actions/cache@v2

      with


        path: /tmp/.buildx-cache

        key: ${{ runner.os }}-buildx-${{ github.sha }}


        restore-keys: |

          ${{ runner.os }}-buildx-


    - name: 登录 Docker Hub

      uses: docker/login-action@v1

        username: ${{ secrets.DOCKERHUB_USERNAME }}

        password: ${{ secrets.DOCKERHUB_TOKEN }}

    - name: Docker Compose 构建

      run: docker-compose -f docker-compose.yaml build

    - name: Docker Compose 启动

      run: docker-compose -f docker-compose.yaml up -d

    - name: 推送 Docker 镜像到 Docker Hub
      run: docker-compose -f docker-compose.yaml push

    - name: Docker Compose 关闭

      run: docker-compose -f docker-compose.yaml down

  1. 3. **环境和密钥**
  2. 工作流利用 GitHub 密钥 (DOCKERHUB_USERNAMEDOCKERHUB_TOKEN) 安全地登录 Docker Hub。这种方法确保敏感信息不会在工作流文件中暴露。

  1. 4. **构建和推送 Docker 镜像**
  2. 作业中的步骤自动执行使用 Docker Compose 构建 Docker 镜像、将其推送到 Docker Hub 以及使用 docker-compose up 和 docker-compose down 命令管理部署生命周期的过程。
  1. 5. **测试**
  1. 嵌入徽章:将复制的 Markdown 代码粘贴到您的 README.md 文件中您希望徽章显示的位置。

对于 GitHub Actions,代码通常如下所示:

![workflow name](https://github.com/cdaprod/repository/actions/workflows/docker-workflow.yml/badge.svg)

分别将用户、仓库和工作流文件名替换为您的 GitHub 用户名、仓库名称和工作流文件名。

  1. 提交更改:将更新的README.md 文件提交到您的仓库。状态徽章现在将出现在您放置 Markdown 代码的任何位置,显示工作流的当前状态(例如,通过、失败)。

如果您使用的是其他平台(例如 GitLab、Bitbucket 等),则流程应该类似:查找 CI/CD 设置或管道配置,您可以在其中找到创建状态徽章的选项。

如果您一直跟着我们一起操作,那么恭喜!使用此状态徽章,我们现在可以查看构建进度和 GitOps 的状态。到目前为止,您应该已经为利用 Git 作为您基础设施和应用程序部署的唯一真相来源奠定了坚实的基础。

使用 GitHub Actions 的优势

  • 自动化: 简化构建、测试和部署流程,减少人为错误并节省时间。
  • 灵活: 支持各种编程语言和框架。
  • 集成: 与 GitHub 仓库无缝集成,增强协作和反馈。
  • 可扩展性: 轻松适应任何规模的项目,从小规模创业公司到大企业。

通过将 GitHub Actions 集成到 Docker Compose 项目的工作流中,团队可以实现更高的效率、更好的可靠性和更快的部署周期。这种集成体现了自动化在现代软件开发中的强大功能,使开发人员能够更加专注于创新,而不是部署的机制。

本教程演示了如何将 GitOps 原则应用于自动化任何涉及 MinIO 及其服务的复杂应用程序设置的部署和测试。通过利用 GitHub Actions,对仓库的更改会自动触发工作流,确保应用程序的组件始终处于可部署和测试状态。

拥抱 GitOps 和 AI 的未来

正如我们通过将 MinIO 与 GitOps 和 AI 开发工具(Weaviate 和 Python)深度集成所共同演示的那样,我们已经制定了一个蓝图,旨在重新定义技术和 AI 研究的格局。这种融合不仅简化了我们的开发流程,而且使我们能够以全新的敏捷性和精确性应对 AI 的复杂性。

MinIO 的存储弹性,加上 Weaviate 的智能元数据管理和 Python 的动态功能,所有这些都在 GitOps 的原则下协调运作,为开发、部署和管理 AI 应用程序提供了一个全面的环境。这个强大的基础鼓励我们放眼未来,不断探索,利用高效、可扩展和自动化的基础设施,探索 AI 的巨大潜力。

无论是本土开发者、业余爱好者还是行业资深人士,现在都是我们利用这些进步,从根本上推动创新的最佳时机。无论您是着手进行第一个 AI 项目,还是希望增强现有工作流,本文讨论的工具和方法都提供了一条通往成功的途径,最大限度地降低障碍,最大限度地发挥潜力。我鼓励您将这些见解应用到您自己的开发工作中。尝试使用这些技术,将它们集成到您的项目中,并与社区分享您的经验。通过这样做,我们不仅促进了 AI 的发展,而且确保我们站在这个令人兴奋的领域的前沿,准备好抓住未来的机遇。

我们期待成为您探索这些高级解决方案并在数据驱动工作中取得新高度的旅程的一部分。如果您有任何问题,或者只是想打个招呼,请务必在Slack 上与我们联系。

祝您构建未来,一次编写一行代码!