# 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 .
```

## 配置说明

### 环境变量

| 变量名 | 说明 | 默认值 | 必需 |
|--------|------|--------|------|
| `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 | - | 是 |

### 白名单配置

**方式 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 <pod-name> -- 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 <pod-name> -n ad-automation

# 查看事件
kubectl get events -n ad-automation --sort-by='.lastTimestamp'

# 查看日志
kubectl logs <pod-name> -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 <pod-name> -- bash

# 复制文件到本地
kubectl cp ad-automation/<pod-name>:/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
