跳至主要內容

將 Mastra 部署至 Kubernetes

Kubernetes 的多個 Pod 上執行 Mastra 應用程式,使其能在負載平衡器後方水平擴充。由於每個 Pod 都是獨立的處理程序,因此 Pod 必須共用發布/訂閱後端與資料庫,否則在某個 Pod 上開始的工作,其他 Pod 將無法得知。

資訊

本指南說明如何部署 Mastra server。如果你使用 server adapterweb framework,請依照該框架平常的方式部署。

警告

多 Pod 支援仰賴 durable Agent,此功能目前為 beta。API 可能會在次要版本中變更。將此功能用於正式環境之前,請先閱讀已知限制

開始之前
「開始之前」的直接連結

你需要:

為什麼多個 Pod 需要共用基礎架構
「為什麼多個 Pod 需要共用基礎架構」的直接連結

單一 Pod 會將執行狀態保存在自己的記憶體中。只有一個 Pod 時沒有問題,因為每個請求都會到達同一個處理程序。但跨 Pod 時就會失效:瀏覽器可能正在串流來自 Pod A 的內容,而使用者的下一個請求卻被路由至 Pod B,但 Pod B 沒有 Pod A 上該次執行的任何記錄。

Redis 與 Postgres 能解決這個落差:

  • 發布/訂閱會在 Pod 之間傳遞事件。當事件在某個 Pod 上發布時,其他 Pod 都會收到。Mastra 使用 RedisStreamsPubSub,它也提供每個執行緒各自的租約,確保同一時間只有一個 Pod 擁有某段對話。請參閱 PubSub
  • 儲存空間會保存執行狀態。Durable Agent 會將每次執行儲存為 Workflow 快照,因此重新啟動後,或請求被路由到其他位置時,任何 Pod 都能從資料庫恢復執行。

設定共用基礎架構
「設定共用基礎架構」的直接連結

Mastra 執行個體指向 Redis 與 Postgres。從環境變數讀取連線資訊,讓每個 Pod 都能執行相同的映像檔。

安裝後端套件:

npm install @mastra/redis-streams @mastra/pg @mastra/redis ioredis

Mastra 執行個體上設定發布/訂閱、儲存空間與共用快取:

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 運作。重新連線的使用者端會從這個快取重播遺漏的事件,因此該快取必須共用。預設的記憶體內快取只能在單一處理程序內提供重播。

使用 durable Agent
「使用 durable Agent」的直接連結

一般的 Agent 會將串流與核准狀態保存在某個 Pod 的記憶體中,因此當請求落到其他 Pod 時,這些狀態無法保留。Durable 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 執行個體註冊 durable Agent。現在,其執行狀態位於 Postgres 中,而事件會透過 Redis 傳遞,因此每個 Pod 都能存取該次執行。

部署
「部署」的直接連結

  1. 建置 Mastra server 並將其容器化,接著把映像檔推送至你的登錄檔。請依照 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. 套用 Deployment 以執行映像檔並讀取共用 Secret。先從一個副本開始,讓第一個 Pod 自行建立資料庫結構,再於下一步擴充:

    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 請求,自動擴縮器就無法計算目標,也不會進行擴縮。

    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 清單,表示部署已開始提供服務。

    警告

    將端點公開之前,請先設定驗證

串流與重新連線
「串流與重新連線」的直接連結

durable Agent 會透過共用的發布/訂閱機制,將串流區塊發布至每次執行各自的主題。使用者端中斷連線後,可使用該次執行的 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。請參閱可恢復串流

多個使用者端可以同時觀察同一次執行。每次 observe() 呼叫都會收到完整串流,因此無論是使用者從兩台裝置觀看,還是兩個人關注同一次執行,都能保持同步。

跨 Pod 核准 Tool
「跨 Pod 核准 Tool」的直接連結

durable 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,並透過共用發布/訂閱機制發布結果,讓觀察該次執行的使用者端收到後續內容。請參閱 Tool 核准

已知限制
「已知限制」的直接連結

  • 預設的處理程序內設定會將執行狀態保存在單一 Pod 的記憶體中,不會與其他 Pod 共用。請使用共用 Redis 與 Postgres 的 durable Agent,讓串流、核准與重新連線能跨 Pod 運作。
  • 跨 Pod 串流、核准與重新連線需要使用 durable Agent 路徑。一般 Agent 會將執行狀態保存在記憶體中,無法在其他 Pod 上恢復。
  • 當多個 Pod 同時針對尚未初始化的資料庫啟動時,它們可能會競相建立資料庫結構,導致其中一個 Pod 無法啟動。請先以一個副本啟動,讓資料庫結構只建立一次,再增加副本數。
  • 若要採用更嚴謹的設定,請在應用程式外部初始化資料庫結構(例如使用一次性的 Kubernetes Job),並將 disableInit: true 設定於每個 Pod 的 PostgresStore