跳到主要内容

运维指南

本指南覆盖 Open ACE 日常运维:健康探针与监控端点、调度器服务、数据采集、TLS 证书、数据保留与合规、日志与告警。首次安装见 DEPLOYMENT.md;集群部署见 KUBERNETES.md;反向代理见 NGINX.md。

健康与监控端点​

以下端点均由 Web 应用在 19888 端口提供(定义于 app/__init__.py)。

端点用途返回失败行为
/livez存活探针{"status": "alive", "timestamp": ...}进程能响应即 200。不检查任何依赖,避免重启风暴。
/readyz就绪探针{"status": "ready" | "not_ready", "checks": {...}, "action": ...}任一关键检查失败返回 503。
/metricsPrometheus 指标Prometheus 文本格式(prometheus_flask_exporter,按端点分组,延迟桶 0.01–5 秒)未安装 prometheus_flask_exporter 时返回 503 JSON 降级响应。
/security-status安全基线基线检查结果,附 security_mode(mode / source / explicit)、pilot_metadata 与 migration_status基线报告 unhealthy 或安全模式解析出错时返回 503。
/health已废弃委托 /readyz,再附加 deprecated: true、迁移提示消息与 version(git commit)与 /readyz 相同。请改用 /livez + /readyz。

/readyz 共执行九项检查,逐项体现在 checks 中:

  • security_mode —— 必须显式设置(OPENACE_SECURITY_MODE);production 模式下存在 pilot 元数据会产生告警
  • database —— 2 秒超时的探测连接(专用连接,不占用连接池)
  • schema_version —— 通过 SchemaCompatibilityService 校验 Alembic head(仅 PostgreSQL 生产模式;SQLite 报 skipped;紧急旁路生效时强制 503)
  • config_dir、workspace_dir —— 存在且可写/可读
  • encryption_keys —— 加密密钥注册表已初始化
  • init_status —— 应用初始化已完成
  • ssh_sync —— 不存在 SSH 同步失败告警文件(见"日志与告警")
  • frontend_build —— 管理端 UI 构建产物存在(仅生产模式失败才影响就绪)

未就绪时响应带 action 提示,例如执行 alembic upgrade head。

Kubernetes 探针该用哪个端点​

k8s/deployment.yaml 对 Web Pod 的配置如下(端口 http = 19888):

livenessProbe:
httpGet:
path: /livez
port: http
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /readyz
port: http
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 10
failureThreshold: 3
# Startup probe for slow initialization (Issue #2186)
startupProbe:
httpGet:
path: /readyz
port: http
initialDelaySeconds: 0
periodSeconds: 5
timeoutSeconds: 10
failureThreshold: 60 # 300s max startup time
  • 存活探针 → /livez(只看进程存活;依赖故障不得触发 Pod 重启)
  • 就绪探针 → /readyz(依赖故障时把 Pod 摘出 Service 端点)
  • 启动探针 → /readyz,failureThreshold: 60(首次启动与迁移最长 300 秒)

Web Pod 还带有 Prometheus 抓取注解(prometheus.io/scrape: "true",端口 19888,路径 /metrics);gunicorn 多 worker 场景下部署清单设置了 PROMETHEUS_MULTIPROC_DIR 以聚合多进程指标。Docker Compose 中 open-ace 服务的 healthcheck 轮询 http://localhost:19888/readyz(30 秒间隔、3 次重试、30 秒 start period)。

调度器服务​

后台任务(数据采集、配额执行、自主开发工作流、告警补偿、调度器健康监控、SSO 清理)已与 Web worker 解耦(Issue #2187),由 SCHEDULER_MODE 控制:

  • SCHEDULER_MODE=scheduler —— 进程启动全部后台调度器,使用数据库领导选举(scheduler_leaders 表保证同一时刻只有一个活跃 leader)
  • SCHEDULER_MODE=web 或未设置 —— 不启动任何调度器(Web worker)
  • 开发模式 python3 server.py 在单进程中同时运行 Web 与调度器

Docker Compose​

调度器是可选的 Compose profile(docker-compose.yml 的 scheduler 服务):

scheduler:
image: ${IMAGE_NAME:-openace/open-ace:latest}
container_name: open-ace-scheduler
restart: unless-stopped
profiles:
- scheduler
environment:
- FLASK_ENV=production
- PYTHONUNBUFFERED=1
- SCHEDULER_MODE=scheduler
- SECRET_KEY=${SECRET_KEY:-}
- OPENACE_ENCRYPTION_KEY=${OPENACE_ENCRYPTION_KEY:-}
- DATABASE_URL=postgresql://${DB_USER:-ace}:${DB_PASSWORD:-dev-password-change-in-production}@postgres:5432/${DB_NAME:-ace}
# Issue #3095: Pass DB_PASSWORD as standalone env var for security baseline check.
- DB_PASSWORD=${DB_PASSWORD:-}
- SCHEDULER_HEARTBEAT_INTERVAL=${SCHEDULER_HEARTBEAT_INTERVAL:-10}
- SCHEDULER_HEARTBEAT_TIMEOUT=${SCHEDULER_HEARTBEAT_TIMEOUT:-60}
- SCHEDULER_LOCK_TIMEOUT=${SCHEDULER_LOCK_TIMEOUT:-1800}
- SCHEDULER_METRICS_PORT=9090
# #3237: must match the app service exactly.
- OPENACE_AGENT_STATE_ROOT=/var/lib/openace/agent-state

通过 docker compose --profile scheduler up -d 启用。它与应用服务共享 config-data、workspace-data 与 agent-state 卷 —— 共享 agent-state 卷是有意为之(#3237):清理路由跑在 Web 容器里,而调度器负责写入 transcript。其健康检查轮询 http://localhost:9090/metrics。

心跳与选举参数(在 app/services/leader_election.py 中读取):

变量默认值含义
SCHEDULER_HEARTBEAT_INTERVAL10(秒)leader 刷新心跳行的频率
SCHEDULER_HEARTBEAT_TIMEOUT60(秒)心跳超过该时长视为失去领导权
SCHEDULER_LOCK_TIMEOUT1800(秒)分布式锁过期时间
SCHEDULER_METRICS_PORT9090调度器独立指标 HTTP 服务端口

调度器 worker(python -m app.scheduler_worker)在 9090 端口启动自己的指标服务,提供三个端点:/livez(存活)、/health(存活并附领导选举的 is_leader)、/metrics(Prometheus)。启动时依次校验显式安全模式、schema 版本(REQUIRE_HEAD)、调度器表是否存在,以及数据采集配置漂移(FETCH_USE_SUDO 的 wrapper/sudoers,Issues #2543/#3145 —— 出现严重漂移时会把采集置为 degraded 并跳过注定失败的采集任务)。

Kubernetes​

k8s/scheduler-deployment.yaml 是对应的集群版本:open-ace-scheduler 以 2 副本运行(主 + 备,仅一个活跃 leader),command: ["python", "-m", "app.scheduler_worker"],心跳参数同上(10/60/1800/9090),探针打向 metrics 端口(9090)的 /livez 与 /health,并配置 PodDisruptionBudget(minAvailable: 1)、PriorityClass(open-ace-scheduler,值 1000000)防止驱逐、Pod 反亲和,以及共享 open-ace-data PVC 挂载 /workspace、agent state 与 config —— OPENACE_AGENT_STATE_ROOT 必须与 Web 部署完全一致。

裸机部署可参考 scripts/openace.service(Web,不跑调度器)与 scripts/openace-scheduler.service(SCHEDULER_MODE=scheduler,经领导选举运行全部后台服务)。

数据采集(cron)​

用量数据由 scripts/ 下按工具划分的脚本从 CLI 工具数据目录采集:

脚本采集内容
scripts/fetch_claude.pyClaude Code 会话
scripts/fetch_codex.pyCodex CLI 会话
scripts/fetch_qwen.pyQwen Code 会话
scripts/fetch_openclaw.pyOpenClaw 会话
scripts/fetch_zcode.pyZCode CLI 数据库

采集有两条路径:

  1. 应用内调度器(容器部署默认):数据采集调度器默认每 300 秒(最小 60 秒)以子进程方式运行采集脚本。可用环境变量 DATA_FETCH_INTERVAL / DATA_FETCH_ENABLED 或 config.json 的 data_fetch 段配置(环境变量优先)。多用户容器中脚本经 /usr/local/bin/openace-fetch-wrapper 与 sudoers 规则执行(FETCH_USE_SUDO=true,用 scripts/generate-sudoers.sh 生成规则);默认单用户容器中 FETCH_USE_SUDO=false,直接使用 venv Python。
  2. 宿主机 cron(裸机部署):部署指南中的经典 crontab:
30 0 * * * cd /path/to/open-ace && python3 scripts/fetch_claude.py >> logs/cron.log 2>&1
35 0 * * * cd /path/to/open-ace && python3 scripts/fetch_qwen.py >> logs/cron.log 2>&1
40 0 * * * cd /path/to/open-ace && python3 scripts/fetch_openclaw.py >> logs/cron.log 2>&1

如使用 Codex / ZCode,按相同方式追加 fetch_codex.py / fetch_zcode.py 行。手动执行支持 --days N 回填,例如 python3 scripts/fetch_claude.py --days 7。

中心服务器 + 远程采集器:scripts/upload-to-central/​

分布式环境下,远程机器改跑增量同步守护进程而非 cron。一条命令完成部署(来自 scripts/upload-to-central/README.md):

./deploy-remote.sh \
--host user@remote-host \
--server http://CENTRAL_SERVER:19888 \
--auth-key YOUR_AUTH_KEY \
--hostname remote-hostname

本机部署使用 deploy.sh,--server / --auth-key / --hostname 参数相同。常用选项:--interval(同步间隔秒数,默认 300)、--user、--install-dir(默认 ~/upload-to-central)、--uninstall。

运维要点:

  • 守护进程安装 systemd 服务 upload-to-central;用 sudo systemctl status upload-to-central 与 sudo journalctl -u upload-to-central -f 检查
  • 手动同步:./upload.sh;强制全量重传:./upload.sh --full
  • 同步状态保存在 ~/.open-ace/sync_state.json(按主机记录 last_sync_time、last_upload、total_uploaded);增量同步只上传新消息
  • 守护进程向中央服务器的 /api/upload/batch 发起 POST,携带 X-Auth-Key 头 —— 该密钥必须与中央服务器 ~/.open-ace/config.json 中的 server.upload_auth_key 一致
  • 远程部署需要 SSH 权限;安装 systemd 服务需要 root

TLS 证书​

  • Compose / 裸机:TLS 在 nginx 反向代理终结。NGINX.md 给出完整配置:443 端口监听并指定 ssl_certificate /path/to/ssl/fullchain.pem 与 ssl_certificate_key /path/to/ssl/privkey.pem,仅 TLSv1.2/1.3,80 端口 HTTP→HTTPS 跳转。仓库不附带 certbot 配置;请用 certbot(webroot 或 standalone 方式)为域名获证,并让 nginx 指向 Let's Encrypt 路径。续期由 certbot 自带的定时器自动完成 —— 确保续期钩子会 reload nginx,使新证书生效。
  • Kubernetes:k8s/service.yaml 的 Ingress 已为 cert-manager 预配置 letsencrypt-prod ClusterIssuer(注解 cert-manager.io/cluster-issuer: "letsencrypt-prod",TLS secret open-ace-tls,ssl-redirect: "true")。应用清单前必须先安装 cert-manager:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.0/cert-manager.yaml

之后证书的签发与续期完全由 cert-manager 处理,无需手动续期。

数据保留与合规​

  • k8s/configmap.yaml 声明了 AUDIT_LOG_RETENTION_DAYS: "90" 与 DATA_RETENTION_DAYS: "365"(第 40–41 行)。这两个值声明了预期的保留周期,并与内置默认值一致(租户设置默认 90/365 天;响应时长清理器默认原始数据 90 天 / 聚合数据 365 天)。注意:当前代码中没有后台任务直接读取这两个环境变量 —— 运行时保留由下列机制驱动。
  • 保留规则(app/modules/compliance/retention.py 的 DataRetentionManager),按数据类型:
数据类型默认动作
audit_logs90 天delete
quota_alerts30 天delete
sessions7 天delete
sso_sessions1 天delete
usage_data365 天archive
messages90 天anonymize
user_activity365 天archive
  • 管理 API(blueprint /api/compliance,仅管理员):GET/PUT /api/compliance/retention/rules、POST /api/compliance/retention/cleanup(支持 ?dry_run=true)、GET /api/compliance/retention/history|storage|status。没有内置调度器自动触发保留 —— 请通过 API 执行或排期;合规状态检查会把"上次清理超过一周"的实例标记为不合规。每次执行都会记录到 retention_history 表。
  • Schema 铺垫(Issue #2188 Phase 1):迁移 20260803_002_create_retention_tables 创建了 retention_policies、retention_executions、legal_holds、retention_evidence、archive_files 与 recycle_bin。这些持久化策略/执行表(含 legal hold 与回收站)属于 schema 准备;运维上应把 legal hold 与回收站视为尚未接入运行时自动化,依赖前请先核实所用版本的覆盖情况。
  • 审计日志同步:scripts/openace-ssh-sync 自行按 30 天清理其审计日志(/var/log/openace/ssh-sync.log)。

日志与告警​

  • 日志级别:k8s/configmap.yaml 设置 LOG_LEVEL: "INFO"。应用工厂当前在代码中固定级别(app/__init__.py 的 logging.basicConfig(level=logging.INFO);调度器 worker 同为 INFO),可视为生效级别就是 INFO。
  • 容器日志:docker compose logs -f open-ace / docker compose logs -f scheduler。所有 Compose 服务使用 json-file 驱动,max-size: 10m、max-file: 3 轮转。应用还会写容器内 /app/logs,Compose 中绑定挂载到宿主机 ./logs(Kubernetes 中为 emptyDir)。
  • 告警通知历史:alerts_history 表记录每次外发通知(告警类型、严重级、消息、通道、接收者、status sent/failed、sent_at)。
  • 告警失败队列:告警创建失败时,告警补偿 worker(调度器服务的一部分)从队列重试。用 GET /api/alerts/failure-queue 查看、POST /api/alerts/failure-queue/retry 强制处理一轮(管理员)。调度器状态端点 GET /api/schedulers/data-fetch 与 GET /api/schedulers/quota-enforcement 报告对应后台任务。完整 Alerts API 见 API.md。
  • SSH 同步失败影响就绪(Issue #2328):安全 SSH 同步失败时,entrypoint 会写 /var/log/openace/ssh-sync-failure.warning(人类可读,含修复提示)与 .../ssh-sync-failure.json(结构化)。告警文件存在期间,/readyz 的 ssh_sync 检查失败、Pod 报未就绪。修复原因后删除该文件;详情见同目录的 ssh-sync.log。

相关文档​