manynames3/clearpath-fargate-api
GitHub: manynames3/clearpath-fargate-api
基于 Terraform 的生产级 AWS 基础设施项目,为房地产潜在客户智能 API 提供从网络、计算、数据库到边缘安全的完整编排方案。
Stars: 0 | Forks: 0
# Clearpath 潜在客户智能 API
[](https://github.com/manynames3/clearpath-fargate-api/actions/workflows/build-push.yml)
[](https://github.com/manynames3/clearpath-fargate-api/actions/workflows/terraform-validate.yml)
容器化 REST API 运行在 ECS Fargate、RDS PostgreSQL、RDS Proxy、CloudFront、可选的 Route53、WAF 和 Secrets Manager 上。
本仓库作为一个生产级的 AWS Terraform 项目构建,用于 Clearpath Property Group 的场外房地产潜在客户工作流。它在应用层刻意保持轻量:基础设施才是核心所在。ECS Fargate 是主要的 AWS 部署路径,同时在 `k8s/` 中提供了可选的 Kubernetes/EKS 清单路径。
## 部署状态
本仓库已在本地和短期的 AWS 部署中进行了验证。为避免产生持续的 ECS、ALB、RDS、RDS Proxy、NAT、CloudFront、WAF 和日志记录费用,AWS 资源栈目前已被销毁。在您有意创建计费的 AWS 资源之前,请勿再次运行 `terraform apply`。
## 实时 AWS 验证
一次短期的 AWS 验证运行已于 2026-05-10 完成,随后使用 Terraform 进行了销毁。该运行验证了生产式部署路径:
- 在 apply 之前审查了 Terraform plan;完成销毁,移除了所有 Terraform 管理的资源
- ECS Fargate 服务达到了两个健康运行的任务
- ALB API 和 webhook 目标组报告了健康目标
- RDS PostgreSQL 在 RDS Proxy 后的私有数据库子网中运行
- CloudFront 在附加了 WAF 的情况下提供了 API 健康端点服务
- 在运行期间可以看到 CloudWatch 指标和警报
- VPC 资源映射显示了公有、私有 ECS 和私有数据库子网层
原始 AWS 控制台截图被刻意排除在 Git 之外,因为它们包含账户元数据、ARN、生成的端点和机密 ARN。公开的截图在发布前应进行脱敏处理。有关证据摘要和拆除说明,请参见 [docs/live-validation-summary.md](docs/live-validation-summary.md)。
GoHighLevel 相关工作被准确地定位为一个兼容 GHL 的 webhook 接收器。实时外部 GHL Workflow Custom Webhook 仍需要账户/位置访问权限、工作流配置、共享密钥设置和投递日志证据。
## 临时部署策略
本项目设计为短暂部署、记录文档然后销毁。其架构价值在于 Terraform 实现和服务设计,而不是让 ECS、ALB、RDS、RDS Proxy、NAT、CloudFront 和 WAF 处于空闲运行状态。
默认的 AWS 验证路径不需要购买域名。Terraform 通过 CloudFront 生成的 `*.cloudfront.net` 域提供 API,并保持 Route53/ACM 自定义域资源处于禁用状态,除非提供 `use_custom_domain = true` 和真实的托管区域 ID。
主要的数据库权衡是基于成本感知和工作负载驱动的:实施 RDS PostgreSQL 是因为当前的工作负载适中且可预测,而 Aurora 作为更高规模或可用性要求的升级路径被记录在文档中。
在有意的 AWS 验证运行期间,捕获操作构件,然后拆除资源栈:
- 具有健康 Fargate 任务的 ECS 服务
- ALB 目标组健康状态
- 位于私有子网中的 RDS PostgreSQL 实例
- RDS Proxy 目标健康
- 附带 WAF 的 CloudFront 分配
- `/api/market/*` 缓存行为或响应头
- CloudWatch 仪表板和警报
- Terraform plan/apply/destroy 输出
有关短期部署清单,请参见 [docs/deployment-validation.md](docs/deployment-validation.md)。
在捕获截图和命令输出时,请使用 [docs/deployment-evidence-template.md](docs/deployment-evidence-template.md)。
在 AWS 中应用之前,请查阅 [docs/cost-estimate.md](docs/cost-estimate.md)。
有关 Kubernetes/EKS 路径,请查阅 [docs/kubernetes.md](docs/kubernetes.md)。
有关适配 GoHighLevel 的 webhook 接收器、设置要求和负载映射,请使用 [docs/ghl-integration.md](docs/ghl-integration.md)。
有关手动 GitHub Actions 镜像部署路径,请使用 [docs/github-deploy-setup.md](docs/github-deploy-setup.md)。
在从本地状态迁移到远程 Terraform 状态之前,请使用 [docs/terraform-backend.md](docs/terraform-backend.md)。
有关架构决策记录,请参见 [docs/decisions](docs/decisions/README.md)。
在打开 AWS 验证窗口之前,请运行:
```
make preflight
```
## 本地快速启动
最快的本地运行方式是使用 Docker Compose:FastAPI 加上 Postgres,无需 AWS 资源。
```
cp .env.example .env
make dev-detached
make seed
make smoke
```
打开:
- `http://localhost:8000/health`
- `http://localhost:8000/api/leads?county=Gwinnett&limit=5`
- `http://localhost:8000/api/market/gwinnett`
停止并移除本地容器:
```
make clean
```
如果未安装 Docker,请使用 SQLite 备用方案:
```
make install
make seed-local
make dev-local
```
然后运行相同的 `localhost:8000` API 调用。
## 示例 API 调用
```
curl -f http://localhost:8000/health
```
```
curl -f "http://localhost:8000/api/leads?county=Gwinnett&limit=5"
```
```
curl -f "http://localhost:8000/api/market/gwinnett"
```
```
curl -X POST http://localhost:8000/webhooks/ghl \
-H "Content-Type: application/json" \
-d '{
"contact_id": "sample-webhook-001",
"first_name": "Jordan",
"last_name": "Carter",
"phone": "+14045550199",
"source": "sms",
"status": "warm",
"custom_fields": {
"property_address": "25 Sample Ridge",
"city": "Lawrenceville",
"county": "Gwinnett",
"state": "GA",
"situation": "inherited"
}
}'
```
## 为什么选择这种架构
| 服务 | 为什么不选择替代方案 |
|---|---|
| ECS Fargate | GHL webhooks 需要温暖且可预测的响应。VPC 中的 Lambda 可能会引入冷启动延迟,并且未来的评分任务可能会超出 Lambda 的运行时模型限制。 |
| RDS PostgreSQL | 潜在客户、房产和跟进数据是关系型的,并且得益于 join 操作。DynamoDB 不是此工作流的合适主要形态,而 Aurora 的容量超出了当前工作负载的需求。 |
| RDS Proxy | Fargate 任务会创建数据库连接;代理池化并保护数据库免受连接压力。 |
| CloudFront | 市场快照响应是可缓存的,不应在每次读取时都触及 Fargate 或数据库。 |
| Route53 | 可选的自定义域层。默认的短期验证运行使用生成的 CloudFront 域,以避免域名购买和托管区域维护。 |
| ALB | 将 `/api/*`、`/webhooks/*` 和 `/health` 路由到 ECS 目标。在无域名模式下,查看器 TLS 在 CloudFront 处终止,CloudFront 通过 HTTP 从托管的原点面向前缀列表到达 ALB。 |
| Secrets Manager | RDS 托管的数据库凭证和 webhook HMAC 密钥不会出现在代码和 Terraform 变量值中。 |
| WAF | AWS 托管规则和 webhook 速率限制保护 CloudFront 边缘。 |
| Kubernetes/EKS 清单 | 作为可选的平台路径包含在内,用于可移植的容器操作。ECS 仍是成本受控的 AWS 部署路径。 |
详细的决策记录保存在 [docs/decisions](docs/decisions/README.md) 中。
## RDS 与 Aurora 决策依据
本项目当前使用标准 RDS PostgreSQL,因为预期的工作负载小且可预测:webhook 摄取、潜在客户查询和缓存的县级市场读取。对于现阶段,RDS 是比 Aurora 更具成本效益的选择,因为它可以在适度的预置实例上运行,避免了 Aurora 的容量开销,并且仍然提供 API 所需的关系数据库功能。
性能要求是实用的,而非极端。API 需要为 GoHighLevel webhooks 和简单的联接潜在客户查询提供快速响应,但它目前还不需要 Aurora 的分布式存储层、读副本或高吞吐量自动缩放。CloudFront 也吸收了 `/api/market/*` 的重复流量,从而减少了对应用程序和数据库的压力。
对于生产故障转移和高可用性,当项目具有真实的正常运行时间要求时,可以将 RDS 提升到 Multi-AZ。这是一条直接的升级路径,无需过早承担 Aurora 特定的操作行为。如果潜在客户量大幅增长、并发 webhook 流量增加、读取缩放变得必要,或者业务需要更强的区域可用性和更快的故障转移特性,Aurora 稍后会更有意义。
自动缩放是另一个权衡。Aurora Serverless 可以更动态地扩展容量,但此 API 目前没有足够波动的数据库需求来证明这种复杂性的合理性。一个小的预置 RDS 实例更容易推理,更容易估计短期验证运行的成本,并且对于预期流量来说更便宜。当流量、缩放或可用性需求不再适合预置 RDS 时,项目可以重新考虑 Aurora。
## 生产升级路径
默认的开发设置是有意进行成本控制的。对于真正的生产发布,请保持相同的服务边界,但加强数据库和拆除设置:
- 使用 `terraform/environments/dev/production.tfvars.example` 作为起始覆盖文件
- 设置 `rds_multi_az = true`
- 根据恢复要求设置 `rds_backup_retention_days = 7` 或更高
- 在负载测试后选择更大的 RDS 类,例如 `db.t4g.small` 或 `db.t4g.medium`
- 设置 `rds_deletion_protection = true`
- 设置 `rds_skip_final_snapshot = false` 并提供 `rds_final_snapshot_identifier`
- 设置 `alb_deletion_protection = true`
- 保持 `rds.force_ssl = 1`
- 保持 RDS Proxy 用于 Fargate 连接池
- 为 CPU、存储、连接、延迟和可用内存添加警报
如果 webhook 量、并发潜在客户搜索、读取缩放或故障转移需求超出预置 RDS 的能力,Aurora PostgreSQL 将成为下一个数据库选项。
## 架构
```
flowchart LR
client["GHL workflow or API client"] --> cf["CloudFront generated domain"]
cf --> waf["AWS WAF WebACL"]
waf --> alb["ALB listener restricted to CloudFront"]
alb --> ecs["ECS Fargate clearpath-api"]
ecs --> proxy["RDS Proxy"]
proxy --> db["RDS PostgreSQL"]
ecs --> secrets["Secrets Manager"]
ecs --> logs["CloudWatch Logs"]
```
## 网络架构
Terraform 网络模块在 `us-east-1` 的两个可用区中构建了一个三层 VPC。公有子网仅托管面向互联网的入口基础设施。ECS 任务和 RDS Proxy 位于私有应用子网中,而 PostgreSQL 位于没有默认互联网路由的私有数据库子网中。
| 层 | us-east-1a | us-east-1b | 资源 | 路由 |
|---|---|---|---|---|
| VPC | `10.0.0.0/16` | `10.0.0.0/16` | 共享网络边界 | 已标记并启用流日志 |
| 公有 | `10.0.1.0/24` | `10.0.2.0/24` | ALB, NAT gateway | `0.0.0.0/0` 到 Internet Gateway |
| 私有应用 | `10.0.10.0/24` | `10.0.11.0/24` | ECS Fargate tasks, RDS Proxy, VPC endpoints | NAT 用于受控的出站;S3 和接口端点用于 AWS 服务 |
| 私有数据 | `10.0.20.0/24` | `10.0.21.0/24` | RDS PostgreSQL | 隔离的路由表,无互联网默认路由 |
安全组流程是刻意严格的:
| 来自 | 到 | 端口 | 控制 |
|---|---|---|---|
| CloudFront 源面向前缀列表 | ALB | 默认 `80`,自定义域源 TLS 为 `443` | ALB 不接受任意互联网源 |
| ALB 安全组 | ECS 安全组 | `8000` | 仅来自负载均衡器的应用流量 |
| ECS 安全组 | RDS Proxy 安全组 | `5432` | 应用程序仅通过代理连接 |
| RDS Proxy 安全组 | RDS 安全组 | `5432` | 数据库仅接受来自 RDS Proxy 的 PostgreSQL |
| ECS 安全组 | VPC 端点安全组 | `443` | 运行时使用的 AWS API 的私有访问 |
## 端点
- `POST /webhooks/ghl` - 兼容 GoHighLevel 的联系人 webhook 摄取
- `GET /api/leads?county=Gwinnett&status=warm&days_since_contact=30` - 配置后使用 `X-Clearpath-API-Key` 进行保护
- `GET /api/market/gwinnett`
- `GET /health`
- `GET /ready` - 数据库就绪检查
## 本地验证
```
make validate
```
等效的单个命令:
```
.venv/bin/pytest app/tests
terraform -chdir=terraform/environments/dev init -backend=false
terraform -chdir=terraform/environments/dev validate
.venv/bin/checkov -d terraform/ --framework terraform --quiet
```
## 应用门槛
预期的工作流始终是:
```
terraform -chdir=terraform/environments/dev plan -out=tfplan
terraform -chdir=terraform/environments/dev apply tfplan
```
不要跳过计划审查。仅在有意图启用 DNS/ACM 自定义域资源时,才在 `terraform/environments/dev/terraform.tfvars` 中设置 `route53_zone_id`。
对于默认的无域验证路径,请保持 `use_custom_domain = false` 并在应用后使用生成的 API 输出:
```
terraform -chdir=terraform/environments/dev output -raw api_base_url
```
## 部署验证构件
在 AWS 中验证资源栈时,请捕获展示端到端构建运行的构件:
| 证据 | 展示内容 |
|---|---|
| Terraform plan/apply | 审查的计划、成功的应用,以及 ALB、CloudFront、RDS Proxy 和 `api_base_url` 的输出 |
| 网络 | VPC、两个 AZ 的六个子网、路由表、NAT 网关、VPC 端点和 VPC 流日志 |
| 安全组 | CloudFront 到 ALB,ALB 到 ECS,ECS 到 RDS Proxy,RDS Proxy 到 RDS |
| ECS/Fargate | 集群、服务、两个运行的任务、任务定义和 CloudWatch 日志 |
| 数据库 | RDS PostgreSQL 私有可访问性、加密、Secrets Manager 集成和 RDS Proxy 健康目标 |
| 边缘 | CloudFront 分配已部署、已附加 WAF、生成的域或可选的自定义域行为,以及 `/api/market/*` 缓存命中 |
| API | 通过 `api_base_url` 的 `/health`、`/ready`、`/webhooks/ghl`、受保护的 `/api/leads` 和 `/api/market/gwinnett` 响应 |
| 拆除 | ECS 已缩容,Terraform 销毁完成,计费资源已移除 |
应用后,使用以下命令收集只读 CLI 证据:
```
make deployment-evidence
```
## 成本概况
该资源栈专为短期验证窗口和拆除而设计。RDS 是当前的数据库目标,因为它在保持现实关系架构的同时使成本可预测。为了控制成本,请在验证结束前将 ECS 缩容至零或销毁资源栈。
| 服务 | 大致成本驱动因素 |
|---|---|
| ECS Fargate | 部署期间运行 2 个小型持续任务 |
| RDS PostgreSQL | 部署期间运行小型预置数据库实例 |
| RDS Proxy | 每小时代理容量 |
| ALB | 每小时负载均衡器成本 |
| CloudFront/WAF | 低流量请求和规则处理成本 |
AWS 验证后,验证截图应存储在 `docs/screenshots/` 下。不要仅仅为了保留图像而保持资源栈运行。
## CI/CD
GitHub Actions 验证应用程序测试和 Terraform。镜像部署通过 `workflow_dispatch` 和 `deploy=true` 进行手动门控,因此普通推送不会意外推送镜像或滚动 ECS。在 Terraform 创建 ECR 和 ECS 之后,首选的镜像路径是 GitHub Actions;本地 Docker 是可选的。
GitLab CI 镜像了 Terraform 验证以实现 CI 覆盖。
标签:Aurora PostgreSQL, AWS, CISA项目, CloudFront, CloudWatch, DPI, ECS, ECS Fargate, EKS, NIDS, RDS Proxy, REST API, Route53, Secrets Manager, StruQ, Terraform, VPC, WAF, 后端架构, 容器化, 工作流自动化, 房地产科技, 生产就绪, 线索智能, 网络应用防火墙, 请求拦截, 逆向工具