1. 生产环境CVAT部署需求分析
计算机视觉标注工具CVAT在AI训练数据准备环节扮演着关键角色。当标注任务达到企业级规模时,单机部署方案在可靠性、扩展性和协作效率方面都会遇到瓶颈。这正是我们选择Kubernetes+Helm进行生产级部署的核心原因——通过容器编排实现资源动态调度,利用Helm标准化应用配置管理。
生产环境部署CVAT需要重点解决三大挑战:
- 持久化存储需求:标注数据(原始图片/视频+标注结果)需要高性能、高可靠的存储方案,传统本地存储无法满足容量和可用性要求
- GPU资源调度:交互式标注工具依赖GPU加速预览和智能标注功能,需要精确控制Pod调度
- 访问安全性:标注数据通常包含未公开的原始素材,必须通过HTTPS加密传输
我们最终确定的架构方案如下:
- 存储层:采用Ceph RGW提供S3兼容对象存储,通过RBD提供块存储
- 调度层:通过节点亲和性+污点容忍实现GPU节点专有化
- 网络层:使用Cert-Manager自动管理Let's Encrypt证书
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础环境准备
2.1 Kubernetes集群配置
推荐使用至少包含3个Worker节点的集群,硬件配置建议:
- Master节点:4核8GB内存(仅运行控制平面组件)
- Worker节点:
- 通用计算节点:8核16GB内存(运行前端、后端等无状态服务)
- GPU节点:16核64GB内存 + NVIDIA T4/Tesla V100(运行AI辅助标注组件)
bash复制# 验证节点资源情况
kubectl get nodes -o wide
kubectl describe nodes | grep -A 10 "Capacity"
2.2 Helm客户端配置
使用Helm 3.12+版本,配置稳定仓库和CVAT实验仓库:
bash复制helm repo add stable https://charts.helm.sh/stable
helm repo add cvat https://cvat.github.io/cvat-helm
helm repo update
注意:生产环境建议通过helm pull下载chart后审计内容,再通过本地路径安装
2.3 Ceph集群对接
在Kubernetes集群中部署Ceph CSI驱动:
yaml复制# ceph-csi-rbd-sc.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-rbd-sc
provisioner: rbd.csi.ceph.com
parameters:
clusterID: ceph-cluster-id
pool: rbd
imageFeatures: layering
csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
csi.storage.k8s.io/provisioner-secret-namespace: default
csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
csi.storage.k8s.io/node-stage-secret-namespace: default
reclaimPolicy: Retain
allowVolumeExpansion: true
创建存储卷声明示例:
yaml复制# cvat-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: cvat-data-pvc
spec:
storageClassName: csi-rbd-sc
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Gi
3. Helm定制化部署CVAT
3.1 values.yaml关键配置
yaml复制# values-prod.yaml
global:
ingress:
enabled: true
className: nginx
hosts:
- host: cvat.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: cvat-tls
hosts:
- cvat.example.com
redis:
enabled: true
architecture: standalone
persistence:
enabled: true
size: 50Gi
postgresql:
enabled: true
persistence:
enabled: true
size: 100Gi
resources:
requests:
memory: 4Gi
cpu: 2
cvat:
backend:
replicas: 3
resources:
limits:
cpu: 4
memory: 8Gi
extraEnv:
- name: DJANGO_MODWSGI_EXTRA_ARGS
value: "--processes 4 --threads 2"
worker:
replicas: 4
resources:
limits:
cpu: 2
memory: 4Gi
gpu:
enabled: true
count: 1
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
ui:
replicas: 2
resources:
limits:
cpu: 1
memory: 2Gi
storage:
useCeph: true
ceph:
accessKey: "CEPH_ACCESS_KEY"
secretKey: "CEPH_SECRET_KEY"
bucket: "cvat-data"
endpoint: "http://ceph-rgw.example.com"
3.2 GPU节点调度策略
- 标记GPU节点并添加污点:
bash复制kubectl label nodes gpu-node-1 hardware-type=gpu
kubectl taint nodes gpu-node-1 nvidia.com/gpu=present:NoSchedule
- 在values.yaml中配置对应的亲和性和容忍:
yaml复制worker:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: hardware-type
operator: In
values:
- gpu
tolerations:
- key: "nvidia.com/gpu"
operator: "Exists"
effect: "NoSchedule"
3.3 安装部署命令
bash复制# 安装Cert-Manager(如尚未安装)
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.11.0 \
--set installCRDs=true
# 部署CVAT
helm install cvat cvat/cvat \
-f values-prod.yaml \
--namespace cvat-prod \
--create-namespace \
--version 0.7.0
4. HTTPS配置与优化
4.1 Cert-Manager证书签发
创建ClusterIssuer资源:
yaml复制# letsencrypt-prod.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
更新Ingress配置自动获取证书:
yaml复制# 在values.yaml中补充
ingress:
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
4.2 安全加固配置
- 强制HTTPS跳转:
yaml复制nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
- 启用HSTS:
yaml复制nginx.ingress.kubernetes.io/hsts: "true"
nginx.ingress.kubernetes.io/hsts-max-age: "31536000"
nginx.ingress.kubernetes.io/hsts-include-subdomains: "true"
- 密码策略增强(通过Django配置):
yaml复制extraEnv:
- name: AUTH_PASSWORD_VALIDATORS
value: |
[
{"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"},
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", "OPTIONS": {"min_length": 12}},
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"}
]
5. 运维监控与问题排查
5.1 健康检查配置
在values.yaml中添加存活和就绪探针:
yaml复制backend:
livenessProbe:
httpGet:
path: /api/health
port: 8080
initialDelaySeconds: 60
periodSeconds: 30
readinessProbe:
httpGet:
path: /api/health
port: 8080
initialDelaySeconds: 30
periodSeconds: 15
worker:
livenessProbe:
exec:
command: ["python", "/usr/bin/health_check.py"]
initialDelaySeconds: 120
periodSeconds: 60
5.2 常见问题处理手册
问题1:GPU节点Pod无法启动
- 检查项:
bash复制kubectl describe pod <pod-name> | grep -A 10 Events nvidia-smi -L # 在GPU节点执行 kubectl get nodes -o json | jq '.items[].status.allocatable' - 解决方案:确认nvidia-device-plugin已正确安装,检查驱动版本兼容性
问题2:Ceph存储访问超时
- 检查项:
bash复制
ceph -s ceph osd pool stats kubectl get pv <pv-name> -o yaml | grep volumeHandle - 解决方案:检查Ceph集群状态,确认网络连通性,调整RBD内核参数
问题3:HTTPS证书续期失败
- 检查项:
bash复制
kubectl describe certificate <cert-name> kubectl logs -n cert-manager <cert-manager-pod-name> - 解决方案:确认DNS解析正确,检查ACME挑战记录,必要时切回HTTP验证
5.3 性能优化建议
-
数据库调优:
yaml复制postgresql: configuration: shared_buffers: 4GB effective_cache_size: 12GB maintenance_work_mem: 1GB -
Redis缓存优化:
yaml复制redis: config: maxmemory: 8gb maxmemory-policy: allkeys-lru -
GPU共享策略:
yaml复制worker: gpu: sharing: enabled: true strategy: "time-slicing" slices: 4
6. 升级与备份策略
6.1 Helm版本升级
-
获取最新chart:
bash复制
helm repo update helm search repo cvat -
差异化比较:
bash复制
helm pull cvat/cvat --version 0.8.0 tar xzvf cvat-0.8.0.tgz diff -urN cvat/ templates/ -
滚动升级:
bash复制helm upgrade cvat cvat/cvat \ -f values-prod.yaml \ --version 0.8.0 \ --namespace cvat-prod \ --atomic \ --timeout 15m
6.2 数据备份方案
-
数据库定时备份:
yaml复制# postgresql-backup-cron.yaml apiVersion: batch/v1beta1 kind: CronJob metadata: name: postgresql-backup spec: schedule: "0 2 * * *" jobTemplate: spec: template: spec: containers: - name: pgdump image: postgres:13 command: ["/bin/sh", "-c"] args: - pg_dump -h postgresql -U postgres -Fc cvat > /backup/cvat-$(date +%Y%m%d).dump volumeMounts: - name: backup-volume mountPath: /backup volumes: - name: backup-volume persistentVolumeClaim: claimName: backup-pvc -
Ceph存储快照:
bash复制# 创建RBD快照 rbd snap create rbd/cvat-data@$(date +%Y%m%d) # 定期清理旧快照 rbd snap purge rbd/cvat-data -
配置备份:
bash复制helm get values cvat -n cvat-prod > cvat-values-$(date +%Y%m%d).yaml kubectl get all,ingress,pvc -n cvat-prod -o yaml > cvat-resources-$(date +%Y%m%d).yaml
