FunASR OpenAI 兼容 API 的 Kubernetes 部署实战:SenseVoice CPU 与 MOSS GPU 双配方指南
2026/9/14 1:19:08 网站建设 项目流程

FunASR OpenAI 兼容 API 的 Kubernetes 部署实战:SenseVoice CPU 与 MOSS GPU 双配方指南

【免费下载链接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.项目地址: https://gitcode.com/GitHub_Trending/fun/FunASR

导读:本文以 FunASR 仓库内 examples/openai_api/kubernetes/README_zh.md 为核心,完整讲解如何把 FunASR 的 OpenAI 兼容语音接口部署进 Kubernetes 集群,为集群内部的 Agent、Web 后端、工作流引擎或批处理 worker 提供语音能力。你将掌握镜像构建与推送、Kustomize 清单部署、内网 port-forward 冒烟验证、按集群规模调整资源配置,以及 MOSS-Transcribe-Diarize GPU 配方的完整落地路径,并理解探针预算、PVC 缓存、GPU 调度与安全边界等运维要点。

1. 部署概览与前置条件

这套 Kubernetes 模板服务于一个明确场景:让集群内部的服务(而非公网用户)调用语音接口。典型调用方包括 Agent、Web 后端、工作流引擎(如 Dify、n8n)或批处理 worker。模板默认先使用 SenseVoice CPU 配方,文档同时提供独立的 MOSS GPU 配方,用于转写 + 说话人分离(speaker diarization)。

所有命令都必须从 FunASR 仓库根目录执行,包括新开终端中的命令。开始之前,请确认以下前置条件齐备:

  • Docker 可用,且有可推送的镜像仓库(示例使用registry.example.com,构建前必须替换);
  • kubectl已配置并指向目标集群;
  • 当前账号有在speechnamespace 中创建资源的权限;
  • 集群存在可供缓存 PVC 使用的默认 StorageClass
  • 本地 smoke 客户端需要Python 3.10 或更高版本,且不需要安装任何第三方 Python 包(脚本仅使用标准库,见下文源码分析)。

1.1 安全边界:ClusterIP 不是鉴权

这是本指南反复强调的第一原则:ClusterIP 不是鉴权。两套清单(CPU 与 MOSS)都没有提供 NetworkPolicy、鉴权网关、TLS 或请求限制。在允许不可信客户端访问前,务必先阅读 服务安全指南。以下所有配方都通过本地port-forward访问服务,不是公网入口

1.2 模板默认的保守设计

从清单源码可以逐条印证模板的保守取向(见 funasr-api.yaml):

  • 默认ClusterIP:Service 类型为ClusterIP,不直接暴露公网LoadBalancer
  • 默认FUNASR_DEVICE=cpu:与便携 CPU Dockerfile 匹配,避免镜像与运行时不一致;
  • 持久化模型缓存:在/root/.cache挂载 20Gi 的 PVC(funasr-cache),避免 Pod 重启后重复下载模型;
  • 健康检查三件套:startup、readiness、liveness 探针全部使用/health
  • 内存型/dev/shm:挂载emptyDir+medium: Memory(2Gi),便于 PyTorch 和音频预处理使用共享内存。

2. 仓库清单结构速览

Kubernetes 目录下共 4 个文件,分工清晰:

文件作用
kustomization.yamlKustomize 入口,声明资源并覆盖镜像名与 tag
funasr-api.yamlCPU/SenseVoice 配方:PVC + ConfigMap + Deployment + Service
funasr-moss-api.yamlMOSS GPU 配方:PVC + Deployment + Service
README_zh.md本指南对应文档(另有 README.md 英文版)

2.1 CPU 配方对象详解

funasr-api.yaml包含 4 个 Kubernetes 对象:

  • PVCfunasr-cacheReadWriteOnce,20Gi,label 标记为component: cache
  • ConfigMapfunasr-api-config:通过envFrom注入三个环境变量——FUNASR_PORT=8000FUNASR_DEVICE=cpuFUNASR_MODEL=sensevoice
  • Deploymentfunasr-apireplicas: 1strategy: Recreate(单副本滚动,避免 PVC 被多副本同时挂载),容器请求cpu: 2/memory: 8Gi,限制memory: 16Gi;挂载cache(PVC)到/root/.cachedshm(内存 emptyDir)到/dev/shm
  • Servicefunasr-apiClusterIPport: 8000targetPort: http

探针参数与源码一一对应:

探针pathperiodSecondstimeoutSecondsfailureThreshold
startup/health10560
readiness/health1053
liveness/health3053

其中 startup probe 的失败预算约 10 分钟(周期 10s × 失败阈值 60),用于覆盖模型下载与首次加载。

3. 第一步:构建并推送镜像

保持 shell 位于仓库根目录。CPU 镜像使用 API 目录作为构建上下文:

docker build -f examples/openai_api/Dockerfile -t registry.example.com/speech/funasr-api:cpu-latest examples/openai_api docker push registry.example.com/speech/funasr-api:cpu-latest

3.1 CPU Dockerfile 的构建语义

查看 Dockerfile 可以确认几个关键事实:

  • 基础镜像为python:3.10-slim,安装ffmpeggitlibsndfile1等运行时依赖;
  • 通过 pip 安装funasrfastapiuvicorn[standard]python-multipart——从 PyPI 安装 FunASR,而不是安装当前 checkout 的 FunASR 包;依赖环境也未锁定(无固定版本约束);
  • ENV预设默认值FUNASR_MODEL=sensevoiceFUNASR_DEVICE=cpuFUNASR_PORT=8000
  • 仅复制server.py/app/server.py(构建上下文小);
  • Docker 层内置HEALTHCHECK(interval 30s、start-period 60s),与 Kubernetes 探针互为补充;
  • 启动命令python server.py --host 0.0.0.0 --port ${FUNASR_PORT:-8000} --device ${FUNASR_DEVICE:-cpu} --model ${FUNASR_MODEL:-sensevoice},四个参数均可被环境变量覆盖。

3.2 修改镜像引用与不可变部署

推送完成后,需要修改 kustomization.yaml 的images配置:

images: - name: funasr-api newName: registry.example.com/speech/funasr-api newTag: cpu-latest

需要可复现部署时,把示例可变 tag(如cpu-latest)换成镜像仓库的不可变 digest。每次 rollout 前记录镜像 digest 与清单内容,便于故障时回滚。

4. 第二步:部署到集群

依次执行三条命令:

kubectl create namespace speech --dry-run=client -o yaml | kubectl apply -f - kubectl -n speech apply -k examples/openai_api/kubernetes kubectl -n speech rollout status deploy/funasr-api --timeout=15m

说明:

  • 第一条命令以幂等方式创建speechnamespace(dry-run 生成 manifest 再 apply);
  • 第二条命令通过 Kustomize 应用整个目录(PVC、ConfigMap、Deployment、Service 一次到位);
  • 第三条命令阻塞等待 Deployment 完成滚动,超时 15 分钟。

启动耗时预期:CPU 服务在启动 HTTP 前会预加载配置的模型(从 ModelScope/HuggingFace 下载权重并加载),下载与首次加载可能需要几分钟。startup probe 的失败预算约 10 分钟,不包含拉取镜像、调度或 PVC 绑定时间。/health成功只代表进程存活与 HTTP 就绪,不代表推理验收通过——接入流量前,还必须完成下面的真实音频请求。

5. 第三步:内网 Smoke Test

建议保持服务内网私有,通过port-forward验证,不要直接暴露服务:

kubectl -n speech port-forward --address 127.0.0.1 svc/funasr-api 8000:8000

保持 port-forward 运行。在另一个终端的同一仓库根目录执行:

python3 examples/openai_api/smoke_test.py --base-url http://127.0.0.1:8000 --model sensevoice --response-format verbose_json

5.1 smoke 客户端的行为细节

阅读 smoke_test.py 的源码可以明确它的实际行为:

  • 纯标准库实现urllib.request+json+uuid),无需第三方依赖,这也是文档要求 Python 3.10+ 的原因;
  • 仅在当前目录不存在sample.wav时下载公开中文样本(默认 URL 指向阿里云 OSS 的 BAC009 测试音频),已有文件会被复用、不重复下载;
  • 依次请求并打印三部分内容:/health/v1/models(模型 metadata)、/v1/audio/transcriptions(multipart/form-data 上传音频并携带modelresponse_format字段),转写结果以完整 JSON 输出;
  • 支持--audio-path(位置参数,默认sample.wav)、--base-url--model--response-formatjson/verbose_json)、--sample-url--timeout等参数,均可通过环境变量BASE_URLMODELRESPONSE_FORMAT等覆盖。

必须理解验收边界:退出码为零只代表 HTTP 链路通畅,并不验证识别准确率、说话人标签、内存容量或并发能力。请自行核对输出的文本与时间戳。同时注意:

  • 避免保留敏感音频或未脱敏输出;
  • 客户端不发送Authorization;安全指南中的"仅转写"网关会主动拒绝 metadata 路由(如/v1/models),因此这套 smoke 应通过本地 port-forward 运行,不要直接指向该网关

5.2 集群内客户端的 base URL

集群内其他 Pod 访问该服务时,应使用 Kubernetes service name:

  • 直接 HTTP 调用:http://funasr-api.speech.svc.cluster.local:8000
  • OpenAI SDK 调用:http://funasr-api.speech.svc.cluster.local:8000/v1

6. 第四步:根据集群调整配置

配置默认值什么时候调整
FUNASR_MODELsensevoice先检查目标模型的依赖与硬件要求;/v1/models列出别名,不证明每个模型都已就绪
FUNASR_DEVICEcpu只有在镜像已适配 CUDA 且集群 GPU 调度已配置后才改成cuda
PVC 大小20Gi缓存多个模型或较大模型版本时增大
内存 request8Gi根据启动过程和真实音频负载观测结果调整
Startup probe约 10 分钟按模型初始化情况调整;镜像拉取、调度和 PVC 绑定需分别排查

6.1 从 server.py 理解模型别名体系

为什么FUNASR_MODEL的默认值是sensevoice?查看 server.py 中的MODEL_CONFIGS字典可以找到答案。服务内置了 5 个可配置模型别名,每个别名对应一组加载参数(模型 ID、VAD 模型、标点模型、hub 来源等):

别名底层模型关键加载参数
sensevoiceiic/SenseVoiceSmallvad_model=fsmn-vadvad_kwargs.max_single_segment_time=30000
paraformerparaformer-zh附带punc_model=ct-punc
paraformer-enparaformer-en附带vad_model=fsmn-vad
fun-asr-nanoFunAudioLLM/Fun-ASR-Nano-2512hub=hftrust_remote_code=True
moss-transcribe-diarizeOpenMOSS-Team/MOSS-Transcribe-Diarizehub=hfbackend=hf、固定model_revision

load_model()(server.py)在首次调用时通过funasr.AutoModel懒加载模型并缓存进MODEL_REGISTRY,加载耗时会被记录到日志。这意味着:

  • 修改FUNASR_MODEL前,先确认目标模型的依赖与硬件要求(部分模型需要 HuggingFace hub、trust_remote_code或 GPU);
  • 服务启动时只预加载ConfigMap 指定的模型,其他别名只有在被请求时才会现场加载;
  • 换用未在MODEL_CONFIGS中的名字会得到 400 错误。

7. MOSS GPU 替代方案(转写 + 说话人分离)

MOSS-Transcribe-Diarize 是 OpenMOSS-Team 的模型,由 FunASR 集成。这套清单运行打包后的 FunASR HTTP 适配器,使用verbose_json响应格式,不是原生 vLLM 或其diarized_json接口。分离标签是说话人区分结果,不是经过验证的说话人身份。模型要求、输出格式、不依赖外部 VAD 的行为及其他服务后端,见 MOSS 部署指南。

7.1 与 CPU 配方的关键差异

  • kustomization.yaml不包含MOSS 清单,需要单独apply -f
  • MOSS 模板请求一张 NVIDIA GPU、24Gi 内存、40Gi 缓存 PVC,并配置 8Gi 内存型/dev/shm——这些是模板设置,不是实测容量保证
  • 部署前先配置集群的 GPU device plugin 和调度;
  • 与 CPU 镜像不同,Dockerfile.moss复制并安装整个 checkoutCOPY . /opt/funasr+pip install .),因此构建上下文必须是仓库根目录;请使用干净的 checkout,不要把凭据或私有数据放入构建上下文。

从 Dockerfile.moss 还可以确认:基础镜像是pytorch/pytorch:2.9.1-cuda12.8-cudnn9-runtime,额外安装transformers>=5.6,<6,启动命令为打包入口funasr-server --host 0.0.0.0 --port ${FUNASR_PORT:-8000} --device ${FUNASR_DEVICE:-cuda:0} --model ${FUNASR_MODEL:-moss-transcribe-diarize}

7.2 构建、推送与应用

docker build -f examples/openai_api/Dockerfile.moss -t registry.example.com/speech/funasr-api:moss-local . docker push registry.example.com/speech/funasr-api:moss-local

应用前,将 funasr-moss-api.yaml 中 Deployment 的image: funasr-moss-api:local替换为已推送镜像的不可变 digest。如果跳过了 CPU 部署,先按第 4 节创建speechnamespace。保存镜像 digest 和修改后的清单作为回滚记录。

kubectl -n speech apply -f examples/openai_api/kubernetes/funasr-moss-api.yaml kubectl -n speech rollout status deploy/funasr-moss-api --timeout=15m kubectl -n speech port-forward --address 127.0.0.1 svc/funasr-moss-api 8001:8000

在另一个终端的仓库根目录中,使用本地端口 8001(与 CPU 示例的 8000 区分):

python3 examples/openai_api/smoke_test.py --base-url http://127.0.0.1:8001 --model moss-transcribe-diarize --response-format verbose_json

7.3 MOSS 探针差异与验收边界

对比两份清单可以发现:MOSS 模板有 startup 和 readiness probe,没有 liveness probe;其/health只做存活检查,不测试转写能力。因此必须对照音频检查返回的文本与分离结果。这套配方不认证具体 GPU 型号、实时性能或生产负载——它提供的是可运行的起点,容量与性能需要你在真实负载下自行验证。

8. GPU 资源调度说明

普通 Dockerfile 默认面向 CPU,单独设置FUNASR_DEVICE=cuda不会使它成为受支持的 GPU 镜像。其他 GPU 模型需要额外适配依赖与调度配置。下面是字段位置的示意——resources属于 container,nodeSelector属于 Pod spec,不是可以整体粘贴的同层完整清单

resources: limits: nvidia.com/gpu: "1" nodeSelector: nvidia.com/gpu.present: "true"

不同 Kubernetes 发行版的 GPU label、runtime class 和 device plugin 配置并不相同,请以集群实际提供的资源扩展为准。服务对外开放前,先补齐鉴权、TLS、上传大小限制和限流。

9. 运维检查清单

  • 排查顺序:修改探针预算前,先检查 PVC 绑定、镜像拉取、Pod events 和模型加载日志,再检查/health/v1/models和真实音频响应;
  • 记录关键信息:模型别名、设备、音频时长、响应格式、延迟和错误文本;
  • 单副本起步:缓存 PVC 是ReadWriteOnce,建议先从 1 个副本开始;横向扩容前先评估镜像、每 Pod 缓存或共享只读模型缓存方案;
  • 网络隔离:为预期客户端实施鉴权和 NetworkPolicy——namespace 本身不是网络隔离边界
  • 集群内调用规范:Dify、n8n 或 Web 后端在同一集群内访问时,应使用 Kubernetes service name(如http://funasr-api.speech.svc.cluster.local:8000),不要使用localhost

10. 安全与上线边界(补充自服务安全指南)

Kubernetes 模板使用ClusterIP,这本身不能阻止其他 Pod 或可达主机调用服务。在增加 Ingress 或 LoadBalancer 前,建议按 SECURITY_zh.md 的 Kubernetes 注意事项完成:

  • 使用 Ingress controller 或 API 网关强制 TLS、鉴权、上传大小限制和限流;
  • 模型缓存卷只暴露给拥有该服务的 namespace 或 node pool;
  • 使用NetworkPolicy限制可调用服务的 namespace;
  • 第一次验证先kubectl port-forward+smoke_test.py,再开放路由;
  • 增加 GPU 后固定调度规则,并在部署说明中记录镜像 tag、CUDA runtime 和模型 alias。

上线前的验收检查至少覆盖:无鉴权本地 loopback 诊断、带凭据的认证上传、未认证请求必须 401 且不触发推理、非转写路由(/health/v1/models/openapi.json/docs等)保持拒绝、大小与超时边界、以及从不可信网络确认后端不可直连。示例服务会把上传内容读入内存并写临时音频文件,压缩文件的上传字节数不等于解码后的时长或内存占用,容量评估必须以真实音频负载为准。

11. 总结

本指南完整覆盖了 FunASR OpenAI 兼容 API 在 Kubernetes 上的两条部署路径:SenseVoice CPU 配方(Kustomize 一键部署 + 20Gi 模型缓存 + 三探针健康检查)与MOSS GPU 配方(单卡调度 + 转写/说话人分离 + 40Gi 缓存)。从镜像构建、命名空间创建、滚动状态确认、内网 smoke 验证到资源配置调整,每一步都有对应清单源码与 server.py 实现可供查证。部署完成后,集群内的 Agent、Web 后端与工作流引擎即可通过 OpenAI 兼容的/v1/audio/transcriptions接口获得语音识别能力——但请始终牢记:ClusterIP 不是鉴权,对外开放前务必补齐网络策略与网关防护。

【免费下载链接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.项目地址: https://gitcode.com/GitHub_Trending/fun/FunASR

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询