将 Mastra 部署到 Kubernetes
在 Kubernetes 的多个 Pod 中运行 Mastra 应用,使其在负载均衡器后水平扩缩。由于每个 Pod 都是独立进程,Pod 必须共享发布/订阅后端和数据库;否则,一个 Pod 上启动的工作对其他 Pod 不可见。
本指南介绍如何部署 Mastra Server。如果你使用的是 Server 适配器或 Web 框架,请按该框架的常规方式进行部署。
开始之前开始之前的直接链接
你需要:
- 一个 Mastra 应用
- 一个 Kubernetes 集群和
kubectl - 一个集群可以从中拉取镜像的容器 Registry
- 一个所有 Pod 均可访问的共享 Redis 实例
- 一个所有 Pod 均可访问的共享 PostgreSQL 数据库
多个 Pod 为何需要共享基础设施多个 Pod 为何需要共享基础设施的直接链接
单个 Pod 会将运行状态保存在自身内存中。只有一个 Pod 时没有问题,因为每个请求都会到达同一个进程。但跨 Pod 时便会失效:浏览器可能正从 Pod A 接收流,而用户的下一个请求被路由到 Pod B,但 Pod B 没有 Pod A 上该次运行的记录。
Redis 和 Postgres 可以解决这一问题:
- 发布/订阅在 Pod 之间传递事件。当一个 Pod 发布事件时,其他 Pod 会收到该事件。Mastra 使用
RedisStreamsPubSub,它还提供按线程租约,确保任一时刻只有一个 Pod 是对话的所有者。请参阅 PubSub。 - Storage 持久化运行状态。持久化 Agent 将每次运行保存为 Workflow 快照,因此重启后或请求被路由到其他位置时,任何 Pod 都可以从数据库恢复运行。
配置共享基础设施配置共享基础设施的直接链接
将 Mastra 实例指向 Redis 和 Postgres。从环境变量中读取连接详情,使同一个镜像可以在每个 Pod 中运行。
安装后端:
- npm
- pnpm
- Yarn
- Bun
npm install @mastra/redis-streams @mastra/pg @mastra/redis ioredis
pnpm add @mastra/redis-streams @mastra/pg @mastra/redis ioredis
yarn add @mastra/redis-streams @mastra/pg @mastra/redis ioredis
bun add @mastra/redis-streams @mastra/pg @mastra/redis ioredis
在 Mastra 实例上配置发布/订阅、Storage 和共享缓存:
import { Mastra } from '@mastra/core'
import { RedisStreamsPubSub } from '@mastra/redis-streams'
import { RedisServerCache } from '@mastra/redis'
import { PostgresStore } from '@mastra/pg'
import Redis from 'ioredis'
export const mastra = new Mastra({
// Carries events between pods, and provides
// per-thread leases so one pod owns a conversation at a time.
pubsub: new RedisStreamsPubSub({
url: process.env.REDIS_URL!,
}),
// Persists run state so any pod can resume a run.
storage: new PostgresStore({
id: 'mastra-storage',
connectionString: process.env.DATABASE_URL!,
}),
// Shared event cache so a reconnecting client can replay missed chunks
// from any pod, not only the one that started the run.
cache: new RedisServerCache({ client: new Redis(process.env.REDIS_URL!) }),
})
cache 让可恢复流能够跨 Pod 工作。重新连接的 Client 会从该缓存重放错过的事件,因此它必须共享。默认内存缓存只能在单个进程内提供重放。
使用持久化 Agent使用持久化 Agent的直接链接
普通 Agent 会将流和审批状态保存在一个 Pod 的内存中,因此请求落到另一个 Pod 时,这些状态无法保留。持久化 Agent 在 Workflow 内运行 Agent 循环并持久化状态,因此任何 Pod 都可以观察或恢复同一次运行。
使用 createDurableAgent() 封装 Agent:
import { Agent } from '@mastra/core/agent'
import { createDurableAgent } from '@mastra/core/agent/durable'
const agent = new Agent({
id: 'assistant',
name: 'Assistant',
instructions: 'You are a helpful assistant.',
model: 'openai/gpt-5.6-sol',
})
export const durableAssistant = createDurableAgent({ agent })
向上述 Mastra 实例注册持久化 Agent。它的运行状态现在保存在 Postgres 中,事件通过 Redis 流转,因此每个 Pod 都能访问该次运行。
部署部署的直接链接
构建 Mastra Server 并将其容器化,然后将镜像推送到 Registry。按照 Mastra Server 指南进行构建,并确保 Server 读取
process.env.PORT且监听0.0.0.0。将共享连接字符串存储为 Secret:
kubectl create secret generic mastra-secrets \--from-literal=REDIS_URL='redis://redis:6379' \--from-literal=DATABASE_URL='postgresql://user:pass@postgres:5432/mastra'应用一个运行该镜像并读取共享 Secret 的 Deployment。先从一个副本开始,让第一个 Pod 单独创建数据库 schema,然后在下一步扩容:
deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata:name: mastraspec:replicas: 1selector:matchLabels:app: mastratemplate:metadata:labels:app: mastraspec:containers:- name: mastraimage: your-registry/mastra:latestports:- containerPort: 8080env:- name: PORTvalue: '8080'envFrom:- secretRef:name: mastra-secretsreadinessProbe:tcpSocket:port: 8080livenessProbe:tcpSocket:port: 8080resources:requests:cpu: 500mmemory: 512Mi下方 HorizontalPodAutoscaler 需要
resources.requests.cpu值。Kubernetes 将 CPU 利用率计算为使用量除以请求量,因此没有 CPU 请求时,autoscaler 无法计算目标,也不会扩缩。kubectl apply -f deployment.yaml第一个 Pod 就绪后进行扩容:
kubectl wait --for=condition=available deployment/mastrakubectl scale deployment/mastra --replicas=3备注每个副本都运行相同镜像,并连接到同一个 Redis 和 Postgres。正是共享基础设施而非 Pod 数量,让运行可以跨 Pod。
使用 Service 暴露 Deployment:
service.yamlapiVersion: v1kind: Servicemetadata:name: mastraspec:selector:app: mastraports:- port: 80targetPort: 8080kubectl apply -f service.yaml使用 HorizontalPodAutoscaler 自动扩缩副本:
hpa.yamlapiVersion: autoscaling/v2kind: HorizontalPodAutoscalermetadata:name: mastraspec:scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: mastraminReplicas: 3maxReplicas: 10metrics:- type: Resourceresource:name: cputarget:type: UtilizationaverageUtilization: 70kubectl apply -f hpa.yaml备注基于 CPU 的自动扩缩要求集群中运行 metrics-server。GKE、EKS 和 AKS 等托管集群包含该组件,而 kind 和 minikube 等本地集群不包含,因此请先在本地集群中启用(例如运行
minikube addons enable metrics-server)。验证 Pod 是否正在运行:
kubectl get pods -l app=mastra在一个终端中转发 Service。该命令会保持在前台运行:
kubectl port-forward service/mastra 8080:80在另一个终端中调用 API:
curl http://localhost:8080/api/agents如果返回 Agent 的 JSON 列表,则表示部署正在提供服务。
注意在公开暴露端点之前,请设置身份验证。
流式传输与重新连接流式传输与重新连接的直接链接
持久化 Agent 通过共享发布/订阅将流块发布到每次运行专属的主题。断开连接的 Client 使用运行 ID 调用 observe() 重新连接,并从共享缓存中重放错过的块:
const { output, cleanup } = await durableAssistant.observe(runId)
for await (const chunk of output.fullStream) {
// Chunks from the run, including any missed while disconnected
}
cleanup()
由于运行状态保存在 Postgres 中、事件保存在 Redis 中,因此重新连接请求可以由任何 Pod 提供服务,而不仅限于启动运行的 Pod。请参阅可恢复流。
多个 Client 可以同时观察同一次运行。每次 observe() 调用都会接收完整流,因此无论一个用户从两台设备观察,还是两个人关注同一次运行,都能保持同步。
跨 Pod 的 Tool 审批跨 Pod 的 Tool 审批的直接链接
持久化 Agent 会在 Tool 调用处暂停,直到人工批准。由于暂停的运行保存在 Postgres 中,审批可以到达任意 Pod,而不仅限于启动运行的 Pod。
启动需要审批的运行:
const { runId } = await durableAssistant.stream('Delete the archived records', {
requireToolApproval: true,
memory: { thread: 'thread-1', resource: 'user-1' },
})
运行会在 Tool 执行前暂停。稍后可以从任意 Pod 批准:
await durableAssistant.resume(runId, { approved: true })
处理审批的 Pod 会从 Postgres 加载暂停的运行,然后执行获批的 Tool,并通过共享发布/订阅发布结果,使观察该次运行的 Client 能够接收后续内容。请参阅 Tool 审批。
已知限制已知限制的直接链接
- 默认的进程内设置会将运行状态保存在一个 Pod 的内存中,不会跨 Pod 共享。请将持久化 Agent 与共享 Redis 和 Postgres 配合使用,使流式传输、审批和重新连接能跨 Pod 工作。
- 跨 Pod 流式传输、审批和重新连接需要使用持久化 Agent 路径。普通 Agent 会将运行状态保存在内存中,无法在另一个 Pod 上恢复。
- 当多个 Pod 针对未初始化的数据库同时启动时,它们可能会争相创建 schema,导致某个 Pod 启动失败。请先使用一个副本,让 schema 只创建一次,然后再扩容。
- 如需更严格的设置,请在应用外部初始化 schema(例如使用一次性 Kubernetes Job),并在每个 Pod 的
PostgresStore上设置disableInit: true。
相关内容相关内容的直接链接
- PubSub
- 持久化 Agent
- Worker:在 Kubernetes 上将后台处理拆分到独立容器中
- Worker 部署指南:用于编排器、Scheduler 和后台任务 Worker 的完整 Kubernetes manifest
- Mastra Server
- 部署概览