Files
NianAIGC/docs/DEPLOYMENT.md

6.3 KiB
Raw Blame History

智念AIGC平台部署说明

生产拓扑

生产环境只有两类运行时:

  • zhinian-webNginx 静态容器,只包含 Next.js out/ 导出结果,不读取 Secret、 ConfigMap、数据库或 Go 内网地址。
  • zhinian-go-api:唯一应用后端,负责 /api/uploads/generated-results、登录会话、权限、数据库、供应商调用及内嵌 WorkerLoop。

浏览器始终请求同一个公网域名。Ingress 将后端路径转发给 Go其余页面和静态资源转发给 Web。登录 Cookie 为 HttpOnly Cookie由浏览器自动随同域 API 请求携带;静态 Web 不解析 Cookie也不持有会话签名密钥。

公网路径 工作负载
/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

Web Nginx 对 Go 所有的三类路径也会直接返回 404避免绕过 Ingress 后形成第二套 API 边界。

构建镜像

Web 镜像在 builder 阶段执行静态导出runner 只保留非 root Nginx 和 out/

docker build -t REGISTRY/PROJECT/zhinian-aigc:TAG .

Go 镜像构建方式见 backend/README.md。国内 CI 可使用:

docker build -f backend/Dockerfile.alpine \
  -t REGISTRY/PROJECT/zhinian-go-api:TAG backend/

发布前把 deploy/ack/web.yamldeploy/ack/go-api.yaml 中的镜像占位符替换为 不可变标签或 digest。

RDS 与首次初始化

生产固定使用 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_PHONEZHINIAN_BOOTSTRAP_ADMIN_PASSWORD,仅在不存在 超级管理员时创建一次。当前 ACK 清单不注入 ZHINIAN_BOOTSTRAP_ADMIN_NAME,因此名称 使用 Go 的默认值“平台超级管理员”。

ACK 配置与发布

先根据 deploy/ack/secrets.example.yaml 创建不提交 Git 的 deploy/ack/secrets.production.yaml替换所有占位值。Web 不需要任何运行时 Secret会话密钥只属于 Go。

仓库内静态检查:

npm run deploy:check

提交到集群前还应使用目标集群验证准入策略:

# 首次部署必须先真实创建 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

确认无误后发布:

# 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 的 emptyDirPod 重建或滚动升级同样会永久丢失上传文件和生成结果;生产持久化这些 文件必须先接入 OSS 或其他共享对象存储。

配置边界

zhinian-go-runtime ConfigMap 只保存非敏感 Go 运行参数。下列敏感值必须放在 Kubernetes Secret

  • DATABASE_URL
  • ZHINIAN_AUTH_SESSION_SECRETSecret 名 zhinian-go-auth,仅注入 Go
  • ZHINIAN_BOOTSTRAP_ADMIN_PHONEZHINIAN_BOOTSTRAP_ADMIN_PASSWORD
  • 服务商与 OSS 凭据
  • 开放 API Key、Webhook 签名密钥等

生产配置的事实来源是 ACK Secret/ConfigMap。不要通过静态页面或修改 Pod 文件来更新 生产密钥;修改 Secret/ConfigMap 后滚动 Go Deployment。

探针与验收

  • Web /healthzNginx 静态进程存活检查。
  • Go /api/healthGo 进程存活检查,不查询数据库。
  • Go /api/ready:检查 PostgreSQL schema、表权限和业务函数权限。

发布后执行:

kubectl rollout status deployment/zhinian-go-api -n zhinian
kubectl rollout status deployment/zhinian-web -n zhinian

curl -f https://你的域名/
curl -f https://你的域名/api/health
curl -f https://你的域名/api/ready
curl https://你的域名/api/v1/openapi.json

还应验证:

  • 未登录访问受保护页面后,浏览器跳转到 /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。