AI时代的Kubernetes教程36招-第3招-企业数字人平台为什么适合用Kubernetes贯穿学习?
企业数字人平台四视图:从服务清单到可编排系统
数字人平台难点不在模型,而在四视图对不上。
[读者] 正在把数字人平台迁到 Kubernetes 的架构师
[痛点] 服务能跑,但 GPU、实时媒体、状态与 HTTP 服务混在一张清单里
[现在读] 需要把应用、节点、网络、数据四视图拆开并重新对齐
[读完] 能独立画出一张可部署、可排查、可演进的企业数字人平台架构图
[旧方案] Docker Compose 里堆 ASR、TTS、LLM、Avatar 和 LiveKit
|
v
[新需求] 多人实时互动、GPU 弹性、RAG 检索与会话持久化同时进入生产
|
v
[冲突] 普通 HTTP 思维管理实时媒体、GPU 节点与有状态数据
|
v
[后果] 调度错层、网络乱配、数据丢失,故障定位只能靠重启
我是老李,做过语音、数字人和实时互动系统。这次拿一个企业数字人平台作为贯穿案例,不聊模型效果,只聊部署边界。
平台里会同时出现 Gateway、User、ASR、TTS、LLM Gateway、RAG、Avatar、LiveKit、PostgreSQL、Redis、Object Storage。它们看起来都是服务,实际运行形态完全不同。
有的吃 CPU,有的吃 GPU;有的无状态,有的保存房间和会话;有的走普通 HTTP,有的必须交换实时媒体;有的同步返回,有的异步回调。把这些差异写进同一张应用清单,就是后面所有故障的起点。
如果应用视图只列服务名,节点视图只列机器,网络视图只列端口,数据视图只列库表,它们能在一次故障里互相对上吗?
当 ASR、TTS、Avatar 要 GPU,LiveKit 要 UDP,PostgreSQL 要持久卷,Redis 要低延迟内存,你还能用同一种 Deployment 模板吗?
如果仍把实时媒体当普通 HTTP、把有状态组件当无状态副本,下一次扩容会先打穿哪一层?
01、故事
现场是一个企业数字人平台:用户从 Web 或 App 进入,先经过 Gateway 和 User,再创建会话。ASR 把语音转文本,LLM Gateway 调用大模型,RAG 补企业知识,TTS 生成语音,Avatar 驱动形象,LiveKit 负责房间内实时音视频。
最初方案很直接:Docker Compose 起所有服务,Gateway 用 Nginx,User 用 Spring Boot,ASR/TTS/Avatar 各起一个 GPU 容器,LLM Gateway 反向代理模型,RAG 用 Python,PostgreSQL、Redis、MinIO 各一个容器。任务是让单路数字人对话先跑通。
单路演示没问题。变化来自生产:要支持多人房间、要弹性扩缩、要 GPU 排队、要 RAG 检索、要会话回放和审计。于是团队把 Compose 翻译成 Kubernetes YAML,问题也从此开始。
他们把 LiveKit 写成 Deployment,把 PostgreSQL 写成 Deployment,把 Redis 也写成 Deployment;Gateway 和 User 用 ClusterIP,LiveKit 用 ClusterIP 加一个错误的 TCP Service;GPU 服务没有 nodeSelector,和普通服务抢节点。应用视图看起来完整,节点、网络、数据视图全是空白。
第一次线上故障发生在晚高峰:房间间歇断流,PostgreSQL Pod 重启后数据丢失,Avatar 扩容一直 Pending。团队以为是模型服务不稳,实际是工作负载类型选错、网络面暴露错、存储边界画错。
先看故事,再看原理。数字人平台不是微服务清单,而是 CPU/GPU、有状态/无状态、同步/异步、实时媒体/普通 HTTP 四组边界的组合。Kubernetes 官方 Workloads 概念里,Pod 是最小单元,但真正决定行为的是上层控制器:Deployment、StatefulSet、DaemonSet、Job、CronJob。选错控制器,等于选错系统假设。
服务先看态
节点再看牌
网络分数据
调度定成败
02、问题
旧方案失效不是某一个服务挂了,而是四视图没有完成映射。应用视图说 LiveKit 是服务,节点视图说它跑在任意节点,网络视图说它走 ClusterIP,数据视图说房间状态在内存。四个视图各自自洽,合起来矛盾。
业务影响先出现:多人房间进入后,用户听到断音;会话记录写不进 PostgreSQL;Avatar 渲染排队,数字人长时间黑屏。客服看到的是“数字人卡”,研发看到的是多个 Pod 重启,运维看到的是 GPU 节点空闲但 Pod Pending。
技术表现可以归为四类:工作负载错配,把 StatefulSet 语义压进 Deployment;节点错配,GPU 服务没有调度约束;网络错配,实时媒体没有 UDP 和外部可达地址;数据错配,有状态数据没有 PVC 和备份恢复路径。
可验证的完成标准不是“平台能跑”,而是四条:应用视图每个组件都有明确工作负载类型;节点视图每个 GPU/CPU/媒体节点都有标签、污点和资源契约;网络视图每个服务都有明确的协议、端口和可达范围;数据视图每个状态都有持久化、生命周期和恢复目标。
清单非架构
映射才是图
状态定形态
协议定边界
03、原理
本篇只需要一个原理:Kubernetes 不是“容器运行器”,而是“工作负载语义管理器”。官方 Workloads 把应用分成不同控制器:Deployment 管理无状态副本,StatefulSet 管理需要稳定网络标识和持久存储的 Pod,DaemonSet 确保每个节点运行守护进程,Job 和 CronJob 处理批处理与定时任务。
反直觉判断:数字人平台里最需要状态语义的,未必是 PostgreSQL,而是 LiveKit 和 Avatar 这类实时会话组件。因为数据库的状态可以落盘、可以主从,实时媒体状态活在房间、发布者、订阅关系和 UDP 路径上,一旦按无状态副本轮转,用户先感知为断流。
第二层原理是资源类型。CPU 服务适合密集打包,GPU 服务需要设备插件、节点标签、污点容忍和配额。普通 HTTP 请求可以经过 Ingress,实时媒体需要 UDP、TURN/TLS 或 LoadBalancer。同步接口适合快速失败,ASR/TTS 流式、RAG 索引、媒体录制更适合异步任务或队列。
第三层原理是数据边界。PostgreSQL 保存用户、会话、审计和配置,要求事务与持久卷;Redis 保存房间路由、短期 token、热缓存,允许丢失但要明确降级;Object Storage 保存录音、视频、模型文件和知识库原始文档,走 S3 API,不进入容器文件系统。
语义定形态
资源定节点
协议定网络
状态定数据
04、架构
[输入] 用户语音、文本、房间事件
|
v
[模块] Gateway/User -> ASR -> LLM Gateway/RAG -> TTS/Avatar
| |
| +-> LiveKit 实时媒体
v
[数据/状态] PostgreSQL、Redis、Object Storage
|
v
[处理] 会话编排、模型推理、RAG 检索、渲染、媒体转发
|
v
[输出] 音频、视频、文本回复、会话记录、审计事件
应用视图先拆服务:
Gateway:CPU、无状态、同步入口、普通 HTTP/WebSocket 边缘,适合 Deployment。
User:CPU、无状态、同步、普通 HTTP,适合 Deployment。
ASR:GPU、会话级有状态、流式/异步、实时音频,适合 Deployment 加会话粘性,或 StatefulSet 管理会话。
TTS:GPU、请求级无状态、流式、音频返回,适合 Deployment。
LLM Gateway:CPU、无状态、同步/流式、普通 HTTP/SSE,适合 Deployment。
RAG:CPU、无状态计算、同步/异步、普通 HTTP,索引数据在外部存储。
Avatar:GPU、会话有状态、实时媒体渲染,适合 StatefulSet 或带粘性的工作负载。
LiveKit:CPU、房间有状态、实时媒体、WebRTC/UDP,适合 StatefulSet、Headless Service、LoadBalancer/NodePort。
PostgreSQL:CPU、有状态、事务、普通 TCP,适合 StatefulSet 或托管数据库。
Redis:CPU、有状态但可降级、低延迟、普通 TCP,适合 StatefulSet 或托管缓存。
Object Storage:外部有状态服务、异步、S3 API,通过 VPC Endpoint 或公网访问。
节点视图分三池:CPU 通用池跑 Gateway、User、LLM Gateway、RAG、Redis、PostgreSQL;GPU 池跑 ASR、TTS、Avatar,带 nvidia.com/gpu 资源、taint 与 tolerations;媒体池或边缘池跑 LiveKit,保证 UDP 端口、带宽和公网地址。应用视图决定 Pod,节点视图决定 Pod 能落在哪。
网络视图按数据面拆:北向入口用 Ingress/LoadBalancer 到 Gateway;内部普通 HTTP 用 ClusterIP;StatefulSet 用 Headless Service 提供稳定 DNS;LiveKit 需要 WebSocket/TCP 信令加 UDP 媒体,必要时 LoadBalancer 或 NodePort;PostgreSQL、Redis 只开内网 ClusterIP;Object Storage 不经过业务 Pod 本地盘。
数据视图按状态类型拆:PostgreSQL 管用户、会话、审计、配置;Redis 管房间路由、token、热缓存,允许重建;Object Storage 管录音、视频、模型 artifact、RAG 原始文档;向量索引可放 PostgreSQL 扩展或独立向量库,但必须纳入备份。边界是:无状态服务可以随时滚动,有状态服务必须定义备份、恢复、扩缩顺序和故障域。收益是四视图能互相验证;代价是部署清单更复杂;适用条件是平台已经进入多人实时和 GPU 生产阶段。
应用说形态
节点说资源
网络说数据
数据说恢复
05、实战一次
环境与版本:Kubernetes 当前受支持版本,NVIDIA device plugin 按集群核验,LiveKit、PostgreSQL、Redis 镜像以项目 deploy/ 为准。以下 YAML 是最小 V1 骨架,未在当前环境实测,以下为预期结果。
依赖:一个命名空间、一个 CPU 节点池、一个 GPU 节点池、一个支持 LoadBalancer 或 NodePort 的集群。若没有 GPU,先只跑 CPU 路径。
配置:先给 GPU 节点打标签和污点。
kubectl label node gpu-node-1 node-pool=gpu
kubectl taint node gpu-node-1 dedicated=gpu:NoSchedule
kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/main/deployments/static/nvidia-device-plugin.yml
核心实现:用 Deployment 跑 Gateway,用 StatefulSet 跑 Redis,用 StatefulSet 跑 LiveKit,用 StatefulSet 跑 PostgreSQL。
apiVersion: apps/v1
kind: Deployment
metadata:
name: gateway
spec:
replicas: 2
selector:
matchLabels:
app: gateway
template:
metadata:
labels:
app: gateway
spec:
containers:
- name: gateway
image: registry.example.com/digital-human/gateway:latest
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /healthz
port: 8080
---
apiVersion: v1
kind: Service
metadata:
name: gateway
spec:
selector:
app: gateway
ports:
- port: 80
targetPort: 8080
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis-headless
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7
ports:
- containerPort: 6379
volumeMounts:
- name: data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:
name: redis-headless
spec:
clusterIP: None
selector:
app: redis
ports:
- port: 6379
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: livekit
spec:
serviceName: livekit-headless
replicas: 1
selector:
matchLabels:
app: livekit
template:
metadata:
labels:
app: livekit
spec:
containers:
- name: livekit
image: livekit/livekit-server:latest
args: [--config, /etc/livekit/config.yaml]
ports:
- containerPort: 7880
- containerPort: 7881
- containerPort: 50000
protocol: UDP
volumeMounts:
- name: config
mountPath: /etc/livekit
volumes:
- name: config
configMap:
name: livekit-config
---
apiVersion: v1
kind: Service
metadata:
name: livekit-headless
spec:
clusterIP: None
selector:
app: livekit
ports:
- name: signal
port: 7880
- name: rtc-tcp
port: 7881
- name: rtc-udp
port: 50000
protocol: UDP
启动:
kubectl apply -f deploy/namespace.yaml
kubectl apply -f deploy/gateway.yaml
kubectl apply -f deploy/redis.yaml
kubectl apply -f deploy/livekit.yaml
kubectl get pods -o wide
请求与验证:
kubectl run curl --rm -it --image=curlimages/curl -- curl -s http://gateway/healthz
kubectl get svc
kubectl get pvc
kubectl logs statefulset/livekit
示例输出:
gateway-7d9c8f6b5d-abcde 1/1 Running 0 2m cpu-node-1
redis-0 1/1 Running 0 1m cpu-node-2
livekit-0 1/1 Running 0 1m media-node-1
NAME STATUS VOLUME
data-redis-0 Bound pvc-redis-0
V1 的目标是先跑通普通 HTTP 入口、Redis 持久卷和 LiveKit 骨架,但还没有解决 GPU 调度、UDP 公网暴露和 PostgreSQL 高可用,这些问题留给排查与优化。
先跑通骨架
再暴露状态
再补资源牌
最后压网络
06、排查
现象一:LiveKit 房间频繁断流,Pod 重启后房间消失,客户端 ICE 失败。怀疑是 LiveKit 进程不稳。检查 kubectl get deploy livekit、kubectl get svc livekit、kubectl logs statefulset/livekit。证据显示 LiveKit 原本被当成 Deployment 多副本,Service 只有 ClusterIP,没有 UDP 暴露,日志里 announce IP 指向 Pod IP。根因是实时媒体有状态且需要 UDP 直连,不能按无状态 HTTP 副本轮转。修复:改成 StatefulSet 加 Headless Service,使用 LoadBalancer 或 NodePort 暴露 TCP 信令与 UDP 媒体,固定 announce IP。
错误尝试: 先给 LiveKit 加 HPA,把副本从 1 扩到 3。为什么错误:每个副本各自维护房间状态,客户端被负载到不同房间,断流和状态分裂更严重。扩容不是网络修复。
现象二:PostgreSQL Pod 重启后数据丢失,用户会话查询为空。怀疑是镜像写错目录。检查 kubectl get pvc、kubectl describe pod postgres-0、kubectl get statefulset postgres。证据显示最初用 Deployment 加 emptyDir,没有任何 PVC。根因是有状态数据库被当成无状态服务。修复:改为 StatefulSet,使用 volumeClaimTemplates 申请 PVC,加入备份 CronJob。
错误尝试: 把 PostgreSQL Deployment 副本调到 3,希望提高可用性。为什么错误:多个 PostgreSQL 实例写同一套存储或各自写本地盘,会出现双主或数据分叉;数据库可靠性来自主从、备份和恢复演练,不是无状态副本。
现象三:Avatar Pod 一直 Pending,GPU 节点看似空闲。怀疑 GPU 不够。检查 kubectl describe pod avatar-xxx、kubectl get nodes --show-labels。证据显示事件为 0/3 nodes available: 3 tainted,Pod 没有 tolerations,也没有 nodeSelector。根因是节点视图与调度契约缺失。修复:给 GPU Pod 加 nodeSelector 与 tolerations,确认 device plugin DaemonSet 就绪。
错误尝试: 给所有节点打上 gpu=true 标签。为什么错误:标签不是设备资源,调度器仍看不到 nvidia.com/gpu;普通服务还会被错误吸引到 GPU 节点,污染资源视图。
断流非模型
丢数据非镜像
挂起非算力
错配才是因
07、优化
V2 从第 06 章证据出发,不改业务代码,先改工作负载、网络和数据边界。
根因一:实时媒体被当无状态。修改:LiveKit 改 StatefulSet,Service 改 Headless 加 LoadBalancer/NodePort,TCP 信令与 UDP 媒体分开,配置固定 announce IP。原因:房间状态和 ICE 路径需要稳定身份。新行为:副本重启后身份稳定,客户端通过外部地址建立媒体。验证:kubectl get statefulset livekit、kubectl get svc livekit、客户端加入房间日志。
根因二:数据库被当无状态。修改:PostgreSQL 改 StatefulSet 或托管数据库,使用 volumeClaimTemplates,加入备份 CronJob。原因:事务和持久卷是状态边界。新行为:Pod 重建后 PVC 重新挂载,备份可恢复。验证:kubectl get pvc、kubectl describe statefulset postgres、备份 Job 日志。
根因三:GPU 调度契约缺失。修改:GPU 节点打 taint,ASR/TTS/Avatar 加 nodeSelector、tolerations、resources.limits nvidia.com/gpu,device plugin 用 DaemonSet 管理。原因:GPU 是节点级扩展资源。新行为:GPU Pod 只落 GPU 池,CPU 服务不抢占。验证:kubectl describe pod asr-xxx、kubectl get daemonset -n kube-system。
根因四:网络面混用。修改:Gateway 走 Ingress/LoadBalancer;内部 HTTP 走 ClusterIP;StatefulSet 用 Headless;LiveKit 单独媒体入口;PostgreSQL/Redis 只允许内网。原因:普通 HTTP 与实时媒体协议不同。新行为:端口和可达范围与数据面一致。验证:kubectl get ingress,svc -o wide。
根因五:数据生命周期缺失。修改:PostgreSQL 管事务,Redis 管可重建状态,Object Storage 管录音、视频、模型和 RAG 原始文件,向量索引纳入备份。原因:不同状态有不同恢复目标。新行为:恢复时能按数据视图找到副本。验证:列出 PVC、Bucket、备份策略并与应用字段对齐。
根因定修改
修改定行为
行为定验证
验证定闭环
08、演进
[同一输入]
|
+--[V1] Deployment 一把梭 / 扩展快,房间与数据库状态丢失
|
+--[V2] 按语义分控制器 / 清单复杂,但恢复与调度可验证
|
[Trade-off]
得到状态边界与调度契约;失去一份 YAML 走天下的简单;适用于多人实时、GPU 与持久化同时存在的阶段
正确性:V1 只保证进程能启动,V2 保证应用视图能映射到节点、网络、数据视图。稳定性:V1 依赖重启和手动修正,V2 依赖控制器语义、健康检查和持久卷。复杂度:V1 清单少,V2 需要 StatefulSet、Headless Service、PVC、DaemonSet、Ingress/LoadBalancer 和备份任务。成本:V2 增加节点池、存储、公网带宽和运维人力。适用范围:V1 适合单路演示,V2 适合企业生产。遗留问题:GPU 共享、模型冷启动、RAG 索引一致性、跨区媒体延迟,仍需要后续专题。
一把梭能演示
分语义可生产
复杂度换恢复
契约换稳定
09、洞见
9.1 应用视图先问状态在哪,再问服务叫什么
反直觉判断:数字人平台里最需要 Kubernetes 状态语义的,往往不是 PostgreSQL,而是 LiveKit 和 Avatar 这类实时会话组件。数据库状态可以落盘、可以主从,实时房间状态却直接决定用户是否断流。应用视图如果不标注有状态/无状态,后面的工作负载选择一定错。
9.2 节点视图不是机器清单,而是调度契约
反直觉判断:GPU 节点越多,如果没有 taint 和资源声明,普通服务越容易抢占,GPU 服务反而更容易 Pending。节点视图必须写清标签、污点、容忍、设备插件和资源配额,否则它只是资产表,不是调度图。
9.3 网络视图按数据面拆,不按服务名拆
Gateway 和 User 走普通 HTTP,可以共享 Ingress;ASR/TTS 可能是流式 WebSocket;LiveKit 需要 TCP 信令加 UDP 媒体;PostgreSQL/Redis 只该在内网。网络视图若只写服务名和端口,不写协议、方向和可达范围,实时媒体一定在公网暴露环节失败。
9.4 数据视图决定恢复目标,而不是存储实现
PostgreSQL、Redis、Object Storage 不是三个同类数据库。PostgreSQL 要事务与备份,Redis 要明确可丢失范围,Object Storage 要生命周期与权限。数据视图先定义 RPO/RTO 和所有权,再选 StatefulSet、托管服务或 S3 兼容存储。
状态先于名
调度先于量
协议先于端口
恢复先于存
10、系统落地
原来有什么:一份服务清单和若干 Docker Compose 文件,能启动 Gateway、User、ASR、TTS、LLM Gateway、RAG、Avatar、LiveKit、PostgreSQL、Redis、Object Storage,但无法解释状态、资源和网络边界。
本篇新增什么:应用视图、节点视图、网络视图、数据视图。应用视图标注 CPU/GPU、有状态/无状态、同步/异步、实时媒体/普通 HTTP;节点视图定义 CPU、GPU、媒体节点池;网络视图定义 Ingress、ClusterIP、Headless、LoadBalancer、UDP;数据视图定义 PostgreSQL、Redis、Object Storage 的职责与恢复目标。
现在能做什么:能把 docs/03-digital-human-architecture.md 中的服务逐项映射到工作负载类型,把 deploy/ 中的 YAML 检查一遍:无状态用 Deployment,有状态用 StatefulSet 或托管服务,GPU 加 nodeSelector 与 tolerations,LiveKit 加媒体入口,数据库加 PVC 与备份。
还缺什么:GPU 共享与隔离策略、模型预热与冷启动、RAG 索引版本化、LiveKit 多区域级联、端到端可观测性、成本分摊。下一步演进:先固化四视图模板,再把每个服务补上资源画像、SLO、恢复目标和容量基线;若仓库文档与当前集群不一致,需按当前官方文档核验。
四图先对齐
清单再落地
缺口列清楚
演进有基线
11、小结
Q1 → 四视图必须能互相映射,否则故障时对不上
Q2 → 不能同模板;无状态 Deployment,有状态 StatefulSet,GPU 节点 taint/toleration,实时媒体独立网络
Q3 → 先打穿网络或调度层,LiveKit UDP 与 GPU Pending 最先暴露
状态 → 形成应用/节点/网络/数据四视图与 V2 工作负载清单
Q1 的答案不是“画一张架构图”,而是四个视图之间的映射关系可验证。Q2 的答案不是选一个控制器,而是按状态和协议选控制器。Q3 的答案不是扩容,而是先补网络面和节点契约。
本篇最终可交付能力:给定企业数字人平台的服务列表,能拆出 Gateway、User、ASR、TTS、LLM Gateway、RAG、Avatar、LiveKit、PostgreSQL、Redis、Object Storage 的 CPU/GPU、有状态/无状态、同步/异步、实时媒体/普通 HTTP 属性,并落成部署检查表。
四图对得上
工作负载选得对
网络数据分得开
生产演进才可控
12、作业
12.1 理解题:为什么 LiveKit 不适合无状态 Deployment 多副本?
参考答案:LiveKit 维护房间、发布者、订阅关系和媒体转发路径,属于实时媒体有状态组件。多副本无状态轮转会让客户端落到不同房间,UDP 路径和 announce 地址也会不稳定。应按 StatefulSet 加 Headless Service 管理稳定身份,再通过 LoadBalancer 或 NodePort 暴露媒体入口。
12.2 实战题:把 Gateway、ASR、PostgreSQL、Object Storage 分别映射到应用、节点、网络、数据四视图。
参考答案:Gateway 是 CPU、无状态、同步、普通 HTTP,应用视图用 Deployment,节点视图落 CPU 池,网络视图走 Ingress/ClusterIP,数据视图不保存核心状态。ASR 是 GPU、会话级有状态、流式/异步、实时音频,节点视图落 GPU 池并加 tolerations,网络视图支持 WebSocket 或流式协议,数据视图只保存临时会话状态。PostgreSQL 是 CPU、有状态、事务、普通 TCP,应用视图用 StatefulSet 或托管数据库,网络视图内网 ClusterIP,数据视图用 PVC 和备份。Object Storage 是外部有状态、异步、S3 API,网络视图走 VPC Endpoint,数据视图管录音、视频、模型和原始文档。
12.3 排障题:Avatar Pod 一直 Pending,GPU 节点却空闲,先查什么?
参考答案:先查 kubectl describe pod 事件,确认是资源不足、污点不容忍还是没有节点匹配。再查 kubectl get nodes --show-labels 和 GPU 节点 taint。常见根因是 Pod 缺少 nvidia.com/gpu 资源声明、nodeSelector 或 tolerations,或 device plugin DaemonSet 未就绪。不要先给所有节点打 GPU 标签,标签不是设备资源。
12.4 架构判断题:如果团队提出“把所有服务都改成 StatefulSet,保证不丢状态”,是否合理?
参考答案:不合理。StatefulSet 适合需要稳定网络标识和持久存储的有状态工作负载,但无状态服务用 StatefulSet 会增加滚动、扩缩和运维复杂度。正确做法是按状态边界分类:Gateway、User、LLM Gateway、RAG 计算层用 Deployment;LiveKit、PostgreSQL、Redis 按状态和恢复目标用 StatefulSet 或托管服务;GPU 设备插件、日志采集等每节点组件用 DaemonSet;索引构建、媒体转码、备份用 Job/CronJob。
题在边界外
答在证据里
排障先视图
架构后取舍
13、思考
数字人平台的核心冲突,不是模型强不强,而是服务清单与运行语义是否对齐。Gateway、User、ASR、TTS、LLM Gateway、RAG、Avatar、LiveKit、PostgreSQL、Redis、Object Storage 可以出现在同一张应用图里,但不能用同一种工作负载假设。
可复用的工程判断是:先画四视图,再选控制器。应用视图标注状态、资源和协议;节点视图定义 CPU/GPU/媒体调度契约;网络视图按数据面拆 TCP、UDP、HTTP、WebSocket;数据视图定义持久化、恢复目标和生命周期。
只要四视图能互相验证,扩容、排障和演进才有共同语言。反直觉判断仍然成立:实时媒体的状态和网络边界,往往比数据库更早决定生产成败。
清单会过期
视图能复用
状态定边界
协议定真章

浙公网安备 33010602011771号