☰
Kubernetes生产环境部署CVAT标注系统的实践指南
2026/11/5 2:54:24 网站建设 项目流程

1. 项目概述

最近在部署CVAT(Computer Vision Annotation Tool)计算机视觉标注系统时,遇到了一系列生产环境特有的挑战。作为一个基于Kubernetes的开源标注工具,CVAT虽然提供了Helm Chart,但在实际企业环境中部署时,往往会遇到各种官方文档未提及的"坑"。

本文将详细记录在Kubernetes 1.21集群上部署CVAT 2.56的全过程,重点解决以下核心问题:

  • 如何在特定GPU节点(带有污点)上调度CVAT服务
  • 如何将CVAT的持久化存储对接Ceph集群
  • 如何配置HTTPS访问以解决浏览器安全策略问题
  • 如何处理内网环境下的依赖下载问题

2. 环境准备与Chart处理

2.1 下载Chart包

首先需要从官方仓库拉取CVAT的Helm Chart:

helm pull oci://registry-1.docker.io/cvat/cvat --version 2.55.0 tar -xzf cvat-2.55.0.tgz cd cvat

这里需要注意,由于公司内网环境限制,可能需要配置HTTP代理才能成功拉取Chart:

export http_proxy=http://proxy.example.com:8080 export https_proxy=http://proxy.example.com:8080

2.2 解决Kubernetes版本兼容性问题

官方Chart的Chart.yaml中明确要求Kubernetes版本>=1.23.0,而我们的生产环境仍在使用1.21.10。直接安装会报版本不兼容错误。

解决方案是修改Chart.yaml文件:

# Chart.yaml kubeVersion: '>= 1.21.0-0' # 将1.23改为1.21

注意:这种版本降级操作存在一定风险,需要确保API兼容性。经过测试,CVAT 2.56的核心功能在K8s 1.21上可以正常运行。

2.3 初始化配置文件

为了保持原始配置文件的完整性,建议创建一份覆盖配置:

cp values.yaml values.override.yaml

3. 核心配置修改

3.1 存储配置:对接Ceph集群

CVAT默认使用20Gi的本地存储,这显然不适合生产环境。我们需要将其修改为使用Ceph存储:

# values.override.yaml defaultStorage: enabled: true storageClassName: rook-cephfs # 指定Ceph StorageClass accessModes: - ReadWriteMany # 多节点读写模式 size: 1000Gi # 生产环境建议大容量

对于KV Rocks(Redis)的存储也需要类似配置:

kvrocks: persistence: enabled: true storageClassName: rook-cephfs accessModes: - ReadWriteOnce size: 100Gi

3.2 节点调度配置

我们的CVAT需要运行在特定的GPU节点gpusrv14上,该节点有两个特点:

  1. 有GPU资源
  2. 被打上了污点dedicated=ceph:NoSchedule

首先给目标节点打上标签:

kubectl label node gpusrv14.aa.com cvat-node=true

然后在values文件中配置调度策略:

cvat: backend: # 节点亲和性配置 affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - gpusrv14.aa.com # 节点选择器 nodeSelector: cvat-node: "true" # 污点容忍配置 tolerations: - key: "dedicated" operator: "Equal" value: "ceph" effect: "NoSchedule"

关键点:CVAT Chart设计得比较好的一点是backend配置会被worker等子组件继承,所以不需要每个微服务都单独配置调度策略。

4. 部署与问题排查

4.1 执行安装命令

准备好配置后,执行Helm安装:

helm install gpu-cvat . -n gpu-cvat --create-namespace -f values.yaml -f values.override.yaml

4.2 OPA服务连接问题

部署后遇到的第一个问题是OPA(Open Policy Agent)服务不断重启。查看日志发现健康检查失败:

requests.exceptions.ConnectionError: HTTPConnectionPool(host='opa', port=8181): ... Connection refused

原因分析:

  • OPA默认只监听localhost(127.0.0.1)
  • Kubernetes的健康检查是通过Pod IP访问的
  • 导致探针连接被拒绝,服务被判定为不健康

临时解决方案是直接编辑Deployment:

kubectl edit deployment gpu-cvat-opa -n gpu-cvat

在容器参数中添加--addr=0.0.0.0:8181:

containers: - args: - run - --server - --addr=0.0.0.0:8181 # 关键修改 - --bundle

永久解决方案是在values文件中配置:

cvat: opa: extraArgs: - "--addr=0.0.0.0:8181"

4.3 浏览器安全策略问题

配置好Nginx转发后,访问页面出现白屏或报错:

  1. API请求报405 Not Allowed或401 Unauthorized
  2. 控制台报错:The Cross-Origin-Opener-Policy header has been ignored...
  3. JS报错:ReferenceError: structuredClone is not defined

原因分析: CVAT使用了SharedArrayBuffer等现代浏览器特性,这些特性要求页面必须在安全上下文(Secure Context)中运行,即必须是HTTPS或localhost。

解决方案是配置Nginx SSL并添加必要的安全头:

server { listen 443 ssl; server_name gpu-cvat.aa.com; ssl_certificate /etc/nginx/conf.d/sans_crt2/server.crt; ssl_certificate_key /etc/nginx/conf.d/sans_crt2/server.key; # 后端API转发 location ~ ^/(api|auth|admin|django-static)/ { proxy_pass http://gpu-cvat-backend-service.gpu-cvat.svc.cluster.local:8080; 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; } # 前端页面转发 location / { proxy_pass http://gpu-cvat-frontend-service.gpu-cvat.svc.cluster.local:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 必须的安全头 add_header Cross-Origin-Opener-Policy 'same-origin'; add_header Cross-Origin-Embedder-Policy 'require-corp'; } }

5. 后期配置与管理

5.1 创建管理员账号

CVAT默认不创建任何账号,需要通过Django命令创建超级用户:

export HELM_RELEASE_NAMESPACE="gpu-cvat" export HELM_RELEASE_NAME="gpu-cvat" BACKEND_POD_NAME=$(kubectl get pod --namespace $HELM_RELEASE_NAMESPACE -l tier=backend,app.kubernetes.io/instance=$HELM_RELEASE_NAME,component=server -o jsonpath='{.items[0].metadata.name}') kubectl exec -it --namespace $HELM_RELEASE_NAMESPACE $BACKEND_POD_NAME -c cvat-backend -- python manage.py createsuperuser

5.2 验证存储配置

确认Ceph存储是否正确挂载:

kubectl get pv | grep gpu-cvat

查看PV详情,确认使用的是Ceph存储:

kubectl describe pv/pvc-ec561f53-c54b-47d7-9ddb-6e01850046df | grep subvolumePath

6. 经验总结与注意事项

  1. 微服务架构的运维复杂性: CVAT采用微服务架构,虽然提高了灵活性,但也增加了运维复杂度。特别是当需要统一配置(如节点调度策略)时,需要确保配置能正确继承到所有相关组件。

  2. 生产环境默认配置不足: 很多默认配置(如OPA监听地址)在开发环境可能没问题,但在生产环境会导致严重问题。部署前需要仔细检查各服务的默认配置。

  3. HTTPS不是可选项: 现代浏览器安全策略要求类似CVAT这样的复杂前端应用必须运行在HTTPS下,这一点官方文档强调不足,容易导致部署后出现难以排查的前端问题。

  4. 内网环境适配: 在内网环境中部署时,需要注意:

  • 配置HTTP代理
  • 可能需要预先下载依赖镜像
  • 某些服务(如Grafana插件)可能需要离线安装
  1. 版本兼容性测试: 虽然我们通过修改Chart.yaml成功在K8s 1.21上部署了CVAT,但这种操作存在风险。建议:
  • 充分测试核心功能
  • 记录所有修改点
  • 制定回滚方案
  1. 监控与日志收集: CVAT包含多个组件,建议部署后立即配置:
  • 集中式日志收集
  • 资源使用监控
  • 健康检查告警

在实际使用过程中,我们还发现CVAT的Redis实例(KV Rocks)在高负载下可能出现性能问题,建议根据实际使用情况调整资源配置和持久化策略。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询