refactor: serve static frontend with Go APIs
This commit is contained in:
@@ -1,333 +1,156 @@
|
||||
# 智念AIGC平台部署说明
|
||||
|
||||
## 阿里云 ACK + RDS PostgreSQL(生产)
|
||||
## 生产拓扑
|
||||
|
||||
生产环境设置 `ZHINIAN_DATA_BACKEND=postgres`,并通过 Kubernetes Secret 注入
|
||||
`DATABASE_URL`。优先使用 RDS 内网连接地址;ACK 节点/Pod 与 RDS 必须位于同一
|
||||
或网络可达的 VPC,并在 RDS 白名单或安全组中仅放行实际工作负载网段。
|
||||
生产环境只有两类运行时:
|
||||
|
||||
数据库连接只配置一个 `DATABASE_URL`。默认按 `sslmode=verify-full` 建立 TLS 连接;如果
|
||||
容器内没有 RDS CA 根证书,请把 CA 路径直接写进连接串,例如:
|
||||
`...?sslmode=verify-full&sslrootcert=/etc/zhinian/rds/ca.pem`,并按需挂载 CA 文件。
|
||||
不再设置 `DATABASE_SSL_MODE` 或 `DATABASE_CA_CERT_PATH`。
|
||||
- `zhinian-web`:Nginx 静态容器,只包含 Next.js `out/` 导出结果,不读取 Secret、
|
||||
ConfigMap、数据库或 Go 内网地址。
|
||||
- `zhinian-go-api`:唯一应用后端,负责 `/api`、`/uploads`、
|
||||
`/generated-results`、登录会话、权限、数据库、供应商调用及内嵌 WorkerLoop。
|
||||
|
||||
```bash
|
||||
kubectl apply -f deploy/ack/configmap.yaml
|
||||
kubectl apply -f deploy/ack/secrets.example.yaml # 仅作模板;先替换全部占位值
|
||||
kubectl apply -f deploy/ack/web.yaml -f deploy/ack/go-api.yaml \
|
||||
-f deploy/ack/service.yaml -f deploy/ack/ingress.yaml
|
||||
```
|
||||
浏览器始终请求同一个公网域名。Ingress 将后端路径转发给 Go,其余页面和静态资源转发给
|
||||
Web。登录 Cookie 为 HttpOnly Cookie,由浏览器自动随同域 API 请求携带;静态 Web
|
||||
不解析 Cookie,也不持有会话签名密钥。
|
||||
|
||||
生产拓扑为 ADR-003 双工作负载:Next.js 只服务页面/静态资源/SSR(不持有任何
|
||||
RDS/服务商凭据,仅共享会话密钥);Go 工作负载 `zhinian-go-api` 独占
|
||||
`/api`、`/uploads`、`/generated-results`,内嵌 WorkerLoop(生产**不部署**
|
||||
Node Worker,`worker.yaml` 已弃用保留)。Ingress 按路径分流:页面 → Web,
|
||||
后端路径 → Go,`/api/internal/worker` → 无端点 deny Service。
|
||||
|
||||
Next.js 的生产 SSR 通过 Web runtime ConfigMap 中的
|
||||
`ZHINIAN_GO_INTERNAL_BASE_URL=http://zhinian-go-api:8080` 访问集群内 Go
|
||||
Service。该变量只供 Next 服务端 SSR 使用,不是公开访问地址,不应放入
|
||||
`NEXT_PUBLIC_*` 或暴露给浏览器;公网请求仍通过 Ingress 的公开域名进入。
|
||||
|
||||
Go 镜像构建(四选一,详见 [`backend/README.md`](./backend/README.md)):
|
||||
|
||||
```bash
|
||||
# 自包含构建(推荐国内 CI):单条命令,只拉 alpine 基础镜像,Go 工具链来自
|
||||
# alpine 包(阿里云 apk 镜像),模块走 goproxy.cn
|
||||
docker build -f backend/Dockerfile.alpine -t REGISTRY/PROJECT/zhinian-go-api:TAG backend/
|
||||
|
||||
# 标准多阶段构建
|
||||
docker build -f backend/Dockerfile -t REGISTRY/PROJECT/zhinian-go-api:TAG backend/
|
||||
|
||||
# 镜像加速器无法拉取 golang 镜像时,用 --build-arg 换源
|
||||
docker build -f backend/Dockerfile \
|
||||
--build-arg GOLANG_IMAGE=<可用镜像源>/golang:1.21-alpine \
|
||||
--build-arg RUNTIME_IMAGE=<可用镜像源>/alpine:3.20 \
|
||||
-t REGISTRY/PROJECT/zhinian-go-api:TAG backend/
|
||||
|
||||
# 完全绕开 golang 镜像:先在任意有 Go 1.21 的机器编译静态二进制,再只基于 alpine 组装
|
||||
cd backend
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
|
||||
go build -trimpath -ldflags="-s -w" -o zhinian-api.linux ./cmd/zhinian-api
|
||||
docker build -f backend/Dockerfile.runtime -t REGISTRY/PROJECT/zhinian-go-api:TAG backend/
|
||||
```
|
||||
|
||||
Go 首次启动时从 `zhinian-go-bootstrap` Secret 读取
|
||||
`ZHINIAN_BOOTSTRAP_ADMIN_*`,仅当不存在任何超级管理员时创建一次。
|
||||
|
||||
数据库 schema 由部署负责人在发布前手工执行,**不部署迁移 Job Pod**(清单
|
||||
`deploy/ack/migration-job.yaml` 已弃用保留):使用迁移角色账号依次执行
|
||||
`database/migrations/0001_initial_schema.sql`、`0002_generation_lifecycle_fencing.sql`,
|
||||
再执行应用角色授权语句(表权限 + 两个并发函数 `claim_generation_jobs` 与
|
||||
`billing_post_wallet_entry` 的 EXECUTE 权限,参见
|
||||
`scripts/migrate-postgres.mjs` 中的 `provisionApplicationRole`)。Web/Go 的数据库
|
||||
账号应只具有应用运行权限。以后每次 schema 变更同样按版本化 SQL 文件手工执行,并在
|
||||
变更后再滚动工作负载。
|
||||
|
||||
迁移 SQL 包含重复数据保护:遇到重复的历史 `usage_events.job_id` 会失败并要求人工
|
||||
审计,不会自动删除计费/用量记录;清理后重新执行对应文件。
|
||||
|
||||
替换模板占位符后,可先运行 `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` | 应用角色名;手工执行授权语句时使用,与 Web/Go 的 RDS 用户名一致 |
|
||||
| `DATABASE_URL` 的 `sslmode` / `sslrootcert` | 可在同一个连接串中指定 TLS 模式和 CA 路径;默认 `sslmode=verify-full` |
|
||||
| `DATABASE_POOL_MAX` | 单个 Web Pod 最大连接数 |
|
||||
| `DATABASE_CONNECTION_TIMEOUT_MS` | 建连超时;模板为 5000 ms |
|
||||
| `DATABASE_IDLE_TIMEOUT_MS` | 空闲连接回收时间 |
|
||||
| `DATABASE_STATEMENT_TIMEOUT_MS` | SQL 语句超时 |
|
||||
| `/api/internal/worker` | selectorless deny Service,不对公网开放 |
|
||||
| `/api/*` | `zhinian-go-api:8080` |
|
||||
| `/uploads/*` | `zhinian-go-api:8080` |
|
||||
| `/generated-results/*` | `zhinian-go-api:8080` |
|
||||
| 其他路径 | `zhinian-web:3000` |
|
||||
|
||||
旧 `NEXT_PUBLIC_SUPABASE_URL`、`NEXT_PUBLIC_SUPABASE_ANON_KEY` 和
|
||||
`SUPABASE_SERVICE_ROLE_KEY` 已废弃,直连 PostgreSQL 路径不会读取它们。
|
||||
Web Nginx 对 Go 所有的三类路径也会直接返回 404,避免绕过 Ingress 后形成第二套 API
|
||||
边界。
|
||||
|
||||
本文面向运维部署。推荐使用 Docker Compose,同一套编排会启动 Web 服务和任务 Worker。
|
||||
## 构建镜像
|
||||
|
||||
## 服务器要求
|
||||
|
||||
- Linux 服务器
|
||||
- Docker
|
||||
- Docker Compose v2(`docker compose`)或旧版 `docker-compose`
|
||||
- 可访问外网供应商接口:火山 Visual、EvoLink、Seedance、OSS
|
||||
|
||||
## 一键部署
|
||||
Web 镜像在 builder 阶段执行静态导出,runner 只保留非 root Nginx 和 `out/`:
|
||||
|
||||
```bash
|
||||
git clone <仓库地址>
|
||||
cd NianAIGC
|
||||
bash scripts/deploy.sh
|
||||
docker build -t REGISTRY/PROJECT/zhinian-aigc:TAG .
|
||||
```
|
||||
|
||||
脚本会自动:
|
||||
|
||||
- 从 `.env.example` 创建 `.env.local`(如果不存在)
|
||||
- 创建 `.runtime/data`、`.runtime/uploads`、`.runtime/generated-results`
|
||||
- 创建 `.runtime/logs`
|
||||
- 构建镜像
|
||||
- 启动 `zhinian-aigc` Web 服务
|
||||
- 启动 `zhinian-worker` 任务 Worker
|
||||
- 输出容器状态
|
||||
|
||||
默认访问:
|
||||
|
||||
```text
|
||||
http://服务器IP:3000
|
||||
```
|
||||
|
||||
## 必填生产配置
|
||||
|
||||
部署前编辑 `.env.local`:
|
||||
|
||||
```env
|
||||
APP_PORT=3000
|
||||
PORT=3000
|
||||
HOSTNAME=0.0.0.0
|
||||
NEXT_PUBLIC_APP_URL=https://你的域名
|
||||
|
||||
ZHINIAN_AUTH_REQUIRED=auto
|
||||
ZHINIAN_AUTH_SESSION_SECRET=请替换为强随机会话密钥
|
||||
ZHINIAN_DATA_BACKEND=postgres
|
||||
DATABASE_URL=postgresql://应用账号:密码@RDS内网地址:5432/数据库名
|
||||
# 可选:把 sslmode/sslrootcert 直接写入 DATABASE_URL
|
||||
|
||||
ZHINIAN_API_KEYS=partner-a:请替换为强随机key
|
||||
ZHINIAN_INTERNAL_WORKER_TOKEN=请替换为强随机token
|
||||
ZHINIAN_WEBHOOK_SECRET=请替换为webhook签名密钥
|
||||
```
|
||||
|
||||
`ZHINIAN_API_KEYS` 冒号前是开放 API 账号 ID。不同账号 ID 的任务、素材和幂等键会写入不同 owner 分区,例如 `api:partner-a`。
|
||||
|
||||
真实生成能力按需配置:
|
||||
|
||||
```env
|
||||
IMAGE_GENERATE_ENGINE=evolink
|
||||
|
||||
EVOLINK_API_KEY=
|
||||
|
||||
VOLCENGINE_ACCESS_KEY_ID=
|
||||
VOLCENGINE_SECRET_ACCESS_KEY=
|
||||
|
||||
SEEDANCE_API_KEY=
|
||||
|
||||
ALI_OSS_ENDPOINT=
|
||||
ALI_OSS_BUCKET=
|
||||
ALI_OSS_ACCESS_KEY_ID=
|
||||
ALI_OSS_ACCESS_KEY_SECRET=
|
||||
ALI_OSS_PUBLIC_BASE_URL=
|
||||
```
|
||||
|
||||
如果不配置真实供应商密钥,mock 配置会保留本地验收能力,但生产对接应配置真实密钥。
|
||||
|
||||
平台账号部署说明:
|
||||
|
||||
```text
|
||||
npm run bootstrap:admin -- --phone 13800138000 --password '请替换为强密码' --name '平台超级管理员'
|
||||
```
|
||||
|
||||
生产部署前先手工执行版本化 SQL 完成建库建表与授权(见上文"手工建库建表"步骤),然后
|
||||
通过环境变量初始化超级管理员:Go 后端首次启动时读取
|
||||
`ZHINIAN_BOOTSTRAP_ADMIN_PHONE` / `ZHINIAN_BOOTSTRAP_ADMIN_PASSWORD` /
|
||||
`ZHINIAN_BOOTSTRAP_ADMIN_NAME`(密码至少 8 位,名称缺省为"平台超级管理员"),仅在
|
||||
不存在任何超级管理员时创建一次,无需单独脚本。旧的 `npm run bootstrap:admin` 脚本
|
||||
仅为本地/Next 开发保留。授权只向应用角色显式授予当前业务表 DML 和两个数据库函数
|
||||
EXECUTE;不会授予未来对象的默认权限、`schema_migrations` 或 DDL 权限。新增表/函数时
|
||||
必须随对应版本 SQL 显式更新授权。旧账号导入脚本 `npm run migrate:accounts` 仅为历史
|
||||
遗留工具保留,新部署无需使用。
|
||||
|
||||
## 旧版组织账号接口(已停用)
|
||||
|
||||
如需启用 `/accounts` 后台账号管理,按组织能力接口文档配置:
|
||||
|
||||
```env
|
||||
ZHINIAN_ORG_API_BASE_URL=https://<gateway-domain>/hotelStaff
|
||||
ZHINIAN_ORG_API_TOKEN=
|
||||
ZHINIAN_STAFF_API_BASE_URL=https://<gateway-domain>/hotelStaff
|
||||
ZHINIAN_STAFF_API_TOKEN=
|
||||
ZHINIAN_ORG_TENANT_ID=
|
||||
ZHINIAN_ORG_ID=
|
||||
ZHINIAN_ORG_MEMBER_LIST_PATH=
|
||||
```
|
||||
|
||||
平台后端会代理调用组织、部门、角色、成员和企业端用户接口;成员分页列表默认通过 `hotelStaff` 的 `/adminOrganization/organizationMember/organizationMemberList` 对外代理,只有直连基础组织服务内部 `/organizationMember/organizationMemberList` 时才需要 `from: Y`。如统一服务路径不同,可配置 `ZHINIAN_ORG_MEMBER_LIST_PATH` 覆盖。创建账号调用 `/adminOrganization/organizationMember/addOrganizationMemberAndCreatePlatformUser`,重置密码调用 `/adminPcUser/resetPlatformUserPassword`。这些接口默认转发当前登录管理员账号的 `access_token`,企业端用户接口会校验该 token 是否具备管理员角色 `1`;`ZHINIAN_ORG_API_TOKEN` / `ZHINIAN_STAFF_API_TOKEN` 只作为无登录 token 时的服务端兜底。
|
||||
|
||||
## 常用运维命令
|
||||
Go 镜像构建方式见 [`backend/README.md`](../backend/README.md)。国内 CI 可使用:
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
docker compose logs -f zhinian-aigc
|
||||
docker compose logs -f zhinian-worker
|
||||
docker compose restart
|
||||
docker compose down
|
||||
docker build -f backend/Dockerfile.alpine \
|
||||
-t REGISTRY/PROJECT/zhinian-go-api:TAG backend/
|
||||
```
|
||||
|
||||
Web 后台可在登录后访问:
|
||||
发布前把 `deploy/ack/web.yaml` 和 `deploy/ack/go-api.yaml` 中的镜像占位符替换为
|
||||
不可变标签或 digest。
|
||||
|
||||
```text
|
||||
https://你的域名/logs
|
||||
https://你的域名/settings
|
||||
https://你的域名/accounts
|
||||
https://你的域名/usage
|
||||
https://你的域名/billing
|
||||
```
|
||||
## RDS 与首次初始化
|
||||
|
||||
日志默认写入 `.runtime/logs/server-events.jsonl`,用于查看 API 500 错误、Worker 任务异常、错误栈和请求路径。可通过环境变量 `ZHINIAN_LOG_DIR` 调整目录,通过 `ZHINIAN_LOG_MAX_BYTES` 调整单文件轮转大小。
|
||||
生产固定使用 PostgreSQL。数据库连接只通过 Go Deployment 的 Secret 注入,不得进入
|
||||
Web 镜像或 ConfigMap。优先使用 RDS 内网地址,并仅对白名单中的 ACK 工作负载网段放行。
|
||||
|
||||
更新部署:
|
||||
`DATABASE_URL` 应包含完整 TLS 参数。默认建议 `sslmode=verify-full`;需要自定义 CA 时,
|
||||
把 `sslrootcert=/etc/zhinian/rds/ca.pem` 写入同一个连接串并挂载对应 Secret。
|
||||
|
||||
首次发布前,部署负责人按顺序手工执行:
|
||||
|
||||
1. `database/migrations/0001_initial_schema.sql`
|
||||
2. `database/migrations/0002_generation_lifecycle_fencing.sql`
|
||||
3. 应用角色授权语句(参考 `scripts/migrate-postgres.mjs`)
|
||||
|
||||
生产不部署迁移 Job。遇到历史重复数据时迁移会失败,需先人工审计,不能跳过或自动删除
|
||||
计费与用量记录。仓库不再提供可误执行的 Node Migration Job 或 Node Worker 清单;后台
|
||||
任务由 Go API 内嵌 WorkerLoop 处理。
|
||||
|
||||
Go 首次启动会读取 `zhinian-go-bootstrap` Secret 中的
|
||||
`ZHINIAN_BOOTSTRAP_ADMIN_PHONE` 和 `ZHINIAN_BOOTSTRAP_ADMIN_PASSWORD`,仅在不存在
|
||||
超级管理员时创建一次。当前 ACK 清单不注入 `ZHINIAN_BOOTSTRAP_ADMIN_NAME`,因此名称
|
||||
使用 Go 的默认值“平台超级管理员”。
|
||||
|
||||
## ACK 配置与发布
|
||||
|
||||
先根据 [`deploy/ack/secrets.example.yaml`](../deploy/ack/secrets.example.yaml) 创建不提交
|
||||
Git 的 `deploy/ack/secrets.production.yaml`,替换所有占位值。Web 不需要任何运行时
|
||||
Secret;会话密钥只属于 Go。
|
||||
|
||||
仓库内静态检查:
|
||||
|
||||
```bash
|
||||
git pull
|
||||
bash scripts/deploy.sh
|
||||
npm run deploy:check
|
||||
```
|
||||
|
||||
健康检查:
|
||||
提交到集群前还应使用目标集群验证准入策略:
|
||||
|
||||
```bash
|
||||
curl -f http://127.0.0.1:${APP_PORT:-3000}/api/health
|
||||
# 首次部署必须先真实创建 Namespace;否则后续 namespaced Secret/资源无法 dry-run。
|
||||
kubectl apply -f deploy/ack/namespace.yaml
|
||||
|
||||
kubectl apply --dry-run=server -f deploy/ack/secrets.production.yaml
|
||||
kubectl apply --dry-run=server -f deploy/ack/configmap.yaml
|
||||
kubectl apply --dry-run=server -f deploy/ack/go-api.yaml
|
||||
kubectl apply --dry-run=server -f deploy/ack/web.yaml
|
||||
kubectl apply --dry-run=server -f deploy/ack/service.yaml
|
||||
kubectl apply --dry-run=server -f deploy/ack/ingress.yaml
|
||||
```
|
||||
|
||||
OpenAPI:
|
||||
确认无误后发布:
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:${APP_PORT:-3000}/api/v1/openapi.json
|
||||
# Namespace 已在上一步单独创建;Secret 必须先于引用它的工作负载发布。
|
||||
kubectl apply -f deploy/ack/secrets.production.yaml
|
||||
kubectl apply -f deploy/ack/configmap.yaml
|
||||
kubectl apply -f deploy/ack/go-api.yaml
|
||||
kubectl apply -f deploy/ack/web.yaml
|
||||
kubectl apply -f deploy/ack/service.yaml
|
||||
kubectl apply -f deploy/ack/ingress.yaml
|
||||
```
|
||||
|
||||
## 数据持久化
|
||||
Web 使用固定 UID/GID `101`、只读根文件系统和 `/tmp` 临时卷,监听容器端口
|
||||
`3000`。它是无状态静态服务,可以独立扩容。Go 模板默认一个副本;未接入 OSS 或其他
|
||||
共享对象存储前,不要扩容 Go,否则上传及生成文件不能在副本间共享。此时文件位于 Go
|
||||
Pod 的 `emptyDir`,Pod 重建或滚动升级同样会永久丢失上传文件和生成结果;生产持久化这些
|
||||
文件必须先接入 OSS 或其他共享对象存储。
|
||||
|
||||
Docker Compose 会挂载:
|
||||
## 配置边界
|
||||
|
||||
```text
|
||||
./.runtime:/app/.runtime
|
||||
```
|
||||
`zhinian-go-runtime` ConfigMap 只保存非敏感 Go 运行参数。下列敏感值必须放在
|
||||
Kubernetes Secret:
|
||||
|
||||
本地 JSON 数据层、上传文件和生成结果都会放在 `.runtime/` 下。`local` 仅适合单实例开发;如临时使用,必须备份该目录。
|
||||
服务端日志也会放在 `.runtime/logs/` 下,建议和运行时数据一起备份或接入服务器日志采集。
|
||||
- `DATABASE_URL`
|
||||
- `ZHINIAN_AUTH_SESSION_SECRET`(Secret 名 `zhinian-go-auth`,仅注入 Go)
|
||||
- `ZHINIAN_BOOTSTRAP_ADMIN_PHONE`、`ZHINIAN_BOOTSTRAP_ADMIN_PASSWORD`
|
||||
- 服务商与 OSS 凭据
|
||||
- 开放 API Key、Webhook 签名密钥等
|
||||
|
||||
生产 PostgreSQL 发布前必须按顺序手工执行版本化 SQL 文件(0001 再 0002)与角色授权;不部署 `zhinian-db-migrate` Job。执行完成后再滚动工作负载。首次打开 `/billing` 或提交真实任务时,系统会自动导入内置标准成本目录;平台参数档案会同步,已有倍率会保留,超级管理员只维护上浮倍率。
|
||||
生产配置的事实来源是 ACK Secret/ConfigMap。不要通过静态页面或修改 Pod 文件来更新
|
||||
生产密钥;修改 Secret/ConfigMap 后滚动 Go Deployment。
|
||||
|
||||
建议备份:
|
||||
## 探针与验收
|
||||
|
||||
- Web `/healthz`:Nginx 静态进程存活检查。
|
||||
- Go `/api/health`:Go 进程存活检查,不查询数据库。
|
||||
- Go `/api/ready`:检查 PostgreSQL schema、表权限和业务函数权限。
|
||||
|
||||
发布后执行:
|
||||
|
||||
```bash
|
||||
tar -czf zhinian-runtime-$(date +%Y%m%d%H%M%S).tar.gz .runtime
|
||||
```
|
||||
kubectl rollout status deployment/zhinian-go-api -n zhinian
|
||||
kubectl rollout status deployment/zhinian-web -n zhinian
|
||||
|
||||
## 服务组成
|
||||
|
||||
- `zhinian-aigc`:Next.js Web/API 服务,默认容器端口 `3000`
|
||||
- `zhinian-worker`:后台任务 Worker,负责提交供应商任务、轮询结果、导入资产和触发 Webhook
|
||||
|
||||
注意:只启动 Web 服务时,任务会停留在 `queued` 或 `running`,必须同时运行 Worker。
|
||||
|
||||
## 反向代理建议
|
||||
|
||||
Nginx 示例:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name your-domain.com;
|
||||
|
||||
client_max_body_size 100m;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
配置反向代理后,将 `.env.local` 里的 `NEXT_PUBLIC_APP_URL` 设置成公网 HTTPS 地址。
|
||||
|
||||
## 验收清单
|
||||
|
||||
部署后执行:
|
||||
|
||||
```bash
|
||||
curl -f https://你的域名/
|
||||
curl -f https://你的域名/api/health
|
||||
curl -H "Authorization: Bearer <API_KEY>" https://你的域名/api/v1/capabilities
|
||||
curl -f https://你的域名/api/ready
|
||||
curl https://你的域名/api/v1/openapi.json
|
||||
```
|
||||
|
||||
确认:
|
||||
还应验证:
|
||||
|
||||
- 未登录访问 Web 页面会跳转到 `/auth/login`
|
||||
- 普通用户登录后看到创作、账号和计费;账号页可修改自己的密码,任务详情、输入要素和结果下载均在创作页右侧任务模块完成,点击页头账号 ID 可查看自己的快捷周期用量
|
||||
- 从管理员入口登录且命中管理员账号或专用角色白名单后,可访问 `/logs`、`/settings`、`/usage`,并在 `/accounts` 额外维护组织和成员;超级管理员还可配置 `/billing` 计费规则和组织余额
|
||||
- `/usage` 可按日期、组织、账号、功能和服务商筛选,Mock 与开放 API 任务不计入
|
||||
- `/billing` 可查看组织余额、成员消耗和账务流水;管理员通过“余额与上账”直接记入组织额度
|
||||
- `/api/health` 返回 `ok: true`
|
||||
- `/logs` 可查看后台错误日志
|
||||
- `/api/v1/capabilities` 使用 API Key 可访问
|
||||
- `zhinian-worker` 日志持续输出 `claimed=...`
|
||||
- OSS、EvoLink、火山、Seedance 密钥按业务需要配置完成
|
||||
- 未登录访问受保护页面后,浏览器跳转到 `/auth/login`。
|
||||
- 登录成功后,`GET /api/auth/me` 返回当前用户,刷新页面仍保持登录态。
|
||||
- 普通用户无法访问管理员 API;管理员页面与 API 权限一致。
|
||||
- 上传、生成结果访问分别通过 `/uploads`、`/generated-results` 命中 Go。
|
||||
- Web Pod 中不存在数据库、服务商、会话签名密钥或 Go 内网地址。
|
||||
|
||||
## 本地开发
|
||||
|
||||
`npm run dev` 仍用于前端开发;`npm run build` 生成可静态托管的 `out/`。生产不运行
|
||||
Node Web 进程。需要完整联调时,同时启动 Go API,并用反向代理按
|
||||
与生产相同的路径规则将同一站点的后端请求转发给 Go。
|
||||
|
||||
Reference in New Issue
Block a user