第 15 期 | Agent 驱动的 DevOps:部署自动化

更新于 2026/4/15

好的,作为技术教育专家,我将为您撰写这篇关于 Hermes Agent 在 DevOps 领域应用的深度教程。


副标题:让 Hermes 参与自动化构建、Docker 打包、测试发布流程,体验向"AI原生运维"范式的跳跃。


学习目标

在本期课程中,您将深入探索如何将 Hermes Agent 的能力从对话和信息处理扩展到实际的软件工程实践中。完成本教程后,您将能够:

  1. 理解 Agent-Driven DevOps 的核心思想:了解它与传统 CI/CD 工具(如 Jenkins, GitLab CI)的区别与优势。
  2. 创建强大的 DevOps Skill:编写一个能够执行本地 Shell 命令的 Hermes Skill,作为连接 Agent 与服务器操作的桥梁。
  3. 实现完整的自动化部署流程:通过 Git Webhook 触发,让 Hermes Agent 自动完成拉取代码、构建 Docker 镜像、停止旧容器、启动新容器的完整 CI/CD (Continuous Integration/Continuous Deployment) 流程。
  4. 构建闭环反馈系统:在部署任务完成后,让 Hermes Agent 主动通过消息网关(如 Telegram)向您汇报结果,实现无人值守的自动化运维。

核心概念讲解

1. 什么是 Agent 驱动的 DevOps (Agent-Driven DevOps)?

传统的 DevOps 自动化依赖于预定义的、结构化的配置文件(如 .gitlab-ci.yml, Jenkinsfile)。这些工具强大但通常缺乏灵活性和上下文感知能力。它们的执行逻辑是固定的,遇到非预期情况时,往往需要人工介入排查日志。

Agent-Driven DevOps 是一种新的范式,它将大型语言模型(LLM)驱动的 Agent 置于 DevOps 流程的核心。其关键特点包括:

  • 自然语言交互:除了自动化触发,你还可以通过自然语言向 Agent下达指令,如“部署主分支到预发环境”、“回滚上一个版本”、“检查生产环境服务状态”。
  • 上下文感知与决策:Agent 能够理解上下文。例如,当一个部署任务失败时,它不仅能报告错误,还能根据错误日志(通过 Skill 读取)尝试分析原因,甚至提出解决方案。
  • 动态工作流编排:Agent 可以根据情况动态调整工作流。例如,如果测试阶段发现高危漏洞,它可以自动暂停部署流程,并立即通知安全团队,而不是僵化地继续执行下一步。
  • 集成与协同:Hermes Agent 可以作为一个智能中枢,连接代码仓库 (GitHub)、项目管理工具 (Jira)、监控系统 (Prometheus) 和通信平台 (Telegram, Slack),实现跨系统的信息整合与任务协同。

在本教程中,我们将实现 Agent-Driven DevOps 的第一步:将 Hermes Agent 打造为一个由 Git 事件驱动的、能够执行部署任务的智能运维机器人。

2. Hermes Agent 在 DevOps 中的角色

在这个自动化流程中,Hermes Agent 扮演着“智能编排器”和“执行者”的角色。

  • 监听器 (Listener):通过 Webhook 接口,实时监听来自外部系统(如 GitHub)的事件。
  • 决策者 (Decision Maker):接收到事件后,Agent 的大脑(LLM)根据其内置的 Prompt 和可用的 Skills,决定应该执行哪个工具(Tool/Function)。
  • 执行者 (Executor):通过专门为 DevOps 设计的 Skill,调用底层的 Shell 脚本或命令来完成实际工作,如 git pull, docker build, docker run 等。
  • 报告者 (Reporter):任务执行完毕后,通过消息网关将结果(成功或失败)反馈给用户,形成一个完整的闭环。

3. 关键技术组件

  • Skill (execute_shell_command): 这是我们实现 DevOps 自动化的核心武器。我们将创建一个 Skill,它包含一个可以安全执行 Shell 命令的工具。这是 Agent 与操作系统交互的唯一通道。
  • Webhook: Webhook 是一种反向 API,允许外部服务在特定事件发生时,主动向 Hermes Agent 发送一个 HTTP POST 请求。在本例中,GitHub 在我们 git push 代码时,会向 Hermes 的 Webhook URL 推送一个包含提交信息的 JSON 数据包。
  • Shell 脚本 (deploy.sh): 将复杂的部署逻辑封装在一个独立的 Shell 脚本中是一种最佳实践。这使得 Hermes 的 Skill 职责单一(只负责调用脚本),同时也让部署逻辑更易于维护和在其他地方复用。

💻 实战演示

我们将以一个简单的 Python Flask 应用为例,构建一个完整的自动化部署流水线。当开发者向 GitHub 仓库推送代码时,Hermes Agent 将自动将其部署到服务器上。

Step 1: 准备项目环境

首先,我们需要一个待部署的应用。我们创建一个简单的 Flask Web 应用,并为其编写 Dockerfile 和部署脚本。

1. 创建项目目录

在您的服务器上,创建一个项目目录。

mkdir hermes-devops-demo
cd hermes-devops-demo

2. 创建 Flask 应用 (app.py)

这是一个最简单的 "Hello World" 应用。

# app.py
from flask import Flask
import os

app = Flask(__name__)

@app.route('/')
def hello():
    # 我们将通过环境变量来验证部署是否更新
    version = os.environ.get('APP_VERSION', 'v1.0.0')
    return f"Hello from Hermes DevOps Demo! Version: {version}"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

3. 创建依赖文件 (requirements.txt)

Flask==2.2.2

4. 创建 Dockerfile

这个文件定义了如何将我们的应用打包成一个 Docker 镜像。

# Dockerfile
FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY app.py .

CMD ["python", "app.py"]

5. 创建部署脚本 (deploy.sh)

这是整个自动化流程的核心执行逻辑。该脚本负责停止并移除旧的容器,然后使用最新的代码构建并运行新的容器。

#!/bin/bash

# deploy.sh

# 确保脚本在任何命令失败时退出
set -e

# --- 配置变量 ---
# Docker 镜像名称
IMAGE_NAME="hermes-demo-app"
# 容器名称
CONTAINER_NAME="hermes-demo-container"
# 应用端口
APP_PORT=5000
# 项目路径 (确保这是脚本所在的绝对路径)
PROJECT_PATH=$(pwd)
# 获取当前的 Git Commit Hash 作为版本号
GIT_COMMIT_HASH=$(git rev-parse --short HEAD)

echo "====== [ HERMES DEVOPS ] ======"
echo "Starting deployment for commit: $GIT_COMMIT_HASH"
echo "Project path: $PROJECT_PATH"

# --- 1. 拉取最新代码 ---
echo "--> Step 1: Pulling latest code from git..."
git pull origin main

# --- 2. 构建 Docker 镜像 ---
echo "--> Step 2: Building Docker image: $IMAGE_NAME:$GIT_COMMIT_HASH..."
docker build -t $IMAGE_NAME:$GIT_COMMIT_HASH -t $IMAGE_NAME:latest .

# --- 3. 停止并移除旧容器 ---
# 使用 docker ps -q 来检查容器是否存在,如果存在则停止并删除
if [ "$(docker ps -q -f name=$CONTAINER_NAME)" ]; then
    echo "--> Step 3: Stopping and removing old container..."
    docker stop $CONTAINER_NAME
    docker rm $CONTAINER_NAME
fi

# --- 4. 启动新容器 ---
echo "--> Step 4: Starting new container..."
docker run -d \
    --name $CONTAINER_NAME \
    -p $APP_PORT:5000 \
    -e APP_VERSION=$GIT_COMMIT_HASH \
    --restart always \
    $IMAGE_NAME:latest

echo "====== [ DEPLOYMENT SUCCESS ] ======"
echo "Application deployed successfully!"
echo "Access it at: http://<your_server_ip>:$APP_PORT"

# 将部署结果返回给调用者(Hermes Skill)
echo "Deployment of version $GIT_COMMIT_HASH completed."

重要: 赋予脚本执行权限。

chmod +x deploy.sh

6. 初始化 Git 仓库并推送到 GitHub

git init
git add .
git commit -m "Initial commit for DevOps demo"
# 在 GitHub 上创建一个新的空仓库,然后执行以下命令
git remote add origin <your_github_repo_url.git>
git branch -M main
git push -u origin main

至此,我们的应用代码和部署脚本已经准备就绪。

Step 2: 创建 DevOps Skill

现在,我们为 Hermes Agent 创建一个 Skill,让它能够调用我们刚刚编写的 deploy.sh 脚本。

  1. 进入 Hermes Agent 的 skills 目录,创建一个新的 Skill 文件 devops_skill.py
  2. 编辑 devops_skill.py 文件,内容如下:
# skills/devops_skill.py
import subprocess
import os
from hermes_agent.skills.skill import Skill

class DevOpsSkill(Skill):
    def __init__(self, agent):
        super().__init__(agent)
        # 你的项目部署脚本所在的绝对路径
        self.project_path = "/path/to/your/hermes-devops-demo" 

    def get_tools(self):
        return [self.deploy_project]

    def deploy_project(self, project_name: str, branch: str) -> str:
        """
        Deploys a specified project by executing its deployment script.
        This tool should be triggered by a webhook from a Git repository.
        It executes the deploy.sh script within the project's directory.
        
        :param project_name: The name of the project to deploy, e.g., 'hermes-devops-demo'.
        :param branch: The branch that was pushed, e.g., 'main'.
        :return: A string containing the output of the deployment script.
        """
        # 安全检查:只允许部署主分支
        if branch != 'main':
            return f"Deployment skipped. Only pushes to the 'main' branch trigger deployment. Received push to '{branch}'."

        if project_name != 'hermes-devops-demo':
            return f"Deployment skipped. Unknown project name: '{project_name}'."
            
        script_path = os.path.join(self.project_path, "deploy.sh")
        
        if not os.path.exists(script_path):
            error_msg = f"Error: Deployment script not found at {script_path}"
            self.agent.logger.error(error_msg)
            return error_msg

        try:
            self.agent.logger.info(f"Executing deployment script for project '{project_name}' from branch '{branch}'...")
            
            # 使用 subprocess 执行 shell 脚本
            # cwd 参数确保脚本在正确的项目目录下执行
            result = subprocess.run(
                [script_path],
                capture_output=True,
                text=True,
                check=True,
                cwd=self.project_path 
            )
            
            output = result.stdout
            self.agent.logger.info(f"Deployment script executed successfully. Output:\n{output}")
            
            # 部署成功后,发送通知
            self.send_deployment_notification(status="✅ SUCCESS", details=output)

            return f"Deployment successful. Log:\n{output}"

        except subprocess.CalledProcessError as e:
            error_output = e.stderr
            self.agent.logger.error(f"Deployment script failed. Error:\n{error_output}")
            
            # 部署失败后,发送通知
            self.send_deployment_notification(status="❌ FAILED", details=error_output)

            return f"Deployment failed. Error:\n{error_output}"
        
    def send_deployment_notification(self, status: str, details: str):
        """通过消息网关发送部署状态通知"""
        if not self.agent.message_gateway:
            self.agent.logger.warning("Message gateway not configured. Skipping notification.")
            return
            
        # 假设你已经配置好了 Telegram (或其它) 网关
        # 从配置中获取管理员的用户ID
        admin_user_id = self.agent.config.get('admin_user_id')
        if not admin_user_id:
            self.agent.logger.warning("Admin user ID not set in config. Skipping notification.")
            return

        commit_hash = details.split("commit: ")[1].split("\n")[0] if "commit: " in details else "N/A"
        message = (
            f"**Hermes DevOps Notification**\n\n"
            f"**Status**: {status}\n"
            f"**Project**: hermes-devops-demo\n"
            f"**Commit**: `{commit_hash}`\n\n"
            f"**Details**:\n```\n{details[-1000:]}\n```" # 只发送最后1000个字符的日志
        )
        
        # 发送消息给管理员
        self.agent.message_gateway.send_message(message, admin_user_id)
        self.agent.logger.info(f"Sent deployment notification to admin user {admin_user_id}.")

3. 注册 Skill

打开 Hermes Agent 的 config.yml 文件,在 skills 部分添加我们的新 Skill。

# config.yml
skills:
  - name: devops_skill.DevOpsSkill
    enabled: true
# ... 其他配置

同时,为了让通知功能生效,请确保你已经配置了消息网关(如 Telegram,参考第05期课程),并在 config.yml 中添加管理员的用户ID。

# config.yml
# ...
message_gateways:
  telegram:
    enabled: true
    api_token: "your_telegram_bot_token"

# 添加一个新的配置项
admin_user_id: "your_telegram_user_id" 

Step 3: 配置 Webhook 接入

现在,我们需要告诉 GitHub,当有代码 push 事件时,请通知我们的 Hermes Agent。

  1. 获取 Hermes Webhook URL: Hermes Agent 的 Webhook URL 格式为:http://<your_hermes_server_ip>:<port>/v1/webhook/{webhook_id}

    • webhook_id:你可以在 config.yml 中自定义,或者使用默认的。我们在此处定义一个新的。
    • api_key:用于验证请求的来源,也在 config.yml 中设置。

    config.yml 中添加 webhook 配置:

    # config.yml
    server:
      host: "0.0.0.0"
      port: 8888
      api_key: "a_very_secret_api_key" # 请使用一个强密码
    
    webhooks:
      # 为我们的 DevOps 流程定义一个专用的 webhook
      - id: "github-devops-trigger"
        # 当此 webhook 被触发时,Agent 会执行此指令
        # 我们利用 LLM 的能力,将 webhook 的 JSON 内容作为上下文,让它调用正确的工具
        prompt: >
          The following JSON payload was received from a GitHub webhook for the 'hermes-devops-demo' repository.
          The 'ref' field indicates the branch that was pushed.
          Based on this information, call the deploy_project tool with the correct project name and branch.
          Do not ask for confirmation, just execute the tool.
          Webhook Payload: {payload}
    

    根据此配置,我们的 Webhook URL 是: http://<your_hermes_server_ip>:8888/v1/webhook/github-devops-trigger

  2. 在 GitHub 中配置 Webhook

    • 打开你的 GitHub 仓库页面,进入 Settings -> Webhooks
    • 点击 Add webhook
    • Payload URL: 填入你的 Hermes Webhook URL。
    • Content type: 选择 application/json
    • Secret: 填入你在 config.yml 中设置的 api_key
    • Which events would you like to trigger this webhook?: 选择 Just the push event
    • 确保 Active 复选框被勾选,然后点击 Add webhook

(这是一个示意图,请根据实际界面操作)

Step 4: 触发与验证

一切准备就绪!现在我们来触发整个流程。

  1. 重启 Hermes Agent 以加载新的 Skill 和配置。

    # 在 Hermes Agent 的根目录
    python main.py
    

    观察启动日志,确保 DevOpsSkill 已成功加载。

  2. 修改代码并推送: 在本地克隆的 hermes-devops-demo 项目中,对 app.py 做一个小的修改。

    # app.py (修改后)
    @app.route('/')
    def hello():
        version = os.environ.get('APP_VERSION', 'v1.0.0')
        # 添加一句新的问候
        return f"Hello from Hermes DevOps Demo! Version: {version}. Deployment was automated!"
    
  3. 提交并推送代码

    git add app.py
    git commit -m "feat: Update greeting message to test auto-deployment"
    git push origin main
    
  4. 观察 Hermes Agent 日志: 在 git push 命令成功后,你应该会立刻在 Hermes Agent 的控制台看到类似以下的日志:

    INFO:hermes_agent.services.http_server:Received webhook request for ID: github-devops-trigger
    INFO:hermes_agent.agent:Received instruction from webhook 'github-devops-trigger'. Processing...
    INFO:hermes_agent.models.provider:Calling tool: deploy_project with args: {'project_name': 'hermes-devops-demo', 'branch': 'main'}
    INFO:skills.devops_skill:Executing deployment script for project 'hermes-devops-demo' from branch 'main'...
    # ... deploy.sh 脚本的输出 ...
    INFO:skills.devops_skill:Deployment script executed successfully. Output:
    ====== [ HERMES DEVOPS ] ======
    ...
    ====== [ DEPLOYMENT SUCCESS ] ======
    ...
    INFO:skills.devops_skill:Sent deployment notification to admin user 123456789.
    
  5. 验证部署结果

    • 在服务器上运行 docker ps,你会看到一个新的容器正在运行,它的启动时间就是刚刚。
    • 使用 curl 或浏览器访问你的应用:curl http://localhost:5000
    • 你应该能看到更新后的内容,并且版本号是新的 Git Commit Hash。
    $ curl http://localhost:5000
    Hello from Hermes DevOps Demo! Version: a1b2c3d. Deployment was automated!
    
  6. 检查通知: 打开你的 Telegram,你应该会收到来自 Hermes Bot 的一条消息,详细报告了部署成功的信息和日志。

涉及命令

  • 项目设置: mkdir, cd, git init, git add, git commit, git remote add, git push
  • 权限管理: chmod +x deploy.sh
  • Docker: docker build, docker ps, docker stop, docker rm, docker run
  • 验证: curl http://localhost:5000

要点回顾

  1. Agent-Driven DevOps 的核心是智能与交互:我们利用 LLM 的理解能力,通过一个通用的 Prompt 来解析 Webhook 内容并调用正确的工具,这比写死的 if-else 逻辑更具扩展性。
  2. 职责分离是关键:复杂的部署逻辑应封装在独立的 Shell 脚本 (deploy.sh) 中,而 Hermes Skill 只负责触发、监控和报告。这种解耦使得两部分都易于维护。
  3. Webhook 是连接外部世界的桥梁:通过配置 Webhook,Hermes Agent 能够响应外部系统的事件,从而实现事件驱动的自动化。
  4. 安全是第一要务:在 Skill 中执行 Shell 命令具有潜在风险。务必对输入参数进行严格校验(如我们检查了 branchproject_name),并确保执行的脚本来自可信的源。在生产环境中,应考虑使用更安全的执行沙箱。
  5. 闭环反馈至关重要:自动化流程的最后一步永远是报告。通过消息网关发送通知,可以让我们在不登录服务器的情况下,实时掌握系统状态,真正实现“无人值守”。

通过本期课程,您已经成功地将 Hermes Agent 集成到了一个现代化的 DevOps 工作流中。这仅仅是一个开始,您可以基于此框架进行扩展,例如:

  • 增加测试阶段:在部署前自动运行单元测试。
  • 支持多环境部署:通过解析分支名(如 develop, release/*)来决定部署到哪个环境。
  • 增加人工审批环节:在部署到生产环境前,Agent 在群组里发起一个投票,等待管理员确认后才继续。

欢迎继续探索 Hermes Agent 的无限可能,向着真正的 "AI-Native Ops" 迈进!

参考资料