fc-ttsreader: deploy Kokoro to the cluster (replaces BLUEJAY-WS host pointer)

The cluster ttsreader-web was reaching across to BLUEJAY-WS:10401 for
Kokoro synthesis, which meant a workstation-down event broke render-
pipeline TTS. Add a cluster-native ttsreader-kokoro Deployment and
Service inside fc-ttsreader so the cluster owns the engine.

- Image: ghcr.io/remsky/kokoro-fastapi-cpu:latest. Model + 67 voices
  ship inside the image, so no PVC is required.
- Port 8880 (the kokoro-fastapi default; the entrypoint hardcodes it).
- Resources: 250m/1Gi request, 2000m/3Gi limit. CPU-only inference
  matches what AiStation runs locally on BLUEJAY-WS.
- dnsPolicy: None to bypass CoreDNS's *.iamworkin.lan template hijack
  on huggingface.co lookups, same shape as ttsreader-align.
- Probes hit /v1/audio/voices since the kokoro server doesn't expose
  /health; that endpoint is cheap (lists configured voice files).

ttsreader-web env var TtsReader__Kokoro__BaseUrl flips from the
workstation pointer to the cluster service:
http://ttsreader-kokoro.fc-ttsreader.svc.cluster.local.:8880.

AiStation keeps its local http://localhost:8880 since the workstation
operator still wants the audio to render on the local sound device
without a network hop.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Andrew Stoltz
2026-04-25 16:56:39 -05:00
parent e8c5d2afd2
commit 87050e72a9

View File

@@ -229,6 +229,89 @@ spec:
targetPort: 9200
name: http
---
# ttsreader-kokoro — Kokoro-82M TTS via the kokoro-fastapi container.
# Provides high-quality English voices alongside Piper for the TtsReader
# render pipeline AND for AiStation when it talks to the cluster TTS plane
# (instead of pointing back at BLUEJAY-WS:10401). Model + voices ship
# inside the container image, so no PVC is needed.
apiVersion: apps/v1
kind: Deployment
metadata:
name: ttsreader-kokoro
namespace: fc-ttsreader
labels:
app.kubernetes.io/name: ttsreader-kokoro
app.kubernetes.io/part-of: flowercore
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: ttsreader-kokoro
template:
metadata:
labels:
app.kubernetes.io/name: ttsreader-kokoro
app.kubernetes.io/part-of: flowercore
spec:
# Same DNS bypass as ttsreader-align — without it, the *.iamworkin.lan
# CoreDNS template would hijack hexgrad/Kokoro-82M's HuggingFace-style
# repo lookups during model warmup.
dnsPolicy: None
dnsConfig:
nameservers:
- 10.43.0.10
searches:
- fc-ttsreader.svc.cluster.local
- svc.cluster.local
- cluster.local
options:
- name: ndots
value: "2"
containers:
- name: kokoro
image: ghcr.io/remsky/kokoro-fastapi-cpu:latest
ports:
- containerPort: 8880
name: http
resources:
requests:
cpu: 250m
memory: 1Gi
limits:
cpu: 2000m
memory: 3Gi
readinessProbe:
httpGet:
path: /v1/audio/voices
port: 8880
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 18
livenessProbe:
httpGet:
path: /v1/audio/voices
port: 8880
initialDelaySeconds: 180
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
name: ttsreader-kokoro
namespace: fc-ttsreader
spec:
selector:
app.kubernetes.io/name: ttsreader-kokoro
ports:
- port: 8880
targetPort: 8880
name: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -286,7 +369,11 @@ spec:
- name: TtsReader__Kokoro__Enabled
value: "true"
- name: TtsReader__Kokoro__BaseUrl
value: "http://10.0.56.20:10401"
# Cluster-native ttsreader-kokoro Service — replaces the prior
# BLUEJAY-WS host pointer so the render pipeline doesn't need
# the workstation up. AiStation can still hit its local
# http://localhost:8880 instance.
value: "http://ttsreader-kokoro.fc-ttsreader.svc.cluster.local.:8880"
- name: TtsReader__Kokoro__TimeoutSeconds
value: "120"
- name: Speech__Alignment__Enabled