WiFi-DensePose 生产部署指南:从单机 Docker 到 Kubernetes、多云与可观测体系实战
本篇技术指南以 archive/v1/docs/deployment.md(WiFi-DensePose Deployment Guide)为核心主体,系统讲解如何把 WiFi-DensePose 服务从单节点 Docker 一步步部署为具备高可用、可伸缩、可观测与安全加固的生产集群。读者将掌握:基于环境变量与集中式配置的部署编排、Docker Compose 与 Kubernetes 的完整清单写法、AWS/GCP/Azure 托管服务选型、HPA/VPA 弹性伸缩、Prometheus+Grafana 监控告警,以及数据库备份与灾难恢复的落地方式。文中还结合仓库源码给出环境变量的底层映射关系与可验证依据,方便读者对照真实实现排查部署问题。
适用前提与文档定位(阅读前须知)
本指南对应的主体是 archive/v1 中记载的原始纯 Python 版 WiFi-DensePose API 的生产部署体系(FastAPI + PostgreSQL/Redis + 推理服务 + 观测栈)。需要先明确两点事实,避免误用:
- 根据 archive/v1/DEPRECATED.md 与 ADR-187 归档弃用诚实标注,
archive/v1整棵代码树已被归档、不再维护,仅作为研究存档保留;其DensePoseHead只定义了网络结构、未携带训练权重(随机初始化,无 checkpoint 加载路径)。因此本文是一份面向该 v1 API 技术栈的部署方法参考,不建议在新项目中直接照搬该目录代码;当前仓库中被维护的实现位于v2/Rust workspace,落地容器化运行时见 docker/docker-compose.yml。 - 本指南所引环境变量、端点、模块路径均在 v1 源码(src/config.py、src/config/settings.py、src/app.py、src/main.py)中有真实对应实现,可作为阅读与验证的锚点。
部署选项与总体架构
WiFi-DensePose 生产部署覆盖从单机到大规模集群的完整梯度:
| 部署方式 | 适用场景 |
|---|---|
| Docker Compose | 单节点开发环境与小型生产部署 |
| Kubernetes | 多节点生产部署,支持自动伸缩 |
| 云平台 | AWS / GCP / Azure 托管服务 |
| 边缘部署 | IoT 网关与边缘计算设备 |
该文档给出了一个典型的目标架构,包含负载均衡(Nginx)、CSI 数据源(WiFi 路由器)、横向扩展的 API 服务副本、时序数据库与缓存、以及独立监控栈:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Load Balancer │ │ WiFi Routers │ │ Monitoring │
│ (Nginx) │ │ (CSI Source) │ │ (Prometheus) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ WiFi-DensePose │ │ Database │ │ Redis │
│ API Servers │◄──►│ (PostgreSQL) │ │ (Cache) │
│ (3+ replicas) │ │ (TimescaleDB) │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
架构中的职责对应到源码并不难确认:API 服务由 src/app.py 中的 FastAPI create_app() 工厂构建,中间件按"速率限制 → 认证 → CORS → 可信主机"顺序装配(RateLimitMiddleware / AuthenticationMiddleware / CORSMiddleware / TrustedHostMiddleware),路由以 settings.api_prefix 为前缀挂载 Pose、Stream,健康检查固定挂在 /health;服务生命周期则由 src/main.py 中的 ServiceOrchestrator 管理,并注册了 SIGINT/SIGTERM 信号处理实现优雅停机。因此架构图里"3+ 副本 + 健康检查 + 优雅上下线"的设计,都对应到 app 与 main 两个入口的真实行为。
前置条件
系统资源要求
文档给出了两档参考基线(非当前仓库实测数据,仅作容量规划起点):
最低配置
- CPU:4 核 2.4GHz
- 内存:8GB RAM
- 存储:100GB SSD
- 网络:1Gbps 以太网
推荐配置
- CPU:8+ 核 3.0GHz
- 内存:16GB+ RAM
- 存储:500GB+ NVMe SSD
- 网络:10Gbps 以太网
- GPU:NVIDIA GPU,8GB+ 显存(可选,用于推理加速)
软件依赖
容器运行时与编排工具安装方式如下(对应文档原文命令):
# Docker(20.10+)
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Docker Compose(2.0+)
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
Kubernetes 部署还需要 kubectl 与 Helm:
# kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
# Helm(3.0+)
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
仓库视角:根目录 example.env 可作为环境变量模板的起点;更贴近本仓库当前运行方式的容器编排见 docker/docker-compose.yml(Rust sensing-server + python-sensing),其中的
healthcheck、cap_drop: ALL、no-new-privileges等写法与本指南的安全建议一致,可互相印证。
Docker 部署
单节点 Docker Compose
1. 获取源码与环境模板
将仓库(RuView,其中 v1 代码位于 archive/v1)检出到本地后,拷贝环境模板:
git clone https://gitcode.com/GitHub_Trending/wi/RuView
cd RuView
# 将环境模板复制为 .env 并编辑
cp example.env .env
2. 配置环境变量
编辑 .env 文件,以下几组变量对应文档给出的最小可运行集合:
# Application Settings
APP_NAME=WiFi-DensePose API
VERSION=1.0.0
ENVIRONMENT=production
DEBUG=false
# Server Settings
HOST=0.0.0.0
PORT=8000
WORKERS=4
# Security (CHANGE THESE!)
SECRET_KEY=your-super-secret-key-change-this
JWT_SECRET=your-jwt-secret-change-this
# Database
DATABASE_URL=postgresql://postgres:password@postgres:5432/wifi_densepose
REDIS_URL=redis://:password@redis:6379/0
# Hardware
WIFI_INTERFACE=wlan0
CSI_BUFFER_SIZE=1000
HARDWARE_POLLING_INTERVAL=0.1
# Features
ENABLE_AUTHENTICATION=true
ENABLE_RATE_LIMITING=true
ENABLE_WEBSOCKETS=true
这些变量并非"纸面参数",它们被 src/config/settings.py 中的 Settings(基于 pydantic-settings 的 BaseSettings)逐字段读取,再经 src/config.py 的 ConfigManager 汇总为各业务子配置。可以对照源码确认的映射关系包括:
SECRET_KEY/JWT_ALGORITHM/JWT_EXPIRE_HOURS→get_security_config(),用于 JWT 签发与认证中间件;DATABASE_URL、DATABASE_POOL_SIZE(源码默认10)、DATABASE_MAX_OVERFLOW(默认20)→get_database_config(),还会附加pool_pre_ping=True、pool_recycle=3600等连接池调优项;REDIS_URL/REDIS_PASSWORD→get_redis_config(),包含socket_connect_timeout=5、retry_on_timeout=True、health_check_interval=30等稳健性参数;WIFI_INTERFACE/CSI_BUFFER_SIZE/HARDWARE_POLLING_INTERVAL→get_hardware_config();POSE_*系列 →get_pose_config()(含model_path、confidence_threshold、batch_size、max_persons,源码默认分别为0.5/32/10,文档中的0.7/64/20属于生产调优取值);ENABLE_*功能开关 →create_app()中控制是否加载对应中间件/路由(例如关闭metrics_enabled则不注册/api/v1/metrics端点,docs_url/redoc_url/openapi_url在is_production时置为None)。
需要特别提醒:Settings.secret_key 的开发默认值是 dev-not-secret-CHANGE-IN-PROD,生产环境必须通过 SECRET_KEY 覆盖;同时源码在启动时执行 validate_settings(),生产模式下若校验不通过会以 sys.exit(1) 拒绝启动(见 src/main.py)。
3. 用 Docker Compose 启动服务
# 启动所有服务
docker-compose up -d
# 查看服务状态
docker-compose ps
# 跟踪日志
docker-compose logs -f wifi-densepose
# 横向扩展 API 副本
docker-compose up -d --scale wifi-densepose=3
4. 验证部署
# 健康检查(对应 /health 路由)
curl http://localhost:8000/api/v1/health
# 打开 API 文档(非生产模式默认开启 /docs)
open http://localhost:8000/docs
注意:文档中的健康检查路径 /api/v1/health 与源码的挂载方式存在版本差异——src/app.py 中 health 路由无前缀挂在 /health,而 Pose/Stream 路由使用 settings.api_prefix + "/pose"、settings.api_prefix + "/stream"。部署前请以实际运行版本的 OpenAPI(/docs 或 /redoc)为准核对路径。
生产级 Docker Compose
单机生产建议使用独立 Compose 文件,在应用副本前加 Nginx 入口、并补齐 PostgreSQL、Redis、Prometheus、Grafana 全套依赖。文档给出的 docker-compose.prod.yml 完整内容如下,已保留全部关键配置:
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
depends_on:
- wifi-densepose
restart: unless-stopped
wifi-densepose:
image: wifi-densepose:latest
build:
context: .
target: production
environment:
- ENVIRONMENT=production
- WORKERS=4
env_file:
- .env
volumes:
- ./data:/app/data
- ./logs:/app/logs
- ./models:/app/models
depends_on:
- postgres
- redis
restart: unless-stopped
deploy:
replicas: 3
resources:
limits:
cpus: '2.0'
memory: 4G
reservations:
cpus: '0.5'
memory: 1G
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: wifi_densepose
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
restart: unless-stopped
deploy:
resources:
limits:
cpus: '1.0'
memory: 2G
redis:
image: redis:7-alpine
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
restart: unless-stopped
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
restart: unless-stopped
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD}
volumes:
- grafana_data:/var/lib/grafana
- ./monitoring/grafana:/etc/grafana/provisioning:ro
restart: unless-stopped
volumes:
postgres_data:
redis_data:
prometheus_data:
grafana_data:
值得注意的工程细节:
env_file注入.env,密钥统一以POSTGRES_PASSWORD、REDIS_PASSWORD、GRAFANA_PASSWORD这类"占位 + Compose 内插值"的方式管理,避免把明文写进 YAML;deploy.resources同时对 API 副本做 CPU/内存的limits与reservations双层约束,与仓库当前 docker/docker-compose.yml 中deploy.resources.limits的约束风格一致;- Prometheus 与 Grafana 配置通过只读卷挂载进容器,分别对应仓库中的 monitoring/prometheus-config.yml、monitoring/grafana-dashboard.json 与 monitoring/alerting-rules.yml,可参考它们反向补齐本机
monitoring/目录。
Kubernetes 部署
1. 准备集群基础环境
# 创建命名空间并切换上下文
kubectl create namespace wifi-densepose
kubectl config set-context --current --namespace=wifi-densepose
安装所需 Operator:
# Prometheus Operator(监控栈)
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack \
--namespace monitoring --create-namespace
# Ingress Controller(入口流量)
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx --create-namespace
2. 创建 Secrets 与 ConfigMaps
Secrets 用于数据库、Redis、应用级密钥与 TLS 证书:
# 数据库密钥
kubectl create secret generic postgres-secret \
--from-literal=POSTGRES_DB=wifi_densepose \
--from-literal=POSTGRES_USER=postgres \
--from-literal=POSTGRES_PASSWORD=your-secure-password
# Redis 密钥
kubectl create secret generic redis-secret \
--from-literal=REDIS_PASSWORD=your-redis-password
# 应用密钥
kubectl create secret generic wifi-densepose-secrets \
--from-literal=SECRET_KEY=your-super-secret-key \
--from-literal=JWT_SECRET=your-jwt-secret \
--from-literal=DATABASE_URL=postgresql://postgres:password@postgres:5432/wifi_densepose \
--from-literal=REDIS_URL=redis://:password@redis:6379/0
# TLS 证书
kubectl create secret tls tls-secret \
--cert=path/to/tls.crt \
--key=path/to/tls.key
ConfigMaps 用于非敏感配置与初始化文件:
# 应用配置
kubectl create configmap wifi-densepose-config \
--from-literal=ENVIRONMENT=production \
--from-literal=LOG_LEVEL=INFO \
--from-literal=WORKERS=4 \
--from-literal=ENABLE_AUTHENTICATION=true \
--from-literal=ENABLE_RATE_LIMITING=true
# Nginx 配置
kubectl create configmap nginx-config \
--from-file=nginx.conf=./k8s/nginx.conf
# PostgreSQL 初始化 SQL
kubectl create configmap postgres-init \
--from-file=init.sql=./k8s/init.sql
密钥/配置与运行时强耦合的这一设计,在源码侧同样可见:ConfigManager 提供 set_environment_override()/clear_environment_overrides()(见 src/config.py),把"配置项"抽象成可热替换的环境变量覆盖;SECRET_KEY、JWT_SECRET、DATABASE_URL、REDIS_URL 正是 get_security_config()/get_database_config()/get_redis_config() 的输入来源。因此 K8s Secret 的值可以做到与 Docker 阶段 .env 完全同名互通。
3. 部署持久化卷(PVC)
文档建议为数据、模型、PostgreSQL、Redis 分别申请独立 PVC(存储类 fast-ssd 需按集群实际提供):
# k8s/pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wifi-densepose-data-pvc
namespace: wifi-densepose
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
storageClassName: fast-ssd
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wifi-densepose-models-pvc
namespace: wifi-densepose
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Gi
storageClassName: fast-ssd
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data-pvc
namespace: wifi-densepose
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 200Gi
storageClassName: fast-ssd
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-data-pvc
namespace: wifi-densepose
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
storageClassName: fast-ssd
模型与数据目录分离非常重要:姿态推理模型以只读方式挂给副本(对应 .env 中 POSE_MODEL_PATH 指向的目录),原始 CSI/日志走独立的数据盘,避免副本重建时丢失任何离线积累。
4. 应用全部 Kubernetes 清单
kubectl apply -f k8s/pvc.yaml
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
kubectl apply -f k8s/ingress.yaml
# 观察部署状态
kubectl get pods -w
kubectl get services
kubectl get ingress
5. 配置 Ingress 与 TLS
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wifi-densepose-ingress
namespace: wifi-densepose
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/rate-limit: "100"
spec:
tls:
- hosts:
- api.wifi-densepose.com
secretName: wifi-densepose-tls
rules:
- host: api.wifi-densepose.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: wifi-densepose-service
port:
number: 80
域名
api.wifi-densepose.com为文档示例值,实际部署必须替换为你自己的域名并保证 DNS 解析指向 Ingress 入口。
云平台部署
AWS 部署
1. EKS 集群
# 安装 eksctl
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
sudo mv /tmp/eksctl /usr/local/bin
# 创建 EKS 集群(节点 1~10 自动伸缩)
eksctl create cluster \
--name wifi-densepose \
--region us-west-2 \
--nodegroup-name workers \
--node-type m5.xlarge \
--nodes 3 \
--nodes-min 1 \
--nodes-max 10 \
--managed
2. RDS PostgreSQL
aws rds create-db-instance \
--db-instance-identifier wifi-densepose-db \
--db-instance-class db.r5.large \
--engine postgres \
--engine-version 15.4 \
--allocated-storage 100 \
--storage-type gp2 \
--storage-encrypted \
--master-username postgres \
--master-user-password your-secure-password \
--vpc-security-group-ids sg-xxxxxxxxx \
--db-subnet-group-name default \
--backup-retention-period 7 \
--multi-az
3. ElastiCache Redis
aws elasticache create-cache-cluster \
--cache-cluster-id wifi-densepose-redis \
--cache-node-type cache.r5.large \
--engine redis \
--num-cache-nodes 1 \
--security-group-ids sg-xxxxxxxxx \
--subnet-group-name default
GCP 部署
1. GKE 集群
gcloud container clusters create wifi-densepose \
--zone us-central1-a \
--machine-type n1-standard-4 \
--num-nodes 3 \
--enable-autoscaling \
--min-nodes 1 \
--max-nodes 10 \
--enable-autorepair \
--enable-autoupgrade
2. Cloud SQL for PostgreSQL
gcloud sql instances create wifi-densepose-db \
--database-version POSTGRES_15 \
--tier db-n1-standard-2 \
--region us-central1 \
--storage-size 100GB \
--storage-type SSD \
--backup-start-time 02:00
Azure 部署
1. AKS 集群
az group create --name wifi-densepose-rg --location eastus
az aks create \
--resource-group wifi-densepose-rg \
--name wifi-densepose-aks \
--node-count 3 \
--node-vm-size Standard_D4s_v3 \
--enable-addons monitoring \
--generate-ssh-keys
2. Azure Database for PostgreSQL
az postgres server create \
--resource-group wifi-densepose-rg \
--name wifi-densepose-db \
--location eastus \
--admin-user postgres \
--admin-password your-secure-password \
--sku-name GP_Gen5_2 \
--storage-size 102400
云端部署的核心收益是让数据库、缓存、证书等有状态组件全部走托管服务(自动备份、多可用区、加密),EKS/GKE/AKS 只承载无状态 API 副本——这样 HPA 缩容、故障重建都不会造成数据丢失。如果你的生产数据需要具备时间序列特性(CSI 流、姿态事件、系统指标),可进一步把 PostgreSQL 升级为 TimescaleDB 的托管形态或自建扩展(见下节)。
生产配置详解
完整生产环境变量文件
文档提供了一份 .env.prod 作为"生产基线清单",覆盖应用、服务、安全、数据库、Redis、硬件、姿态处理、功能开关、监控与性能共十个分组:
# Production environment file
cat > .env.prod << EOF
# Application
APP_NAME=WiFi-DensePose API
VERSION=1.0.0
ENVIRONMENT=production
DEBUG=false
# Server
HOST=0.0.0.0
PORT=8000
WORKERS=4
# Security
SECRET_KEY=${SECRET_KEY}
JWT_SECRET=${JWT_SECRET}
JWT_ALGORITHM=HS256
JWT_EXPIRE_HOURS=24
# Database
DATABASE_URL=${DATABASE_URL}
DATABASE_POOL_SIZE=20
DATABASE_MAX_OVERFLOW=30
DATABASE_POOL_TIMEOUT=30
# Redis
REDIS_URL=${REDIS_URL}
REDIS_POOL_SIZE=10
# Hardware
WIFI_INTERFACE=wlan0
CSI_BUFFER_SIZE=2000
HARDWARE_POLLING_INTERVAL=0.05
# Pose Processing
POSE_CONFIDENCE_THRESHOLD=0.7
POSE_PROCESSING_BATCH_SIZE=64
POSE_MAX_PERSONS=20
# Features
ENABLE_AUTHENTICATION=true
ENABLE_RATE_LIMITING=true
ENABLE_WEBSOCKETS=true
ENABLE_REAL_TIME_PROCESSING=true
# Monitoring
ENABLE_METRICS=true
METRICS_PORT=8080
LOG_LEVEL=INFO
# Performance
ENABLE_GPU=true
MIXED_PRECISION=true
OPTIMIZE_FOR_INFERENCE=true
EOF
对照源码进一步理解其中几组"性能相关"开关的真实含义:
ENABLE_METRICS=true且METRICS_PORT=8080:在 src/app.py 中只有settings.metrics_enabled为真时才注册/api/v1/metrics端点,Prometheus 抓取目标即wifi-densepose:8080(与 Compose 阶段端口一致);ENABLE_REAL_TIME_PROCESSING/ENABLE_WEBSOCKETS:进入get_streaming_config(),决定 WebSocket 连接管理(websocket_ping_interval、websocket_timeout)与实时处理链路是否启用;POSE_*三件套:文档建议的0.7/64/20高于源码默认(0.5/32/10),说明生产吞吐更大、对误报更敏感时应调高阈值与批大小、放宽人数上限;DATABASE_POOL_SIZE/DATABASE_MAX_OVERFLOW:文档给20/30,源码默认10/20,API 多副本时应在数据库侧预留充足并发连接配额。
PostgreSQL / TimescaleDB 调优
对时序型负载,文档建议同时做两件事:一是基础参数调优,二是启用 TimescaleDB 扩展并把核心表转成 hypertable:
-- postgresql.conf optimizations
shared_buffers = 256MB
effective_cache_size = 1GB
maintenance_work_mem = 64MB
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 100
random_page_cost = 1.1
effective_io_concurrency = 200
work_mem = 4MB
min_wal_size = 1GB
max_wal_size = 4GB
-- TimescaleDB extension
CREATE EXTENSION IF NOT EXISTS timescaledb;
-- Create hypertables for time-series data
SELECT create_hypertable('csi_data', 'timestamp');
SELECT create_hypertable('pose_detections', 'timestamp');
SELECT create_hypertable('system_metrics', 'timestamp');
-- Create indexes
CREATE INDEX idx_pose_detections_person_id ON pose_detections (person_id);
CREATE INDEX idx_pose_detections_zone_id ON pose_detections (zone_id);
CREATE INDEX idx_csi_data_router_id ON csi_data (router_id);
其中 csi_data 是逐包 CSI(信道状态信息)样本,pose_detections 是姿态估计事件,system_metrics 是运行指标——三张表都以时间戳为分区键做自动分区,配合 router_id/person_id/zone_id 业务索引,才能支撑高频率写入与按区域、按人检索。
Redis 调优
# redis.conf optimizations
maxmemory 2gb
maxmemory-policy allkeys-lru
save 900 1
save 300 10
save 60 10000
appendonly yes
appendfsync everysec
allkeys-lru 淘汰策略配合 maxmemory 上限,保证缓存/会话在内存压力下不 OOM;appendonly yes + appendfsync everysec 在持久化与写入性能之间取得平衡——这与 Redis 在系统中所承担的角色(速率限制计数、WebSocket 连接状态、短期缓存)匹配。
弹性伸缩与负载均衡
HorizontalPodAutoscaler(HPA)
以 CPU 70% 与内存 80% 两个维度驱动 3~20 副本伸缩,并配置了独立的升缩稳定窗口与速率策略:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: wifi-densepose-hpa
namespace: wifi-densepose
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: wifi-densepose
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 50
periodSeconds: 60
伸缩行为的关键点:缩容稳定窗口 300s、每 60s 最多缩 10%;扩容稳定窗口仅 60s、每 60s 最多扩 50%——即"快速响应突增、谨慎回收资源",非常契合姿态推理这类带有瞬时热点负载的在线服务。
VerticalPodAutoscaler(VPA)
若不想手算副本数对应的资源规格,可让 VPA 自动给出每副本的 CPU/内存建议并自动更新(updateMode: Auto):
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: wifi-densepose-vpa
namespace: wifi-densepose
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: wifi-densepose
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: wifi-densepose
maxAllowed:
cpu: 4
memory: 8Gi
minAllowed:
cpu: 500m
memory: 1Gi
注意 VPA 的 Auto 模式会通过重建 Pod 来应用资源变更,实践中常与 HPA 配合使用(VPA 负责单副本规格、HPA 负责副本数量),且建议先以 Off/Initial 观察建议再开启自动更新。
Nginx 负载均衡配置
入口层采用 least_conn 策略在多副本间分发,并同时提供 SSL 终结、速率限制、gzip 与 WebSocket 升级支持:
upstream wifi_densepose_backend {
least_conn;
server wifi-densepose-1:8000 max_fails=3 fail_timeout=30s;
server wifi-densepose-2:8000 max_fails=3 fail_timeout=30s;
server wifi-densepose-3:8000 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
listen 443 ssl http2;
server_name api.wifi-densepose.com;
# SSL configuration
ssl_certificate /etc/nginx/ssl/tls.crt;
ssl_certificate_key /etc/nginx/ssl/tls.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req zone=api burst=20 nodelay;
# Gzip compression
gzip on;
gzip_types text/plain application/json application/javascript text/css;
location / {
proxy_pass http://wifi_densepose_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
location /health {
access_log off;
proxy_pass http://wifi_densepose_backend;
}
}
两份超时与 WebSocket 升级配置和 ENABLE_WEBSOCKETS 的开销是直接相关的:实时姿态流走 WebSocket 长连接,因此 Nginx 必须开启 Upgrade/Connection: upgrade 并把读写超时调到可覆盖一次推理回传的时间尺度,否则长连接会被网关 60s 掐断。
监控与可观测性
Prometheus 抓取配置
# monitoring/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "wifi_densepose_rules.yml"
scrape_configs:
- job_name: 'wifi-densepose'
static_configs:
- targets: ['wifi-densepose:8080']
metrics_path: /metrics
scrape_interval: 10s
- job_name: 'postgres'
static_configs:
- targets: ['postgres-exporter:9187']
- job_name: 'redis'
static_configs:
- targets: ['redis-exporter:9121']
- job_name: 'nginx'
static_configs:
- targets: ['nginx-exporter:9113']
应用自身的抓取目标 wifi-densepose:8080/metrics 正对应 .env.prod 里的 ENABLE_METRICS=true 与 METRICS_PORT=8080;PostgreSQL、Redis、Nginx 则各配一个 exporter 从旁采集。仓库根目录的 monitoring/prometheus-config.yml 与 monitoring/alerting-rules.yml 是现成的同构配置,可对照查看 scrape job 与告警规则的另一种落地写法。
Grafana 面板
文档给出一个最小可用的 JSON 面板模型,核心是三条 PromQL:
{
"dashboard": {
"title": "WiFi-DensePose Monitoring",
"panels": [
{
"title": "Request Rate",
"type": "graph",
"targets": [
{
"expr": "rate(http_requests_total[5m])",
"legendFormat": "{{method}} {{status}}"
}
]
},
{
"title": "Response Time",
"type": "graph",
"targets": [
{
"expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))",
"legendFormat": "95th percentile"
}
]
},
{
"title": "Pose Detection Rate",
"type": "graph",
"targets": [
{
"expr": "rate(pose_detections_total[5m])",
"legendFormat": "Detections per second"
}
]
}
]
}
}
三个面板分别回答三个问题:QPS 与错误分布(http_requests_total)、95 分位延迟(http_request_duration_seconds_bucket)、以及业务吞吐——每秒姿态检出数(pose_detections_total)。最后这个"业务指标"是姿态系统特有的,比起纯基础设施指标更能反映服务是否真正在干活。仓库已提供可导入的成品面板 monitoring/grafana-dashboard.json。
告警规则
# monitoring/wifi_densepose_rules.yml
groups:
- name: wifi-densepose
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.1
for: 5m
labels:
severity: critical
annotations:
summary: High error rate detected
description: "Error rate is {{ $value }} errors per second"
- alert: HighResponseTime
expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 1
for: 5m
labels:
severity: warning
annotations:
summary: High response time detected
description: "95th percentile response time is {{ $value }} seconds"
- alert: PoseDetectionDown
expr: rate(pose_detections_total[5m]) == 0
for: 2m
labels:
severity: critical
annotations:
summary: Pose detection stopped
description: "No pose detections in the last 2 minutes"
三条规则(5xx 错误率持续 5 分钟 > 0.1/s、95 分位延迟 > 1s 持续 5 分钟、姿态检出数归零持续 2 分钟)分别对应稳定性、体验、业务存活三个告警维度。其中 PoseDetectionDown 的设计很实用:当 CSI 数据源或推理管线静默停摆时,HTTP 层面可能依然 200,只有业务吞吐归零才会触发 critical。
安全加固
网络策略
通过 NetworkPolicy 把 API Pod 的入站流量收敛到 Ingress 命名空间、出站流量收敛到 PostgreSQL 与 Redis:
# Network policies
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: wifi-densepose-netpol
namespace: wifi-densepose
spec:
podSelector:
matchLabels:
app: wifi-densepose
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 8000
egress:
- to:
- podSelector:
matchLabels:
component: postgres
ports:
- protocol: TCP
port: 5432
- to:
- podSelector:
matchLabels:
component: redis
ports:
- protocol: TCP
port: 6379
Pod 安全上下文
apiVersion: v1
kind: Pod
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: wifi-densepose
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
这一"非 root + 只读根文件系统 + 丢弃全部 capabilities + seccomp RuntimeDefault"的组合与仓库当前运行时容器 docker/docker-compose.yml 中的 security_opt: no-new-privileges、cap_drop: ALL 是同一种最小权限哲学。需要注意的是:readOnlyRootFilesystem: true 要求日志、模型、数据目录都通过 emptyDir/PVC 显式挂载(对应 Compose 阶段的三块 volume)。
密钥管理(External Secrets)
把 Secrets 的存储从 etcd 上移到云厂商的密钥服务,实现密钥轮换无需重建 Secret:
# 安装 external secrets operator
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets \
--namespace external-secrets-system \
--create-namespace
# AWS Secrets Manager 集成示例
kubectl apply -f - <<EOF
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: aws-secrets-manager
namespace: wifi-densepose
spec:
provider:
aws:
service: SecretsManager
region: us-west-2
auth:
jwt:
serviceAccountRef:
name: external-secrets-sa
EOF
在 GCP 侧可把 provider 换成 gcp + Secret Manager,Azure 则换 azure + Key Vault,SecretStore 的资源形态保持一致。结合前文源码中 ConfigManager.set_environment_override() 的能力,运行时仍然以环境变量形态消费这些外部密钥,对应用代码完全透明。
备份与灾难恢复
PostgreSQL 定时备份脚本
#!/bin/bash
# backup-database.sh
BACKUP_DIR="/backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="wifi_densepose_backup_${TIMESTAMP}.sql"
# Create backup
pg_dump -h postgres -U postgres -d wifi_densepose > "${BACKUP_DIR}/${BACKUP_FILE}"
# Compress backup
gzip "${BACKUP_DIR}/${BACKUP_FILE}"
# Upload to S3
aws s3 cp "${BACKUP_DIR}/${BACKUP_FILE}.gz" s3://wifi-densepose-backups/
# Clean old backups (keep last 30 days)
find ${BACKUP_DIR} -name "*.gz" -mtime +30 -delete
脚本要点:pg_dump 生成逻辑备份 → gzip 压缩 → aws s3 cp 异地归档 → find -mtime +30 只保留最近 30 天。逻辑备份(SQL)对跨版本恢复最友好;若使用 TimescaleDB hypertable,可额外考虑 timescaledb_backup 工具或持续归档(WAL)作为补充。
集群级灾难恢复(Velero)
Kubernetes 层面的对象与卷快照可用 Velero Schedule 统一管理:
# Velero backup configuration
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: wifi-densepose-backup
namespace: velero
spec:
schedule: "0 2 * * *"
template:
includedNamespaces:
- wifi-densepose
storageLocation: default
volumeSnapshotLocations:
- default
ttl: 720h0m0s
每天凌晨 2 点对 wifi-densepose 命名空间做一次包含卷快照的备份,保留 720 小时(30 天),与上一脚本的保留窗口一致。RPO 层面注意:仅靠每日全量备份最多丢失 24 小时数据,对 CSI/姿态事件这类时序流,建议同时保留托管库(云 RDS/Cloud SQL 自带的 PITR)或 TimescaleDB 连续归档。
故障排查
常见问题定位命令
1. Pod 启动失败
kubectl get pods -n wifi-densepose
kubectl logs -f deployment/wifi-densepose -n wifi-densepose
kubectl describe pod <pod-name> -n wifi-densepose
2. 数据库连接问题
# 用一次性 Pod 测试连通性
kubectl run -it --rm debug --image=postgres:15-alpine --restart=Never -- \
psql -h postgres -U postgres -d wifi_densepose
# 查看数据库日志
kubectl logs -f deployment/postgres -n wifi-densepose
3. 性能问题
kubectl top pods -n wifi-densepose
kubectl top nodes
kubectl get hpa -n wifi-densepose
curl http://localhost:8080/metrics
调试命令集
# 端口转发做本地调试
kubectl port-forward service/wifi-densepose-service 8000:80 -n wifi-densepose
# 进入 Pod 执行命令
kubectl exec -it deployment/wifi-densepose -n wifi-densepose -- /bin/bash
# 检查 Service 端点
kubectl get endpoints -n wifi-densepose
# 查看 Ingress 状态与事件
kubectl describe ingress wifi-densepose-ingress -n wifi-densepose
补充两点源码级排查提示(对应 src/main.py 的启动逻辑):
- 启动日志中若出现
Configuration issues found:,且环境为production,进程会直接sys.exit(1)(如SECRET_KEY仍是开发默认值、未配置DATABASE_URL、未配置任何路由器或姿态模型等,都会被 src/config.py 的validate_configuration()收集为 issue)。这是"Pod 反复 CrashLoopBackOff"最常见的原因,先看日志再 describe Pod; ENABLE_DATABASE_FAILSAFE/ENABLE_REDIS_FAILSAFE两个开关(源码默认开启)会在 PostgreSQL/Redis 不可用时自动降级到 SQLite 与禁用缓存,生产环境如不希望"静默降级",应在 ConfigMap 中显式关闭并让依赖故障直接暴露。
扩展阅读
围绕部署与使用,仓库内还有以下可直接衔接的资料(均在 archive/v1 归档范围内,新项目请优先参考 v2/ 与根目录文档):
- 完整使用手册:archive/v1/docs/user_guide.md
- REST API 端点清单:archive/v1/docs/api_reference.md
- 详细故障排查指南:archive/v1/docs/troubleshooting.md
- DevOps 扩展指南(Terraform / CI/CD / Ansible 章节):archive/v1/docs/deployment/README.md
- v1 归档状态与迁移说明:archive/v1/DEPRECATED.md、ADR-187 归档弃用诚实标注
- 当前维护中的 pip 化路径(ruview / wifi-densepose 2.x 轮子):ADR-117 pip 现代化
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0625
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00