> Discover all available pages from the documentation index: https://mastra.zisheng.pro/llms.txt # 将 Mastra 部署到 Kubernetes 在 [Kubernetes](https://kubernetes.io/) 的多个 Pod 中运行 Mastra 应用,使其在负载均衡器后水平扩缩。由于每个 Pod 都是独立进程,Pod 必须共享发布/订阅后端和数据库;否则,一个 Pod 上启动的工作对其他 Pod 不可见。 > **信息:** 本指南介绍如何部署 [Mastra Server](https://mastra.zisheng.pro/docs/server/mastra-server)。如果你使用的是 [Server 适配器](https://mastra.zisheng.pro/docs/server/server-adapters)或 [Web 框架](https://mastra.zisheng.pro/docs/deployment/web-framework),请按该框架的常规方式进行部署。 > **注意:** 多 Pod 支持依赖[持久化 Agent](https://mastra.zisheng.pro/docs/long-running-agents/durable-agents),该功能目前处于 **beta** 阶段。API 可能在次要版本中发生变化。在生产环境中依赖此功能前,请阅读[已知限制](#known-limitations)。 ## 开始之前 你需要: - 一个 [Mastra 应用](https://mastra.zisheng.pro/guides/getting-started/quickstart) - 一个 [Kubernetes](https://kubernetes.io/docs/setup/) 集群和 [`kubectl`](https://kubernetes.io/docs/tasks/tools/) - 一个集群可以从中拉取镜像的容器 Registry - 一个所有 Pod 均可访问的共享 [Redis](https://redis.io/) 实例 - 一个所有 Pod 均可访问的共享 [PostgreSQL](https://www.postgresql.org/) 数据库 ## 多个 Pod 为何需要共享基础设施 单个 Pod 会将运行状态保存在自身内存中。只有一个 Pod 时没有问题,因为每个请求都会到达同一个进程。但跨 Pod 时便会失效:浏览器可能正从 Pod A 接收流,而用户的下一个请求被路由到 Pod B,但 Pod B 没有 Pod A 上该次运行的记录。 Redis 和 Postgres 可以解决这一问题: - **发布/订阅**在 Pod 之间传递事件。当一个 Pod 发布事件时,其他 Pod 会收到该事件。Mastra 使用 [`RedisStreamsPubSub`](https://mastra.zisheng.pro/reference/pubsub/redis-streams),它还提供按线程租约,确保任一时刻只有一个 Pod 是对话的所有者。请参阅 [PubSub](https://mastra.zisheng.pro/docs/server/pubsub)。 - **Storage** 持久化运行状态。[持久化 Agent](https://mastra.zisheng.pro/docs/long-running-agents/durable-agents) 将每次运行保存为 Workflow 快照,因此重启后或请求被路由到其他位置时,任何 Pod 都可以从数据库恢复运行。 ## 配置共享基础设施 将 `Mastra` 实例指向 Redis 和 Postgres。从环境变量中读取连接详情,使同一个镜像可以在每个 Pod 中运行。 安装后端: **npm**: ```bash npm install @mastra/redis-streams @mastra/pg @mastra/redis ioredis ``` **pnpm**: ```bash pnpm add @mastra/redis-streams @mastra/pg @mastra/redis ioredis ``` **Yarn**: ```bash yarn add @mastra/redis-streams @mastra/pg @mastra/redis ioredis ``` **Bun**: ```bash bun add @mastra/redis-streams @mastra/pg @mastra/redis ioredis ``` 在 `Mastra` 实例上配置发布/订阅、Storage 和共享缓存: ```typescript 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`](https://mastra.zisheng.pro/docs/agents/overview) 会将流和审批状态保存在一个 Pod 的内存中,因此请求落到另一个 Pod 时,这些状态无法保留。[持久化 Agent](https://mastra.zisheng.pro/docs/long-running-agents/durable-agents) 在 Workflow 内运行 Agent 循环并持久化状态,因此任何 Pod 都可以观察或恢复同一次运行。 使用 `createDurableAgent()` 封装 Agent: ```typescript 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](https://mastra.zisheng.pro/docs/server/mastra-server) 指南进行构建,并确保 Server 读取 `process.env.PORT` 且监听 `0.0.0.0`。 2. 将共享连接字符串存储为 Secret: ```bash 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,然后在下一步扩容: ```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 无法计算目标,也不会扩缩。 ```bash kubectl apply -f deployment.yaml ``` 第一个 Pod 就绪后进行扩容: ```bash kubectl wait --for=condition=available deployment/mastra kubectl scale deployment/mastra --replicas=3 ``` > **备注:** 每个副本都运行相同镜像,并连接到同一个 Redis 和 Postgres。正是共享基础设施而非 Pod 数量,让运行可以跨 Pod。 4. 使用 Service 暴露 Deployment: ```yaml apiVersion: v1 kind: Service metadata: name: mastra spec: selector: app: mastra ports: - port: 80 targetPort: 8080 ``` ```bash kubectl apply -f service.yaml ``` 5. 使用 HorizontalPodAutoscaler 自动扩缩副本: ```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 ``` ```bash kubectl apply -f hpa.yaml ``` > **备注:** 基于 CPU 的自动扩缩要求集群中运行 [metrics-server](https://github.com/kubernetes-sigs/metrics-server)。GKE、EKS 和 AKS 等托管集群包含该组件,而 kind 和 minikube 等本地集群不包含,因此请先在本地集群中启用(例如运行 `minikube addons enable metrics-server`)。 6. 验证 Pod 是否正在运行: ```bash kubectl get pods -l app=mastra ``` 在一个终端中转发 Service。该命令会保持在前台运行: ```bash kubectl port-forward service/mastra 8080:80 ``` 在另一个终端中调用 API: ```bash curl http://localhost:8080/api/agents ``` 如果返回 Agent 的 JSON 列表,则表示部署正在提供服务。 > **注意:** 在公开暴露端点之前,请设置[身份验证](https://mastra.zisheng.pro/docs/server/auth)。 ## 流式传输与重新连接 持久化 Agent 通过共享发布/订阅将流块发布到每次运行专属的主题。断开连接的 Client 使用运行 ID 调用 `observe()` 重新连接,并从共享缓存中重放错过的块: ```typescript 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。请参阅[可恢复流](https://mastra.zisheng.pro/docs/long-running-agents/durable-agents)。 多个 Client 可以同时观察同一次运行。每次 `observe()` 调用都会接收完整流,因此无论一个用户从两台设备观察,还是两个人关注同一次运行,都能保持同步。 ## 跨 Pod 的 Tool 审批 持久化 Agent 会在 Tool 调用处暂停,直到人工批准。由于暂停的运行保存在 Postgres 中,审批可以到达任意 Pod,而不仅限于启动运行的 Pod。 启动需要审批的运行: ```typescript const { runId } = await durableAssistant.stream('Delete the archived records', { requireToolApproval: true, memory: { thread: 'thread-1', resource: 'user-1' }, }) ``` 运行会在 Tool 执行前暂停。稍后可以从任意 Pod 批准: ```typescript await durableAssistant.resume(runId, { approved: true }) ``` 处理审批的 Pod 会从 Postgres 加载暂停的运行,然后执行获批的 Tool,并通过共享发布/订阅发布结果,使观察该次运行的 Client 能够接收后续内容。请参阅 [Tool 审批](https://mastra.zisheng.pro/docs/long-running-agents/durable-agents)。 ## 已知限制 - 默认的进程内设置会将运行状态保存在一个 Pod 的内存中,不会跨 Pod 共享。请将[持久化 Agent](https://mastra.zisheng.pro/docs/long-running-agents/durable-agents) 与共享 Redis 和 Postgres 配合使用,使流式传输、审批和重新连接能跨 Pod 工作。 - 跨 Pod 流式传输、审批和重新连接需要使用持久化 Agent 路径。普通 Agent 会将运行状态保存在内存中,无法在另一个 Pod 上恢复。 - 当多个 Pod 针对未初始化的数据库同时启动时,它们可能会争相创建 schema,导致某个 Pod 启动失败。请先使用一个副本,让 schema 只创建一次,然后再扩容。 - 如需更严格的设置,请在应用外部初始化 schema(例如使用一次性 Kubernetes Job),并在每个 Pod 的 `PostgresStore` 上设置 `disableInit: true`。 ## 相关内容 - [PubSub](https://mastra.zisheng.pro/docs/server/pubsub) - [持久化 Agent](https://mastra.zisheng.pro/docs/long-running-agents/durable-agents) - [Worker](https://mastra.zisheng.pro/docs/deployment/workers):在 Kubernetes 上将后台处理拆分到独立容器中 - [Worker 部署指南](https://mastra.zisheng.pro/guides/deployment/mastra-workers):用于编排器、Scheduler 和后台任务 Worker 的完整 Kubernetes manifest - [Mastra Server](https://mastra.zisheng.pro/docs/server/mastra-server) - [部署概览](https://mastra.zisheng.pro/docs/deployment/overview)