feat: add direct PostgreSQL and ACK deployment support
This commit is contained in:
@@ -1,5 +1,80 @@
|
||||
# 智念AIGC平台部署说明
|
||||
|
||||
## 阿里云 ACK + RDS PostgreSQL(生产)
|
||||
|
||||
生产环境设置 `ZHINIAN_DATA_BACKEND=postgres`,并通过 Kubernetes Secret 注入
|
||||
`DATABASE_URL`。优先使用 RDS 内网连接地址;ACK 节点/Pod 与 RDS 必须位于同一
|
||||
或网络可达的 VPC,并在 RDS 白名单或安全组中仅放行实际工作负载网段。
|
||||
|
||||
启用 RDS SSL 后,下载实例对应的 CA,创建 `zhinian-rds-ca` Secret,并将其挂载到
|
||||
`/etc/zhinian/rds/ca.pem`;同时设置 `DATABASE_SSL_MODE=verify-full` 和
|
||||
`DATABASE_CA_CERT_PATH=/etc/zhinian/rds/ca.pem`。不要使用关闭证书校验的配置。
|
||||
|
||||
```bash
|
||||
kubectl -n zhinian create secret generic zhinian-rds-ca \
|
||||
--from-file=ca.pem=./path/to/downloaded-rds-ca.pem
|
||||
kubectl apply -f deploy/ack/configmap.yaml
|
||||
kubectl apply -f deploy/ack/secrets.example.yaml # 仅作模板;先替换全部占位值
|
||||
kubectl apply -f deploy/ack/migration-job.yaml
|
||||
kubectl -n zhinian wait --for=condition=complete job/zhinian-db-migrate --timeout=5m
|
||||
kubectl apply -f deploy/ack/web.yaml -f deploy/ack/worker.yaml \
|
||||
-f deploy/ack/service.yaml -f deploy/ack/ingress.yaml
|
||||
```
|
||||
|
||||
迁移 Job 运行 `node scripts/migrate-postgres.mjs`,读取镜像内
|
||||
`database/migrations/*.sql`。迁移使用独立的 `zhinian-migration-db` Secret,以便
|
||||
授予建表/变更权限;Web 的 `zhinian-web-db` 应只具有应用运行权限。每次发布先运行
|
||||
迁移并确认成功,再滚动 Web。
|
||||
|
||||
首次把已有数据库纳入版本化迁移前必须先做 RDS 快照/逻辑备份,并在维护窗口执行。迁移器
|
||||
遇到重复的历史 `usage_events.job_id` 会安全失败并要求人工审计,不会自动删除计费/用量
|
||||
记录;清理后重新运行同一 Job。
|
||||
|
||||
替换模板占位符后,可先运行 `npm run deploy:check` 做仓库内静态契约检查;真正发布前仍需
|
||||
使用目标 ACK 集群的 `kubectl apply --dry-run=server` 验证 CRD/准入策略和 Ingress 行为。
|
||||
|
||||
ACK 中的 Secret/ConfigMap 才是配置事实来源。不要在 `/settings` 页面修改生产密钥:该
|
||||
页面写入容器内 `.env.local`,Pod 重建会丢失,也不会自动更新 Kubernetes Secret。应修改
|
||||
Secret/ConfigMap 后触发 Deployment 滚动更新。
|
||||
|
||||
模板默认 Web 为 1 副本,因为仅启用 PostgreSQL 并不会共享上传/生成文件。确认这些文件
|
||||
已使用 OSS 或其他共享对象存储后,才可水平扩容;本地 `.runtime` 数据或文件不能在副本
|
||||
之间共享。Worker 只持有内部 token 并调用集群内 `zhinian-web` Service,不持有
|
||||
`DATABASE_URL`。Ingress 通过更长的 `/api/internal/worker` Prefix 把公网请求路由到
|
||||
没有 Endpoint 的 `zhinian-public-deny` Service,因此不会把内部接口转发给 Web;也可以
|
||||
在 API Gateway/WAF 再配置等价拒绝规则。不要默认添加依赖 Terway 或特定 ACK 托管组件
|
||||
的 webhook/白名单注解。
|
||||
|
||||
探针约定:`/api/health` 是不查询数据库的进程存活检查;`/api/ready` 会确认 PostgreSQL
|
||||
关键表存在,并验证应用角色具备任务表读写和两个业务函数的执行权限,失败返回 503。
|
||||
启动探针避免迁移/冷启动期间过早重启。Worker 每次内部 tick 默认 120 秒超时,避免网络
|
||||
半开连接让轮询进程永久卡住;可用 `ZHINIAN_WORKER_REQUEST_TIMEOUT_MS` 调整。
|
||||
|
||||
连接预算按 `Web 副本数 × DATABASE_POOL_MAX` 计算,并为迁移、管理连接和故障切换
|
||||
预留余量。滚动更新默认可能短暂同时存在旧、新 Pod;模板将 `maxSurge` 设为 1,容量
|
||||
预算至少覆盖 `(replicas + 1) × pool max`,否则应降低 pool 或使用 `maxSurge: 0`。
|
||||
|
||||
当前 Docker runner 默认以 Node Alpine 镜像的 root 用户运行,模板没有虚构一个未经
|
||||
镜像验证的 UID。生产加固应在镜像中创建固定非 root 用户、修正 `/app/.runtime` 权限,
|
||||
验证写入与启动后,再把 Pod 设置为 `runAsNonRoot: true`。
|
||||
|
||||
关键数据库变量:
|
||||
|
||||
| 变量 | 说明 |
|
||||
| --- | --- |
|
||||
| `ZHINIAN_DATA_BACKEND` | 生产固定为 `postgres`;配置错误不会降级到本地 JSON |
|
||||
| `DATABASE_URL` | PostgreSQL URI,仅存 Secret;不要写入镜像、ConfigMap 或日志 |
|
||||
| `DATABASE_APP_ROLE` | 迁移 Job 使用;与 Web 的 RDS 用户名一致,用于授予最小应用权限 |
|
||||
| `DATABASE_SSL_MODE` | `disable` 或 `verify-full`;RDS SSL 生产建议 `verify-full` |
|
||||
| `DATABASE_CA_CERT_PATH` | 已挂载 CA 文件路径 |
|
||||
| `DATABASE_POOL_MAX` | 单个 Web Pod 最大连接数 |
|
||||
| `DATABASE_CONNECTION_TIMEOUT_MS` | 建连超时;模板为 5000 ms |
|
||||
| `DATABASE_IDLE_TIMEOUT_MS` | 空闲连接回收时间 |
|
||||
| `DATABASE_STATEMENT_TIMEOUT_MS` | SQL 语句超时 |
|
||||
|
||||
旧 `NEXT_PUBLIC_SUPABASE_URL`、`NEXT_PUBLIC_SUPABASE_ANON_KEY` 和
|
||||
`SUPABASE_SERVICE_ROLE_KEY` 已废弃,直连 PostgreSQL 路径不会读取它们。
|
||||
|
||||
本文面向运维部署。推荐使用 Docker Compose,同一套编排会启动 Web 服务和任务 Worker。
|
||||
|
||||
## 服务器要求
|
||||
@@ -45,8 +120,10 @@ NEXT_PUBLIC_APP_URL=https://你的域名
|
||||
|
||||
ZHINIAN_AUTH_REQUIRED=auto
|
||||
ZHINIAN_AUTH_SESSION_SECRET=请替换为强随机会话密钥
|
||||
NEXT_PUBLIC_SUPABASE_URL=https://你的项目.supabase.co
|
||||
SUPABASE_SERVICE_ROLE_KEY=请替换为服务端密钥
|
||||
ZHINIAN_DATA_BACKEND=postgres
|
||||
DATABASE_URL=postgresql://应用账号:密码@RDS内网地址:5432/数据库名
|
||||
DATABASE_SSL_MODE=verify-full
|
||||
DATABASE_CA_CERT_PATH=/etc/zhinian/rds/ca.pem
|
||||
|
||||
ZHINIAN_API_KEYS=partner-a:请替换为强随机key
|
||||
ZHINIAN_INTERNAL_WORKER_TOKEN=请替换为强随机token
|
||||
@@ -82,7 +159,12 @@ ALI_OSS_PUBLIC_BASE_URL=
|
||||
npm run bootstrap:admin -- --phone 13800138000 --password '请替换为强密码' --name '平台超级管理员'
|
||||
```
|
||||
|
||||
生产部署前请在 Supabase SQL Editor 执行幂等脚本 [`supabase/schema.sql`](../supabase/schema.sql),然后运行一次超级管理员初始化命令。旧账号使用 `npm run migrate:accounts -- path/to/legacy-accounts.json` 导入;迁移会保留用量并把历史素材、任务、项目和模板映射到本地账号。
|
||||
生产部署前设置 `DATABASE_APP_ROLE` 并执行 `npm run db:migrate`,然后运行一次超级管理员
|
||||
初始化命令。迁移器只向该应用角色显式授予当前业务表 DML 和两个数据库函数 EXECUTE;
|
||||
不会授予未来对象的默认权限、`schema_migrations` 或 DDL 权限。新增表/函数时必须随对应
|
||||
版本迁移显式更新授权。旧账号使用
|
||||
`npm run migrate:accounts -- path/to/legacy-accounts.json` 导入;迁移会保留用量并把历史
|
||||
素材、任务、项目和模板映射到平台账号。
|
||||
|
||||
## 旧版组织账号接口(已停用)
|
||||
|
||||
@@ -149,10 +231,10 @@ Docker Compose 会挂载:
|
||||
./.runtime:/app/.runtime
|
||||
```
|
||||
|
||||
本地 JSON 数据层、上传文件和生成结果都会放在 `.runtime/` 下。生产环境如果未启用 Supabase/Postgres,请定期备份该目录。
|
||||
本地 JSON 数据层、上传文件和生成结果都会放在 `.runtime/` 下。`local` 仅适合单实例开发;如临时使用,必须备份该目录。
|
||||
服务端日志也会放在 `.runtime/logs/` 下,建议和运行时数据一起备份或接入服务器日志采集。
|
||||
|
||||
如果生产环境启用了 Supabase/Postgres,发布包含用量和计费管理的版本前,必须在 Supabase SQL Editor 重新执行仓库中的 `supabase/schema.sql`。脚本会幂等升级表结构、补充计费规则的模型变体、来源和参数档位字段、按 `job_id` 去重历史用量,并把计量记录调整为不随生成任务删除。首次打开 `/billing` 或提交真实任务时,系统会自动导入内置标准成本目录;平台参数档案会同步,已有倍率会保留,超级管理员只维护上浮倍率。
|
||||
生产 PostgreSQL 发布前必须执行 `npm run db:migrate`,或先完成 ACK 的 `zhinian-db-migrate` Job。迁移器使用版本记录、校验和、事务和 advisory lock;迁移成功后再滚动 Web。首次打开 `/billing` 或提交真实任务时,系统会自动导入内置标准成本目录;平台参数档案会同步,已有倍率会保留,超级管理员只维护上浮倍率。
|
||||
|
||||
建议备份:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user