跳转至

部署指南

HermesX v2.4.0-dev SaaS API 的 SaaS-only 部署方式:Docker Compose、Kubernetes 和 Helm。

HermesX v2.0.0 部署说明

HermesX v2.0.0 相比 v1.x 版本有以下关键变化:

变化项 v1.x v2.0.0
二进制名称 hermes hermesx
Helm Chart 路径 deploy/helm/hermes-agent/ deploy/helm/hermesx/
默认副本数 1 2
PodDisruptionBudget 未配置 默认启用(minAvailable: 1)
HPA 默认禁用 默认启用(2-10 副本)
OTel 配置 手动挂载 内置环境变量注入
LLM Model 单一模型 支持模型目录热重载

部署前置检查

  • [ ] Go 1.23+ 用于从源码构建
  • [ ] PostgreSQL 16+(需要 RLS 支持)
  • [ ] Redis 7+(用于限流 Lua 脚本)
  • [ ] Kubernetes 1.28+(若使用 Helm 部署)
  • [ ] Docker 24+(若使用 Docker Compose 部署)

SaaS 镜像

Dockerfile.saas 是唯一受支持的发布镜像。它会构建 Go SaaS API 二进制、构建 React WebUI、将 WebUI 产物复制到 /static、打包默认 Skills 用于租户初始化,并默认执行 CMD ["saas-api"]

Dockerfile.saas 特性

# 多阶段构建
# Stage 1: 构建 WebUI
# Stage 2: 编译 Go 二进制
# Stage 3: 复制二进制 + WebUI 静态文件到运行时镜像
# 包含 /static 供 SAAS_STATIC_DIR 使用
# 默认 CMD: ["saas-api"]

Docker Compose 配置对比

配置 用途 包含服务 API 端口 健康检查
docker-compose.prod.yml 生产部署 hermesx-saas + postgres + redis + minio + OTel + Jaeger + Nginx LB 8080/8081 wget health/live
docker-compose.saas.yml SaaS 预发或本地 SaaS 验证 hermesx-saas + postgres + redis + minio 18080/18081 curl health/ready
docker-compose.test.yml 集成测试 postgres-test + redis-test + minio-test(tmpfs 无持久化) 测试端口隔离 pg_isready

生产级配置(docker-compose.prod.yml)

docker-compose.prod.yml 是生产推荐的 Docker Compose 配置,包含以下特性:

  • OTel Collector:接收 gRPC/HTTP OTLP,导出到 Jaeger + Prometheus
  • Jaeger:分布式追踪后端(UI: http://localhost:16686)
  • Nginx:3 副本负载均衡(ip_hash 会话亲和)
  • 资源限制:每个服务均配置 CPU/memory limits
  • 健康检查:所有关键服务均有 healthcheck
  • 备份脚本:postgres 容器挂载 ./scripts/backup 目录
# 启动完整生产栈
docker compose -f docker-compose.prod.yml up -d

# 查看所有服务状态
docker compose -f docker-compose.prod.yml ps

# 查看 OTel collector 日志
docker compose -f docker-compose.prod.yml logs -f otel-collector

# 访问 Jaeger UI(追踪)
open http://localhost:16686

# 访问 Prometheus metrics
curl http://localhost:8889/metrics | grep hermesx

方式一:Docker Compose SaaS

docker-compose.prod.yml 用于生产化部署,docker-compose.saas.yml 用于预发或本地 SaaS 验证。两者都运行 hermesx saas-api,API 服务从 /static 提供内嵌 WebUI。

docker compose -f docker-compose.saas.yml up -d --build
curl http://localhost:18080/health/ready
open http://localhost:18080/admin.html

方式二:Kubernetes / Kind 验证

使用 Kind 在本地运行 Kubernetes 集群。

1. 创建集群

kind create cluster --name hermes

2. 部署 PostgreSQL

kubectl apply -f deploy/kind/postgres.yaml

postgres.yaml 包含: - PersistentVolumeClaim(1Gi) - Deployment(PostgreSQL 16 单实例) - Service(ClusterIP, port 5432) - ConfigMap(初始化用户和数据库)

3. 构建并加载镜像

# 构建 SaaS 镜像
docker build -t hermes-agent-saas:local -f Dockerfile.saas .

# 加载到 Kind 集群
kind load docker-image hermes-agent-saas:local --name hermes

4. 安装 Helm Chart

# v2.0.0: Chart 路径变更为 hermesx/
helm install hermesx deploy/helm/hermesx/ \
  -f deploy/kind/values.local.yaml

values.local.yaml 覆盖: - image.pullPolicy: Never(使用本地镜像) - DATABASE_URL 指向 Kind 内 PostgreSQL Service

5. 验证

kubectl get pods
kubectl port-forward svc/hermesx 8080:8080

curl http://localhost:8080/health/ready

OTel Collector 接入说明

deploy/otel-collector.yaml 是 HermesX v2.0.0 内置的可观测性收集器配置。

协议 端口 说明
OTLP gRPC 4317 接收 HermesX OTel 导出(推荐)
OTLP HTTP 4318 HTTP 方式接收 OTel 数据

处理器:memory_limiter(512MiB limit)+ batch(1024 batch, 5s timeout) 导出器:Jaeger(traces)+ Prometheus:8889(metrics)+ Logging(warn 级别)

# 在 Helm 中启用 OTel
helm install hermesx deploy/helm/hermesx/ \
  --set env.OTEL_EXPORTER_OTLP_ENDPOINT="http://otel-collector:4317" \
  --set env.OTEL_SERVICE_NAME="hermesx"

# 独立部署 OTel Collector
kubectl apply -f deploy/otel-collector.yaml

方式三:Helm Chart 生产部署

Chart 结构

deploy/helm/hermesx/
├── Chart.yaml          # Chart 元数据
├── values.yaml         # 默认值
└── templates/          # K8s 资源模板

安装

kubectl create secret generic hermesx-runtime \
  --namespace hermesx \
  --from-literal=DATABASE_URL="postgres://user:pass@pg-host:5432/hermes?sslmode=require" \
  --from-literal=HERMES_ACP_TOKEN="$(openssl rand -hex 32)" \
  --from-literal=HERMES_API_KEY="$(openssl rand -hex 32)" \
  --from-literal=REDIS_URL="redis://redis:6379" \
  --from-literal=LLM_API_KEY="replace-me" \
  --from-literal=MINIO_ACCESS_KEY="replace-me" \
  --from-literal=MINIO_SECRET_KEY="replace-me"

helm install hermesx deploy/helm/hermesx/ \
  --namespace hermesx \
  --create-namespace \
  --set image.tag="v2.4.0-dev" \
  --set secretEnv.existingSecret="hermesx-runtime" \
  --set env.SAAS_ALLOWED_ORIGINS="https://your-domain.example.com"

values.yaml 关键配置

replicaCount: 2

image:
  repository: hermesx/hermesx-saas
  # 空值默认使用 Chart.appVersion;生产环境应固定 release tag 或 digest。
  tag: ""
  pullPolicy: IfNotPresent

secretEnv:
  # 生产环境优先引用预创建的 Kubernetes Secret。
  existingSecret: "hermesx-runtime"
  keys:
    DATABASE_URL: DATABASE_URL
    HERMES_ACP_TOKEN: HERMES_ACP_TOKEN
    HERMES_API_KEY: HERMES_API_KEY
    REDIS_URL: REDIS_URL
    LLM_API_KEY: LLM_API_KEY
    MINIO_ACCESS_KEY: MINIO_ACCESS_KEY
    MINIO_SECRET_KEY: MINIO_SECRET_KEY

serviceAccount:
  create: true
  automountServiceAccountToken: false

service:
  type: ClusterIP
  port: 8080

args:
  - saas-api

env:
  SAAS_API_PORT: "8080"
  SAAS_ALLOWED_ORIGINS: "https://your-domain.example.com"  # 生产必须设置具体域名
  SAAS_STATIC_DIR: "/static"
  HERMES_API_PORT: "8081"
  LLM_API_URL: ""
  LLM_MODEL: ""

podSecurityContext:
  seccompProfile:
    type: RuntimeDefault

containerSecurityContext:
  runAsNonRoot: true
  runAsUser: 1000
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  capabilities:
    drop:
      - ALL

networkPolicy:
  enabled: false  # 生产命名空间应启用并收紧 ingressFrom/egressTo。

resources:
  limits:
    cpu: "1000m"
    memory: "512Mi"
  requests:
    cpu: "200m"
    memory: "128Mi"

probes:
  liveness:
    path: /health/live
    initialDelaySeconds: 5
    periodSeconds: 10
  readiness:
    path: /health/ready
    initialDelaySeconds: 5
    periodSeconds: 10

# PodDisruptionBudget — v2.0.0 默认启用
pdb:
  enabled: true
  minAvailable: 1

# 自动扩缩容 — v2.0.0 默认启用
autoscaling:
  enabled: true
  minReplicas: 2
  maxReplicas: 10
  targetCPUUtilizationPercentage: 70
  targetMemoryUtilizationPercentage: 80
  scaleDownStabilizationSeconds: 300

# TLS
tls:
  enabled: false
  certFile: ""
  keyFile: ""

# PostgreSQL 子 Chart(开发用)
postgresql:
  enabled: true
  auth:
    database: hermesx
    username: hermes
    password: hermes-dev-password

使用外部 PostgreSQL

生产环境应使用外部管理的 PostgreSQL:

helm install hermesx deploy/helm/hermesx/ \
  --set postgresql.enabled=false \
  --set env.DATABASE_URL="postgres://hermes:pass@rds-endpoint:5432/hermes?sslmode=require"

生产环境检查清单(Pre-flight Checklist)

安全性检查

  • [ ] HERMES_ACP_TOKEN 使用高强度随机字符串(32+ 字符)
  • [ ] SAAS_ALLOWED_ORIGINS 设置为具体域名,禁止 *
  • [ ] DATABASE_URL 通过 Kubernetes Secret 注入(不使用明文 values)
  • [ ] 启用 TLS(通过 Ingress 或 tls.enabled
  • [ ] API Key 定期轮换机制已建立
  • [ ] Helm values.yaml 中所有 changeme 占位符已替换

高可用性检查

  • [ ] replicaCount >= 2(v2.0.0 默认 2)
  • [ ] autoscaling.enabled: true(v2.0.0 默认启用)
  • [ ] pdb.enabled: true(v2.0.0 默认启用,minAvailable: 1)
  • [ ] 健康探针 livenessreadiness 已配置
  • [ ] PostgreSQL 配置主从复制或使用云托管服务(RDS/Cloud SQL)
  • [ ] Redis 启用 AOF 持久化用于分布式速率限制

可观测性检查

  • [ ] /metrics 端点已接入 Prometheus(指标见下表)
  • [ ] OTEL_EXPORTER_OTLP_ENDPOINT 配置 OpenTelemetry Collector
  • [ ] OTEL_SERVICE_NAME 设置为 hermesx
  • [ ] 日志采集到集中式日志平台(EFK/Loki)
  • [ ] 配置审计日志保留策略(建议 365 天)
  • [ ] OTel Collector 已部署并验证可接收数据

资源规划检查

  • [ ] CPU/Memory requests 和 limits 已设置(参考下方扩缩容表格)
  • [ ] PostgreSQL 配置连接池(推荐 PgBouncer,>5 实例时必需)
  • [ ] MinIO 使用持久化存储卷(不使用 hostPath)
  • [ ] audit_logs / execution_receipts > 10M 行时考虑分区

v2.0.0 特有检查

  • [ ] Helm Chart 路径已更新为 deploy/helm/hermesx/(不再是 hermes-agent/
  • [ ] 镜像仓库地址已更新为 hermesx/hermesx-saas(不再是 hermes-agent-saas
  • [ ] HERMES_API_PORT: "8081" 已加入 values(v2.0.0 双端口架构)
  • [ ] REDIS_URL 环境变量已配置(v2.0.0 限流依赖)
  • [ ] MINIO_BUCKET 设置为 hermesx-skills(区分多环境)

方式四:多副本 HA (Docker Compose)

3 实例 + Nginx LB,适用于小规模生产或验证水平扩展能力。

cd deploy/
docker compose -f docker-compose.multi-replica.yml up -d --build

架构:Nginx (ip_hash) → 3× hermes instances → 共享 PG + Redis + MinIO


生产环境变量完整参考

必须

Variable Description Example
DATABASE_URL PostgreSQL 连接串 postgres://user:pass@host:5432/hermes?sslmode=require
HERMES_API_KEY API 认证 Bearer token sk-prod-xxxxx
HERMES_API_KEY_LLM LLM Provider API key sk-...
HERMES_PROVIDER LLM Provider openai, anthropic, gemini
HERMES_MODEL 默认模型 gpt-4o, claude-sonnet-4-20250514

基础设施(推荐)

Variable Default Description
REDIS_URL Redis 连接,启用分布式限流(v2.0.0 新增)
MINIO_ENDPOINT MinIO/S3 endpoint
MINIO_ACCESS_KEY MinIO access key
MINIO_SECRET_KEY MinIO secret key
MINIO_BUCKET hermes-skills Skills bucket

企业多副本部署必须配置 REDIS_URL。Redis 不可用时,运行时会降级到进程内 LocalDualLimiter,这是可用性优先的故障策略;每个副本独立计数,因此故障窗口内有效限流约为 limit × replica_count。强监管环境需要在发布证据中记录 Redis HA/故障演练,或在入口层选择 fail-closed/限流降载策略。

SaaS API(v2.0.0)

Variable Default Description
HERMES_ACP_TOKEN 静态管理员 Token(必填)
SAAS_API_PORT 8080 SaaS API 端口
SAAS_ALLOWED_ORIGINS —(不启用 CORS) CORS 允许的源(生产必须设置具体域名)
SAAS_STATIC_DIR 静态文件目录
HERMES_API_PORT 8081 HTTP API 端口(v2.0.0 新增)
HERMES_API_KEY API 认证 Token(v2.0.0 新增)

Agent 运行时

Variable Default Description
HERMES_INSTANCE_ID hostname HA 实例标识
HERMES_MAX_ITERATIONS 20 Agent 最大迭代次数
HERMES_MAX_TOKENS 4096 最大响应 token
HERMES_BASE_URL provider default 自定义 LLM endpoint
HERMES_DEBUG false Debug 日志
HERMES_ENV development 设为 production 时 egress 默认改为 deny-all
HERMES_EGRESS_DEFAULT 环境推导 显式覆盖 egress 默认策略:allow-alldeny-alllog-only

可观测性(v2.0.0 增强)

Variable Default Description
OTEL_EXPORTER_OTLP_ENDPOINT OTel Collector gRPC/HTTP
OTEL_EXPORTER_OTLP_INSECURE false 禁用 OTel TLS
OTEL_SERVICE_NAME hermesx 服务名(v2.0.0 默认值变更)

Prometheus 指标

Scrape endpoint: GET /v1/metrics

Metric Type Labels
hermes_http_requests_total Counter method, path, status, tenant_id
hermes_http_request_duration_seconds Histogram method, path, tenant_id
hermes_http_requests_in_flight Gauge
hermes_llm_request_duration_seconds Histogram provider, model, status, tenant_id
hermes_llm_tokens_total Counter provider, model, direction, tenant_id
hermes_rate_limit_rejected_total Counter tenant_id
hermes_tool_executions_total Counter tool_name, status, tenant_id
hermes_tool_execution_duration_seconds Histogram tool_name, status, tenant_id
hermes_active_sessions Gauge tenant_id
hermes_chat_completions_total Counter tenant_id, status
hermes_store_operation_duration_seconds Histogram operation, entity

告警建议

- alert: HermesHighErrorRate
  expr: rate(hermes_http_requests_total{status=~"5.."}[5m]) / rate(hermes_http_requests_total[5m]) > 0.05
  for: 2m

- alert: HermesLLMSlow
  expr: histogram_quantile(0.95, rate(hermes_llm_request_duration_seconds_bucket[5m])) > 30
  for: 5m

- alert: HermesRateLimitSurge
  expr: rate(hermes_rate_limit_rejected_total[5m]) > 100
  for: 1m

备份恢复

RPO/RTO 目标

组件 RPO(最大数据丢失) RTO(最大恢复时间) 策略
PostgreSQL < 5 min < 1 h WAL archiving + pg_dump
Redis < 15 min < 5 min BGSAVE + RDB 复制
MinIO < 1 h < 30 min mc mirror 全量镜像

PostgreSQL 备份

# 自动备份(在 postgres 容器内或有 pg_dump 的主机上执行)
./scripts/backup/backup.sh /backup
# 输出: /backup/hermes_YYYYMMDD_HHMMSS.sql.gz
# BACKUP_RETENTION_DAYS=7 (默认保留 7 天)

PostgreSQL 恢复

./scripts/backup/restore.sh /backup/hermes_20260507_120000.sql.gz
# 单事务恢复 + 自动运行 pending migrations

PITR

生产环境建议启用 WAL archiving 实现 < 5 min RPO。配置模板见 deploy/pitr/

Redis 备份

# 触发 BGSAVE 并复制 RDB 到备份目录
./scripts/redis-backup.sh

# 环境变量:
#   REDIS_HOST=localhost      Redis 地址
#   REDIS_PORT=6379           Redis 端口
#   REDIS_PASSWORD=           Redis 密码
#   BACKUP_DIR=/backup/redis  本地备份目录
#   S3_BUCKET=                可选 S3 存储桶(设置后自动上传)
#   REDIS_DATA_DIR=/data      Redis 数据目录
#   RETENTION_DAYS=7          本地备份保留天数

Redis 恢复

# 1. 停止 Redis 服务
docker compose stop redis

# 2. 复制备份 RDB 到 Redis 数据目录
cp /backup/redis/redis-20260515_120000.rdb /data/dump.rdb

# 3. 启动 Redis(自动加载 dump.rdb)
docker compose start redis

# 4. 验证
redis-cli DBSIZE

MinIO 备份

# 镜像 bucket 到本地目录或远程 bucket
./scripts/minio-backup.sh

# 环境变量:
#   MINIO_ENDPOINT=http://localhost:9000   MinIO 地址
#   MINIO_ACCESS_KEY=                      Access Key(必填)
#   MINIO_SECRET_KEY=                      Secret Key(必填)
#   SOURCE_BUCKET=hermes-skills            源 bucket
#   TARGET=/backup/minio                   目标:本地路径或 s3://bucket-name
#   RETENTION_DAYS=7                       本地备份保留天数

MinIO 恢复

# 从本地备份恢复到 MinIO
mc alias set hermesx http://localhost:9000 $MINIO_ACCESS_KEY $MINIO_SECRET_KEY
mc mirror /backup/minio/hermes-skills-20260515_120000 hermesx/hermes-skills

# 验证
mc ls --recursive hermesx/hermes-skills | wc -l

灾难恢复验证

# 运行 DR 测试脚本,验证备份可恢复
./scripts/dr-test.sh

# 该脚本会:
#   1. 检查 Redis 备份文件存在性和完整性
#   2. 检查 MinIO 备份目录和文件数量
#   3. 验证 Redis 和 MinIO 在线数据一致性
#   4. 输出 PASS/FAIL 报告

Cron 调度建议

# PostgreSQL — 每 4 小时备份一次
0 */4 * * * /opt/hermesx/scripts/backup/backup.sh /backup/postgres >> /var/log/hermesx-backup-pg.log 2>&1

# Redis — 每 15 分钟备份一次
*/15 * * * * /opt/hermesx/scripts/redis-backup.sh >> /var/log/hermesx-backup-redis.log 2>&1

# MinIO — 每天凌晨 2 点全量镜像
0 2 * * * /opt/hermesx/scripts/minio-backup.sh >> /var/log/hermesx-backup-minio.log 2>&1

# DR 验证 — 每周日凌晨 4 点
0 4 * * 0 /opt/hermesx/scripts/dr-test.sh >> /var/log/hermesx-dr-test.log 2>&1

水平扩展

HermesX 实例无状态,所有持久化状态在 PG + Redis 中。

负载 CPU/实例 内存/实例 实例数
< 100 req/s 1 core 512MB 1-2
100-500 req/s 2 cores 1GB 3-5
500+ req/s 4 cores 2GB 5+

数据库扩展建议: - > 5 实例时使用 PgBouncer 连接池 - audit_logs / execution_receipts > 10M 行时考虑分区


安全加固

认证体系

  1. API Key: SHA-256 hash 存储,支持 scopes + expiry + rotation
  2. JWT: 签名验证 + claims 提取 tenant_id
  3. Static Token: 单租户部署的简单 Bearer token

行级安全 (RLS)

所有租户数据表启用 PostgreSQL RLS。每个事务通过 SET LOCAL app.current_tenant 设置上下文——即使应用层有 bug,数据库层面也阻止跨租户访问。

网络安全

  • API 仅绑定内部网络,通过 reverse proxy + TLS 暴露
  • PG/Redis/MinIO 禁止公网暴露
  • 生产环境 MinIO 启用 TLS

回滚策略

应用回滚

docker compose -f docker-compose.prod.yml up -d --no-build  # 使用上一个镜像
# 或
docker service update --image ghcr.io/org/hermes:previous-tag hermes

数据库回滚

Migrations 仅前向。回滚步骤: 1. 从最近备份恢复 2. 部署上一个应用版本 3. 验证数据完整性

回滚触发条件

  • Error rate > 5% 持续 5 分钟
  • P95 latency > 30s 持续 5 分钟
  • 数据完整性告警(跨租户数据泄漏)
  • 发布后发现 Critical 安全漏洞

相关文档