155 lines
8.1 KiB
Markdown
155 lines
8.1 KiB
Markdown
# Orbit Compose 部署基线
|
||
|
||
本文给出单节点部署的可重复入口,适合开发、验收和小规模生产前置环境。它把 MySQL、迁移、schema 核验和 Orbit 服务串成一条有明确失败边界的启动链路;生产多节点、数据库高可用、备份恢复和容量门禁仍按[生产验收](05-production-acceptance.md)执行。
|
||
|
||
前置条件:Docker Engine、Docker Compose v2.20 或更高版本;如果使用仓库里的 Nginx 示例,需要 Nginx 1.25.1 或更高版本;正式环境还应具备镜像仓库、Secret 管理器和 HTTPS 反向代理。
|
||
|
||
## 1. 启动契约
|
||
|
||
`deploy/docker-compose.yml` 使用同一个 Orbit 镜像启动 Orbit 相关服务,并使用一个短生命周期的 MySQL 客户端服务收紧运行账号权限:
|
||
|
||
1. `mysql` 先通过 MySQL 8.4 健康检查。
|
||
2. `migrate` 使用迁移账号执行 `orbit-migrate up`。
|
||
3. `grant` 撤销 MySQL 初始化时给运行账号的全库权限,只保留 Orbit 运行所需的 `SELECT`、`INSERT`、`UPDATE`、`DELETE`。
|
||
4. `verify` 使用收紧后的运行账号执行 `orbit-admin verify`。
|
||
5. `orbit` 只有在迁移、权限收紧和核验都成功后才启动,运行账号不承担迁移职责。
|
||
|
||
迁移或核验失败时,Compose 的 `service_completed_successfully` 依赖会阻止 Orbit 进入流量。修复数据库或发布物后,用同一项目重新执行 `docker compose up -d`;不要通过删除迁移记录或手工改表来绕过核验。
|
||
|
||
Compose 文件要求显式提供数据库密码,仓库没有默认密码,也不读取隐式凭据。密码应来自部署平台的 Secret 注入,不应提交到 Git、镜像或日志。
|
||
|
||
## 2. 首次启动
|
||
|
||
先构建不可变镜像。正式发布时应把 `ORBIT_IMAGE` 换成带版本和摘要的镜像地址:
|
||
|
||
```sh
|
||
docker build \
|
||
--build-arg VERSION=1.0.0 \
|
||
--build-arg REVISION="$(git rev-parse HEAD)" \
|
||
--build-arg BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
||
-t orbit:1.0.0 .
|
||
```
|
||
|
||
在当前 shell 或 Secret 管理器中注入配置。以下值仅是变量示例,不是生产密码:
|
||
|
||
```sh
|
||
export ORBIT_IMAGE=orbit:1.0.0
|
||
export ORBIT_DB_NAME=orbit
|
||
export ORBIT_DB_USER=orbit_runtime
|
||
export ORBIT_DB_PASSWORD='从秘密管理器读取'
|
||
export ORBIT_DB_ROOT_PASSWORD='从秘密管理器读取'
|
||
export ORBIT_HTTP_BIND=127.0.0.1
|
||
export ORBIT_HTTP_PORT=8080
|
||
```
|
||
|
||
`ORBIT_DB_NAME` 和 `ORBIT_DB_USER` 仅使用字母、数字和下划线;权限收紧服务会拒绝其他字符。数据库密码由 Secret 管理器注入,建议使用字母、数字和短横线组成的随机值,避免 DSN 转义差异。
|
||
|
||
首次启动先只拉起 MySQL、迁移、权限收紧和核验:
|
||
|
||
```sh
|
||
docker compose -f deploy/docker-compose.yml up -d mysql verify
|
||
docker compose -f deploy/docker-compose.yml ps
|
||
docker compose -f deploy/docker-compose.yml logs --no-log-prefix migrate grant verify
|
||
```
|
||
|
||
`verify` 成功后,使用同一镜像和数据库连接创建初始业务资源与控制台管理员。密码通过标准输入传入,不能写在命令行参数中:
|
||
|
||
```sh
|
||
credential_dir="$(mktemp -d)"
|
||
umask 077
|
||
printf '%s\n' "$ORBIT_CONSOLE_PASSWORD" | \
|
||
docker compose -f deploy/docker-compose.yml run --rm -T --no-deps \
|
||
--entrypoint /usr/local/bin/orbit-admin \
|
||
-e ORBIT_MYSQL_DSN="root:${ORBIT_DB_ROOT_PASSWORD}@tcp(mysql:3306)/${ORBIT_DB_NAME:-orbit}?parseTime=true&multiStatements=true" \
|
||
-v "$credential_dir:/run/orbit" migrate bootstrap \
|
||
--application platform \
|
||
--namespace default \
|
||
--environment production \
|
||
--queue default \
|
||
--worker-access \
|
||
--schedule-access \
|
||
--console-username "$ORBIT_CONSOLE_USERNAME" \
|
||
--console-display-name 'Orbit 管理员' \
|
||
--console-password-stdin \
|
||
--output /run/orbit/credentials.json
|
||
```
|
||
|
||
将 `credentials.json` 按 Secret 文件处理,仅用于保存业务接入凭据;控制台登录使用上面创建的用户名和密码。完成安全保存后再启动服务:
|
||
|
||
```sh
|
||
export ORBIT_CONSOLE_QUEUE_ID="$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1]))["queue_id"])' "$credential_dir/credentials.json")"
|
||
docker compose -f deploy/docker-compose.yml up -d orbit
|
||
curl --fail http://127.0.0.1:"${ORBIT_HTTP_PORT:-8080}"/health/ready
|
||
```
|
||
|
||
如果只需业务 SDK 接入,可以省略控制台管理员;如果要创建多个管理员,使用 `orbit-admin console-user create`,每个账号单独审计和轮换,不共享密码。
|
||
|
||
## 3. 访问和域名
|
||
|
||
Orbit Console 使用当前页面的同源地址调用服务端,浏览器不需要再填写 API URL,也不需要上传凭据 JSON 才能查看控制台。直接访问 `http://主机:端口/console/`,未登录会跳转到 `/console/login`。
|
||
|
||
接入域名时,参考 [`deploy/nginx/orbit.conf.example`](../deploy/nginx/orbit.conf.example),将 HTTPS 反向代理转发到 Orbit 的 `8080` 端口,并保留 WebSocket Upgrade/Connection 头;浏览器访问的域名就是 Console 自动使用的 API 地址。`ORBIT_HTTP_BIND` 控制主机监听地址,`ORBIT_HTTP_PORT` 控制主机映射端口;两者都不是业务域名配置。生产建议保持 `ORBIT_HTTP_BIND=127.0.0.1`,只允许同机 Nginx 访问。TLS 证书、域名和安全头由反向代理或入口网关管理。
|
||
|
||
修改 Nginx 配置后先执行 `nginx -t`,再平滑加载配置;不要在未验证证书、HTTP 到 HTTPS 跳转和 WSS 升级前切换公网流量。Nginx 不应代理 Orbit 的独立 metrics 监听,metrics 只在内部采集网络开放。
|
||
|
||
## 4. 日常操作与失败处理
|
||
|
||
```sh
|
||
# 查看迁移、核验和服务状态
|
||
docker compose -f deploy/docker-compose.yml ps
|
||
|
||
# 读取结构化服务日志
|
||
docker compose -f deploy/docker-compose.yml logs --tail=200 orbit
|
||
|
||
# 发布新镜像:先完成迁移和核验,再启动新服务
|
||
docker compose -f deploy/docker-compose.yml up -d verify
|
||
docker compose -f deploy/docker-compose.yml up -d orbit
|
||
|
||
# 停止服务但保留数据库卷
|
||
docker compose -f deploy/docker-compose.yml down
|
||
```
|
||
|
||
Compose 没有为 scratch 镜像伪造容器内 HTTP healthcheck;编排器或入口网关应调用 `/health/live`、`/health/ready` 和 `/version`。`ready` 返回 `503` 时摘除节点,保留原幂等键并等待数据库恢复。只有明确的废弃环境才使用 `docker compose down -v`,生产数据卷不得随服务停止删除。
|
||
|
||
## 5. 两节点覆盖与滚动替换
|
||
|
||
需要在同一台主机验证多节点接管时,叠加 `deploy/docker-compose.ha.yml`。两个 Orbit 节点共享 MySQL、迁移账本、租约和流程检查点;每个进程仍生成独立节点标识,停止一个节点不会把另一个节点的持久化执行权一并停止:
|
||
|
||
```sh
|
||
export ORBIT_HTTP_BIND=127.0.0.1
|
||
export ORBIT_HTTP_PORT_A=8081
|
||
export ORBIT_HTTP_PORT_B=8082
|
||
|
||
docker compose \
|
||
-f deploy/docker-compose.yml \
|
||
-f deploy/docker-compose.ha.yml \
|
||
up -d mysql verify orbit-a orbit-b
|
||
|
||
curl --fail http://127.0.0.1:8081/health/ready
|
||
curl --fail http://127.0.0.1:8082/health/ready
|
||
```
|
||
|
||
入口层把 Nginx `upstream orbit_backend` 改为两个后端:
|
||
|
||
```nginx
|
||
upstream orbit_backend {
|
||
server 127.0.0.1:8081;
|
||
server 127.0.0.1:8082;
|
||
keepalive 64;
|
||
}
|
||
```
|
||
|
||
滚动替换时先让入口健康检查摘除一个节点,再停止并更新它;确认另一节点 `ready` 后再恢复流量,最后启动更新后的节点并等待两个后端都通过健康检查:
|
||
|
||
```sh
|
||
docker compose -f deploy/docker-compose.yml -f deploy/docker-compose.ha.yml stop orbit-a
|
||
# 更新镜像标签后重新拉起 orbit-a;迁移和 verify 仍必须先成功
|
||
docker compose -f deploy/docker-compose.yml -f deploy/docker-compose.ha.yml up -d orbit-a
|
||
```
|
||
|
||
这个覆盖配置用于单机和隔离验收;生产环境应把两个 Orbit 节点放在不同故障域,前置负载均衡器负责健康摘除,MySQL 由独立数据库高可用方案提供,不把单机 Compose 多节点样本当成生产 HA 结论。
|
||
|
||
## 6. 当前边界
|
||
|
||
该文件是可重复的单节点启动基线,不代表自动数据库故障切换、跨故障域多副本、备份恢复或容量目标已经验收。生产上线还需要真实 MySQL 拓扑、滚动替换、凭据轮换、备份恢复、压测和 RPO/RTO 证据;对应门槛以[交付核对清单](release-checklist.md)为准。
|