跳到主要内容

将 Mastra 部署到 Kubernetes

Kubernetes 的多个 Pod 中运行 Mastra 应用,使其在负载均衡器后水平扩缩。由于每个 Pod 都是独立进程,Pod 必须共享发布/订阅后端和数据库;否则,一个 Pod 上启动的工作对其他 Pod 不可见。

信息

本指南介绍如何部署 Mastra Server。如果你使用的是 Server 适配器Web 框架,请按该框架的常规方式进行部署。

注意

多 Pod 支持依赖持久化 Agent,该功能目前处于 beta 阶段。API 可能在次要版本中发生变化。在生产环境中依赖此功能前,请阅读已知限制

开始之前
开始之前的直接链接

你需要:

  • 一个 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 install @mastra/redis-streams @mastra/pg @mastra/redis ioredis

Mastra 实例上配置发布/订阅、Storage 和共享缓存:

src/mastra/index.ts
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:

src/mastra/agents/assistant.ts
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 都能访问该次运行。

部署
部署的直接链接

  1. 构建 Mastra Server 并将其容器化,然后将镜像推送到 Registry。按照 Mastra Server 指南进行构建,并确保 Server 读取 process.env.PORT 且监听 0.0.0.0

  2. 将共享连接字符串存储为 Secret:

    kubectl create secret generic mastra-secrets \
    --from-literal=REDIS_URL='redis://redis:6379' \
    --from-literal=DATABASE_URL='postgresql://user:pass@postgres:5432/mastra'
  3. 应用一个运行该镜像并读取共享 Secret 的 Deployment。先从一个副本开始,让第一个 Pod 单独创建数据库 schema,然后在下一步扩容:

    deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: mastra
    spec:
    replicas: 1
    selector:
    matchLabels:
    app: mastra
    template:
    metadata:
    labels:
    app: mastra
    spec:
    containers:
    - name: mastra
    image: your-registry/mastra:latest
    ports:
    - containerPort: 8080
    env:
    - name: PORT
    value: '8080'
    envFrom:
    - secretRef:
    name: mastra-secrets
    readinessProbe:
    tcpSocket:
    port: 8080
    livenessProbe:
    tcpSocket:
    port: 8080
    resources:
    requests:
    cpu: 500m
    memory: 512Mi

    下方 HorizontalPodAutoscaler 需要 resources.requests.cpu 值。Kubernetes 将 CPU 利用率计算为使用量除以请求量,因此没有 CPU 请求时,autoscaler 无法计算目标,也不会扩缩。

    kubectl apply -f deployment.yaml

    第一个 Pod 就绪后进行扩容:

    kubectl wait --for=condition=available deployment/mastra
    kubectl scale deployment/mastra --replicas=3
    备注

    每个副本都运行相同镜像,并连接到同一个 Redis 和 Postgres。正是共享基础设施而非 Pod 数量,让运行可以跨 Pod。

  4. 使用 Service 暴露 Deployment:

    service.yaml
    apiVersion: v1
    kind: Service
    metadata:
    name: mastra
    spec:
    selector:
    app: mastra
    ports:
    - port: 80
    targetPort: 8080
    kubectl apply -f service.yaml
  5. 使用 HorizontalPodAutoscaler 自动扩缩副本:

    hpa.yaml
    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
    name: mastra
    spec:
    scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: mastra
    minReplicas: 3
    maxReplicas: 10
    metrics:
    - type: Resource
    resource:
    name: cpu
    target:
    type: Utilization
    averageUtilization: 70
    kubectl apply -f hpa.yaml
    备注

    基于 CPU 的自动扩缩要求集群中运行 metrics-server。GKE、EKS 和 AKS 等托管集群包含该组件,而 kind 和 minikube 等本地集群不包含,因此请先在本地集群中启用(例如运行 minikube addons enable metrics-server)。

  6. 验证 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() 重新连接,并从共享缓存中重放错过的块:

src/server/reconnect.ts
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。

启动需要审批的运行:

src/server/approval.ts
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