e6472b0ec6
为什么改:发布执行链是"与目标同机"假设写死的(本机 docker.sock、本机 drain.json、 本机 Redis/PG),把目标换成云测试不能只改展示 URL;直接搬整套 worker 又会抢走 本机封存/QA/周报队列并按本机配置写错目标。所以先把"谁消费哪段队列"变成显式角色, 再补齐跨主机搬运与目标侧门禁。 角色(LIBRARY_WORKER_ROLE=full/release-executor/capture)不只影响 handler 列表, 还决定是否拥有 DDL(release-executor 只读校验迁移版本,落后即拒绝启动)、 收拾哪些 library_jobs.kind、是否跑 release 接管扫描、是否起 scheduler/QA/周报/探测。 capture 保留本机原有全部业务;release-executor 只挂 sync/restore/recover/baseline。 快照跨主机:新增内容寻址的 bundle(版本清单先落、blob 按 sha256 命名、清单最后 Link 作提交点),pack/unpack 幂等且拒绝覆盖与同名不同内容;执行器使用前仍逐 blob 重算 sha256,因此传输不可变有两道证据。 目标侧门禁:目标知识库 graph_enabled=true 时拒绝发布(发布只写 PG/ES/OSS,不写 Neo4j;未知也拒绝),只读检测、不改目标配置、不做图谱迁移。 云端入口:新增 drain 感知的 ingress 闸门(建连超时与读超时分离,半关闭单向传播, SIGTERM 排空后写 drain.json 并 exit 0/2)、compose 叠加片段(app 不再发布端口、 frontend 与 adapter 的入口收敛到闸门、指向真实网络 weknora-test-v071-network)、 执行器启动脚本与治理 PG 反向隧道脚本(默认 unix socket,不占 TCP)。 验证:deploy/cloud-test/test_gate.py 13 项全 PASS(含 12 秒静默流、半关闭、2MiB 完整、 排空 exit 0/active_at_close=1、排空超时 exit 2、上游不可达不挂住);go test 相关包全绿; scripts/ci_checks.py 16 项全部 success(EXIT=0,1241 用例通过/0 失败/191 已声明可选集成跳过); 云测试只读预检 17 项 / 6 FAIL,FAIL 项即当前部署缺口(无闸门、app 仍发布端口、 adapter 与 frontend 仍直连 app、云端归档根未建),未部署、未改云端任何状态。
48 lines
2.5 KiB
Bash
Executable File
48 lines
2.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# 在云测试主机上启动/更新"发布执行器"容器(由父在目标机执行,不在本机远程包装)。
|
|
#
|
|
# 为什么单独 docker run 而不是塞进 weknora-test-v071 这个 compose 项目:
|
|
# 维护协调器要求项目里每个服务都被声明为写入者或"非写入者",执行器不是目标的一部分,
|
|
# 放进同一个项目只会让拓扑清单多一条无关服务。它只需要挂上目标项目的网络即可。
|
|
set -euo pipefail
|
|
|
|
IMAGE="${RELEASE_EXECUTOR_IMAGE:-}"
|
|
NETWORK="${TARGET_NETWORK:-weknora-test-v071_default}"
|
|
ENV_FILE="${RELEASE_EXECUTOR_ENV:-/srv/knowledge-governance/release-executor.env}"
|
|
ARCHIVE="${RELEASE_ARCHIVE_ROOT:-/srv/knowledge-governance/library}"
|
|
JOURNAL="${RELEASE_JOURNAL_ROOT:-/srv/knowledge-governance/target-journal}"
|
|
GATE_STATE="${RELEASE_GATE_STATE:-/srv/kgtest-gate/state}"
|
|
NAME="${RELEASE_EXECUTOR_NAME:-kgtest-release-executor}"
|
|
|
|
die() { echo "release-executor: $*" >&2; exit 1; }
|
|
|
|
[ -n "$IMAGE" ] || die "RELEASE_EXECUTOR_IMAGE 未设置(必须是与已验收提交同 sha 的 worker 镜像)"
|
|
[ "$(id -u)" -eq 0 ] || die "需要 root:要读 docker.sock 并读写 0700 归档目录"
|
|
docker network inspect "$NETWORK" >/dev/null 2>&1 || die "网络 $NETWORK 不存在(先部署目标项目)"
|
|
[ -f "$ENV_FILE" ] || die "缺少 env 文件 $ENV_FILE"
|
|
[ "$(stat -c '%a' "$ENV_FILE")" = "600" ] || die "$ENV_FILE 必须是 0600(里面有目标凭据)"
|
|
grep -q '^LIBRARY_WORKER_ROLE=release-executor$' "$ENV_FILE" || die "$ENV_FILE 里 LIBRARY_WORKER_ROLE 必须是 release-executor"
|
|
[ -d "$GATE_STATE" ] || die "闸门状态目录 $GATE_STATE 不存在(先部署 ingress 闸门)"
|
|
|
|
install -d -m 0700 "$ARCHIVE" "$JOURNAL"
|
|
install -d -m 0700 "$ARCHIVE/blobs" "$ARCHIVE/versions"
|
|
|
|
if docker inspect "$NAME" >/dev/null 2>&1; then
|
|
echo "release-executor: 已存在,按同一 env 重建(先停,便于看清失败原因)"
|
|
docker rm -f "$NAME" >/dev/null
|
|
fi
|
|
|
|
docker run -d --name "$NAME" \
|
|
--restart unless-stopped \
|
|
--network "$NETWORK" \
|
|
--label com.nous.role=release-executor \
|
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
|
-v "$ARCHIVE:/var/lib/knowledge-governance/library" \
|
|
-v "$JOURNAL:/var/lib/knowledge-governance/target-journal" \
|
|
-v "$GATE_STATE:/gate-state" \
|
|
--env-file "$ENV_FILE" \
|
|
"$IMAGE" >/dev/null
|
|
|
|
sleep 2
|
|
docker ps --filter "name=$NAME" --format '{{.Names}} {{.Status}} {{.Image}}'
|
|
echo "release-executor: 启动完成;日志用 docker logs -f $NAME(准入失败会在第一屏写明原因)" |