docs: complete Chinese project documentation
This commit is contained in:
335
docs/operations/production-runbook.md
Normal file
335
docs/operations/production-runbook.md
Normal file
@@ -0,0 +1,335 @@
|
||||
# 生产部署与恢复手册
|
||||
|
||||
本文适用于单机 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=<独立随机令牌>
|
||||
```
|
||||
|
||||
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`,完成真实案例验收后再按策略开启
|
||||
- 使用正式 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。
|
||||
- [ ] 统一蓝图报告明确区分已通过和待真实环境验收门槛。
|
||||
14
docs/operations/recovery-drill-2026-07-27.json
Normal file
14
docs/operations/recovery-drill-2026-07-27.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"status": "passed",
|
||||
"verified_at": "2026-07-27T09:24:21Z",
|
||||
"compose_project": "ai-ticket-restore-drill-5124",
|
||||
"backup_id": "20260727T092235Z",
|
||||
"duration_seconds": 106.57,
|
||||
"database_smoke": "ticket_and_attachment_restored",
|
||||
"object_storage_smoke": "marker_restored",
|
||||
"django_check": "passed",
|
||||
"artifact_refs": [
|
||||
"docs/operations/recovery-drill-2026-07-27.md"
|
||||
]
|
||||
}
|
||||
62
docs/operations/recovery-drill-2026-07-27.md
Normal file
62
docs/operations/recovery-drill-2026-07-27.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# 隔离恢复演练记录(2026-07-27)
|
||||
|
||||
## 结论
|
||||
|
||||
状态:**通过**
|
||||
|
||||
PostgreSQL 与 MinIO 已在独立 Docker Compose 项目中完成一致性备份、破坏和恢复。恢复后,
|
||||
工单、附件元数据与对象内容均可读取,Django 系统检查通过。演练没有复用或修改现有开发
|
||||
容器、网络和数据卷。
|
||||
|
||||
## 演练环境
|
||||
|
||||
- Docker Engine:29.6.1
|
||||
- Docker Compose:5.3.0
|
||||
- PostgreSQL:`pgvector/pgvector:pg16`
|
||||
- MinIO:`minio/minio:latest`
|
||||
- 归档辅助镜像:`alpine:3.21`
|
||||
- 隔离 Compose 项目:`ai-ticket-restore-drill-5124`
|
||||
- 备份编号:`20260727T092235Z`
|
||||
- 总耗时:106.57 秒
|
||||
|
||||
## 执行步骤与证据
|
||||
|
||||
1. 启动独立 PostgreSQL 与 MinIO 数据卷,构建当前后端镜像。
|
||||
2. 执行所有 Django 迁移与治理基线初始化。
|
||||
3. 创建工单 `RESTORE-DRILL-001`、关联附件元数据和 MinIO 标记对象。
|
||||
4. 生成 PostgreSQL custom-format dump、结构清单、MinIO 数据归档及 SHA-256 清单。
|
||||
5. 删除演练工单与 MinIO 对象,确认进入破坏后状态。
|
||||
6. 校验备份哈希,重建数据库并恢复对象存储数据。
|
||||
7. 通过 Django ORM 验证工单及附件关系,通过 `mc cat` 验证对象内容。
|
||||
8. 执行 `python manage.py check`,结果为 0 个问题。
|
||||
9. 销毁本次演练的容器、网络、数据卷和临时后端镜像。
|
||||
|
||||
最终自动化结果:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "passed",
|
||||
"backup_id": "20260727T092235Z",
|
||||
"duration_seconds": 106.57,
|
||||
"database_smoke": "ticket_and_attachment_restored",
|
||||
"object_storage_smoke": "marker_restored",
|
||||
"django_check": "passed"
|
||||
}
|
||||
```
|
||||
|
||||
## 演练中发现并修复的问题
|
||||
|
||||
- Windows PowerShell 缺少 `sh`,已增加与 Linux 脚本等价的备份、校验和恢复入口。
|
||||
- Windows 原生命令参数可能改变多行脚本编码或引号,隔离演练改用无引号 UTF-8 字节表达式。
|
||||
- 当前 MinIO 镜像不包含 `tar`,对象归档与恢复改由固定辅助容器挂载同一数据卷完成。
|
||||
- 生产备份默认冻结当时正在运行的 backend、worker 与 beat,并在退出时恢复原运行集合,
|
||||
避免 PostgreSQL 和 MinIO 分别快照期间继续发生跨存储写入。
|
||||
- 对象卷归档和覆盖期间显式停止 MinIO,只有 MinIO 重新通过健康检查后才恢复业务服务,
|
||||
避免从活跃数据卷读取或在运行进程下替换存储文件。
|
||||
- Linux 恢复脚本增加跳过应用服务启停的隔离演练开关,避免演练误启动业务进程。
|
||||
|
||||
## 仍需生产执行
|
||||
|
||||
本记录证明当前代码和脚本能够恢复一致的数据库与对象数据,不替代生产环境的定期演练。
|
||||
上线前仍需使用真实加密异地备份、正式告警接收方和业务账号执行完整登录、渠道、Agent
|
||||
与附件下载冒烟,并记录生产 RTO/RPO。
|
||||
Reference in New Issue
Block a user