paperclipinc/hermes-operator

GitHub: paperclipinc/hermes-operator

「Hermes Operator」是一款生产级的Kubernetes操作符,用于管理Hermes Agent,提供声明式配置、安全默认设置和自动化更新等功能。

Stars: 24 | Forks: 7

# Hermes Operator

License Go Report Card CI E2E Conformance Release Kubernetes versions Go version OpenSSF Scorecard Artifact Hub

[nousresearch/hermes-agent](https://github.com/nousresearch/hermes-agent) 的 Kubernetes operator:一个基于 Python 的自我改进多平台 AI agent。声明式 spec、强约定的安全默认值、S3 备份、OCI registry 自动更新、基于 SSA 的 GitOps 共存,以及从 openclaw-operator 的一次性迁移路径。 `hermes-operator` 以 v1.0.0 版本发布,并在第一天起就履行 [v1 稳定性承诺](docs/api-versioning.md):没有 v0.x 的煎熬。 ## 快速开始 ``` # 1. 通过 Helm 安装 CRDs 和 operator(OCI chart;Helm 3.8+)。 # 省略 --version 以使用最新版本,或添加 --version X.Y.Z 进行固定。 helm install hermes-operator \ oci://ghcr.io/paperclipinc/charts/hermes-operator \ -n hermes-operator --create-namespace # 2. 应用一个最小实例。agent 运行上游 NousResearch/hermes-agent # s6 镜像(gateway + OpenAI-compatible API server),/health 位于端口 8443。 kubectl apply -n agents -f - <<'YAML' apiVersion: hermes.agent/v1 kind: HermesInstance metadata: name: my-hermes spec: image: repository: ghcr.io/paperclipinc/hermes-agent tag: "v0.16.0" # Point the gateway at an LLM provider and inject the key via spec.env. config: raw: model: gpt-4o-mini base_url: https://api.openai.com/v1 env: - name: OPENAI_API_KEY valueFrom: secretKeyRef: name: hermes-llm key: apiKey storage: persistence: enabled: true size: 10Gi YAML # 3. 查看其收敛过程。 kubectl get hi -n agents -w # NAME READY PHASE IMAGE AGE # my-hermes True Ready ghcr.io/paperclipinc/hermes-agent:v0.16.0 30s ``` 如果您省略了 `spec.config.raw.model`,operator 会注入一个不可路由的占位符,以便 gateway 和 API server 在不发起实时 LLM 调用的情况下依然能启动(并且 `/health` 通过检查);在配置真实的 provider 之前,推理过程将会明确报错。每个实例还会获得一个由 operator 管理的随机 `api_server_key`(位于其 `-gateway-tokens` Secret 中),用于对兼容 OpenAI 的 `/v1/...` API 进行身份验证;`/health` 无需身份验证。请参阅 [Agent runtime](docs/runtime.md)。 有关更复杂的场景,请参阅 [`examples/`](examples/)。 ## 架构 ``` flowchart LR subgraph User GitOps[FluxCD / Argo] Kubectl[kubectl apply] end subgraph ControlPlane["Kubernetes control plane"] APIServer[(kube-apiserver)] HInstance["HermesInstance"] HSelfConfig["HermesSelfConfig"] HClusterDefaults["HermesClusterDefaults
(singleton)"] end subgraph Operator["hermes-operator pod"] DefaulterWebhook[Defaulter] ValidatorWebhook[Validator] InstanceCtrl[HermesInstance
controller] SelfConfigCtrl[HermesSelfConfig
controller
SSA: hermes.agent/selfconfig] ClusterDefaultsCtrl[ClusterDefaults
controller] end subgraph Workload["agent workload (per HermesInstance)"] STS[StatefulSet] Svc[Service] NetPol[NetworkPolicy default-deny] PVC[PVC /opt/data] Honcho[Honcho Deploy
profile store] CronJob[Backup CronJob] end S3[(S3-compatible
backup target)] OCI[(OCI registry
hermes-agent tags)] GitOps --> APIServer Kubectl --> APIServer APIServer <-->|admission| DefaulterWebhook APIServer <-->|admission| ValidatorWebhook APIServer --> HInstance APIServer --> HSelfConfig APIServer --> HClusterDefaults HInstance --> InstanceCtrl HSelfConfig --> SelfConfigCtrl HClusterDefaults --> ClusterDefaultsCtrl InstanceCtrl --> STS InstanceCtrl --> Svc InstanceCtrl --> NetPol InstanceCtrl --> PVC InstanceCtrl --> Honcho InstanceCtrl --> CronJob SelfConfigCtrl -.SSA patch.-> HInstance CronJob --> S3 InstanceCtrl -.poll.-> OCI ``` Agent 在默认拒绝(default-deny)的 NetworkPolicy 下作为 StatefulSet(默认单个副本)运行。`HermesSelfConfig` controller 在 field manager `hermes.agent/selfconfig` 下使用 Server-Side Apply,因此 FluxCD/Argo 可以拥有父级 `HermesInstance` 的其他字段而不会发生冲突(flap)。`HermesClusterDefaults` 是一个集群范围的单例(名称**必须**为 `cluster`),它仅填充 `nil` 字段:实例上的显式值始终具有最高优先级。 ## 功能特性 | 领域 | 功能特性 | 备注 | |---|---|---| | **声明式** | 单个 `HermesInstance` CR 驱动整个技术栈 | StatefulSet, Service, PVC, NetworkPolicy, ConfigMap, PDB, HPA, ServiceMonitor, Honcho deployment, backup CronJob:全部由其拥有并协调。 | | **声明式** | 用于集群范围默认值的 `HermesClusterDefaults` | Defaulting webhook 仅填充 `nil` 字段。 | | **自适应** | 用于受审计的 agent 发起变更的 `HermesSelfConfig` | 在 field manager `hermes.agent/selfconfig` 下进行 SSA。由 `spec.selfConfigure.protectedKeys` 进行策略控制。 | | **自适应** | OCI registry 驱动的自动更新 | 锁定通道的轮询、更新前备份、探针失败回滚。 | | **安全** | 默认拒绝的 NetworkPolicy + 每个 gateway 的允许规则 | 派生自 `spec.gateways` 和 `spec.networking.egress`。 | | **安全** | 加固的容器安全上下文 | 上游 s6 runtime 以 root 身份启动,以便 `/init` (PID 1) 可以将镜像内的用户重新映射为 uid/gid 1000 并 chown `/opt/data`,然后每个服务通过 `s6-setuidgid` 降级到 uid 1000。`allowPrivilegeEscalation=false`、`fsGroup=1000` 和 seccomp `RuntimeDefault` 保留;`runAsNonRoot`/只读 rootfs/drop-ALL-caps 未设置(s6 需要 `CHOWN`/`SETUID`/`SETGID`/`DAC_OVERRIDE`/`FOWNER` 以及可写的 `/run`)。需要允许以 root 启动容器的 SCC(例如 `anyuid`);与 OpenShift `restricted`/`restricted-v2` 不兼容。请参阅 [Agent runtime](docs/runtime.md)。 | | **安全** | 可选的 Tailscale Serve sidecar | 每个实例一个 MagicDNS hostname + Tailscale TLS 证书,无需 LoadBalancer/Ingress。请参阅 [Tailscale Serve](#tailscale-serve)。 | | **安全** | 每个 CRD 的 validating + defaulting webhook | 并对未知的 config 键和无法解析的 gateway token 发出警告。 | | **安全** | RBAC 聚合标签 | `kubectl auth can-i create hermesinstances --as=jane` 可开箱即用。 | | **安全** | 镜像签名 + SBOM | Cosign 无密钥 OIDC,每次发布附带 SPDX SBOM。 | | **可观测** | Prometheus 指标 + ServiceMonitor | 每个 controller、每个实例、每个子系统。`metrics.secure` 保持一致。 | | **可观测** | [Grafana dashboard](docs/grafana/) | 以 JSON 格式提供。变量:`namespace`、`instance`。 | | **可观测** | 详尽的 [condition 目录](docs/conditions.md) | 每个 condition × 每个 reason code,均已记录且稳定。 | | **多平台** | Telegram / Discord / Slack / WhatsApp / Signal gateways | 一等公民 `spec.gateways.*` 部分,易于进行 secret 轮换。 | | **上游 runtime** | 内含受支持的 NousResearch/hermes-agent s6 镜像 | 已发布的 `ghcr.io/paperclipinc/hermes-agent` 是 `FROM` 上游镜像构建的(由 digest 锁定)。它捆绑了 gateway、dashboard、兼容 OpenAI 的 API server、Playwright/Chromium 浏览器、node、ffmpeg 以及所有 Python 依赖。无需 init-container venv 构建——旧的 `uv sync` / `init-apt`/`init-uv`/`init-pip` 链已不复存在。请参阅 [Agent runtime](docs/runtime.md)。 | | **上游 runtime** | 开箱即用的 FFmpeg, ripgrep, 浏览器, node | 捆绑在上游 hermes-agent 镜像中。 | | **可扩展** | 通过 `spec.availability.hpa` 实现可选的 HPA | 保留 StatefulSet 以在重启过程中维持身份。 | | **可扩展** | 可选的 `topologySpreadConstraints` | 合理的默认值以及 `spec.availability.topologySpreadConstraints` 覆盖。 | | **高可用** | 当 `replicas > 1` 时自动管理 PodDisruptionBudget | | | **高可用** | Finalizer 驱动的删除时备份 | 对 finalizer 变更使用 `r.Patch` (JSON patch),从不使用 `r.Update`。 | | **高可用** | 僵尸进程回收器 | s6-overlay 的 `/init` 作为 PID 1 回收僵尸进程;默认 `shareProcessNamespace: false`(它的 `/init` 必须是 PID 1)。 | | **备份 / 恢复** | 兼容 S3 的备份 | 定时备份、删除时备份、更新前备份。`tar.zst` 快照 + `meta.json`。 | | **备份 / 恢复** | 声明式一次性恢复 | `spec.restoreFrom` 一旦应用即不可变。 | | **迁移** | 一次性 OpenClaw → Hermes 迁移 | 从同级的 `OpenClawInstance` 或 S3 备份迁移。使用 hermes-agent 的 importer。 | | **Profile 存储** | 可选的 Honcho 伴随容器 | Deployment + Service + PVC + secret,完全托管。 | | **Gateway 认证** | 每个平台用于 token 的 `secretRef` | 独立轮换,通过 webhook 警告进行审计。 | | **云原生** | Helm chart, OLM bundle, 原生 kustomize manifests | 这三者均是一等公民。CRD 在 Helm chart 下进行模板化。 | | **云原生** | 多架构 (`amd64`+`arm64`)、Cosign 签名、附带 SBOM 证明 | | | **GitOps** | 基于 SSA 的 SelfConfig 与 Argo/Flux 共存 | 在共享实例上不会发生冲突。 | | **稳定性** | v1.0 发布包含[版本控制](docs/api-versioning.md) + [弃用](docs/deprecations.md) 策略 | 为未来的 v2 预留了 Conversion-webhook 基础架构。 | ## Tailscale Serve 设置 `spec.tailscale.enabled=true` 以在您的私有 tailnet 上暴露 gateway。Operator 会注入一个运行 [Tailscale Serve](https://tailscale.com/kb/1312/serve) 的 `tailscale` sidecar:每个实例都会获得自己的 MagicDNS hostname(`https://..ts.net`)以及由 Tailscale 签发的 TLS 证书,该证书在 sidecar 中终结并通过 localhost 代理到 gateway。无需 LoadBalancer 或 Ingress。该字段是附加的:现有的 Service 保持不变。 ``` spec: tailscale: enabled: true mode: serve # only "serve" is implemented today hostname: my-hermes # MagicDNS hostname; defaults to metadata.name authKey: secretRef: name: hermes-tailscale key: authKey # image.{repository,tag,pullPolicy} and resources are also available. ``` 要求及注意事项: - **Auth key。** `authKey.secretRef` 是必需的,并且必须引用一个**可重用 + 临时**的 [Tailscale auth key](https://tailscale.com/kb/1085/auth-keys)。 临时意味着当 pod 停止时,节点会自动从 tailnet 中移除; 可重用意味着 sidecar 在重启时会在相同的稳定 hostname 下重新注册。Validating webhook 会拒绝没有 `secretRef` 的 `enabled=true`,并在 Secret 或 key 无法解析时发出警告。 - **Tailnet 先决条件。** 必须在 tailnet 上启用 MagicDNS 和 HTTPS 证书:Serve 会等待 `TS_CERT_DOMAIN`,如果没有它们,将永远无法就绪。 - **NetworkPolicy。** 当启用由 operator 管理的 NetworkPolicy 时,它会增加用于直接连接的 UDP egress 3478 (STUN) 和 41641 (WireGuard)。如果网络阻止了 UDP,Tailscale 将回退到通过 TCP/443 的 DERP 中继,策略已经允许了这种连接。 - **保留名称。** 用户的 sidecar 不得命名为 `tailscale`,并且 `extraVolumes` 不得命名为 `tailscale-serve` 或 `tailscale-tmp`:webhook 会拒绝这些名称。 Sidecar 的连接状态通过 `TailscaleReady` condition 报告。 请参阅 [`docs/api-reference.md`](docs/api-reference.md#spectailscale) 获取完整的字段列表。 ## 工作示例:self-configure Agent 可以通过在其命名空间中创建一个 `HermesSelfConfig` 来持久化已学习的技能、环境变量、config 补丁、workspace 文件或 Honcho profile。Operator 会根据父实例的 `selfConfigure.protectedKeys` 白名单进行验证,并通过 SSA 应用: ``` apiVersion: hermes.agent/v1 kind: HermesSelfConfig metadata: name: install-finance-skill namespace: agents spec: instanceRef: my-hermes addSkills: - source: "git+https://github.com/foo/finance-skill@v1.2.0" patchConfig: schedules: morning-brief: "0 8 * * *" addEnvVars: - name: FINANCE_TZ value: Europe/Berlin ``` 应用,然后观察: ``` kubectl get hsc -n agents # NAME PHASE INSTANCE AGE # install-finance-skill Applied my-hermes 3s ``` 审计记录存在于 `kubectl describe hsc install-finance-skill` 的输出中,以及通过针对每个字段的 SSA field manager `hermes.agent/selfconfig` 存在于实例上:`kubectl get hi my-hermes -o jsonpath='{.metadata.managedFields}'` 会准确显示哪些字段是由 agent 拥有的,哪些是由 Flux 拥有的,哪些是由您拥有的。 请参阅 [`examples/`](examples/) 获取端到端的实战指南。 ## 支持的 Kubernetes 版本 | Operator | Kubernetes | |---|---| | v1.x | 1.28, 1.29, 1.30, 1.31, 1.32 | 当 Kubernetes 终止支持(EOL)最旧的 k8s 次要版本时,我们会在*下一个* operator 次要版本中放弃对它的支持。Patch 版本永远不会改变支持的矩阵。 ## 发行版 | 渠道 | 内容 | |---|---| | Helm (OCI) | `helm install hermes-operator oci://ghcr.io/paperclipinc/charts/hermes-operator` | | OLM / OperatorHub | `kubectl operator install hermes-operator`(等待首次 OperatorHub 发布) | | 原生 manifests | `kubectl apply -f https://github.com/paperclipinc/hermes-operator/releases/latest/download/install.yaml` | | 容器镜像 | `ghcr.io/paperclipinc/hermes-operator:v0.1.9`(多架构,Cosign 签名,附带 SBOM 证明) | ## 文档 - [设计规范](docs/superpowers/specs/2026-05-12-hermes-operator-design.md):权威的产品/架构文档。 - [API 参考](docs/api-reference.md):每个 CR 上的每个字段。 - [Condition 目录](docs/conditions.md):每个 status condition、reason code、故障排除提示。 - [API 版本控制策略](docs/api-versioning.md):什么是以及什么不是破坏性更新。 - [弃用策略](docs/deprecations.md):三步流程 + 当前活跃的弃用项。 - [路线图](ROADMAP.md):已发布、已计划、未来计划、非目标。 - [示例](examples/):9 个现成的 YAML 配方。 - [Grafana dashboard](docs/grafana/):operator 概览 dashboard JSON。 ## 安全 请参阅 [`SECURITY.md`](SECURITY.md)。通过 GitHub 安全公告流程报告漏洞;请勿为安全漏洞提交公开 issue。 ## 许可证 Apache-2.。请参阅 [`LICENSE`](LICENSE)。
标签:AI代理, EVTX分析, GitOps, Go, Kubernetes, Operator, Ruby工具, 云原生, 运维工具