Retinaface+CurricularFace 人脸识别服务 Kubernetes StatefulSet 部署实战
在将训练好的人脸识别模型投入线上服务时,单机部署往往难以应对流量压力,而普通 Deployment 又面临状态丢失风险。对于 Retinaface+CurricularFace 这类有状态服务,Kubernetes 的 StatefulSet 是更稳妥的选择。本文将介绍如何从零搭建一个高可用、可扩展的人脸识别服务集群。
1. 为什么选择 StatefulSet 部署人脸识别服务?
人脸识别模型服务具有模型文件大、加载时间长、需要持久化存储以及服务发现需稳定等特点。若使用普通的 Deployment,Pod 重启后可能被调度到不同节点,导致存储丢失和网络标识变更。StatefulSet 则提供了稳定的网络标识(如 face-recognition-0)、有序的部署扩展以及每个 Pod 独立的持久化存储。
下图展示了两者在有状态服务场景下的核心区别:
graph TD A[人脸识别服务需求] --> B{选择部署方式}
B --> C[Deployment]
B --> D[StatefulSet]
C --> C1[无状态服务]
C --> C2[Pod 名称随机]
C --> C3[存储随 Pod 删除]
C --> C4[适合 Web 前端]
D --> D1[有状态服务]
D --> D2[Pod 名称固定]
D --> D3[存储持久化]
D --> D4[适合数据库/模型服务]
E[Retinaface+CurricularFace] --> F[模型文件大]
E --> G[加载时间长]
E --> H[需要持久存储]
F --> D
G --> D
H --> D
2. 环境准备与镜像说明
2.1 镜像环境配置
我们使用的镜像已预置完整的推理环境,无需手动安装 PyTorch 或 CUDA。基础配置如下:
- 基础镜像: Ubuntu 20.04
- Python 版本: 3.11.14
- 深度学习框架: PyTorch 2.5.0 + CUDA 12.1
- 算法: Retinaface(检测) + CurricularFace(识别)
- 工作目录: /root/Retinaface_CurricularFace
镜像内包含预训练模型、优化过的推理脚本及完整 Python 环境,开箱即用。
2.2 本地测试验证
部署前建议在本地验证镜像功能,提前发现环境问题。
# 1. 拉取镜像
docker pull your-registry/retinaface-curricularface:latest
# 2. 运行容器并进入
docker run -it --gpus all your-registry/retinaface-curricularface:latest bash
# 3. 激活环境并测试
cd /root/Retinaface_CurricularFace
conda activate torch25
python inference_face.py
正常输出应包含特征提取结果和相似度得分,这验证了 GPU 驱动、CUDA 及模型文件的完整性。
3. Kubernetes StatefulSet 部署配置
3.1 创建命名空间和存储
首先创建独立命名空间,并配置持久化存储以保存日志和临时文件。
# 1-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: face-recognition
labels:
name: face-recognition
---
# 2-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
replication-type: none
---
# 3-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: face-model-pvc
namespace: face-recognition
spec:
accessModes:
- ReadWriteOnce
storageClassName: fast-ssd
resources:
requests:
storage: 10Gi
3.2 StatefulSet 核心配置
这是最关键的部分,重点在于 serviceName、GPU 资源申请及探针配置。
# 4-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: face-recognition
namespace: face-recognition
labels:
app: face-recognition
spec:
serviceName: "face-recognition-service"
replicas: 3
selector:
matchLabels:
app: face-recognition
template:
metadata:
labels:
app: face-recognition
spec:
nodeSelector:
accelerator: nvidia-tesla-t4
containers:
- name: face-recognition-container
image: your-registry/retinaface-curricularface:latest
imagePullPolicy: Always
resources:
limits:
nvidia.com/gpu: 1
memory: "8Gi"
cpu: "4"
requests:
nvidia.com/gpu: 1
memory: "4Gi"
cpu: "2"
env:
- name: MODEL_DIR
value: "/models"
- name: LOG_LEVEL
value: "INFO"
ports:
- containerPort: 8000
name: http
protocol: TCP
command: ["/bin/bash", "-c"]
args:
- |
source /root/miniconda3/bin/activate torch25
if [ ! -f /data/models/retinaface.pth ]; then
echo "复制模型文件到持久化存储..."
cp -r /root/Retinaface_CurricularFace/models/* /data/models/
fi
cd /root/Retinaface_CurricularFace
python http_server.py --port 8000 --model-dir /data/models
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 60
periodSeconds: 30
readinessProbe:
httpGet:
path: /ready
port: 8000
initialDelaySeconds: 90
periodSeconds: 20
volumeMounts:
- name: model-storage
mountPath: /data/models
- name: log-storage
mountPath: /var/log/face-recognition
volumeClaimTemplates:
- metadata:
name: model-storage
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "fast-ssd"
resources:
requests:
storage: 10Gi
- metadata:
name: log-storage
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "fast-ssd"
resources:
requests:
storage: 5Gi
注意 volumeClaimTemplates 会为每个 Pod 自动创建独立的 PVC,确保数据不丢失。探针初始延迟设置较长,因为模型加载需要时间。
3.3 服务暴露配置
使用 Headless Service 配合 Ingress 进行访问控制。
# 5-service.yaml
apiVersion: v1
kind: Service
metadata:
name: face-recognition-service
namespace: face-recognition
spec:
clusterIP: None
selector:
app: face-recognition
ports:
- port: 8000
targetPort: 8000
name: http
---
# 6-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: face-recognition-ingress
namespace: face-recognition
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
spec:
ingressClassName: nginx
rules:
- host: face-recognition.your-domain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: face-recognition-service
port:
number: 8000
4. 部署与验证
按顺序执行以下命令完成部署:
kubectl apply -f 1-namespace.yaml
kubectl apply -f 2-storageclass.yaml
kubectl apply -f 3-pvc.yaml
kubectl apply -f 4-statefulset.yaml
kubectl apply -f 5-service.yaml
kubectl apply -f 6-ingress.yaml
检查状态:
kubectl get statefulset -n face-recognition
kubectl get pods -n face-recognition -l app=face-recognition
kubectl logs -f face-recognition-0 -n face-recognition
健康状态下,所有 Pod 应显示为 Running 且 READY 为 1/1。
5. 生产环境优化建议
5.1 性能与安全配置
添加启动钩子预热模型,减少首次推理延迟,并限制文件系统权限。
containers:
- name: face-recognition-container
lifecycle:
postStart:
exec:
command: ["/bin/bash", "-c", "python /root/Retinaface_CurricularFace/warmup.py"]
securityContext:
capabilities:
add: ["IPC_LOCK"]
privileged: false
readOnlyRootFilesystem: true
resources:
limits:
nvidia.com/gpu: 1
memory: "12Gi"
ephemeral-storage: "20Gi"
5.2 监控与日志收集
集成 Prometheus 指标采集,便于观察请求量和延迟。
# 7-monitoring.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: face-recognition-metrics
namespace: face-recognition
data:
prometheus-scrape.yaml: |
- job_name: 'face-recognition'
scrape_interval: 30s
static_configs:
- targets: ['face-recognition-0.face-recognition-service.face-recognition.svc.cluster.local:8000']
在 http_server.py 中增加 /metrics 接口返回 Prometheus 格式数据。
5.3 自动扩缩容配置
根据 CPU 和内存负载自动调整副本数。
# 8-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: face-recognition-hpa
namespace: face-recognition
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: StatefulSet
name: face-recognition
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300
6. 常见问题与解决方案
GPU 调度失败:检查节点标签是否匹配,确认 NVIDIA 设备插件已安装。
kubectl label nodes <node-name> accelerator=nvidia-tesla-t4
PVC Pending:通常由 StorageClass 配置错误或配额不足引起,查看事件详情排查。
kubectl describe pvc <pvc-name> -n face-recognition
DNS 解析失败:StatefulSet 依赖 CoreDNS,确保 Service 名称正确(pod-name.service.namespace.svc.cluster.local)。
首次推理延迟高:启用 postStart 钩子预热模型,或调整 readinessProbe 的初始延迟。
7. 总结
通过 StatefulSet 部署,我们实现了 Retinaface+CurricularFace 服务的稳定性与持久化。结合 HPA 和监控体系,该方案可支撑从中小规模到大规模的业务增长。后续可根据实际需求引入模型量化、TensorRT 加速或微服务架构进一步优化性能。技术部署是一个持续迭代的过程,保持对业务负载的敏感度并及时调整资源配置是关键。

