升级
要升级两个二进制:manager(docker-compose 栈)和 edge(每台主机一个)。两者走同一套概念流程:把新文件 stage 起来,原子换入,如果新版本起不健康就自动回滚到上一版本。
TL;DR
Manager:
VER=v0.7.160
gh release download "$VER" --repo ongridio/ongrid \
-p 'ongrid-*-linux-amd64.tar.xz*'
sha256sum -c "ongrid-${VER}-linux-amd64.tar.xz.sha256"
tar xf "ongrid-${VER}-linux-amd64.tar.xz"
cd "ongrid-${VER}-linux-amd64"
sudo ./upgrade.shEdge(一次全部,并行,从 UI 触发):
- Edges → Upgrade all —— manager 向每台已连接 edge 发
MethodFetchPackage,每台从https://<manager>/edge/下载 stage 好的 bundle,stage、重启、swap、跑。失败会在下次启动自动回滚。
或者单个 edge 在 shell 里:
sudo systemctl restart ongrid-edge
# The ExecStartPre runs apply-pending-upgrade.sh which picks up any
# staged bundle and applies it before the new agent starts.本页其余部分讲清楚这些到底是怎么跑的,你出了问题才好排查。
Manager 升级:upgrade.sh
upgrade.sh 每个发布 tarball 里都有,要在刚解压的新 tarball 里跑。它假设 ${ONGRID_INSTALL_DIR:-/opt/ongrid}/ 下已经有安装。
按顺序:
- 预检。 确认 docker + compose v2,找到现存
.env。没有就早退。 - 判定新旧版本:从现存
.env和新 tarball 的VERSION文件读。两个都打印——support ticket 时有用。 docker compose down,释放数据卷以便迁移步骤进行。- 重新断言数据目录 owner:
${ONGRID_DATA_DIR}/下(mysql、prom、loki、tempo、grafana、embeddings、qdrant)。镜像 uid 很久没变过,但这是唯一安全的默认——重新断言是幂等的。 - 从新 tarball 重新 stage 配置到
/opt/ongrid/:docker-compose.yml、prometheus.yml、prometheus-rules.yml、loki-config.yaml、tempo-config.yaml、grafana/、searxng/、nginx.conf、frontier.yaml、新的edge/资源、新的VERSION文件。.env保留——upgrade.sh永不覆盖运维改过的 env。 - 加载新 docker 镜像(
ongrid.tar、ongrid-web.tar,存在的话还有frontier.tar)。 - 把
.env里ONGRID_VERSION=抬版本号,下次 compose-up 才会用新 image tag。 docker compose up -d,用新 env。- 轮询
/healthz60 秒。 - Banner:旧 → 新版本、Web URL、几条下一步好用的命令。
如果在第 8 步之前出错,运维修好根因后可以重跑——upgrade.sh 是幂等的。如果第 9 步失败(/healthz 一直不返回 200),docker compose logs ongrid 里有 manager 的日志告诉你哪坏了。
要零停机就上蓝绿,两台 manager 接负载均衡;OSS 单机安装是升级时短暂停机(约 30-60s)。
升级文件从哪来:make package
这是运维路径——从源码构建(而不是拉 release)时怎么打 tarball。从 ongridio/ongrid 的 checkout 里:
make package顺序重要;make package 做的事:
fetch-promtail—— 从上游 Grafana release 下载promtail-<os>-<arch>.zip,解到bin/<os>-<arch>/promtail。带缓存。fetch-otelcol——otelcol-contrib同理。fetch-node-exporter——node_exporter同理。fetch-process-exporter——process_exporter同理。build-edge-all—— 交叉编译ongrid-edge到linux/amd64、linux/arm64、darwin/amd64、darwin/arm64。docker-build—— 构建ongrid:<version>镜像。docker-build-broker—— 从$FRONTIER_SRC构建singchia/frontier:<ver>(本地 image store 里有就跳过)。docker-build-web—— 构建ongrid-web:<version>(前端 SPA + nginx)。build-edge-bundle—— 从散二进制组装edge-bundle-linux-amd64-<ver>.tar.gz。dist/package.sh—— 把所有东西 stage 到dist/stage/ongrid-<version>-linux-amd64/,docker save三个镜像,tar.xz整个目录,算 sha256 sidecar,输出到dist/out/。
输出:
dist/out/ongrid-v0.7.160-linux-amd64.tar.xz
dist/out/ongrid-v0.7.160-linux-amd64.tar.xz.sha256这就是你 scp 到生产主机并喂给 ./upgrade.sh 的东西。
离线 RAG 模型
BGE embedding 模型不在 package 依赖里——国内网络拉很慢,所以单列一个步骤。如果你想恢复后立刻让 ONGRID_EMBEDDING_PROVIDER=local 可用,在 make package 前先跑一次 make fetch-embedding-model。
Edge 升级:ADR-024 stage-then-swap
升级一个 edge 的用户路径是"UI 上点 Upgrade"或 stage 好 bundle 后跑 systemctl restart ongrid-edge。实际发生什么,自顶向下:
1. Manager 触发,edge 拉取
点 "Upgrade all edges"(或单个 edge)时:
- Manager 从
/opt/ongrid/edge/读dist/out/edge-bundle-<arch>-<ver>.tar.gz.sha256(install.sh/upgrade.sh放在那的)。 - Manager 通过隧道给目标 edge 发
MethodFetchPackage(url=https://<manager>/edge/<bundle>, sha256=<sha>, version=<ver>)。 - nginx 从同一个
/edge/目录把 bundle 字节服出去。
2. Edge stage
收到的 edge:
- 把 bundle 下载到
/tmp/。 - 用 manager 发的 manifest 校验 sha256。
- 解到
/var/lib/ongrid-edge/.upgrade/incoming/。 - 校验
MANIFEST.txt的每行<sha> <mode> <src> <dest>(sha 匹配、src 存在)。 - 写一个 "ready" marker。
- 干净退出。systemd 按
Restart=always重启 unit。
3. systemd 的 ExecStartPre 跑 swap
Unit 里带:
ExecStartPre=-+/usr/local/lib/ongrid-edge/apply-pending-upgrade.sh
ExecStart=/usr/local/bin/ongrid-edge+ 前缀让 hook 以 root 跑,尽管 User=ongrid-edge;- 让脚本缺失/失败时返回 0 不挡 unit,确保升级前的二进制总能启动。
apply-pending-upgrade.sh 按顺序:
- Mode 1:自动回滚 —— 如果上次升级跑过但从未写
healthy_marker跟last_upgrade_ver匹配。把每个<dest>.previous还原回<dest>。清 staging 目录。 - Mode 2:bundle 应用 ——
MANIFEST.txt每一行:- 重新校验 sha256,
cp -p $dest $dest.previous(快照用于回滚),- 在同一文件系统上
cp $src $dest.new,让最后那次 rename 是 POSIX 原子的, chmod $mode $dest.new,mv -f $dest.new $dest。
- Mode 3:legacy 单文件应用 —— 兼容还没 bundle 升级过的老 edge(只有 agent 二进制,没 manifest)。
- 记录
last_upgrade_at和last_upgrade_ver,给下次启动的健康检查用。
然后 ExecStart=/usr/local/bin/ongrid-edge 跑新 swap 过的二进制。
4. 新 agent 上报健康(或不上报)
新 agent 成功连上后:
- 写
/var/lib/ongrid-edge/.upgrade/healthy_marker,内容是它跑的版本。 - 经隧道用新版本号
register。
如果下次启动时该文件存在且跟 last_upgrade_ver 匹配,apply-pending-upgrade.sh 宣布升级成功,剪掉所有 .previous 释放磁盘,清 staging。
如果不(agent 崩了、连不上 manager、随便什么),下次启动触发自动回滚:每个 .previous 还原、staging 清空、edge 重新跑上一个能跑的版本。运维在 UI 上看得见这件事(触发了升级后 edge 还在上报 "旧" 版本——这是新 bundle 有问题的信号)。
Bundle 不变量
Edge swap 的每个文件都在 bundle 里;bundle 里的每个文件都是自包含的二进制或脚本。这是硬性要求:
- Agent 二进制(
ongrid-edge) - 插件二进制(
promtail、otelcol-contrib、node_exporter、process_exporter) - Hook 脚本(
apply-pending-upgrade.sh)
插件配置(promtail.yaml、otelcol.yaml)不在 bundle 里——它们落在 /etc/ongrid-edge/,作为热配置通过隧道下发。这样 agent 升级不会覆盖运维手改的配置。
别把 bundle 烤回 docker 镜像里
源码构建时,bundle 在打包时由 dist/build-edge-bundle.sh 在主机上构建,不在容器里。ADR-032 强制——把它烤回镜像会双打包 ~120 MB 不可压缩字节,并打破 sha 一致性。
回滚文件在哪
/usr/local/bin/ongrid-edge # current
/usr/local/bin/ongrid-edge.previous # last known good
/usr/local/lib/ongrid-edge/promtail
/usr/local/lib/ongrid-edge/promtail.previous
...etc.
/var/lib/ongrid-edge/.upgrade/
last_upgrade_at # ISO timestamp
last_upgrade_ver # version string
healthy_marker # written by the new agent触发升级后的一组启动序列:
boot 1 (pre-upgrade):
apply-pending-upgrade.sh sees nothing staged; exit 0
ongrid-edge v0.7.159 runs
(manager pushes bundle, edge stages it, edge exits clean)
boot 2 (apply):
apply-pending-upgrade.sh
mode 1: no healthy_marker yet, but no last_upgrade_at either → skip
mode 2: applies bundle. /usr/local/bin/ongrid-edge.previous = v0.7.159
/usr/local/bin/ongrid-edge = v0.7.160
writes last_upgrade_at, last_upgrade_ver=v0.7.160
clears healthy_marker
ongrid-edge v0.7.160 runs
v0.7.160 connects, writes healthy_marker=v0.7.160
(reboot, e.g. host updates)
boot 3 (settle):
apply-pending-upgrade.sh
mode 1: last_upgrade_ver=v0.7.160, healthy_marker=v0.7.160 → success
prunes all .previous files
clears last_upgrade_at, last_upgrade_ver
ongrid-edge v0.7.160 runs失败场景:
boot 2 (apply):
apply-pending-upgrade.sh: applies bundle as above
ongrid-edge v0.7.160 crashes immediately (e.g. config drift)
systemd restarts repeatedly per Restart=always
boot 3 (rollback):
apply-pending-upgrade.sh
mode 1: last_upgrade_ver=v0.7.160, healthy_marker missing
→ roll back: restore .previous over each dest
(ongrid-edge.previous → ongrid-edge, etc.)
: > last_upgrade_at, rm -rf incoming/
ongrid-edge v0.7.159 runs again (working)降级
Manager 降级:解压老 tarball,在里面跑 ./upgrade.sh。只要中间的版本没做过 DB schema 迁移就行。降级前查发布说明里的 "breaking schema change" 标注。
Edge 降级:UI 上"升级"到老 bundle 版本。Manager 逻辑不关心版本号往哪个方向走。