P3 LightApollo — 拉取式声明式部署与编排引擎
对标 Palantir Apollo。以"期望状态(Desired State)声明 + Spoke Agent 主动拉取"为核心,让被治理的软件与配置安全分发到任何环境(Windows 单机 / 云 / 信创离线 / 星上),控制平面永不主动连入客户环境。服务端口 18082。
Hub-Spoke 纯 Pull 模型
- Agent 主动拉取:Spoke 按周期(默认 60s 可配置)向 Hub 拉取"期望状态 + 制品",自行校验后应用。
- 状态上报出向:Spoke→Hub 为出向 HTTP(拉取=GET、上报=POST);Hub 永不主动向 Spoke 建立连接 → 生产环境无入向端口暴露、离线可用。
- 漂移检测在 Spoke 本地比对(本地有期望 + 实际状态快照),Hub 仅汇总上报,避免中心化比对大量上行流量。
- 单机映射:Windows 单机 = 本机 Agent + 本地期望状态文件(
file://源),机制与集群一致。
Spoke Agent(目标机)
定时/触发 → 拉取期望状态(GET /agent/pull)
→ 校验链:逐文件 SM3 → 整体 SM2 验签 → signer 白名单 → 单调版本 → 依赖就绪
→ 按 DAG 就绪门控推进 → 应用 → 上报实际状态+资源(POST /agent/report)
Reconcile 循环(幂等 + 指数退避 + degraded 态)
期望状态 YAML(声明式 Schema v1)
app: lightaip
version: 1.2.0 # 语义版本(仅展示,不参与连接)
bundle_version: 42 # 单调递增版本号(per app+env 唯一,防回滚攻击判据)
digest: sm3:... # 内容 digest = 不可变连接键
signer_id: ops-signer-01 # 签名者标识(须在 trusted_signers 白名单内)
signature: sm2:... # SM2 签名(对 manifest+SHA256SUMS 整体签名)
target: local # local | remote-hub | k8s(v2)
channel: STABLE
components:
- name: server
artifact: bundle/lightaip-1.2.0.tar.zst
checksum: sm3:...
type: binary # binary | config | llm_route | eval_set | ontology_yaml
depends_on: [database] # 依赖组件(DAG 就绪门控)
probes:
liveness: { type: http, url: "http://127.0.0.1:8080/live", interval_s: 10, failure_threshold: 3 }
readiness: { type: http, url: "http://127.0.0.1:8080/ready", interval_s: 1, failure_threshold: 1 }
restart_policy: always # always | on-failure | never
restart_backoff: { initial_s: 5, multiplier: 2, max_s: 300 }
policy:
require_guomi_signature: true
maintenance_window: "02:00-06:00"
trusted_signers: [ops-signer-01, offline-import-02]
ignore_paths: # 漂移忽略规则(JSON Patch 路径级)
- /components/0/runtime/pid
- /components/0/status/restart_count
rollout: { strategy: auto-rollback, max_surge: 1 }
hub.DesiredStateService 登记期望状态(含 bundle_version/digest/signer_id/signature);Schema 校验:bundle_version 必填且 > 0、depends_on 无环(Kahn 拓扑)、readiness 必填。
bundle 国密签名验签(供应链安全)
server/bundles.go(bundleStore 构建/落盘/记录/验签)实现契约④(签名清单 + signer 白名单):
- 逐文件 SM3 校验(对照 SHA256SUMS.txt 清单)
- 整体 SM2 验签(对 manifest + 清单签名)
- signer_id ∈ trusted_signers 白名单(SM3 公钥指纹匹配)→ 拒绝
VERIFY_SIGNER_NOT_TRUSTED - 单调版本:新 bundle_version > 本地已应用,否则拒绝
VERSION_ROLLBACK_REJECTED - 依赖就绪门控 → 应用
bundle digest = 内容哈希(SM3),作为 bundles 表唯一连接键;Catalog 只存版本引用 + digest,制品本体走 BTS 分离存储(store_ref)。组件类型枚举 binary | config | llm_route | eval_set | ontology_yaml,其中 ontology_yaml 的生产者 = Foundry ontology/export(本体 YAML 跨产品分发闭环)。
渠道 / 策略(Release Channel + Deployment Policy)
| 配置 | 要点 |
|---|---|
| release_channels | RELEASE / CANARY / STABLE;rollout_percent 灰度比例、auto_promote_after 观察期、metric_gate(P2)、require_approval(P2) |
| deployment_policies | policy-as-code:ignore_paths / rollout(auto-rollback 默认开启)/ 信任锚声明 |
| trusted_signers | 签名者白名单(signer_id + SM3 公钥指纹),global / environment 两级作用域,enable/disable |
spoke_agents 记录在线状态;StartAgentBackground 可启动本地演示 Agent 轮询(30s 周期,仅拉取/上报,不应用进程)。
rollout DAG + 门控 + 回滚
- 依赖就绪门控:对 components 构建 DAG,按拓扑序逐批执行"启动 → readiness 通过(或超时)→ 推进下一批";无依赖组件首批并行。
- 就绪判据:
probes.readiness(http/tcp/process/file 四形态);liveness 决定"是否重启",readiness 决定"部署是否成功、能否推进"。 - 部署记录:
deployment_recordsstatus = pending/applying/applied/failed/rolled_back;hub.Orchestrator编排推进(/deployments/start、advance、components)。 - 回滚到任意历史版本(
POST /desired-states/:id/rollback):纯 Pull 下回滚 = 生成新的 desired_states 行(内容/digest 复用目标,bundle_version = max+1 满足单调 UNIQUE,rollback_of指向目标)→ Spoke 下次拉取即见新 digest 应用;同时写一条kind=rollback的可审计部署记录,不覆盖历史。 - 自动回滚(默认开启):组件就绪超时 / liveness 连续失败 → 自动回滚上一稳定成功版本 + 告警;防循环:对 auto-rollback 产生的版本不再触发自动回滚。
- 串行化(部署锁):per (environment_id, app_id) 部署锁,并发回滚/部署排队执行。
漂移检测(字段级结构化 diff)
hub.DriftService:期望状态(declared)与实际状态(快照)按字段递归比对,产出 JSON Patch 风格 diff:
[ { "op": "replace", "path": "/components/0/args/db_host",
"expected": "db.prod:5432", "actual": "db.local:5432" } ]
- 漂移类型按 diff 路径前缀归类:
config_drift / version_drift / file_drift / process_drift。 - 忽略规则 ignore_paths(JSON Pointer,支持尾部通配
/runtime/*):命中不产生漂移、不触发收敛(如动态 PID、restart_count)。 - 收敛结果回填
repair_result(成功/失败/耗时),漂移事件进审计 + 告警。 - API:
GET /drift/events、POST /drift/check、POST /drift/:id/reconcile。
Spoke Agent 与 CLI 规划
- Agent 端点(纯 Pull,可无需认证):
GET /api/v1/agent/pull(拉取期望状态)、POST /api/v1/agent/report(上报实际状态+资源);控制面其余接口 JWT 鉴权。 - ProcManager 冻结接口(products/apollo/agent):Start/Stop/Restart/Status/IsHealthy;实现:
windows_service(srv 包注册 Windows 服务)+process(exec.Cmd);systemd 留接口标注。restart_policy(always/on-failure/never)+ 崩溃指数退避自愈(5s 起步 ×2 封顶 5min,禁快速重启风暴)。 - Reconcile 幂等约定:同一期望状态(以 digest 判定)重复调和 N 次与 1 次一致;Spoke 本地持久化
last_applied_digest,digest 未变跳过应用。 - CLI 规划(PRD F1):
lacli apply -f desired.yaml、lacli status、lacli rollback --to <desired_state_id>、lacli signer add/rm、lacli bundle verify <file>。
HTTP API 分组(/api/v1)
| 分组 | 路径 |
|---|---|
| Agent | /agent/pull、/agent/report |
| 期望状态 | /desired-states CRUD + declaration / activate / deprecate / rollback |
| Bundle | /bundles、/bundles/:id/download|verify |
| 渠道 / 策略 | /channels、/channels/:id/set-desired-state、/policies |
| 签名者 | /signers CRUD + enable/disable |
| 部署编排 | /deployments/start、/deployments、/deployments/:id/advance|components |
| 漂移 / 节点 | /drift/events|check|reconcile、/agents |
audit 事件示例:DEPLOYMENT_SYNC / DRIFT_DETECTED / DRIFT_RECONCILE(ref_type=deployment 落底座)。