From 8ade9bdb5e692c926f94dd56be4cc5bffb6c34c7 Mon Sep 17 00:00:00 2001 From: zhifu gao Date: Mon, 25 May 2026 17:52:43 +0800 Subject: [PATCH] docs: add Kubernetes OpenAI API deployment template Add CPU-first Kubernetes manifests and deployment docs for the FunASR OpenAI-compatible API. --- README.md | 2 +- README_zh.md | 2 +- docs/deployment_matrix.md | 5 + docs/deployment_matrix_zh.md | 5 + docs/use_case_showcase.md | 3 +- docs/use_case_showcase_zh.md | 3 +- examples/openai_api/README.md | 8 +- examples/openai_api/README_zh.md | 8 +- examples/openai_api/kubernetes/README.md | 80 ++++++++++++ examples/openai_api/kubernetes/README_zh.md | 80 ++++++++++++ .../openai_api/kubernetes/funasr-api.yaml | 114 ++++++++++++++++++ .../openai_api/kubernetes/kustomization.yaml | 8 ++ 12 files changed, 312 insertions(+), 6 deletions(-) create mode 100644 examples/openai_api/kubernetes/README.md create mode 100644 examples/openai_api/kubernetes/README_zh.md create mode 100644 examples/openai_api/kubernetes/funasr-api.yaml create mode 100644 examples/openai_api/kubernetes/kustomization.yaml diff --git a/README.md b/README.md index e17a94c6a..2ddb6e696 100644 --- a/README.md +++ b/README.md @@ -198,7 +198,7 @@ curl http://localhost:8000/v1/audio/transcriptions \ docker pull registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-online-cpu-0.1.12 ``` -[OpenAI API example →](./examples/openai_api/) · [Client recipes →](./examples/openai_api/CLIENTS.md) · [JavaScript/TypeScript recipes →](./examples/openai_api/JAVASCRIPT.md) · [Workflow recipes →](./examples/openai_api/WORKFLOWS.md) · [Postman collection →](./examples/openai_api/POSTMAN.md) · [OpenAPI spec →](./examples/openai_api/OPENAPI.md) · [Deployment matrix →](./docs/deployment_matrix.md) · [Deployment docs →](./runtime/readme.md) · [Agent integration →](https://modelscope.github.io/FunASR/agent.html) +[OpenAI API example →](./examples/openai_api/) · [Client recipes →](./examples/openai_api/CLIENTS.md) · [JavaScript/TypeScript recipes →](./examples/openai_api/JAVASCRIPT.md) · [Kubernetes template →](./examples/openai_api/kubernetes/) · [Workflow recipes →](./examples/openai_api/WORKFLOWS.md) · [Postman collection →](./examples/openai_api/POSTMAN.md) · [OpenAPI spec →](./examples/openai_api/OPENAPI.md) · [Deployment matrix →](./docs/deployment_matrix.md) · [Deployment docs →](./runtime/readme.md) · [Agent integration →](https://modelscope.github.io/FunASR/agent.html) --- diff --git a/README_zh.md b/README_zh.md index edca4929e..26b0289e1 100644 --- a/README_zh.md +++ b/README_zh.md @@ -197,7 +197,7 @@ curl http://localhost:8000/v1/audio/transcriptions \ docker pull registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-online-cpu-0.1.12 ``` -[OpenAI API 示例 →](./examples/openai_api/README_zh.md) · [客户端配方 →](./examples/openai_api/CLIENTS.md) · [JavaScript/TypeScript 配方 →](./examples/openai_api/JAVASCRIPT_zh.md) · [工作流配方 →](./examples/openai_api/WORKFLOWS_zh.md) · [Postman 集合 →](./examples/openai_api/POSTMAN_zh.md) · [OpenAPI 规范 →](./examples/openai_api/OPENAPI_zh.md) · [部署选型 →](./docs/deployment_matrix_zh.md) · [部署文档 →](./runtime/readme_cn.md) · [Agent 集成 →](https://modelscope.github.io/FunASR/agent.html) +[OpenAI API 示例 →](./examples/openai_api/README_zh.md) · [客户端配方 →](./examples/openai_api/CLIENTS.md) · [JavaScript/TypeScript 配方 →](./examples/openai_api/JAVASCRIPT_zh.md) · [Kubernetes 模板 →](./examples/openai_api/kubernetes/README_zh.md) · [工作流配方 →](./examples/openai_api/WORKFLOWS_zh.md) · [Postman 集合 →](./examples/openai_api/POSTMAN_zh.md) · [OpenAPI 规范 →](./examples/openai_api/OPENAPI_zh.md) · [部署选型 →](./docs/deployment_matrix_zh.md) · [部署文档 →](./runtime/readme_cn.md) · [Agent 集成 →](https://modelscope.github.io/FunASR/agent.html) --- diff --git a/docs/deployment_matrix.md b/docs/deployment_matrix.md index 141e441c7..2572f65e9 100644 --- a/docs/deployment_matrix.md +++ b/docs/deployment_matrix.md @@ -9,6 +9,7 @@ Use this page to choose the shortest deployment path for a product, demo, benchm | Python API | Notebooks, offline jobs, first model evaluation | [README quick start](../README.md#quick-start) | Lowest ceremony; caller owns batching, retries, and files. | | OpenAI-compatible API | Private speech API, agents, Dify/LangChain/AutoGen-style clients | [OpenAI API example](../examples/openai_api/) | Easiest integration for apps that already support OpenAI audio APIs. | | Docker Compose API | Reproducible local smoke test or small internal service | [OpenAI API Docker docs](../examples/openai_api/#docker-deployment) | CPU by default; adapt the image before using CUDA in containers. | +| Kubernetes API | Internal speech API for cluster services | [Kubernetes template](../examples/openai_api/kubernetes/) | Starts as private `ClusterIP`; add auth, TLS, network policy, and GPU scheduling before broader exposure. | | Runtime WebSocket service | Live captions, meetings, call-center streams | [Runtime service docs](../runtime/readme.md) | Use when partial results, endpointing, or long-lived audio streams matter. | | vLLM acceleration | Higher-throughput LLM-based ASR with Fun-ASR-Nano | [vLLM guide](./vllm_guide.md) | Use for LLM decoder throughput; does not apply to non-autoregressive Paraformer. | | MCP server | Claude/Cursor/desktop agent speech tools | [MCP example](../examples/mcp_server/) | Good when the ASR result should be exposed as a local tool. | @@ -38,6 +39,10 @@ docker compose up --build Keep CPU mode until you have a CUDA-capable PyTorch/FunASR image. After that, set `FUNASR_DEVICE=cuda` and verify with the same smoke test. Use `python examples/openai_api/smoke_test.py --base-url http://localhost:8000` on systems without bash/curl. +### I want an internal Kubernetes service + +Use the [Kubernetes template](../examples/openai_api/kubernetes/) for a private `ClusterIP` OpenAI-compatible API with persistent model cache, `/health` probes, and a port-forward smoke-test path. Keep the CPU default until you have a CUDA-capable image and cluster GPU scheduling in place. + ### I need streaming or live captioning Use the runtime WebSocket service. Validate chunk size, VAD, endpointing, punctuation, speaker diarization, reconnect behavior, and client backpressure with real audio before production rollout. diff --git a/docs/deployment_matrix_zh.md b/docs/deployment_matrix_zh.md index aa644a072..ab2fb8f02 100644 --- a/docs/deployment_matrix_zh.md +++ b/docs/deployment_matrix_zh.md @@ -9,6 +9,7 @@ | Python API | Notebook、离线任务、首次模型评测 | [README 快速开始](../README_zh.md#快速开始) | 最简单;调用方自己负责批处理、重试和文件管理。 | | OpenAI 兼容 API | 私有语音 API、Agent、Dify/LangChain/AutoGen 风格客户端 | [OpenAI API 示例](../examples/openai_api/README_zh.md) | 已支持 OpenAI audio API 的应用最容易接入。 | | Docker Compose API | 可复现本地 smoke test 或小型内部服务 | [OpenAI API Docker 文档](../examples/openai_api/README_zh.md) | 默认 CPU;容器里使用 CUDA 前需要先适配 CUDA-capable 镜像。 | +| Kubernetes API | 集群内私有语音 API | [Kubernetes 模板](../examples/openai_api/kubernetes/README_zh.md) | 默认私有 `ClusterIP`;对外开放前补齐鉴权、TLS、网络策略和 GPU 调度。 | | Runtime WebSocket 服务 | 实时字幕、会议、客服流式音频 | [Runtime 服务文档](../runtime/readme_cn.md) | 需要中间结果、断句或长连接音频流时选择。 | | vLLM 加速 | Fun-ASR-Nano 等 LLM-based ASR 高吞吐 | [vLLM 指南](./vllm_guide.md) | 适合 LLM 解码吞吐;不适用于非自回归 Paraformer。 | | MCP 服务 | Claude/Cursor/桌面 Agent 语音工具 | [MCP 示例](../examples/mcp_server/) | 适合把 ASR 结果暴露成一个本地工具。 | @@ -38,6 +39,10 @@ docker compose up --build 在没有 CUDA-capable PyTorch/FunASR 镜像前保持 CPU 模式。准备好 CUDA 镜像后,再设置 `FUNASR_DEVICE=cuda` 并用同一个 smoke test 验证。没有 bash/curl 时可运行 `python examples/openai_api/smoke_test.py --base-url http://localhost:8000`。 +### 我想部署集群内服务 + +使用 [Kubernetes 模板](../examples/openai_api/kubernetes/README_zh.md) 部署私有 `ClusterIP` OpenAI 兼容 API,包含持久化模型缓存、`/health` probes 和 port-forward smoke test 路径。在没有 CUDA-capable 镜像和集群 GPU 调度前,请保持默认 CPU 模式。 + ### 我需要流式识别或实时字幕 使用 Runtime WebSocket 服务。上线前请用真实音频验证 chunk size、VAD、断句、标点、说话人分离、重连行为和客户端背压。 diff --git a/docs/use_case_showcase.md b/docs/use_case_showcase.md index 34aedcbe0..b93996cf8 100644 --- a/docs/use_case_showcase.md +++ b/docs/use_case_showcase.md @@ -11,7 +11,7 @@ FunASR is useful far beyond a single offline transcription command. This page co | Migrate from Whisper/cloud ASR | [Migration guide](./migration_from_whisper.md) | Map existing pipelines to FunASR, benchmark representative audio, and plan a safe rollout. | | Build a private speech API | [OpenAI-compatible API example](../examples/openai_api/), [client recipes](../examples/openai_api/CLIENTS.md), [JavaScript/TypeScript recipes](../examples/openai_api/JAVASCRIPT.md), and [workflow recipes](../examples/openai_api/WORKFLOWS.md) | Reuse LangChain, Dify, n8n, AutoGen, and other OpenAI-style clients without sending audio to a cloud ASR provider. | | Add speech input to agents | [MCP server](../examples/mcp_server/) and [voice input](../examples/voice_input/) | Connect local ASR to Claude, Cursor, and desktop agent workflows. | -| Choose a deployment path | [Deployment matrix](./deployment_matrix.md) | Compare Python API, OpenAI API, Docker Compose, WebSocket, vLLM, MCP, batch, subtitles, and Triton. | +| Choose a deployment path | [Deployment matrix](./deployment_matrix.md) | Compare Python API, OpenAI API, Docker Compose, Kubernetes, WebSocket, vLLM, MCP, batch, subtitles, and Triton. | | Serve streaming ASR | [Runtime service docs](../runtime/readme.md) | Run WebSocket or service-mode ASR for live captioning and call-center style workloads. | | Accelerate LLM-based ASR | [vLLM guide](./vllm_guide.md) | Use tensor parallel decoding and streaming service support for Fun-ASR-Nano. | | Generate subtitles | [Subtitle example](../examples/subtitle/) | Turn long audio or video into subtitle files for media workflows. | @@ -39,6 +39,7 @@ Recommended next steps: - Run the [OpenAI-compatible API smoke test](../examples/openai_api/smoke_test.sh) or the cross-platform [Python smoke test](../examples/openai_api/smoke_test.py). - For Node.js or Next.js services, start from the [JavaScript/TypeScript recipes](../examples/openai_api/JAVASCRIPT.md). +- For cluster services, start from the [Kubernetes deployment template](../examples/openai_api/kubernetes/). - Add authentication and network controls at your service boundary. - Record model name, device, driver, and audio duration in bug reports and benchmarks. diff --git a/docs/use_case_showcase_zh.md b/docs/use_case_showcase_zh.md index ed2e1e508..190de8bbe 100644 --- a/docs/use_case_showcase_zh.md +++ b/docs/use_case_showcase_zh.md @@ -11,7 +11,7 @@ FunASR 不只是一个离线转写命令。这个页面把常见的评测、部 | 从 Whisper/云端 ASR 迁移 | [迁移指南](./migration_from_whisper_zh.md) | 将现有流水线映射到 FunASR,用代表性音频评测并规划安全上线。 | | 搭建私有语音 API | [OpenAI 兼容 API 示例](../examples/openai_api/README_zh.md)、[客户端配方](../examples/openai_api/CLIENTS.md)、[JavaScript/TypeScript 配方](../examples/openai_api/JAVASCRIPT_zh.md) 和 [工作流配方](../examples/openai_api/WORKFLOWS_zh.md) | 复用 LangChain、Dify、n8n、AutoGen 等 OpenAI 风格客户端,音频不出内网。 | | 给 Agent 增加语音输入 | [MCP 服务](../examples/mcp_server/) 和 [语音输入示例](../examples/voice_input/) | 将本地 ASR 接入 Claude、Cursor 和桌面 Agent 工作流。 | -| 选择部署路径 | [部署选型表](./deployment_matrix_zh.md) | 对比 Python API、OpenAI API、Docker Compose、WebSocket、vLLM、MCP、批处理、字幕和 Triton。 | +| 选择部署路径 | [部署选型表](./deployment_matrix_zh.md) | 对比 Python API、OpenAI API、Docker Compose、Kubernetes、WebSocket、vLLM、MCP、批处理、字幕和 Triton。 | | 部署流式 ASR | [Runtime 服务文档](../runtime/readme_cn.md) | 面向实时字幕、客服、会议等低延迟场景。 | | 加速 LLM-based ASR | [vLLM 指南](./vllm_guide.md) | 为 Fun-ASR-Nano 使用 tensor parallel 解码和流式服务能力。 | | 生成字幕 | [字幕示例](../examples/subtitle/) | 将长音频或视频转成字幕文件。 | @@ -39,6 +39,7 @@ curl http://localhost:8000/v1/audio/transcriptions \ - 运行 [OpenAI 兼容 API smoke test](../examples/openai_api/smoke_test.sh) 或跨平台 [Python smoke test](../examples/openai_api/smoke_test.py)。 - Node.js 或 Next.js 服务可从 [JavaScript/TypeScript 配方](../examples/openai_api/JAVASCRIPT_zh.md) 开始。 +- 集群内服务可从 [Kubernetes 部署模板](../examples/openai_api/kubernetes/README_zh.md) 开始。 - 在服务边界增加鉴权、限流和网络访问控制。 - 记录模型、设备、驱动、音频时长和处理耗时,便于复现问题和 benchmark。 diff --git a/examples/openai_api/README.md b/examples/openai_api/README.md index 8af9622bf..3a250c3ee 100644 --- a/examples/openai_api/README.md +++ b/examples/openai_api/README.md @@ -13,7 +13,7 @@ python server.py --model sensevoice --device cuda --port 8000 Server starts in ~20s (model loading). Health check: `GET /health` -Need copy-paste integration snippets for Python SDK, JavaScript/TypeScript, HTTP clients, agent tools, Postman, OpenAPI imports, or Dify/n8n-style workflows? See [Client recipes](CLIENTS.md), [JavaScript/TypeScript recipes](JAVASCRIPT.md), [workflow recipes](WORKFLOWS.md), the [Chinese workflow recipes](WORKFLOWS_zh.md), the [Postman collection](POSTMAN.md), and the [OpenAPI spec](OPENAPI.md). +Need copy-paste integration snippets for Python SDK, JavaScript/TypeScript, HTTP clients, agent tools, Postman, OpenAPI imports, Kubernetes deployment, or Dify/n8n-style workflows? See [Client recipes](CLIENTS.md), [JavaScript/TypeScript recipes](JAVASCRIPT.md), [workflow recipes](WORKFLOWS.md), the [Chinese workflow recipes](WORKFLOWS_zh.md), the [Postman collection](POSTMAN.md), the [OpenAPI spec](OPENAPI.md), and the [Kubernetes deployment template](kubernetes/README.md). ### End-to-end smoke test @@ -149,6 +149,12 @@ BASE_URL=http://localhost:8000 bash smoke_test.sh python smoke_test.py --base-url http://localhost:8000 ``` +## Kubernetes Deployment + +For an internal cluster service with persistent model cache, health probes, and a private `ClusterIP`, start from the [Kubernetes deployment template](kubernetes/README.md). Build and push the example image, apply the manifests, then verify through `kubectl port-forward` with `python smoke_test.py --base-url http://localhost:8000`. + +Keep the default CPU mode until you have built a CUDA-capable image and configured GPU scheduling for your cluster. + ## Configuration | Arg | Default | Description | diff --git a/examples/openai_api/README_zh.md b/examples/openai_api/README_zh.md index 9a09f96fc..28af9a506 100644 --- a/examples/openai_api/README_zh.md +++ b/examples/openai_api/README_zh.md @@ -13,7 +13,7 @@ python server.py --model sensevoice --device cuda --port 8000 服务通常会在模型加载后启动。健康检查:`GET /health`。 -需要直接复制的接入示例?可以继续查看 [客户端配方](CLIENTS.md)、[JavaScript/TypeScript 配方](JAVASCRIPT_zh.md)、[工作流配方](WORKFLOWS_zh.md)、[Postman 集合](POSTMAN_zh.md) 和 [OpenAPI 规范](OPENAPI_zh.md)。 +需要直接复制的接入示例?可以继续查看 [客户端配方](CLIENTS.md)、[JavaScript/TypeScript 配方](JAVASCRIPT_zh.md)、[工作流配方](WORKFLOWS_zh.md)、[Postman 集合](POSTMAN_zh.md)、[OpenAPI 规范](OPENAPI_zh.md) 和 [Kubernetes 部署模板](kubernetes/README_zh.md)。 ### 端到端 smoke test @@ -137,6 +137,12 @@ BASE_URL=http://localhost:8000 bash smoke_test.sh python smoke_test.py --base-url http://localhost:8000 ``` +## Kubernetes 部署 + +如果需要在集群内部提供带持久化模型缓存、健康检查和私有 `ClusterIP` 的语音 API,可以从 [Kubernetes 部署模板](kubernetes/README_zh.md) 开始。先构建并推送示例镜像,应用 manifests,再通过 `kubectl port-forward` 和 `python smoke_test.py --base-url http://localhost:8000` 验证。 + +在没有 CUDA-capable 镜像和 GPU 调度配置前,请保持默认 CPU 模式。 + ## 配置 | 参数 | 默认值 | 说明 | diff --git a/examples/openai_api/kubernetes/README.md b/examples/openai_api/kubernetes/README.md new file mode 100644 index 000000000..64ee00c5c --- /dev/null +++ b/examples/openai_api/kubernetes/README.md @@ -0,0 +1,80 @@ +# Kubernetes Deployment for the FunASR OpenAI-Compatible API + +This folder provides a CPU-first Kubernetes template for the `examples/openai_api` server. Use it when you want an internal OpenAI-compatible speech endpoint reachable by agents, web backends, workflow engines, or batch workers inside a cluster. + +The manifest is intentionally conservative: + +- `ClusterIP` service by default, not a public `LoadBalancer`. +- `FUNASR_DEVICE=cpu` by default so the image matches the portable Dockerfile. +- A persistent cache volume mounted at `/root/.cache` so model downloads survive pod restarts. +- `/health` startup, readiness, and liveness probes. +- A memory-backed `/dev/shm` volume for PyTorch and audio preprocessing. + +## 1. Build and push the image + +From `examples/openai_api`: + +```bash +docker build -t registry.example.com/speech/funasr-api:cpu-latest . +docker push registry.example.com/speech/funasr-api:cpu-latest +``` + +Edit `kustomization.yaml` if you use a different registry, repository, or tag. + +## 2. Deploy + +```bash +kubectl create namespace speech --dry-run=client -o yaml | kubectl apply -f - +kubectl -n speech apply -k . +kubectl -n speech rollout status deploy/funasr-api --timeout=15m +``` + +Model download and first load can take several minutes. The `startupProbe` allows up to 10 minutes before Kubernetes restarts the container. + +## 3. Smoke test + +Keep the service private and verify it through `port-forward` first: + +```bash +kubectl -n speech port-forward svc/funasr-api 8000:8000 +``` + +From another terminal in `examples/openai_api`: + +```bash +python smoke_test.py --base-url http://localhost:8000 +``` + +For in-cluster clients, use `http://funasr-api.speech.svc.cluster.local:8000` as the direct HTTP base URL and `http://funasr-api.speech.svc.cluster.local:8000/v1` as the OpenAI SDK base URL. + +## 4. Tune for your cluster + +| Setting | Default | When to change it | +|---|---|---| +| `FUNASR_MODEL` | `sensevoice` | Use another alias after checking `/v1/models`. | +| `FUNASR_DEVICE` | `cpu` | Set to `cuda` only after building a CUDA-capable image and configuring GPU scheduling. | +| PVC size | `20Gi` | Increase when caching multiple models or large model revisions. | +| Memory request | `8Gi` | Tune after observing startup and real audio workloads. | +| Startup probe | 10 minutes | Increase if your registry, model hub, or storage backend is slow. | + +## GPU notes + +The example Dockerfile is CPU-first. For GPU clusters you need to adapt the image to CUDA-capable PyTorch/FunASR dependencies, then add your cluster's GPU scheduling fields, for example: + +```yaml +resources: + limits: + nvidia.com/gpu: "1" +nodeSelector: + nvidia.com/gpu.present: "true" +``` + +Exact GPU labels, runtime classes, and device plugin configuration vary by Kubernetes distribution. Keep the service private until authentication, TLS, upload-size limits, and rate limits are in place. + +## Operational checks + +- Use `/health` for readiness and `/v1/models` to confirm model aliases. +- Log model alias, device, audio duration, response format, latency, and error text. +- Start with one replica because the cache PVC is `ReadWriteOnce`; scale horizontally with a registry image, per-pod cache, or a shared read-only model cache after measuring memory and startup time. +- Put authentication and network policy in front of the service before exposing it outside a trusted namespace. +- For Dify, n8n, or web backends inside the same cluster, point them at the Kubernetes service name instead of `localhost`. diff --git a/examples/openai_api/kubernetes/README_zh.md b/examples/openai_api/kubernetes/README_zh.md new file mode 100644 index 000000000..1c9480dfc --- /dev/null +++ b/examples/openai_api/kubernetes/README_zh.md @@ -0,0 +1,80 @@ +# FunASR OpenAI 兼容 API Kubernetes 部署 + +这个目录提供 `examples/openai_api` 服务的 CPU-first Kubernetes 模板。适合在集群内部为 Agent、Web 后端、工作流引擎或批处理 worker 提供 OpenAI 兼容语音转写接口。 + +模板默认比较保守: + +- 默认使用 `ClusterIP`,不直接暴露公网 `LoadBalancer`。 +- 默认 `FUNASR_DEVICE=cpu`,与便携 Dockerfile 匹配。 +- 在 `/root/.cache` 挂载持久化缓存卷,避免 Pod 重启后重复下载模型。 +- 使用 `/health` 做 startup、readiness 和 liveness probe。 +- 挂载内存型 `/dev/shm`,便于 PyTorch 和音频预处理使用。 + +## 1. 构建并推送镜像 + +在 `examples/openai_api` 目录中执行: + +```bash +docker build -t registry.example.com/speech/funasr-api:cpu-latest . +docker push registry.example.com/speech/funasr-api:cpu-latest +``` + +如果使用不同的 registry、repo 或 tag,请修改 `kustomization.yaml`。 + +## 2. 部署 + +```bash +kubectl create namespace speech --dry-run=client -o yaml | kubectl apply -f - +kubectl -n speech apply -k . +kubectl -n speech rollout status deploy/funasr-api --timeout=15m +``` + +模型下载和首次加载可能需要几分钟。`startupProbe` 默认允许最多 10 分钟,超过后 Kubernetes 才会重启容器。 + +## 3. Smoke test + +建议先保持服务内网私有,通过 `port-forward` 验证: + +```bash +kubectl -n speech port-forward svc/funasr-api 8000:8000 +``` + +在另一个终端进入 `examples/openai_api` 后运行: + +```bash +python smoke_test.py --base-url http://localhost:8000 +``` + +集群内客户端可以使用 `http://funasr-api.speech.svc.cluster.local:8000` 作为直接 HTTP base URL,使用 `http://funasr-api.speech.svc.cluster.local:8000/v1` 作为 OpenAI SDK base URL。 + +## 4. 根据集群调整配置 + +| 配置 | 默认值 | 什么时候调整 | +|---|---|---| +| `FUNASR_MODEL` | `sensevoice` | 调用 `/v1/models` 后按需要切换模型别名。 | +| `FUNASR_DEVICE` | `cpu` | 只有在镜像已适配 CUDA 且集群 GPU 调度已配置后才改成 `cuda`。 | +| PVC 大小 | `20Gi` | 缓存多个模型或较大模型版本时增大。 | +| 内存 request | `8Gi` | 根据启动过程和真实音频负载观测结果调整。 | +| Startup probe | 10 分钟 | registry、模型下载或存储后端较慢时增大。 | + +## GPU 说明 + +示例 Dockerfile 默认面向 CPU。GPU 集群需要先把镜像改成 CUDA-capable PyTorch/FunASR 依赖,再根据集群增加 GPU 调度字段,例如: + +```yaml +resources: + limits: + nvidia.com/gpu: "1" +nodeSelector: + nvidia.com/gpu.present: "true" +``` + +不同 Kubernetes 发行版的 GPU label、runtime class 和 device plugin 配置并不相同。服务对外开放前,请先补齐鉴权、TLS、上传大小限制和限流。 + +## 运维检查 + +- 使用 `/health` 做就绪检查,使用 `/v1/models` 确认模型别名。 +- 记录模型别名、设备、音频时长、响应格式、延迟和错误文本。 +- 由于缓存 PVC 是 `ReadWriteOnce`,建议先从 1 个副本开始;横向扩容前先评估镜像、每 Pod 缓存或共享只读模型缓存方案。 +- 服务暴露到可信 namespace 之外前,先加鉴权和网络策略。 +- Dify、n8n 或 Web 后端在同一集群内访问时,应使用 Kubernetes service name,不要使用 `localhost`。 diff --git a/examples/openai_api/kubernetes/funasr-api.yaml b/examples/openai_api/kubernetes/funasr-api.yaml new file mode 100644 index 000000000..4bafffe7c --- /dev/null +++ b/examples/openai_api/kubernetes/funasr-api.yaml @@ -0,0 +1,114 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: funasr-cache + labels: + app.kubernetes.io/name: funasr-api + app.kubernetes.io/component: cache +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: funasr-api-config + labels: + app.kubernetes.io/name: funasr-api + app.kubernetes.io/component: api +data: + FUNASR_PORT: "8000" + FUNASR_DEVICE: "cpu" + FUNASR_MODEL: "sensevoice" +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: funasr-api + labels: + app.kubernetes.io/name: funasr-api + app.kubernetes.io/component: api +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app.kubernetes.io/name: funasr-api + app.kubernetes.io/component: api + template: + metadata: + labels: + app.kubernetes.io/name: funasr-api + app.kubernetes.io/component: api + spec: + containers: + - name: funasr-api + image: funasr-api:local + imagePullPolicy: IfNotPresent + envFrom: + - configMapRef: + name: funasr-api-config + ports: + - name: http + containerPort: 8000 + readinessProbe: + httpGet: + path: /health + port: http + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /health + port: http + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 3 + startupProbe: + httpGet: + path: /health + port: http + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 60 + resources: + requests: + cpu: "2" + memory: 8Gi + limits: + memory: 16Gi + volumeMounts: + - name: cache + mountPath: /root/.cache + - name: dshm + mountPath: /dev/shm + volumes: + - name: cache + persistentVolumeClaim: + claimName: funasr-cache + - name: dshm + emptyDir: + medium: Memory + sizeLimit: 2Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: funasr-api + labels: + app.kubernetes.io/name: funasr-api + app.kubernetes.io/component: api +spec: + type: ClusterIP + selector: + app.kubernetes.io/name: funasr-api + app.kubernetes.io/component: api + ports: + - name: http + port: 8000 + targetPort: http diff --git a/examples/openai_api/kubernetes/kustomization.yaml b/examples/openai_api/kubernetes/kustomization.yaml new file mode 100644 index 000000000..90084cc5e --- /dev/null +++ b/examples/openai_api/kubernetes/kustomization.yaml @@ -0,0 +1,8 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - funasr-api.yaml +images: + - name: funasr-api + newName: registry.example.com/speech/funasr-api + newTag: cpu-latest