# auto_put_ad_mini 生产部署指南 ## 概述 本文档说明如何将 `auto_put_ad_mini` 部署到海外服务器的 Docker/Kubernetes 环境,实现生产级自动化运行。 ## 核心特性 ### 已实现功能 ✅ **Docker 容器化** - Dockerfile 基于 Python 3.10 slim - 多阶段构建,优化镜像大小 - 健康检查支持 ✅ **账户白名单机制** - 环境变量配置白名单账户 - 双重安全检查(决策阶段 + 执行阶段) - 支持 whitelist.json 配置文件 ✅ **海外环境适配** - 代理配置从环境变量读取 - 时区支持(UTC/Asia/Shanghai) - 移除硬编码本地代理 ✅ **定时调度** - FastAPI + APScheduler 常驻服务(推荐) - Kubernetes CronJob 支持(备用) - HTTP API 手动触发 ✅ **监控和日志** - 健康检查端点 `/health` - 请求日志中间件 - Prometheus metrics 导出(可选) - 日志输出到 stdout(Kubernetes 友好) ✅ **安全配置** - Kubernetes Secret 管理敏感信息 - NetworkPolicy 网络隔离 - 非 root 用户运行 - 资源限制和配额 ## 项目结构 ``` auto_put_ad_mini/ ├── Dockerfile # Docker 镜像定义 ├── .dockerignore # Docker 构建排除文件 ├── docker-compose.yml # 本地开发环境 ├── requirements.txt # Python 依赖 ├── server.py # FastAPI + APScheduler 服务器(推荐) ├── execute_once.py # 单次执行入口 ├── schedule.sh # Cron 脚本(备用) ├── whitelist.json # 白名单账户配置 ├── metrics.py # Prometheus 指标导出 ├── utils/ │ └── log_capture.py # 并发日志捕获 ├── k8s/ # Kubernetes 部署清单 │ ├── README.md # K8s 部署详细说明 │ ├── namespace.yaml # 命名空间 │ ├── deployment.yaml # Deployment + Service │ ├── cronjob.yaml # CronJob(备用) │ ├── configmap.yaml # 公开配置 │ ├── secret.yaml # 敏感信息 │ ├── pvc.yaml # 持久化存储 │ └── network-policy.yaml # 网络策略 └── DEPLOYMENT.md # 本文档 ``` ## 快速开始 ### 阶段 1:本地测试 #### 方式 A:Docker Compose(开发环境) ```bash # 1. 进入项目目录 cd /Users/liulidong/project/agent/Agent/examples/auto_put_ad_mini # 2. 创建 .env 文件(从 .env.example 复制并填入真实值) cp .env.example .env vim .env # 填入实际的 API 密钥和配置 # 3. 构建镜像 docker build -t auto-put-ad-mini:test . # 4. 启动服务(APScheduler 模式) docker-compose up -d # 5. 查看日志 docker-compose logs -f # 6. 测试健康检查 curl http://localhost:8080/health | jq . # 7. 手动触发任务 curl -X POST http://localhost:8080/trigger | jq . # 8. 停止服务 docker-compose down ``` #### 方式 B:单次执行测试 ```bash # 测试单次执行(不启动调度服务) docker run --rm \ --env-file .env \ -e EXECUTION_ENABLED=false \ -e WHITELIST_ENABLED=true \ -e WHITELIST_ACCOUNTS=80769799 \ -v $(pwd)/outputs:/app/outputs \ auto-put-ad-mini:test \ python execute_once.py # 验证输出 ls -lh outputs/reports/ cat outputs/reports/llm_decisions_*.csv | head ``` ### 阶段 2:推送镜像到仓库 ```bash # 1. 登录镜像仓库 docker login your-registry.com # 2. 打标签 docker tag auto-put-ad-mini:test your-registry.com/auto-put-ad-mini:v1.0.0 docker tag auto-put-ad-mini:test your-registry.com/auto-put-ad-mini:latest # 3. 推送 docker push your-registry.com/auto-put-ad-mini:v1.0.0 docker push your-registry.com/auto-put-ad-mini:latest ``` ### 阶段 3:Kubernetes 部署 详细步骤见 [k8s/README.md](k8s/README.md) **推荐部署方式**:Deployment + APScheduler ```bash # 1. 创建命名空间 kubectl apply -f k8s/namespace.yaml # 2. 修改 k8s/secret.yaml,填入真实密钥 vim k8s/secret.yaml # 3. 部署所有资源 kubectl apply -f k8s/pvc.yaml kubectl apply -f k8s/configmap.yaml kubectl apply -f k8s/secret.yaml kubectl apply -f k8s/deployment.yaml # 4. 验证部署 kubectl get all -n ad-automation kubectl logs -f -n ad-automation deployment/auto-put-ad-mini # 5. 端口转发测试 kubectl port-forward -n ad-automation svc/auto-put-ad-mini 8080:8080 # 6. 测试健康检查 curl http://localhost:8080/health | jq . # 7. 手动触发任务 curl -X POST http://localhost:8080/trigger | jq . ``` ## 配置说明 ### 日级 ROI 三日口径 - 正式任务每天北京时间09:00执行;在创建数据库批次和发送消息前,必须确认 `loghubods.opengid_base_data` 已存在精确T-1分区,且小程序投流和公众号投流相关数据均非空。未就绪时禁止退回旧分区。 - 日级 ROI 读取 T-1 至 T-3 三个连续完整数据日,数据深度过滤使用最新业务 SQL 的 `usersharedepth<=1`。 - 正式阈值样本为连续三天每天首层 UV>200、成本>0 且 ROI 有效的小程序创意级和公众号实体;两类实体合并后按实体等权计算整体 P20 关停线。 - 小程序广告级从 ODPS 原始数据按广告直接 `COUNT(DISTINCT mid)`,复用同一 P20,但不重复进入样本池;低于关停线且广告 age>3 天时生成广告级关停建议。 - 金额、UV 和人数在三日汇总表展示为三日总量/3;ROI 与裂变率使用三日总分子/总分母的加权口径。 - 未进入三日正式样本的小程序创意增加单日补充判断:最新日首层 UV>200 且预测总效率 ROI≤0.20,或最新日首层 UV>500 且预测总效率 ROI≤全部最新日 UV>500 小程序创意的实体等权 P30;命中且广告 age>3 天时建议关停,命中但 age≤3 天时观察。动作原因同时展示最新日判断值与仅供参考的三日预测 ROI。其余最新日首层 UV>200 的非正式实体继续置底观察,不参与三日 P20。 - 报表包含小程序创意级、小程序广告级、公众号的三日汇总与每日明细共 6 个主 Sheet;广告级两个 Sheet 默认隐藏,企微暂不进入本版计算和报表。 - 每日明细 Sheet 的 `dt` 位于第一列,整表按日期倒序排列。 - 可见 ROI 列简化为“当日效率ROI”和“预测总效率ROI”;其后依次展示“关停线(P20)”和“扩量线(P80)”,公众号不参与扩量故扩量线留空;整体三日排名百分位保留为隐藏审计字段。 - “动作”可见列改为“建议动作”,其后展示“建议说明”;小程序创意级和广告级关停分别显示“关停创意”“关停广告”,但底层动作不变。创意关停按三日P20、单日硬线、单日P30三类原因分组,同类按 ROI 升序。底层无动作的正式中间区间在报表中显示为“观察”,但不生成可执行动作。阈值样本状态、执行状态和执行结果保留为隐藏审计字段。 - 当前三日策略以创意级+公众号合格实体统一等权 P20 生成低 ROI 关停建议;以合格小程序创意实体等权 P80 识别头部20%,广告 age≥3 时生成扩量建议。所有小程序创意级和广告级关停均要求广告 age>3 天;创意级关停批准后只暂停对应动态创意,广告级关停批准后暂停整个广告。 - 汇总表将三日总 T0 裂变人数 / 三日总首层 UV 的加权比例展示为“日均T0裂变率”。汇总顺序为关停、扩量、中间观察、条件不足观察;第一条扩量行和扩量后第一条观察行顶部均使用粗线分隔。“当日效率ROI”和“预测总效率ROI”均使用深红—黄—绿色阶,绿色代表表现好。普通数值显示两位小数,UV、人数、数量和广告年龄显示整数;两个“裂变系数-总裂变UV/…”比率列固定显示两位小数。“传播裂变系数匹配”保留审计数据但默认隐藏。 - “审批选择”默认隐藏,需取消隐藏后审批;创意级“当前创意状态”只对关停建议只读腾讯状态,显示正常、已停止或读取失败,其他行留空。 - 完整主报表保存后,流程会额外按“小程序投流”渠道的“代理名称”生成一代理一份调控建议工作簿;文件名为 `YYYYMMDD_代理名称_调控建议.xlsx`。代理版只包含小程序创意级和广告级三日汇总,广告级 Sheet 继续隐藏,不包含每日明细。包名、广告age、日均首层UV、建议说明、收入、预测总效率ROI、P20/P80/P30、排名、两个裂变系数、日均T0裂变人数/率、审批、执行状态和幂等键均不会写入代理文件;内部“当日效率ROI”仅改名为两位小数的“评分”展示,建议动作仍按预测总效率ROI计算并保留“关停创意/关停广告/扩量/观察”。代理表默认只落本地;开启 `ROI_AGENCY_WEBHOOK_ENABLED` 后,飞书应用先上传在线表,再由 `ROI_AGENCY_WEBHOOKS_JSON` 中精确匹配的代理机器人发送卡片。未配置代理直接跳过,不回退总群;完整 webhook 只能放在真实 `.env` 或密钥系统,数据库和日志只保存哈希指纹。 - 可选内部测试任务每天北京时间15:30执行独立复算,只将“自动化投放”分表发送到“内部”Webhook,不发送完整主表、正式总群或代理群,也不生成可审批腾讯动作。缺少该分表时任务失败并告警。正式任务始终去重;内部测试使用 `ROI_INTERNAL_TEST_DEDUP_ENABLED` 控制,设为`0`时每次显式触发都发送新的测试批次。内部任务无startup入口,重启服务不会自动补发。 - 09:00正式任务或15:30内部测试执行失败时,调度服务通过飞书应用向 `ROI_FAILURE_FEISHU_CHAT_ID` 发送红色告警卡片;未配置时回退 `FEISHU_OPERATOR_CHAT_ID`。告警失败只记日志,不会掩盖原任务失败。 离线复算不发送飞书: ```bash .venv/bin/python examples/auto_put_ad_mini/run_daily_roi.py \ --end-date YYYYMMDD \ --source-revision <稳定修订标识> ``` 只有显式增加 `--send-feishu` 才会发布飞书表格;该命令本身不会直接执行腾讯写操作。 ### 环境变量 | 变量名 | 说明 | 默认值 | 必需 | |--------|------|--------|------| | `WHITELIST_ENABLED` | 启用账户白名单 | true | 否 | | `WHITELIST_ACCOUNTS` | 白名单账户ID(逗号分隔) | - | 是(启用白名单时) | | `EXECUTION_ENABLED` | 启用实际执行 | false | 否 | | `HTTP_PROXY` | HTTP 代理地址 | - | 否 | | `HTTPS_PROXY` | HTTPS 代理地址 | - | 否 | | `TZ` | 时区 | UTC | 否 | | `CRON_SCHEDULE` | 定时表达式 | 0 2 * * * | 否 | | `RUN_ON_STARTUP` | 启动时立即执行 | false | 否 | | `PORT` | FastAPI 端口 | 8080 | 否 | | `FEISHU_APP_ID` | 飞书应用ID | - | 是 | | `FEISHU_APP_SECRET` | 飞书应用密钥 | - | 是 | | `TENCENT_AD_ACCOUNT_ID` | 腾讯广告账户ID | - | 是 | | `ODPS_ACCESS_ID` | ODPS 访问ID | - | 是 | | `ODPS_ACCESS_SECRET` | ODPS 访问密钥 | - | 是 | | `OPEN_ROUTER_API_KEY` | OpenRouter API Key | - | 是 | | `EXTERNAL_RECALL_SOURCE_LABEL` | 外部素材召回源标签 | `外部合作` | 否 | | `EXTERNAL_RECALL_CANDIDATE_LIMIT` | 外部素材进入 UV 排序的候选上限 | `300` | 否 | | `EXTERNAL_RECALL_EDIT_LIMIT_PER_LANDING` | 单个承接视频最多尝试清理的外部素材数 | `3` | 否 | | `EXTERNAL_RECALL_UV_WINDOW_DAYS` | 外部素材访问 UV 汇总窗口天数 | `90` | 否 | | `EXTERNAL_IMAGE_MODEL` | 外部素材参考图编辑模型 | 复用 `OPENROUTER_IMAGE_MODEL` | 否 | ### 白名单配置 **方式 1:环境变量(推荐)** ```bash # .env 或 k8s/secret.yaml WHITELIST_ENABLED=true WHITELIST_ACCOUNTS=80769799,71305011,12345678 ``` **方式 2:配置文件** 编辑 `whitelist.json`: ```json { "accounts": [80769799, 71305011], "description": "生产环境白名单账户列表", "last_updated": "2026-04-22" } ``` ### 定时调度配置 **Cron 表达式格式**:`分 时 日 月 周` 示例: - `0 2 * * *` - 每天凌晨 2 点(UTC) - `30 1 * * *` - 每天凌晨 1:30(UTC) - `0 */6 * * *` - 每 6 小时执行一次 - `0 9 * * 1-5` - 工作日上午 9 点 修改定时: ```bash # Kubernetes ConfigMap kubectl patch configmap ad-config -n ad-automation \ --patch '{"data":{"CRON_SCHEDULE":"0 3 * * *"}}' kubectl rollout restart deployment/auto-put-ad-mini -n ad-automation ``` ## 监控和运维 ### 健康检查 ```bash # 本地 curl http://localhost:8080/health # Kubernetes kubectl exec -n ad-automation -- curl -f http://localhost:8080/health ``` 返回示例: ```json { "status": "healthy", "timestamp": "2026-04-22T10:00:00Z", "scheduler_running": true, "latest_report": "llm_decisions_20260422.csv", "jobs": [ { "id": "decision_pipeline", "name": "广告决策流程", "next_run": "2026-04-23T02:00:00Z" } ] } ``` ### 日志查看 **Docker**: ```bash docker logs -f auto-put-ad-mini ``` **Kubernetes**: ```bash # 实时日志 kubectl logs -f -n ad-automation deployment/auto-put-ad-mini # 最近 100 行 kubectl logs -n ad-automation deployment/auto-put-ad-mini --tail=100 # 查看多个 Pod 日志 kubectl logs -n ad-automation -l app=auto-put-ad-mini --all-containers=true ``` ### 查看输出文件 **Docker**: ```bash docker exec -it auto-put-ad-mini ls -lh /app/outputs/reports/ docker exec -it auto-put-ad-mini cat /app/outputs/reports/llm_decisions_*.csv ``` **Kubernetes**: ```bash POD_NAME=$(kubectl get pods -n ad-automation -l app=auto-put-ad-mini -o jsonpath='{.items[0].metadata.name}') kubectl exec -n ad-automation $POD_NAME -- ls -lh /app/outputs/reports/ kubectl exec -n ad-automation $POD_NAME -- cat /app/outputs/reports/llm_decisions_*.csv ``` ### Prometheus 监控(可选) 如果启用了 Prometheus metrics: ```bash # 查看 metrics 文件 kubectl exec -n ad-automation $POD_NAME -- cat /app/outputs/metrics.prom ``` 配置 Prometheus 抓取: ```yaml scrape_configs: - job_name: 'auto-put-ad-mini' file_sd_configs: - files: - /app/outputs/metrics.prom ``` ## 故障排查 ### 问题 1:容器启动失败 ```bash # 查看 Pod 状态 kubectl describe pod -n ad-automation # 查看事件 kubectl get events -n ad-automation --sort-by='.lastTimestamp' # 查看日志 kubectl logs -n ad-automation --previous ``` 常见原因: - Secret 未配置或配置错误 - PVC 未创建或无法挂载 - 镜像拉取失败 ### 问题 2:定时任务未执行 ```bash # 检查调度器状态 curl http://localhost:8080/health | jq .scheduler_running # 查看下次执行时间 curl http://localhost:8080/health | jq .jobs # 手动触发测试 curl -X POST http://localhost:8080/trigger ``` ### 问题 3:白名单过滤异常 ```bash # 查看日志,搜索白名单相关信息 kubectl logs -n ad-automation deployment/auto-put-ad-mini | grep "白名单" # 检查配置 kubectl get secret ad-secrets -n ad-automation -o jsonpath='{.data.WHITELIST_ACCOUNTS}' | base64 -d ``` ### 问题 4:代理连接失败 ```bash # 检查代理配置 kubectl get configmap ad-config -n ad-automation -o yaml | grep PROXY # 测试代理连接 kubectl exec -n ad-automation $POD_NAME -- curl -x $HTTP_PROXY https://api.e.qq.com ``` ## 回滚和恢复 ### 回滚到上一个版本 ```bash # Deployment 模式 kubectl rollout undo deployment/auto-put-ad-mini -n ad-automation # CronJob 模式 kubectl set image cronjob/auto-put-ad-mini \ decision-engine=your-registry/auto-put-ad-mini:v0.9.0 \ -n ad-automation ``` ### 暂停服务 ```bash # Deployment 模式 kubectl scale deployment auto-put-ad-mini --replicas=0 -n ad-automation # CronJob 模式 kubectl patch cronjob auto-put-ad-mini -n ad-automation -p '{"spec":{"suspend":true}}' ``` ### 恢复服务 ```bash # Deployment 模式 kubectl scale deployment auto-put-ad-mini --replicas=1 -n ad-automation # CronJob 模式 kubectl patch cronjob auto-put-ad-mini -n ad-automation -p '{"spec":{"suspend":false}}' ``` ## 安全最佳实践 ### 1. Secret 管理 - ❌ **不要**将真实 Secret 提交到 Git - ✅ 使用 Kubernetes External Secrets 或 Sealed Secrets - ✅ 定期轮换敏感凭据 - ✅ 限制 Secret 访问权限 ### 2. 网络安全 - ✅ 启用 NetworkPolicy 限制出入站流量 - ✅ 仅允许必要的外部连接(腾讯 API、飞书 API) - ✅ 使用代理服务访问外部资源 ### 3. 资源隔离 - ✅ 使用独立命名空间(`ad-automation`) - ✅ 设置 CPU 和内存 limits - ✅ 使用 LimitRange 和 ResourceQuota ### 4. 运行时安全 - ✅ 非 root 用户运行(UID 1000) - ✅ 禁用特权容器 - ✅ 使用 readOnlyRootFilesystem(输出目录除外) ## 性能优化 ### 资源配置建议 | 环境 | CPU Request | CPU Limit | Memory Request | Memory Limit | |------|-------------|-----------|----------------|--------------| | 测试 | 250m | 500m | 512Mi | 1Gi | | 生产 | 500m | 1 | 1Gi | 2Gi | | 高负载 | 1 | 2 | 2Gi | 4Gi | ### 并发控制 - APScheduler `max_instances=1` 防止任务并发 - Kubernetes CronJob `concurrencyPolicy: Forbid` ### 日志轮转 ```bash # 输出目录定期清理 find /app/outputs -name "cron_*.log" -mtime +30 -delete ``` ## 升级策略 ### 滚动更新 ```bash # 更新镜像 kubectl set image deployment/auto-put-ad-mini \ decision-engine=your-registry/auto-put-ad-mini:v1.1.0 \ -n ad-automation # 查看更新状态 kubectl rollout status deployment/auto-put-ad-mini -n ad-automation ``` ### 灰度发布 ```bash # 创建 Canary Deployment kubectl apply -f k8s/deployment-canary.yaml # 验证 Canary 版本 kubectl logs -n ad-automation deployment/auto-put-ad-mini-canary # 全量发布 kubectl set image deployment/auto-put-ad-mini \ decision-engine=your-registry/auto-put-ad-mini:v1.1.0 \ -n ad-automation # 删除 Canary kubectl delete deployment auto-put-ad-mini-canary -n ad-automation ``` ## 附录 ### A. 两种部署模式对比 | 特性 | Deployment + APScheduler | CronJob | |------|-------------------------|---------| | 资源占用 | 常驻 Pod(低) | 每次启动新 Pod | | 启动速度 | 快(任务触发即执行) | 慢(需启动容器) | | 健康检查 | ✅ HTTP 端点 | ❌ 需额外脚本 | | 手动触发 | ✅ HTTP API | ⚠️ 需创建 Job | | 日志查看 | ✅ 持续输出 | ⚠️ 分散在多个 Job | | 监控集成 | ✅ Prometheus metrics | ⚠️ 需额外配置 | | 适用场景 | 生产环境、频繁调度 | 简单定时任务 | **推荐**:生产环境使用 Deployment + APScheduler 模式。 ### B. 常用命令速查 ```bash # 快速重启 kubectl rollout restart deployment/auto-put-ad-mini -n ad-automation # 查看最近事件 kubectl get events -n ad-automation --sort-by='.lastTimestamp' | tail -20 # 进入 Pod Shell kubectl exec -it -n ad-automation -- bash # 复制文件到本地 kubectl cp ad-automation/:/app/outputs/reports/llm_decisions_*.csv ./local-reports/ # 查看资源使用 kubectl top pod -n ad-automation ``` ### C. 联系支持 - 文档问题:查看 `k8s/README.md` 和本文档 - 代码问题:查看 `CLAUDE.md` 和源码注释 - 配置问题:查看 `.env.example` 和 `k8s/configmap.yaml` --- **文档版本**:v1.0.0 **最后更新**:2026-04-22 **维护者**:auto_put_ad_mini team