Files
ai-ticket-platform/docs/operations/production-runbook.md
2026-09-18 15:26:19 +08:00

345 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 生产部署与恢复手册
本文适用于单机 Docker Compose 私有化部署,覆盖首次部署、升级、监控、备份、恢复和
故障处理。多节点、高可用数据库和企业 Kubernetes 部署需要在此基线之上另行设计。
## 1. 部署拓扑与前置条件
生产 Compose 包含:
- PostgreSQL 16 + pgvector
- Redis 7
- MinIO
- ClamAV
- Django + Gunicorn
- Celery Worker、Celery Beat
- Nginx 静态前端与 API 反向代理
- 可选 Prometheus、Alertmanager
最低前置条件:
- 64 位 Linux
- Docker Engine 与 Compose 插件
- 可持续运行的本地或挂载数据盘
- 企业 DNS 和 TLS 证书
- NTP 时间同步
- 独立备份目录和异地加密存储
试运行建议至少 4 核 CPU、8 GB 内存和 100 GB 可用磁盘;正式规格必须根据附件量、
模型并发、知识向量和保留周期压测确定。ClamAV 病毒库初始化和 PostgreSQL/MinIO 数据量
会显著影响内存与磁盘需求。
## 2. 目录、账号和权限
建议使用专用系统账号部署,例如 `ai-ticket`:
```text
/opt/ai-ticket-platform/ 应用代码和 .env
/var/lib/ai-ticket-backups/ 本机备份
/etc/ai-ticket/ 监控令牌和告警地址
```
要求:
- `.env`、监控令牌和告警 Webhook 仅部署账号可读。
- 备份账号只拥有 Docker 和备份目录所需权限。
- 不把 Docker Socket、PostgreSQL、Redis、MinIO 或 ClamAV 端口暴露到公网。
- `infra/secrets/*.example` 只是结构示例,不能作为生产凭据。
## 3. 生产配置
复制模板:
```bash
cp .env.example .env
chmod 600 .env
```
必须修改:
```env
DJANGO_DEBUG=false
DJANGO_SECRET_KEY=<高强度随机值>
DJANGO_ALLOWED_HOSTS=tickets.example.com
CORS_ALLOWED_ORIGINS=https://tickets.example.com
CSRF_TRUSTED_ORIGINS=https://tickets.example.com
FRONTEND_APP_URL=https://tickets.example.com
OIDC_CALLBACK_BASE_URL=https://tickets.example.com
DJANGO_SUPERUSER_PASSWORD=<首次登录后仍需立即轮换>
POSTGRES_PASSWORD=<数据库密码>
MINIO_ROOT_USER=<MinIO 管理账号>
MINIO_ROOT_PASSWORD=<MinIO 管理密码>
MINIO_ACCESS_KEY=<应用访问账号>
MINIO_SECRET_KEY=<应用访问密钥>
AI_CREDENTIAL_ENCRYPTION_KEY=<稳定 Fernet 密钥>
INTERNAL_MCP_TOKEN=<独立随机令牌>
METRICS_TOKEN=<独立随机令牌>
TICKET_AUTOMATION_ENABLED=false
TICKET_AUTOMATION_MAX_RETRIES=2
TICKET_AUTO_CLOSE_HOURS=24
SUPPORT_REFERENCE_MIN_SCORE=0.35
```
Fernet 密钥生成:
```bash
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
```
密钥一旦用于加密模型、MCP、渠道或 OIDC 凭据,必须进入企业密钥备份流程。直接替换会导致
历史密文不可解密。
生产建议:
- `KNOWLEDGE_EMBEDDING_ALLOW_HASH_FALLBACK=false`
- `TICKET_AUTO_RESOLVE_ENABLED=false`,完成真实案例验收后再按策略开启
- `TICKET_AUTOMATION_ENABLED=false`,完成受理 Agent、支持分析 Agent、模型部署、
Celery、MinIO 和至少一种回复送达方式的就绪检查后再开启
- `TICKET_AUTO_CLOSE_HOURS=24` 是无异议窗口;变更前应完成客户通知与合规评审
- Celery Beat 必须保持单实例运行,否则虽有数据库幂等保护,仍会制造无意义的重复调度
- 使用正式 Embedding 部署并保持向量维度与数据库字段一致
- 根据数据保留政策设置 Agent 运行和临时受理保留周期
- 默认管理员仅用于初始化,随后创建实名管理员并停用或轮换默认账号
## 4. TLS 与网络边界
仓库 Compose 暴露 `${HTTP_PORT:-8080}` 的 HTTP 服务。生产环境应在其前方部署企业负载
均衡器或 TLS 反向代理:
- 外部只开放 443。
- HTTP 强制跳转 HTTPS。
- 保留 `Host`、`X-Forwarded-Proto` 和真实客户端 IP。
- 限制上传体积不低于平台总材料上限 100 MB。
- `/internal-mcp`、MinIO 控制台和监控端点只允许可信网络访问。
- 对模型、MCP、OIDC 和渠道出站目标使用网络白名单,应用层 URL 校验不能替代防火墙。
OIDC 回调地址固定为:
```text
https://<域名>/api/identity/auth/oidc/<provider-slug>/callback
```
## 5. 首次部署
先校验变量展开:
```bash
docker compose -f infra/docker-compose.prod.yml --env-file .env config
```
构建并启动:
```bash
docker compose -f infra/docker-compose.prod.yml --env-file .env up -d --build
docker compose -f infra/docker-compose.prod.yml --env-file .env ps
```
后端入口会等待 PostgreSQL、执行迁移并初始化治理数据。首次部署仍应检查日志:
```bash
docker compose -f infra/docker-compose.prod.yml --env-file .env logs backend --tail 200
docker compose -f infra/docker-compose.prod.yml --env-file .env logs worker --tail 100
docker compose -f infra/docker-compose.prod.yml --env-file .env logs beat --tail 100
```
探针:
```bash
curl -fsS http://127.0.0.1:8080/api/system/health/live
curl -fsS http://127.0.0.1:8080/api/system/health/ready
```
`live` 只表示进程可响应;`ready` 同时检查数据库和缓存。部署完成后验证:
1. HTTPS、登录和权限菜单。
2. 创建、查询和状态流转一张测试工单。
3. 上传安全测试附件并下载。
4. 启动一次 Agent 运行并查看事件。
5. 如已配置渠道,执行入站、出站和回执。
6. 检查后台任务、指标和告警。
## 6. 监控与告警
创建仅运维账号可读的文件:
```bash
install -m 600 /dev/null /etc/ai-ticket/metrics-token
install -m 600 /dev/null /etc/ai-ticket/alert-webhook-url
```
写入与 `.env` 中 `METRICS_TOKEN` 一致的指标令牌,以及真实告警 Webhook。设置路径并启动:
```bash
export METRICS_TOKEN_FILE=/etc/ai-ticket/metrics-token
export ALERT_WEBHOOK_URL_FILE=/etc/ai-ticket/alert-webhook-url
docker compose -f infra/docker-compose.prod.yml --env-file .env \
--profile monitoring up -d
```
Prometheus 与 Alertmanager 默认只绑定宿主机回环地址。指标接口接受
`X-Metrics-Token` 或 Bearer Token。当前告警覆盖:
- 后端无法抓取
- 渠道失败或积压
- Agent/Tool 近期失败
- 任务中心积压
上线前必须触发一条测试告警,确认接收人、升级路径、静默策略和恢复通知。
## 7. 备份、校验和保留
Linux:
```bash
sh infra/scripts/backup.sh
sh infra/scripts/verify-backup.sh backups/<timestamp>
BACKUP_RETENTION_DAYS=30 sh infra/scripts/prune-backups.sh
```
Windows PowerShell:
```powershell
& infra/scripts/backup.ps1
& infra/scripts/verify-backup.ps1 -BackupDirectory backups/<timestamp>
```
备份包含:
- PostgreSQL 自定义格式转储
- 可枚举数据库结构清单
- MinIO 数据归档
- SHA-256 校验文件
- 备份元数据
默认流程会暂停运行中的 backend、worker 和 beat,并在对象卷归档期间停止 MinIO,
形成数据库与对象存储的一致静默窗口。只有确认没有常驻业务写入的隔离演练才允许使用
`BACKUP_SKIP_APPLICATION_SERVICES=true` 或 `-SkipApplicationServices`。
`infra/backup-cron.example` 是宿主机 cron 模板。安装前替换绝对路径和专用账号。校验成功的
备份必须复制到独立、加密、不可被应用主机直接删除且具有保留策略的异地存储。
备份成功不代表可恢复;至少按季度执行恢复演练,并在重大版本发布前再次执行。
## 8. 升级
升级前:
1. 确认当前 Git 版本和镜像标签可追溯。
2. 阅读迁移和配置变更。
3. 执行完整质量门和生产 Compose 校验。
4. 创建并验证一致性备份。
5. 记录维护窗口和回滚负责人。
构建新版本:
```bash
docker compose -f infra/docker-compose.prod.yml --env-file .env build
docker compose -f infra/docker-compose.prod.yml --env-file .env up -d
```
观察:
```bash
docker compose -f infra/docker-compose.prod.yml --env-file .env ps
docker compose -f infra/docker-compose.prod.yml --env-file .env logs backend worker --tail 200
curl -fsS http://127.0.0.1:8080/api/system/health/ready
```
然后执行首次部署中的业务冒烟。迁移必须向后兼容时,才允许应用容器滚动替换;破坏性迁移
需要单独维护窗口和数据转换方案。
## 9. 回滚
应用回滚:
1. 停止写入或进入维护窗口。
2. 切回已验证的代码版本和镜像标签。
3. 使用相同 `.env` 启动旧版本。
4. 检查就绪探针和业务冒烟。
数据库迁移不能盲目反向执行。若新版本已写入旧版本不理解的数据,使用升级前的一致性备份
恢复数据库与 MinIO,而不是只恢复其中一侧。
## 10. 恢复
恢复会替换当前数据库和对象存储,只能在确认的维护窗口执行。
Linux:
```bash
RESTORE_CONFIRM=restore-ai-ticket-platform \
sh infra/scripts/restore.sh backups/<timestamp>
```
Windows PowerShell:
```powershell
& infra/scripts/restore.ps1 `
-BackupDirectory backups/<timestamp> `
-Confirm restore-ai-ticket-platform
```
脚本会先验证备份,在覆盖对象卷前停止 MinIO,并在 MinIO 恢复健康后再启动应用服务。
恢复后依次检查:
1. 就绪探针和登录。
2. 工单数量、抽样状态和解决结果。
3. 附件记录与 MinIO 对象。
4. Agent、任务中心和审计记录。
5. 渠道入站、出站和回执。
隔离自动演练:
```powershell
& infra/scripts/drill-restore.ps1
```
演练创建唯一 Compose 项目和独立数据卷,写入工单、附件及 MinIO 标记,执行备份、删除、
恢复和一致性检查,最后清理临时资源。最近一次证据见
[隔离恢复演练记录](recovery-drill-2026-07-27.md)。
## 11. 故障排查
### 就绪探针失败
```bash
docker compose -f infra/docker-compose.prod.yml --env-file .env ps
docker compose -f infra/docker-compose.prod.yml --env-file .env logs backend postgres redis --tail 200
```
重点检查数据库连接、Redis 地址、迁移状态和磁盘空间。
### Celery 任务积压
检查 worker、Redis 和模型服务连通性。不要通过重复点击绕过幂等控制;先确认任务是否已经
创建业务终态。
### 材料一直扫描失败
检查 ClamAV 健康和病毒库日志。不得为恢复业务而在生产关闭恶意文件扫描。
### 模型、MCP、渠道或 OIDC 凭据无法解密
确认 Django 与 Celery 使用同一 Fernet 主密钥。不要覆盖主密钥;从企业密钥备份恢复原值。
### 磁盘快速增长
分别检查 PostgreSQL、MinIO、ClamAV、Prometheus 和备份目录。先确认保留策略和备份可恢复,
不要直接删除 Docker 数据卷。
## 12. 上线安全检查表
- [ ] `DJANGO_DEBUG=false`,域名和可信来源仅包含生产地址。
- [ ] 默认管理员密码已替换,管理员使用实名账号。
- [ ] `.env`、Fernet、MCP、指标和告警凭据已纳入密钥管理。
- [ ] 外部只开放 HTTPS,内部端口受防火墙限制。
- [ ] 模型、MCP、OIDC 和渠道出口有网络白名单。
- [ ] 自动解决保持关闭,或已经通过真实案例和审批策略验收。
- [ ] 监控、真实告警接收方和升级路径已验证。
- [ ] 定时备份已安装,校验后复制到异地加密存储。
- [ ] 已完成隔离恢复演练并记录 RPO/RTO。
- [ ] 统一蓝图报告明确区分已通过和待真实环境验收门槛。