FunASR OpenAI 兼容 API 的 Kubernetes 部署实战:从 CPU 模板到 MOSS GPU 方案
2026/9/13 22:36:01 网站建设 项目流程

FunASR OpenAI 兼容 API 的 Kubernetes 部署实战:从 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

导读

本文基于 examples/openai_api/kubernetes/README.md 展开,系统讲解如何在 Kubernetes 集群中部署 FunASR 的 OpenAI 兼容语音识别服务,为 Agent、Web 后端、工作流引擎(如 Dify、n8n)或批处理任务提供内部的语音端点。你将掌握镜像构建与推送、基于 Kustomize 的声明式部署、port-forward 冒烟测试、集群内服务寻址、资源调优参数,以及面向 MOSS-Transcribe-Diarize 的 GPU 部署方案;同时会结合仓库内的清单文件与源码,理解每项配置背后的设计意图与安全边界。

部署前置条件与安全边界

在开始之前,请确认环境满足以下条件(原文要求所有命令均在 FunASR 仓库根目录执行,包括另开终端中的命令):

  • 已安装 Docker,且拥有一个可写入的镜像仓库(用于存放构建产物);
  • kubectl已配置好目标集群,且当前账号具备在speech命名空间创建资源的权限;
  • 集群存在默认 StorageClass,用于为模型缓存 PVC 动态供给存储;
  • 本地冒烟测试客户端需要Python 3.10 或更高版本,且不依赖任何第三方 Python 包(smoke_test.py 仅使用标准库urllib/json/mimetypes)。

需要特别强调的是:ClusterIP 不等于认证。两个清单(CPU 与 MOSS)都没有提供 NetworkPolicy、认证网关、TLS 或请求限额。在允许不可信客户端访问之前,请先阅读服务安全指南。本文给出的验证路径是本地port-forward,而不是暴露公网 Ingress。

清单的设计刻意保持保守,其意图可从 funasr-api.yaml 中逐一印证:

  • 服务默认使用ClusterIP,而非公开的LoadBalancer
  • FUNASR_DEVICE=cpu为默认值,保证镜像与可移植的 Dockerfile 匹配;
  • /root/.cache挂载持久化缓存卷,模型下载结果在 Pod 重启后得以保留;
  • 配置了/health的 startup、readiness 与 liveness 三种探针;
  • 提供内存介质(emptyDir.medium: Memory)的/dev/shm卷,供 PyTorch 与音频预处理使用。

1. 构建并推送 CPU 镜像

以 API 目录作为 CPU 构建上下文,但 shell 始终停留在仓库根目录:

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

然后将 kustomization.yaml 中的images替换为你推送的镜像。为了可复现部署,建议将示例的可变 tag 换成你镜像仓库的不可变 digest,并在每次发布前记录镜像 digest 与清单,以便回滚。

CPU Dockerfile 的实现要点

从 Dockerfile 源码可以看到该镜像的构建逻辑:

  • 基础镜像为python:3.10-slim,并通过环境变量固化默认行为:FUNASR_MODEL=sensevoiceFUNASR_DEVICE=cpuFUNASR_PORT=8000
  • 安装ffmpeggitlibsndfile1等运行时依赖(音频解码与模型下载所需);
  • 通过 pip 安装funasrfastapiuvicorn[standard]python-multipart——注意它从 PyPI 安装 FunASR,而不是安装当前 checkout 里的 FunASR 包;
  • 仅复制示例server.py/app,因此该镜像依赖不是锁定环境,依赖版本会随 PyPI 滚动更新;
  • 内置 DockerHEALTHCHECK(每 30s、超时 5s、启动期 60s、重试 3 次),与 Kubernetes 探针互为补充;
  • 启动命令为python server.py --host 0.0.0.0 --port ${FUNASR_PORT} --device ${FUNASR_DEVICE} --model ${FUNASR_MODEL},由环境变量驱动。

2. 部署到集群

使用声明式方式创建命名空间并应用 Kustomize 目录:

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

kubectl create namespace ... --dry-run=client -o yaml | kubectl apply -f -是一种幂等的命名空间创建写法,重复执行不会报 "already exists" 错误。

CPU 服务器会在启动 HTTP 之前预加载配置的模型。模型下载与首次加载可能耗时数分钟,因此 startup 探针的失败预算约为 10 分钟(10s周期 ×60次失败,见 funasr-api.yaml 的startupProbe配置);该预算不含镜像拉取、调度和 PVC 绑定耗时。

需要提醒的是:/health返回成功不等于推理可用。从 server.py 的实现看,/health只返回statusdevicemodels_loadedmodels_available四个字段,并不执行任何语音识别。因此在下文完成音频请求验证之前,不要对外放行流量。

清单结构速览

funasr-api.yaml 是一个多文档 YAML,包含:

资源关键配置
PersistentVolumeClaim名称funasr-cacheReadWriteOnce,请求20Gi
ConfigMap注入FUNASR_PORT=8000FUNASR_DEVICE=cpuFUNASR_MODEL=sensevoice三个环境变量
Deploymentreplicas: 1strategy: Recreate;探针均指向/healthrequests: 2 CPU / 8Gilimits: 16Gi;挂载cache/root/.cachedshmemptyDir.medium: Memory,上限2Gi)到/dev/shm
Servicetype: ClusterIPport: 8000targetPort: http

其中strategy: RecreateReadWriteOnce的缓存 PVC 相匹配——同一时间只允许一个 Pod 挂载该卷,滚动更新会先删旧再建新。

3. 冒烟测试

保持服务私有,先通过port-forward验证:

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

保持该终端运行,在仓库根目录另开一个终端:

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

smoke_test.py 的行为细节如下:

  • 仅当当前目录缺少sample.wav时,才会下载公开中文样例(默认地址指向阿里云 OSS 测试音频);若文件已存在则直接复用;
  • 依次打印/health/v1/models以及完整的转写 JSON;
  • 以 multipart 表单提交filemodelresponse_format字段,构造逻辑见其multipart_body函数;
  • 支持--base-url--model--response-format--sample-url--timeout等参数,且各参数均可通过同名环境变量(BASE_URLMODELRESPONSE_FORMATSAMPLE_URLTIMEOUT)注入。

注意:退出码为 0 并不代表识别准确、说话人标签、内存容量或并发能力通过验证。文本与时间戳需要人工检查。同时应避免保留敏感音频或未脱敏的输出。此外,该客户端不发送Authorization,而安全指南中的转写专用网关会刻意拒绝元数据路由,因此请通过本地port-forward使用本冒烟方案,而不是经由那个网关。

集群内客户端寻址

对于集群内的客户端,直接 HTTP 访问使用:

http://funasr-api.speech.svc.cluster.local:8000

作为 OpenAI SDK 的base_url则使用:

http://funasr-api.speech.svc.cluster.local:8000/v1

Dify、n8n 或 Web 后端若与 API 同处一个集群,应指向该 Kubernetes 服务名,而不是localhost

4. 按集群情况调优

下表汇总了原文给出的调优建议,结合清单可进一步定位配置位置:

设置项默认值何时修改
FUNASR_MODELsensevoice先核对模型的依赖与硬件要求;/v1/models列出的只是别名,并不代表每个模型都已就绪
FUNASR_DEVICEcpu仅在构建了 CUDA 镜像并配置好 GPU 调度后才改为cuda
PVC 大小20Gi需要缓存多个模型或大版本模型时增大(对应 funasr-api.yaml 中 PVC 的storage: 20Gi
内存 request8Gi观察启动与实际音频负载后调整(清单中 limits 为16Gi
startup 探针约 10 分钟针对模型初始化调整;镜像拉取、调度、PVC 绑定问题需单独排查

模型别名与底层映射关系见 server.py 的MODEL_CONFIGS:例如sensevoice映射到iic/SenseVoiceSmall并附带fsmn-vad与 30 秒单段上限的 VAD 参数;paraformer额外加载ct-punc标点模型;fun-asr-nano从 Hugging Face Hub 加载并开启trust_remote_code

5. MOSS GPU 替代方案

MOSS-Transcribe-Diarize 是 OpenMOSS-Team 集成进 FunASR 的模型。该清单运行的是打包好的 FunASR HTTP 适配器(verbose_json输出),并非原生 vLLM,也不遵循其diarized_json契约;且说话人标签不构成经过验证的身份信息。关于模型要求、输出格式、无外部 VAD 行为以及其他服务后端,请参考 MOSS 部署指南。

MOSS 清单包含在kustomization.yaml中,需要单独应用。它申请 1 块 NVIDIA GPU、24Gi 内存、40Gi 缓存 PVC 和 8Gi 的内存/dev/shm(见 funasr-moss-api.yaml);这些是模板设置,不是实测容量承诺。部署前请先配置好集群的 GPU device plugin 与调度。

与 CPU 镜像不同,Dockerfile.moss 会复制并安装整个 checkoutCOPY . /opt/funasr+pip install .),因此其构建上下文必须是仓库根目录:

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

要点说明:

  • 基础镜像是pytorch/pytorch:2.9.1-cuda12.8-cudnn9-runtime,并额外安装transformers>=5.6,<6
  • 启动命令为funasr-server --host 0.0.0.0 --port ${FUNASR_PORT} --device ${FUNASR_DEVICE} --model ${FUNASR_MODEL},其中FUNASR_DEVICE默认为cuda:0FUNASR_MODEL默认为moss-transcribe-diarize
  • 构建上下文包含整个仓库,请使用不含凭据或私有数据的干净 checkout

应用前,将 funasr-moss-api.yaml 中的funasr-moss-api:local替换为已推送镜像的不可变 digest。若跳过了 CPU 部署,请先按第 2 节创建speech命名空间,并保存镜像 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 示例保持隔离:

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

MOSS 模板包含 startup 与 readiness 探针,但没有 liveness 探针;其/health响应同样不测试转写能力。请对照自己的音频检查返回文本与说话人分割结果——本方案不承诺特定 GPU 的实时性能或生产负载能力。

6. GPU 部署注意事项

普通 Dockerfile 是 CPU 优先的。仅设置FUNASR_DEVICE=cuda并不会让该镜像变成受支持的 GPU 镜像——还需要 CUDA 运行时、GPU 驱动与调度配置。对于其他 GPU 模型,需要相应调整依赖与调度。

以下字段示意中,resources属于容器(container)级别,而nodeSelector属于 Pod spec 级别,二者并非同一层级、不能直接合并进同一段 YAML:

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

确切的 GPU 标签(label)、运行时类(runtime class)与 device plugin 配置因 Kubernetes 发行版而异。在认证、TLS、上传大小限制与速率限制就位之前,请始终保持服务私有。

7. 运维检查清单

  • 先查 PVC 绑定、镜像拉取、Pod 事件与模型加载日志,再调整探针预算;随后检查/health/v1/models与一次真实音频响应;
  • 记录模型别名、设备、音频时长、响应格式、延迟与错误文本,便于问题回溯;
  • 从单副本起步,因为缓存 PVC 是ReadWriteOnce;横向扩展需配合注册表镜像、每 Pod 独立缓存或共享只读模型缓存,并先测量内存与启动时间;
  • 为预期客户端强制认证与 NetworkPolicy——命名空间本身不是网络隔离边界;
  • 集群内的 Dify、n8n 或 Web 后端应指向 Kubernetes 服务名而非localhost

安全加固补充

SECURITY.md 对 Kubernetes 场景给出了进一步约束,可作为上文清单的延伸:

  • ClusterIP不会阻止集群内其他 Pod 或可达主机调用该服务,暴露 Ingress/LoadBalancer 前必须先落地 TLS、认证、上传限额与速率限制;
  • 模型缓存卷应限定在拥有该服务的命名空间或节点池内私有使用;
  • NetworkPolicy限制可调用该服务的命名空间;
  • 首次验证务必走kubectl port-forward+smoke_test.py,之后再考虑暴露路由;
  • 若启用 GPU,需固定调度规则,并在部署记录中写明镜像 tag、CUDA 运行时与模型别名。

结语

本文完整覆盖了 FunASR OpenAI 兼容 API 在 Kubernetes 上的部署路径:从保守的 CPU 清单(持久化模型缓存、三探针、/dev/shm内存卷)到面向 MOSS-Transcribe-Diarize 的 GPU 模板,再到集群内寻址、冒烟验证与安全加固。核心要点可以概括为:先本地 port-forward 验证推理,再谈暴露;先补认证与网络策略,再谈公网;先测量内存与启动,再谈扩容。相关清单与脚本均可直接在 examples/openai_api/kubernetes 目录下查看与复用。

【免费下载链接】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),仅供参考

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

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

立即咨询