Beacon 运维手册
面向部署与运维 Beacon 控制面。
docker-compose形态为单 Beacon 容器加 SQLite 持久卷;生产 MySQL 为自行提供的外置数据库。从零搭建集群见 wiki/build-a-cluster.md。
1. 部署
- 默认直接执行
docker compose up -d;Compose 启动 Beacon 并把 SQLite 数据保存在持久卷中。 - 如需覆盖监听、认证或数据库设置,再按
.env.example设置对应环境变量;不要把 namespace token、口令或数据库凭据提交进仓库。 - 使用生产 MySQL 时,先独立部署并备份数据库,再在 Beacon 配置中提供外置连接信息;不要等待不存在的 Compose MySQL healthcheck,也不会自动预置业务 namespace。
- 管理台与 API 同端口(默认 8848)。
1.1 单二进制免容器首启
直接跑 beacon 二进制时首次启动自动脚手架、开箱即跑:在当前目录释放 config.yml(默认 sqlite、零依赖可跑),释放时把留空的 auth.password / auth.secret 就地填入随机强值(文件 0600),随即直接启动(sqlite 落 beacon.db),无需手工 export 或填值(config.yml 已存在则不覆盖)。不再自动生成 .env——凭据就在 config.yml,避免 .env(优先级更高)静默盖掉你对 config.yml 的改动。上手:
- 运行
beacon→ 直接起服(控制台 WARN 提示已释放config.yml)。 - 打开当前目录
config.yml,取auth.password登录管理台(http://本机IP:8848,用户名auth.username,默认admin);按需改config.yml(切 mysql 改database段、改口令 / 端口 / token 等)后重启即生效。 - 接 Agent:先在管理台创建 namespace 与该 namespace 的接入 token;Agent 最小配置只填控制面 endpoint 列表和这个 token,首次注册后在「服务器 → 待确认」批准身份并分配 serverId/拓扑。不要依赖历史全局 bootstrap token。多台机器请用 §1.3 的批量接入脚本,不要逐台手工重复这套调用。
- 如需经环境变量覆盖(如容器内、CI、临时改口令),真实环境变量与手动放置的
.env仍生效,优先级真实 env > .env > config.yml。 - 管理员口令 / 签名密钥强随机、不入库,不得沿用任何固定弱默认口令;管理台登录与写操作(发布 / 回滚 / 改派 / 文件覆盖 / 命令下发)都要求已认证的操作者身份并随审计留痕,agent 侧共享 token 只用于注册阶段的受信内部调用方判定、不构成数据面安全边界——数据面要求 namespace access token 加已确认身份,身份取自 DB 权威绑定;生产 MySQL 按外置数据库方式部署。
1.2 进程监督与崩溃自启(systemd / docker restart 推荐)
控制面是单进程,进程崩溃自启交外部监督——Beacon 自身不再带常驻监督进程。在线更新的「换版自替换 + 自动回滚」依赖外部监督在崩溃后重新拉起进程来累加重试计数、触发回退(见 §2.2),故生产部署务必启用以下任一监督:
- 容器(推荐):
docker-compose.yml已配restart: unless-stopped,beacon 容器崩溃即由 Docker 自动重启,无需额外配置。 - 裸跑(systemd):用 systemd 托管
beacon,关键是Restart=on-failure+RestartSec,示例:[Unit]Description=Beacon 控制面After=network-online.target[Service]Type=simpleWorkingDirectory=/opt/beaconExecStart=/opt/beacon/beacon -config /opt/beacon/config.ymlRestart=on-failureRestartSec=3s[Install]WantedBy=multi-user.targetsystemctl daemon-reload && systemctl enable --now beacon后即托管;崩溃 3 秒后自动重启。 - 裸跑无任何监督:进程崩溃即停、需手动启动;此时换版后「新版起不来」的自动回退要到下次手动启动才触发(可接受,但不建议生产如此部署)。
1.3 批量接入多台服务器(脚本)
逐台手工接入(建 namespace → 每台写配置 → 启动 → 每台两步批准 → 逐台分 配拓扑)在真机上约需 2×N 次接口调用,机器一多极易漏步。scripts/ops/onboard_servers.sh 把这条链路收敛成一条可重入命令:
# 1) 先干跑:只打印将做什么,不产生任何写操作(安全底线)
./scripts/ops/onboard_servers.sh --manifest .tmp/onboard.manifest --namespace demo \
--admin-password-file <(grep -m1 '^BEACON_ADMIN_PASSWORD=' /opt/beacon/.env | cut -d= -f2-)
# 2) 确认无误再加 --apply 真正执行;重复执行会自动跳过已完成的台
./scripts/ops/onboard_servers.sh --manifest .tmp/onboard.manifest --namespace demo --apply \
--admin-password-file <(grep -m1 '^BEACON_ADMIN_PASSWORD=' /opt/beacon/.env | cut -d= -f2-)
凭据怎么到达 curl:控制面凭据(管理台密码 / 会话 token / API key)只从文件或环境变量读入,再由脚本经 **0600 的 curl 配置文件(-K)**转交——Authorization 头与请求体都不展开进 curl 的 argv。argv 可从 /proc/<pid>/cmdline 读到(权限 444,同机任何用户 ps auxww 都能看到),因此密码、会话 token、API key 一律不得出现在命令行里。配置文件写在 mktemp -d 的 0700 临时目录内、用完即删,异常退出由退出钩子兜底。回归测试用一层包装 curl 记录每次调用的 argv 与配置文件权限来锁定该行为。
清单文件每行一台(# 注释,空白分隔的 key=value):
serverId=onb-bc dir=/srv/mc/onb-bc role=proxy target=bc_cluster:onb-bc1
serverId=onb-lobby dir=/srv/mc/onb-lobby role=backend target=lobby_cluster:5
serverId=onb-game-a dir=/srv/mc/onb-game-a role=backend target=zone:onb-zone1 default-entry
脚本按顺序做四件事,任一步失败都给出可执行的修正指引:
- 预检:控制面可达 / 凭据有效 / namespace 存在,并逐台比对
plugins/BeaconAgent/config.yml(代理为BeaconAgentProxy)里的beacon.endpoints[0]与beacon.bootstrap-token;不一致时直接点名该改哪个文件的哪个字段、现值与应改值(token 只打前 11 位前缀,不落明文)。加了--expect-token-file可与控制面当前 token 精确比对,否则退化为「各台之间必须一致」的弱校验。 - 等 pending:按
serverWorkDir轮询agent-identities直到目标出现pending(--wait超时),已在active的直接跳过。 - 批量批准:逐台
POST /admin/v2/agent-identities/{id}/approve(带serverId)→ 用返回的approvalRequestId调POST /admin/v2/approval-requests/{id}/approve→ 轮询到 identity 真正active(不把202当成功)。 - 批量归属:按端点差异自动选路——大厅成员走
server-placement-transfers(字符串serverId),区 / BC 集群首次分配走server-assignments、改派走server-rezones(两者都用 servers 表数字行 id);每条都要再批准一次,脚本内部消化。已归属到目标的直接跳过。- 改派比首次分配多一步:换区是两段式——批准工单只做「清空全部归属 + 写预填目标 + 把绑定身份重入
pending」,归属要等该身份再次确认时才落地。脚本会在批准工单后自动等身份回到pending、再补一次身份批准(汇总表里标为「重批准」),无需人工介入;首次分配与大厅迁移都在批准工单时立即落位,没有这一步。
- 改派比首次分配多一步:换区是两段式——批准工单只做「清空全部归属 + 写预填目标 + 把绑定身份重入
末尾输出中文汇总表(哪台成功 / 哪台卡在哪一步 / 下一步做什么),退出码 0 全部达成、1 预检失败、2 用法错误、3 运行期有台未达成。
轮换接入 token 是独立的一次性命令,不要和接入流程一起跑(--rotate-token-only):
# 只轮换、不接入;新明文按 0600 落盘。默认仍是 dry-run,加 --apply 才真轮换。
./scripts/ops/onboard_servers.sh --namespace demo --apply \
--rotate-token-only --token-out /root/beacon-demo.token \
--admin-password-file <(grep -m1 '^BEACON_ADMIN_PASSWORD=' /opt/beacon/.env | cut -d= -f2-)
- 爆炸半径:轮换让该 namespace 下所有既有 agent 立刻 401(旧 token 立即失效)。轮换后必须把新明文写入每台的
plugins/BeaconAgent/config.yml(代理为BeaconAgentProxy)的beacon.bootstrap-token、重启(或重载)实例、在管理台确认身份重新active,再跑一次接入流程预检——脚本在真正轮换后会把这三步打在输出里。 - 为什么拆开:旧开关
--rotate-token把「轮换」和「按期望 token 逐台比对配置」塞进同一次执行——轮换一生效,各台配置里仍是旧 token,预检必然报「与期望不一致」并退出,而新明文只在那一次响应里出现、调用方拿不到,结果是域内 agent 全断且不可恢复。该开关现已废弃并直接报用法错误,只保留指向--rotate-token-only的提示。 - 新明文必须有可靠去处:
--token-out <文件>(推荐,0600 落盘,目标已存在则拒绝覆盖,避免静默丢掉上一个 token)或--print-token(只打印一次,明文会进终端回滚缓冲与会话日志,非 必要不用);两者都不给则拒绝执行。落盘失败时脚本会把这次唯一可见的明文打到 stderr,避免「轮换已生效却没人知道新 token」。 - 该子命令不执行接入流程(不拉身份、不批准、不归属),且同样默认 dry-run;
--manifest与它互斥。
边界:拓扑节点(BC 集群 / 大区 / 小区 / 大厅集群)的创建仍属人工规划,脚本只做归属分配;控制面凭据一律走文件或环境变量,并由脚本经 0600 的 curl 配置文件转交,不写在命令行。行为级回归测试:sh scripts/ops/test_onboard_servers.sh(本地伪控制面,覆盖预检报错定位、两步批准、轮询生效、三条归属端点、dry-run 零写请求、重复执行幂等、凭据不进 argv / 0600 配置文件、轮换子命令的落盘与拒绝覆盖)。
2. 升级与发布
- 升级前先备份数据库(SQLite 文件/持久卷或外置 MySQL)与 Agent 本地状态(见 §4)。
- 控制面:拉取已核验的 GA 产品资产,再重启服务;数据库迁移只允许 expand / 可重入回填,回滚不依赖 down migration。
- 升级到 v1 数据面要求身份确认的版本前,必须逐项确认以下前提(否则该 agent 的数据面会全部失败;401 / 403 / 409 只按心跳周期静默重试,归属不符的 404 则会触发重新注册):
- 每个 agent 的
beacon.bootstrap-token必须是其所属命名空间的 access token,不能是历史全局共享agent-token; - 该 agent 的身份在管理台须为
active(pending/disabled/conflict均不放行),且已绑定 serverId; - 同批替换 agent 与控制面:先按本节 1、2 项确认 token 类型与身份状态,再统一升级(下方「控制面与 agent 的产品版本必须一致」同样适用,不要让两侧版本错开)。
失败表现为数据面 401 / 403 / 409 / 404:404 属归属不符(含陈旧 boot),agent 侧把心跳 404 识别为「未注册需重新注册」,日志表现为反复 register,看到该现象应先怀疑 token 类型或身份状态,而不是网络连通性。
注册端点自身的归属不符返回 409
IDENTITY_BINDING_MISMATCH(自报 namespace/serverId 与身份绑定不一致),属配置错误,按本节 1、2 项核对即可。 决策依据见仓库内部的 v1 数据面身份鉴权决策记录(不收录进文档站)。
- 每个 agent 的
- agent:按批替换 Bukkit/Bungee JAR 并重启节点,保留
plugins/Beacon/本地身份、配置快照、流位置与幂等账本。控制面与 agent 的产品版本必须一致。 - 产品资产发布前使用
SHA256SUMS.txt校验;平台是否发布由本次 RC 的实际资产决定,不额外引入阶段专属平台准入。
2.1 开发构建、发布准备与 RC/GA 流程
- PR 只过质量门:pull request 运行现有质量任务,不执行
make package,也不上传可下载产品包。 master临时开发构建:质量任务全部成功后,CI 才运行现有make package并上传短期 Actions Artifact。该 Artifact 仅用于开发验证,不能直接晋级为 RC 或 GA。- 发布准备:发布准备只更新根
VERSION与CHANGELOG.md,版本由根VERSION唯一确定。 - RC:按目标版本创建
vX.Y.Z-rc.N,固定一个 commit 和一次构建出的 GitHub 产品资产;候选发布后不可移动、覆盖或补传。完成候选 Release 后,只向远程 Maven releases 仓库发布beacon-agent-api与beacon-agent-kit的X.Y.Z-rc.N坐标。make release-verify-rc必须从仓库中的真实 RC tag 解析 peeled commit,并与发布流程锁定的 40 位提交身份一致,手工传入任意 SHA 不能替代真实 tag。 - GA:最终 RC 与 GA 必须指向同一 commit。GA 先把最终 RC GitHub 产品资产原样复制到独立目录,再以 RC 下载目录为不可变基准运行
make release-verify-ga;创建前与公开回拉后都逐项比较名称、字节大小和 SHA-256。GitHub 产品资产不得重新编译、打包、重建、重签或替换;资产晋级成功后,GA 只为beacon-agent-api与beacon-agent-kit的不同X.Y.ZMaven 坐标重新生成并发布制品。 - Maven 凭据与失败处理:发布地址及凭据仅由发布流水线的 Secret 注入(
BEACON_PUBLISH_*),仓库内不保存这些值。远程 Maven release 坐标不可覆盖、删除或重传;发布失败时必须让本次发布显式失败,处理前先核验远端坐标状态。 - 在线更新:只自动消费严格
vX.Y.Z的 GA,RC 和开发 Artifact 必须显式安装。
通用校验入口:
# 只校验 VERSION、RC/GA tag 格式和 GA 发布流程;不要求 tag 已存在。
make release-check RELEASE_RC_TAG=v1.0.0-rc.1
# RC tag 必须真实存在,且 peeled commit 必须与锁定身份一致。
make release-verify-rc \
RELEASE_RC_TAG=v1.0.0-rc.1 \
RELEASE_ASSETS_DIR=rc-assets \
RELEASE_RC_COMMIT=<RC_COMMIT>
# RC/GA tag 均须真实存在;GA 目录必须与独立 RC 基准目录逐项一致。
make release-verify-ga \
RELEASE_RC_TAG=v1.0.0-rc.1 \
RELEASE_RC_ASSETS_DIR=rc-assets \
RELEASE_ASSETS_DIR=ga-assets \
RELEASE_RC_COMMIT=<RC_COMMIT> \
RELEASE_GA_COMMIT=<GA_COMMIT>
两个资产目录都必须是封闭集合:除 SHA256SUMS.txt 外只能包含当前版本规定的产品文件,清单必须覆盖每个产品文件且不得校验自身。随后 GA 校验会把 SHA256SUMS.txt 本身也作为 RC/GA 对比项,核对其文件名、字节大小和 SHA-256;因此不能通过同时修改 GA 产品文件及其自带清单来制造一套彼此自洽但已偏离 RC 的资产。