Luma 使用手册#
本文是 Luma 首个公开版本的使用手册。
Luma 以五个核心概念组织功能:
node / region / exposure / egress / service
Luma Control 运行于 Manager,负责登录令牌、节点注册、DNS 同步、jobspec 渲染和 Nomad 部署调用,底层编排器为 HashiCorp Nomad。执行 luma login 后,客户端无需 Docker、SSH、Cloudflare 或 Nomad 凭据即可运行 luma deploy。Tailscale 用于控制面网络及家庭服务的可选中继;Cloudflare 提供 DNS 和可选隧道;Egress Gateway 仅用于拉取镜像、安装依赖和服务访问外网等出站流量。
1. 安装 CLI#
curl -fsSL https://raw.githubusercontent.com/LiuTianjie/luma/main/scripts/install-luma.sh | sh
~/.local/bin/luma preflight
安装程序在 ~/.local/share/luma/venv 创建独立虚拟环境,在 ~/.local/bin/luma 写入命令,并按需将该目录加入 Shell 配置。可立即使用完整路径;简写 luma 需打开新 Shell 或执行 exec $SHELL -l。
安装特定标签:
curl -fsSL https://raw.githubusercontent.com/LiuTianjie/luma/main/scripts/install-luma.sh | LUMA_INSTALL_REF=v0.1.365 sh
从检出目录进行本地开发:
./scripts/install-luma.sh
. .venv/bin/activate
卸载本地 CLI:
curl -fsSL https://raw.githubusercontent.com/LiuTianjie/luma/main/scripts/uninstall-luma.sh | sh
默认保留 ~/.luma.config.json 和 ~/.config/luma。如需一并删除本地配置和登录 context:
curl -fsSL https://raw.githubusercontent.com/LiuTianjie/luma/main/scripts/uninstall-luma.sh | sh -s -- --purge
这不会删除服务器上的 Docker、Nomad、Traefik、Luma Control、应用或 /opt/luma。
没有 python3 时,安装程序会显示 macOS 或 Ubuntu/Debian 的安装命令。客户端 Docker 是可选的,仅用于部署前校验渲染的 jobspec。
有仓库 checkout 时可以把 secret 放进 .env(cp .env.example .env)。只用 curl 安装 CLI 时不必有这个文件:bootstrap 和 luma node join 会询问缺的值。存在 .env 时 Luma 会自动加载;Shell 已导出变量优先,方便 CI 或单次命令覆盖。
2. 配置 luma.yaml#
第一台 manager 不必先写这个文件。luma bootstrap manager --domain luma.example.com 可以直接用 curl 安装的 CLI:缺的 secret 会询问,必要时从控制面域名推断 Cloudflare zone,并在 manager 上写出 /opt/luma/luma.yaml。
以后若要固定节点公网 IP、增加节点或镜像源,再写本地 luma.yaml。它是这些覆盖项的项目配置文件:
project: example
providers:
dns:
type: cloudflare
zone: example.com
zoneId: ""
apiTokenEnv: CLOUDFLARE_API_TOKEN
edgeTarget: 203.0.113.10
recordType: A
ttl: 1
proxied: false
nodes:
manager-1:
host: manager-1
publicIp: 203.0.113.10
region: cn
roles:
- nomad-server
- edge
- egress
defaults:
exposure: cn-edge
registry: ghcr.io/liutianjie
stackRoot: stacks
routesRoot: routes
egressNetwork: egress
entrypoint: websecure
certResolver: letsencrypt
engine: nomad
images:
egressGateway: docker.1panel.live/metacubex/mihomo:latest
直接运行实际需要的命令:
luma bootstrap manager --domain luma.example.com
缺少本地值时,Luma 先提示填写,写入 ~/.luma.config.json 后继续;工作节点执行 luma node join ... 时也如此。.env 和导出变量仍可用于覆盖。存在 CLOUDFLARE_API_TOKEN 而无 providers.dns 时,初始化和 luma update manager 根据 Control 域名推导 Cloudflare zone,在安装 /opt/luma/luma.yaml 前写入提供方配置。没有边缘 DNS 目标时,交互初始化询问 LUMA_DNS_EDGE_TARGET;非交互更新使用已配置边缘节点公网 IP 或已有的该变量。
相关键见密钥与凭据。Manager 常用值:
| 变量 | 用途 |
|---|---|
CLOUDFLARE_API_TOKEN |
创建或更新 Control 与服务 DNS 的 Cloudflare 令牌。 |
LUMA_DNS_EDGE_TARGET |
未配置边缘目标时,DNS 应指向的公网 IP 或域名。 |
TRAEFIK_ACME_EMAIL |
Traefik 申请 HTTPS 证书的 Let's Encrypt 邮箱。 |
EGRESS_SUBSCRIPTION_URL |
可选代理订阅,供镜像拉取和 proxy: true 服务使用。 |
TAILSCALE_AUTHKEY |
私网工作节点、家庭节点或 tailscale-relay 的可选认证密钥。 |
LUMA_SUDO_PASSWORD |
sudo 需要密码时的可选备用值。 |
LUMA_CONTROL_IMAGE |
可选开发或固定版本的 Control API 镜像。 |
不要将密钥提交到 Git。
3. 初始化第一个节点#
对于同时运行 Nomad server、Traefik 和出网代理的公共服务器:
luma bootstrap manager --domain luma.example.com
该操作会:
- 安装 Docker 与 Compose;
- 安装 Tailscale,设置
TAILSCALE_AUTHKEY时自动登录; - 按需安装并启动 Nomad server agent;
- 应用节点
meta(region / luma_node_name / ingress / egress); - 创建
/opt/luma/stacks、/opt/luma/routes、/opt/luma/control、/opt/luma/egress-gateway; - 部署 Traefik;
- 部署 Luma Control;
- 配置含
egress角色时部署出网服务; - 配置 UFW,放行 SSH、80、443、tailnet 上的 Nomad 端口 4646/4647/4648,并禁止 7890 入站。
Manager 需要代理拉取 Control 镜像时,执行含 egress 的配置前先设置 EGRESS_SUBSCRIPTION_URL。中国大陆 Manager 使用默认 GHCR 镜像时不应使用 --skip-egress。初始化实时输出 [start]、[ok]、[fail]。某步失败后,修复再重跑,或运行对应层的定向修复命令。
初始化时跳过了 Tailscale 登录:
luma tailscale connect
出网被跳过或需要修复:
luma egress setup
只有可直连 Control 仓库,或 LUMA_CONTROL_IMAGE / defaults.images.lumaControl 指向可拉取仓库时,才在首次初始化明确跳过出网:
luma bootstrap manager --domain luma.example.com --skip-egress
初始化会输出管理令牌、节点加入令牌和 Dashboard 地址。打开 https://luma.example.com/dashboard/,粘贴管理令牌,然后部署 hello-world 首装验证。该冒烟服务不需要额外 DNS、Tailscale、Registry 或 LAE。
客户端使用管理令牌:
luma login https://luma.example.com --token <management-token>
luma context list
luma deploy templates/hello-world.yml
新增服务器使用节点加入令牌:
luma node join https://luma.example.com --token <node-join-token> --region global --name global-sg-1
加入后 Manager 自动记录区域与 Luma 节点 meta。--name 是服务清单中的节点名,写入 Nomad client meta.luma_node_name 并用于固定调度,避免 OrbStack 的 orbstack 等通用 Docker 主机名冲突。Nomad 身份是稳定 UUID,同名重新加入仍可保持固定服务有效。
--region home 节点必须先连接 Tailscale,才能访问 tailnet 上的 Manager。未连接时,luma node join 会将 TAILSCALE_AUTHKEY 视为必需并在注册前询问。也可先 luma tailscale connect 填写密钥并连接,而不尝试 Nomad 注册。
4. 连接 Cloudflare#
luma cloudflare connect --zone example.com
命令验证令牌、查找 zone 并将 providers.dns.zoneId 写回 luma.yaml。尽量在初始化前执行。如果之后才连接 Cloudflare,应刷新 Manager 配置和 Control 状态;当前权威存储是 /opt/luma/control/control.sqlite3,旧 control.json 仅用于迁移。
cn-edge 服务的 DNS 默认指向已配置边缘节点的公网 IP,可在服务中覆盖:
dns:
target: 203.0.113.10
5. 修复或刷新出网#
luma egress setup
single-node 初始化默认执行此步骤,除非使用 --skip-egress。出网被跳过、失败或订阅需修复时,可直接运行。它下载订阅,提取最小 Mihomo 配置,写入 /opt/luma/egress-gateway/config.yaml,部署 egress_mihomo 并配置 Docker daemon 代理:
HTTP_PROXY=http://127.0.0.1:7890
HTTPS_PROXY=http://127.0.0.1:7890
服务运行时代理按服务显式启用。声明 proxy: true,无需手写出网网络或默认代理变量,除非要覆盖它们:
name: ai-worker
image: ghcr.io/acme/ai-worker:1.0.0
region: cn
exposure: none
proxy: true
env:
OPENAI_BASE_URL: https://api.openai.com/v1
Luma 将代理附加到服务,在对应变量未设置时注入 HTTP_PROXY=http://egress_mihomo:7890 和 HTTPS_PROXY=http://egress_mihomo:7890。调度仍按 region。
后续刷新订阅输出:
luma egress refresh
6. 创建服务#
交互模式:
luma service new
手动清单:
name: app
image: ghcr.io/me/app:latest
region: cn
exposure: cn-edge
domain: app.example.com
port: 3000
replicas: 2
固定到单台机器时,添加 node,使用 luma node join --name 指定的名称:
region: home
node: home-mac-mini
7. 部署#
默认部署流程:
luma deploy app.yaml
应用已有项目 .env 时,可作为应用作用域密钥传入:
luma deploy app.yaml --env .env
Luma 仅导入清单引用的变量,按服务 name 保存,在 Manager 渲染时解析 ${NAME}。不同应用可复用 DATABASE_URL 等名称而不冲突。
清单提交到已登录 Control 端点。Manager 在 /opt/luma 渲染文件、同步 DNS,通过 Nomad HTTP API 创建或更新 job,并探测 cn-edge/external-edge 的公共路由。
luma deploy 输出客户端和 Control 每一步进度。路由经验证、在监视目录外暂存后原子发布。探测 / 时,应用 404 表示已到达应用但可能没有根页面;Traefik 默认 404 page not found 代表缺少 router。路由不健康(缺少 router 或短暂 502/503/504)时,会重建一次 allocation 并复测,再判失败。单服务和 Compose 给冷镜像获取 30 分钟、滚动进度 40 分钟,客户端默认等待 3000 秒。可按需覆盖:
luma deploy app.yaml --timeout 3600
重复部署即更新。同一 name 对应同一 Nomad job(ID 为服务 slug),重跑会重写 jobspec 并更新 job。Nomad 保留上一版,可通过 luma rollback app 或控制台版本页回退。这只回滚运行 job,不改 Git/清单;生产应固定镜像标签或 digest。更改 name 会创建不同 job。
无副作用预览:
luma deploy app.yaml --dry-run
提交到 Control 并在 Manager 渲染/写入文件,但跳过 DNS 同步和 Nomad 部署:
luma deploy app.yaml --skip-dns --skip-orchestrator
按部署名称删除服务或 Compose 应用:
luma service remove app
Control 使用最近成功部署的记录清单,删除公共服务 DNS,注销并清除 Nomad job,删除 /opt/luma/stacks/<region>/<service>/<service>.nomad.json、/opt/luma/stacks/compose/<name>/<name>.nomad.json 等生成文件,以及 tailscale-relay 的 routes/<service>.yml。同一命令支持单服务和 Compose。可先预览或按需保留 DNS:
luma service remove app --dry-run
luma service remove app --skip-dns
8. 入口模式#
cn-edge:
user -> Cloudflare DNS -> CN Traefik -> cn service
适合中国大陆公共服务。
tailscale-relay:
user -> Cloudflare DNS -> CN Traefik -> Tailscale -> home service
适合低频家庭服务,同时提供统一公网域名体验。
cloudflare-tunnel:
user -> Cloudflare -> cloudflared -> service
适合不依赖中国大陆边缘节点的家庭服务。
external-edge:
user -> Cloudflare DNS -> global edge -> global service
适合需要外网访问和公共端点的海外服务。
none:
没有公共入口,适合工作任务和内部服务。
9. 诊断#
luma doctor
每项失败检查都包含具体修复命令或环境变量。
10. 首次真实冒烟测试#
先使用参考节点:
luma doctor
luma bootstrap manager --domain luma.example.com
luma egress setup
luma deploy examples/public-cn-service.yaml
然后检查:
nomad job status
curl -I https://whoami.example.com
仓库开源前,轮换所有曾粘贴到聊天或日志中的令牌与订阅 URL。
11. Build And Deploy From Repository (可插拔)#
默认的 luma deploy 只部署已经构建好的镜像。如果想直接从 GitHub/Gitea 仓库的源码构建并上线,用 luma import:它在集群里的构建节点上 clone 仓库、自动发现 .luma.yml 或 luma.compose.yml 这类部署文件、按 Dockerfile/Compose build: 构建镜像、推送到集群内自托管 registry,再走正常部署链路。这一整套是可插拔的——不用它,集群和现有部署不受任何影响;用它,只需下面这套一次性接入。
接入 SOP(已部署好 Luma 的前提下)#
假设你已经走完上面 1–10 节,集群里 manager 正常、至少有一个 worker 节点、luma login 能用。接入「从 Git 仓库构建部署」分四步:
Step 1 — 选一个构建节点并装好 buildx。 构建在某个 Luma 节点上跑,需要 docker buildx(Linux 节点通常随 Docker 一起就有;跨架构构建还需要 qemu/binfmt)。节点 agent 会自动 advertise docker-build 能力,可以这样确认:
luma node list # 找到要用作构建节点的节点名,例如 build-1
如果该节点没有 buildx,先在节点上安装;装好后 agent 会自动带上 docker-build 能力。
Step 2 — 起一个集群内 registry。 构建出的镜像要有地方存,并让其它区域的节点能拉。一条命令搞定(部署 registry 服务 + 给非 manager 的就绪 Linux 节点配 insecure-registries):
luma registry serve --node build-1
它会把 registry:2 部署到 build-1(默认 5000 端口、节点本地卷、仅 Tailscale 内网可达),并遍历非 manager 的就绪 Linux 节点配置 insecure-registries,让它们能经 Tailscale 内网从这个 registry 拉镜像。BuildKit 推送和目标节点拉取都走 <build-1-tailscale-host>:5000;不要再用 localhost:5000 作为 pushHost(在 BuildKit 容器里那是容器自己)。随后用 luma build config 把 registryHost 和 pushHost 都设成这个 Tailscale 端点。
从 0.1.162 起,CLI 会先完成 Docker daemon 配置、再创建 registry allocation;重复写入相同的 insecure-registries 也不会重启 Docker。这个顺序避免首次启用 registry 时由 Docker 重启打断刚创建的 Nomad CNI 网络。
可选 flag:
--port <n>:registry 监听端口,默认5000。--storage-class <name>:可选的遗留 storageClass;省略时使用节点本地 Docker volume。不要为新 registry 注册 NFS class。--image <ref>:registry 镜像,默认registry:2。--name <svc>:服务名,默认luma-registry。--timeout <seconds>:等待部署响应的秒数,默认1800。
manager 节点会被跳过:Control 跑在 manager 的容器里,重启它的 docker 会杀掉 Control 自己。如果 manager 也要跑从该 registry 拉取的服务,手动在 manager 的
/etc/docker/daemon.json加insecure-registries并重启 docker。
Step 3 —(私有仓库才需要)保存 Git provider token。 公开仓库跳过这步。私有 GitHub/Gitea 仓库:
printf '%s' "$GITEA_TOKEN" | luma git-provider set gitea lin \
--base-url https://gcode.example.com \
--username lin \
--token-stdin
luma git-provider repos gitea:lin
同一个 provider 可以保存多个账户,例如 github:personal、github:work、gitea:lin。Token 只写不回显,构建任务被 builder node-agent lease 时才注入 git clone,不写入部署文件或 agent task state。
Step 4 — 在仓库里放 Luma 部署文件。 单服务用普通 .luma.yml / luma.yml service manifest,并用 build 块代替 image:
name: myapp
region: cn
exposure: cn-edge
domain: myapp.example.com
port: 8080
build:
context: .
dockerfile: Dockerfile
platform: linux/amd64
Compose 仓库用 luma.compose.yml 指向标准 docker-compose.yml。Repository Import 会构建 Compose 里带 build: 的服务,推送到 builder registry,然后把这些服务改写成 image: 再部署:
# luma.compose.yml
name: my-stack
compose: docker-compose.yml
region: cn
services:
web:
exposure: cn-edge
domain: myapp.example.com
port: 8080
支持的 Compose sidecar 文件名包括 luma.compose.yml、.luma.compose.yml、*.luma.compose.yml、*.compose.luma.yml、docker-compose.luma.yml。如果本地 Compose 还只有 build:、没有最终 image:,用 import 模式校验:
luma compose validate --import-mode luma.compose.yml
导入并部署#
luma import https://github.com/acme/myapp --build-node build-1
GitHub 仓库也可以用短写:
luma import acme/myapp --build-node build-1
短写会展开成 https://github.com/acme/myapp.git。Gitea/self-hosted Git 用保存的 provider 账户或完整 clone URL。
使用保存的 Git provider 账户:
luma import --provider-id gitea:lin --repository acme/myapp --build-node build-1 --env .env
CLI 流式回传 clone → build → push → deploy 每一步。命令行可覆盖单服务 .luma.yml:
luma import https://github.com/acme/myapp \
--ref release \
--region cn --exposure cn-edge --domain myapp.example.com --port 8080
如果 Builder 排队或构建较慢,也可以直接用当前电脑的 Docker Buildx 构建:
cd myapp
luma build local . --env .env
这个命令从本地 Git origin 识别项目(没有 origin 时传
--repo-url https://github.com/acme/myapp.git),先向 Control 申请项目构建租约,
再把本地构建结果推到 Luma 内部 registry,最后沿用正常部署链路。镜像仍写入
acme/myapp 这一项目命名空间,不会因为改走本地构建而产生另一套项目。
本机需要能访问 build.registryHost;registry 开启鉴权时,先执行对应的
docker login。单服务与 Compose 都支持,也可以传 --compose-sidecar、
--platform、--context、--dockerfile。
如果本机已有带镜像加速或多架构能力的 Buildx builder,可以传
--builder <名称> 直接复用;本地拉取镜像和 Dockerfile 网络访问需要代理时,
可以传 --proxy <地址>,内部 registry 会自动保留在 NO_PROXY。
本地构建和 Builder 构建都会以实际部署目标为准选择容器架构:固定到
Mac/ARM 节点时构建 linux/arm64,目标区域同时存在 amd64 和 arm64 节点时
构建多架构镜像。显式 --platform 只能用于覆盖全部目标架构,不能把镜像
强制构建成与部署节点不兼容的架构。
Control 支持 build-queue-v1 时,新 CLI 自动使用同项目 FIFO 队列:远程
import / build retry 提交后排队;本地构建可以并行构建和上传,上传完成后
才将部署加入同一队列。顺序按服务端接受排队请求的先后计算,不按本地构建
开始时间计算。同一项目一次执行一个队列任务;不同项目可使用其它执行槽位,
但仍受已有 Builder 容量和运行时部署锁约束。前一个成功、失败或取消后,
后一个继续,不自动覆盖或取消旧任务。
CLI 显示任务 ID、队列位置和等待的任务。--timeout 到期或客户端退出只停止
等待,已接受的任务仍由服务端执行;用 luma build logs <id> 查状态,
luma build cancel <id> 取消尚未开始的任务。排队请求持久化,Control 重启后
保留;正在执行的任务明确标记中断,不自动重放可能已经生效的部署,重试前
先检查运行时。尚未上传完成的本地构建仍依赖调用者电脑。
环境变量按任务独立保存在私有 Control 状态中,不进入公开构建历史,任务结束
后清理队列载荷。旧 Control 仍按原来的活动构建互斥规则处理,需要同时升级
CLI 和 Control 才能使用队列。直接部署预构建镜像的 deploy / compose deploy
继续使用已有同步锁。Control 仍为本地上传分配唯一 tag,并校验镜像属于项目
预留的 registry 路径。
构建节点来自控制面声明的 builder 节点;通常不用传 --build-node,只有需要临时覆盖到另一个已声明 builder 时才传。单服务 import 还可用 --context(build 上下文目录,默认 .)、--dockerfile(默认 Dockerfile)、--registry-host(其它节点拉取用的 registry 主机,默认 <build-node>:5000)覆盖仓库里的 build: 字段。对 Compose import,--region 会覆盖 sidecar 的 region;--exposure、--domain、--port 是单服务覆盖项,会被忽略并打印 warning。Compose 的服务级路由请写在 luma.compose.yml 的 services: 里。luma import 默认等待 3600 秒的 build+deploy 响应,用 --timeout <seconds> 覆盖。
预声明 builder 节点和内部 registry 默认值,之后 import/build 就能省掉 --build-node:
luma build config --node build-1 --default-node build-1 \
--registry-host <build-1-tailscale-host>:5000 \
--push-host <build-1-tailscale-host>:5000
--node 可重复声明多个 builder;--default-node 是 luma import 缺省用的 builder;--registry-host 是 target node 拉镜像的地址,--push-host 是 BuildKit 推镜像的地址。两者都必须是 BuildKit 容器和所有目标节点可达的 Builder Tailscale endpoint;不要使用已移除且在 BuildKit namespace 内含义错误的 localhost:5000。不带参数运行 luma build config 只打印当前配置和各 builder 的就绪/能力表。
构建历史和失败日志用 CLI 查看:luma build list(打印 ID/状态/节点/provider/仓库/ref)、luma build logs <id>(某次构建的分步日志)。修好凭据或配置后 luma build retry <id> 重跑整条 build+deploy;retry 也接受 --env .env 重新提供 scoped secrets、--timeout(默认 3600)。
dashboard 的「创建应用」页顶部也有「仓库导入」入口:选择 Git provider、账户、仓库和 ref;或手填 URL。进度实时显示。
CN 节点的
git clone会自动走 manager 的 egress 网关(http://<manager-host>:7890),和镜像拉取、节点 join 用的是同一个出口;global节点直连不走代理。代理出口由控制面的 egress 配置决定,无需在luma import上单独指定。
升级已部署的应用#
升级 = 改完代码、推到 GitHub,再跑一次同样的 luma import。
luma import https://github.com/acme/myapp --build-node build-1
原理:每次构建按 git commit 打 tag(<registry>:5000/acme/myapp:<git-sha>),注入 manifest 的是这个不可变的 sha 标签;而 Nomad job id 来自 .luma.yml 的 name。所以同名 + 新 SHA = 对同一个 Nomad job 做滚动更新,旧版本自动保留。这和普通 luma deploy 的「同名即更新」是同一条链路。
升级特定分支/Tag:
luma import https://github.com/acme/myapp --build-node build-1 --ref v2.1.0
要点:
- 镜像钉死在 git SHA,不是
:latest,所以两次构建之间即使 registry 里:latest变了,已部署的旧版本也不会漂移。 name不变才是升级;改了.luma.yml里的name会创建一个新应用,而不是升级旧的。- 改了
domain/region/port等也通过重跑 import 生效(或用对应 CLI flag 覆盖)。
回滚#
因为每个历史版本的 jobspec 钉的是各自的 :<git-sha>,registry 默认不回收旧镜像,所以回滚拉得回原镜像字节:
luma history myapp # 看版本列表
luma rollback myapp # 回到上一个版本
luma rollback myapp --to-version <N>
dashboard 的 Applications → Versions 也能做同样的回滚。注意这是 Nomad job 版本回退(拉回那个版本钉的镜像),不会改 Git、不会回滚数据库迁移或卷数据。
跨架构注意#
构建节点是 arm64(比如 Mac mini)而目标运行节点是 amd64 时,必须让构建产出 linux/amd64。.luma.yml 的 build.platform 默认就是 linux/amd64,但构建节点要装好 qemu/binfmt 才能跨架构构建。
取消接入#
不想再用时,删掉 registry 服务即可(luma service remove luma-registry),已经在跑的服务不受影响。insecure-registries 配置留在各节点的 docker daemon 里是无害的。
12. 通过 Dashboard 升级 Luma#
日常升级不需要 SSH manager,也不需要在每台节点运行命令。使用管理 Token 登录 https://<control-domain>/dashboard/fleet,在「升级中心」完成整条流程:
- 填写不可变 release tag(例如
v0.1.175)。标准 tag 会自动建议同 tag 的 Control 镜像;自定义分支或 commit 需要明确填写已发布镜像。 - 点击「检查全部公网路由」保存升级前基线。HTTP 成功、重定向和鉴权拒绝都能证明路由已发布;404、网关错误和连接失败会明确标红,但不会悄悄阻断管理员操作。
- 第一次点击「升级 Control」会展示影响和基线结果,第二次确认后,Builder 先通过受管出网代理把外部 Control 镜像缓存到内部 registry 并校验 digest。该任务可恢复、有明确进度,避免 manager 的 Docker daemon 在替换窗口直接依赖 GHCR。
- 内网镜像就绪后才启动 Control 更新。更新运行在独立 systemd 单元中,不会因 node agent 自身重启而被中断。
- Control 替换期间页面自动重连。完成后自动重新检查全部公网路由,并展示有界日志;无需手动重启应用。
- 点击「更新未对齐节点」。操作会只选择版本落后的非 manager 节点,并持久化逐节点状态。安装完成后,节点必须以目标版本重新心跳,才会显示成功。
- 失败或中断的镜像准备、Control 或节点任务都会保留原因,可在同一页面重试。关闭页面、刷新浏览器或 Control 重启都不会丢失操作结果。
首次接入一个早于托管更新能力的历史 agent 时,Dashboard 会明确显示缺失的 capability;只需对该历史节点做一次 CLI 更新。之后的发布均可在升级中心完成。
13. 应用级可观测(luma-observe)#
Dashboard 里的 CPU/内存是节点样本,不是应用是否可用。HTTP 5xx、延迟、Nomad 失败/重启和节点水位走独立的 observe/ 栈,和 Traefik/Control 同机、只绑 loopback。部署该栈后 Control 会把它钉到 manager、把 Grafana 挂到控制面域名的 /grafana,告警规则里会出现 p95 / 5xx / 失败 alloc 预设。详见 Observability。