运维手册
基于
deepdata-20260928分支(commitff22ed3)。本文记录日常运维操作与已核实的已知问题。
一、健康检查
Actuator(Java 主应用)
backend/services/main-application/src/main/resources/application.yml:
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
endpoint:
health:
show-details: when-authorized
health:
elasticsearch:
enabled: false # 显式禁用 ES 健康检查
访问路径(主应用 context-path 为 /api):
http://<host>:8080/api/actuator/health
http://<host>:8080/api/actuator/info
http://<host>:8080/api/actuator/metrics
http://<host>:8080/api/actuator/prometheus
Compose healthcheck
只有 Milvus profile 的三个服务配了 healthcheck(deployment/docker/deepdata/docker-compose.yml):
| 服务 | 检查命令 | 参数 |
|---|---|---|
etcd |
etcdctl endpoint health |
interval 30s / timeout 20s / retries 3 |
minio |
curl -f http://localhost:9000/minio/health/live |
30s / 20s / 3 |
milvus |
curl -f http://localhost:9091/healthz |
30s / 20s / 3,start_period 90s |
⚠️ 注意:核心业务服务(backend / backend-python / gateway / frontend / runtime)都没有 healthcheck,Dockerfile 里也没有
HEALTHCHECK指令。容器"running"不代表服务可用 —— 需靠外部探针或人工确认。
Python 启动期检查
app/main.py lifespan 中会做数据库连通性校验(SELECT 1,URL 密码打码),失败则启动失败。这属于启动期一次性检查,非常驻健康端点。
二、日志
Java侧(Log4j2)
backend/services/main-application/src/main/resources/log4j2.xml:
| 项 | 值 |
|---|---|
LOG_PATH |
/var/log/deepdata/backend |
| 日志文件 | ${LOG_PATH}/app.log |
| 轮转文件名 | app-%d{yyyy-MM-dd}-%i.log |
MAX_FILE_SIZE |
${LOG_ROTATION_MAX_SIZE:-100MB} |
MAX_HISTORY |
${LOG_ROTATION_BACKUP_COUNT:-30} |
| 格式 | %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n |
LOG_LEVEL |
INFO |
SQL_LOG_LEVEL |
WARN |
通过 logging.config: classpath:log4j2.xml 启用。网关有独立 log4j2 配置(backend/api-gateway/src/main/resources/log4j2.xml)。
Python 侧(标准库 logging)
runtime/deepdata-python/app/core/logging.py 的 setup_logging():
- 双handler:
StreamHandler(sys.stdout)+RotatingFileHandler(log_dir/"python-backend.log") - 默认
log_file_dir = /var/log/deepdata/backend-python(app/core/config.py第 29 行;.env.example覆盖为./logs) - 自定义
CenteredLevelNameFormatter与_rotated_log_namer - 显式调低
httpx/httpcore与sqlalchemy.engine为 ERROR;接管 uvicorn 三类日志
日志卷挂载
| 卷 | 路径 | 使用方 |
|---|---|---|
deepdata-log-volume |
/var/log/deepdata |
backend / backend-python / gateway / runtime |
deepdata-frontend-log-volume |
/var/log/deepdata/frontend |
frontend |
deepdata-database-log-volume |
/var/log/deepdata/database |
database |
deep-flow-log-volume |
/var/log/deep-flow |
deep-flow |
deepdata-ray-log-volume |
/tmp/ray |
ray |
日志 PVC 监控(自动清理)
Python 侧实现了 PVC 磁盘水位监控(app/module/system/service/log_pvc_monitor.py):
| 配置 | 默认 | 作用 |
|---|---|---|
LOG_PVC_MONITOR_ENABLED |
true | 开关 |
LOG_PVC_MONITOR_PATH |
./logs |
监控路径 |
LOG_PVC_MONITOR_THRESHOLD |
0.9 | 水位阈值(90% 触发清理) |
LOG_PVC_MONITOR_INTERVAL_SECONDS |
300 | 检查间隔 |
LOG_PVC_MONITOR_DELETE_BATCH_SIZE |
10 | 单次删除文件数 |
LOG_PVC_MONITOR_FILE_SUFFIXES |
log,out,err |
匹配后缀 |
测试覆盖:tests/test_log_pvc_monitor.py、tests/test_logging_rotation.py
轮转脚本
| 脚本 | 用途 |
|---|---|
scripts/images/common/log-rotate-copytruncate.sh |
拷入 runtime 镜像 /usr/local/bin/ |
scripts/images/database/prune-postgres-logs.sh |
PostgreSQL 日志清理 |
三、数据库运维
初始化机制
无 Flyway/Liquibase。数据库变更依赖 scripts/db/ 下 14 个幂等 DDL 脚本,由数据库镜像的 /docker-entrypoint-initdb.d/ 执行。
# scripts/images/database/Dockerfile
COPY scripts/db/ /docker-entrypoint-initdb.d/
⚠️ 关键机制:
docker-entrypoint-initdb.d只在数据卷为空时执行一次。
- 改
scripts/db/*.sql后不会自动生效- 需要手工执行:
docker exec -i deepdata-database psql -U postgres -d deepdata < scripts/db/xxx-init.sql- 或重建数据卷(会丢数据,慎用)
迁移脚本位置问题
backend/api-gateway/migration/ 在 deepdata-20260928 分支不存在(存在于 main 分支的 09-01 基线中)。当前分支的DDL 统一在 scripts/db/。
主库与初始化
| 项 | 值 |
|---|---|
| 镜像 | postgres:15-trixie |
| 启动脚本 | /usr/local/bin/deepdata-database-start.sh |
| 配置 | scripts/images/database/postgresql.cnf |
| 初始化库 | deepdata、labelstudio |
| JDBC | jdbc:postgresql://deepdata-database:5432/deepdata |
| 连接池 | HikariCP(max 20 / min 5) |
| Redis 池 | Lettuce(max-active 20) |
首页 URL 联动
scripts/db/zz-final-task.sh 读取 HOME_PAGE_URL 环境变量:
psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d deepdata
# UPDATE t_sys_param SET param_value = :url WHERE id = 'sys.home.page.url'
未设置则跳过。
备份建议
| 数据 | 位置 | 备份方式 |
|---|---|---|
| 元数据 | deepdata-postgresql-volume |
pg_dump |
| 数据集文件 | deepdata-dataset-volume / MinIO |
卷快照或对象存储同步 |
| 算子包 | deepdata-operator-packages-volume |
卷快照 |
| 向量数据 | milvus-milvus-volume + milvus-minio-volume |
Milvus 官方备份工具 |
四、已知坑(已核实)
🔴 P0 · JWT 认证默认关闭
deepdata.jwt.enable 默认值为 false(backend/api-gateway/.../JwtConfig.java 的 @Value("${deepdata.jwt.enable:false}")),.env.example 中也是 DEEPDATA_JWT_ENABLE=false。
同时网关的 SecurityConfig 是 pathMatchers("**").permitAll()(类注释:暂时禁用所有认证)。
影响:若不改配置,接口层无认证保护。
处置:生产环境显式设 DEEPDATA_JWT_ENABLE=true,并设置足够强的 JWT_SECRET(JwtConfig 在长度 < 32 时仅打warn,不报错 —— 短密钥不会被拒绝)。
🟡 Makefile 目标与 README 不匹配
| README 写的 | 实际情况 |
|---|---|
make install / make uninstall |
❌ 无无后缀目标 |
make build |
❌ 无此目标 |
make install-mineru |
❌ mineru 不在 VALID_SERVICE_TARGETS |
make install-deep-flow |
❌ deep-flow 不在合法目标 |
make install-label-studio |
✅ 可用 |
根因:Makefile 的 install-% 规则指向目录 deployment/compose,而该目录不存在(实际为 deployment/docker/deepdata)。
🟡 数据库 SQL 修改不生效
见前文。改 scripts/db/*.sql 后必须手工执行。
🟡 core 服务无 healthcheck
backend / backend-python / gateway / frontend / runtime 均无 healthcheck 与 Dockerfile HEALTHCHECK。编排系统无法据此判断服务真实状态。
🟡 两份 compose 端口不同
混用docker/docker-compose.yml(开发)与 deployment/docker/deepdata/docker-compose.yml(部署)会撞端口。差异见部署指南。
🟢 backend 无对外端口
deepdata-backend 在两份 compose 中都没有对外端口映射,只能通过 deepdata 内部网络访问。前端只暴露 30000(开发版 40000)。外部调用一律走网关。
🟢 前置 Nacos
NACOS_ADDR 默认值是 https://consulservice:18302(端口 18302 是 Consul 的典型端口,与 Nacos 默认 8848 不符)。纯 Compose 部署不需要服务发现,此配置无实际作用;但若误配会导致网关启动异常。
五、分支差异
| 分支 | commit | 内容 |
|---|---|---|
main |
cbb1048 |
早期基线,含 Casdoor SSO 与 GitHub Actions CI |
deepdata-20260928 |
ff22ed3 |
当前开发基线 |
deepdata-20260928 相对 main:
| 缺失项 | 文件数 |
|---|---|
deepflow/(已改名 deep-flow/) |
396(重命名) |
.github/workflows/ CI |
14 |
| Casdoor SSO 认证模块(Java) | 11 |
.gitattributes |
1 |
原因:zip 交付包(09-28)不含这些文件。Casdoor SSO 与 GitHub Actions 属于早期国际版基线的内容。
影响:切回 main 可找回 CI 与 SSO。若两条线都需要,需人工合并。
六、常见排障
| 现象 | 排查方向 |
|---|---|
| 网关启动即失败 | JWT_SECRET 未配置(JwtConfig @PostConstruct 抛 IllegalStateException) |
| 接口全 401 | deepdata.jwt.enable=false 时不会 401;若出现说明认证已开但 Token 无效/过期(默认 7 天) |
| 前端能开但数据为空 | 检查 backend / backend-python 容器状态(无 healthcheck,只能看日志) |
算子报错 ModuleNotFoundError |
上传包名与 __init__.py 中 module_path 包目录名不一致 |
| 清洗任务卡在调度 | 查 LOG_LEVEL=DEBUG 下的 asyncio 日志;检查 TASK_SCHEDULING_POOL_SIZE |
| 向量检索为空 | 确认 Milvus profile 已启用、MILVUS_URI 指向正确容器名(非 localhost) |
| 磁盘写满 | 检查日志 PVC 水位;确认 LOG_PVC_MONITOR_ENABLED=true |
| 数据库无表 | 数据卷非首次启动,初始化脚本未执行(见"数据库 SQL 修改不生效") |
| 标注结果不同步 | 检查 t_dm_dataset_files.tags_updated_at,同步按时间戳做冲突消解 |
七、日常巡检清单
# 1. 容器状态
docker compose ps
# 2. 后端健康
curl -s http://<host>:8080/api/actuator/health | jq .
# 3. 磁盘水位(数据卷+ 日志卷)
docker exec deepdata-database df -h /var/lib/postgresql/data
docker exec <python后端容器> df -h /var/log/deepdata
# 4. 数据库关键表增长
psql -U postgres -d deepdata -c "
SELECT relname, n_live_tup FROM pg_stat_user_tables
WHERE relname LIKE 't_dm_%' OR relname LIKE 't_clean_%'
ORDER BY n_live_tup DESC LIMIT 10;"
# 5. 清理陈旧算子包(operator-packages 卷)
docker exec <runtime容器> du -sh /opt/runtime/deepdata/ops/user