大规模运行 OpenClaw:Docker、Kubernetes 和高可用性设置
例如,如果您配置了 Telegram 机器人令牌,所有三个网关副本都将拥有相同的令牌,但 Telegram 一次只能将消息发送到一个活动的 Webhook 端点。一台配置良好的单台 VPS,配合 systemd、完善的监控和定期备份,就能处理绝大多数实际工作负载,而无需 Kubernetes 那样复杂的运维。中讨论的高级内存后端(QMD、Cognee、Mem0),则这些服务应该各自拥有独立的持久性
在单个 VPS 上使用 systemd 运行 OpenClaw 可以满足很多需求。对于个人使用、少量频道和轻量级自动化来说,它运行良好。但生产环境的工作负载很快就会达到瓶颈:单个网关同时处理并发会话、繁重的 cron 任务、大型内存索引以及多个频道适配器,最终都会遇到 CPU、内存或可靠性方面的限制。这时,你只有两个选择……要么增加硬件,要么重新设计架构。
本文介绍第二种方案:使用 Docker 将 OpenClaw 容器化,将其部署到 Kubernetes 以实现真正的高可用性,并管理使多实例部署真正发挥作用的有状态存储。本文基于“在 VPS 上安全托管 OpenClaw”和“ systemd 服务设置”两篇文章的内容,因此假设您已经拥有一个可用的单实例部署,并希望在此基础上更进一步。
何时才适合进行规模化?
并非所有 OpenClaw 配置都需要这样做。大多数个人部署和小团队配置在单台服务器上就能正常运行,在没有实际必要的情况下增加编排复杂性只会增加维护负担。以下是需要进行编排的信号:
- 在并发会话期间,CPU 使用率会飙升至 80% 以上。如果您的网关在两到三个会话同时运行时就占用大量 CPU 资源,那么单个实例将无法优雅地应对负载。
- 系统日志中会出现 OOM 终止错误。大型工具链、使用 QMD 或 Cognee 进行内存索引以及多代理路由都会导致内存消耗过高。如果操作系统终止了您的网关进程,则说明您的服务器配置不足或需要分配负载。
- 超过 10 个并发会话,或者大量的 cron/心跳并发。一个网关通过其内部通道系统处理会话隔离,但单个进程在不降低响应时间的情况下所能处理的数量是有限的。
- 零停机时间要求。更新单实例 systemd 服务意味着短暂的停机。如果您的通道需要持续运行,则需要副本和滚动部署。
- 处理大量 Webhook 或 API 集成。如果您每小时要路由数百个入站事件,那么单个网关就会成为瓶颈。
如果以上情况都不适用,那么VPS监控指南可能比本文更适合您。
使用 Docker 将 OpenClaw 容器化
编写生产环境 Dockerfile
OpenClaw 有官方镜像(openclaw/openclaw:latest),但如果您想要控制镜像内容——例如特定的 apt 软件包、非 root 用户、自定义构建步骤——则需要编写自己的 Dockerfile。以下是一个基于 Node 22 slim 的生产就绪型 Dockerfile:
FROM node:22-bookworm-slim
RUN corepack enable && \
curl -fsSL https://bun.sh/install | bash && \
mv /root/.bun/bin/bun /usr/local/bin/
WORKDIR /app
# Cache dependencies before copying source (faster rebuilds)
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
COPY ui/package.json ./ui/
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build && pnpm ui:build
ENV NODE_ENV=production
EXPOSE 18789 18793
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD node dist/index.js health || exit 1
CMD ["node", "dist/index.js"]
以下几点需要根据您的具体设置进行调整:
- 如果您需要
ffmpeg某些技能的本地构建工具,请在步骤RUN apt-get update && apt-get install -y ffmpeg build-essential之前添加,COPY以便单独缓存。 USER node在执行该行命令之前切换到非 root 用户CMD,并确保卷挂载点的所有者已相应更改。在私有 VPS 上以 root 用户身份在容器中运行并非世界末日,但当有通道连接到外部服务时,这不是一个好的做法。- 基于 Alpine 的镜像体积更小,但有时会与原生 Node 模块出现兼容性问题。对于生产环境的网关来说,Slim Bookworm 是更安全的选择。
使用 Docker Compose 构建多服务环境
大多数部署场景至少需要三个服务:网关本身、用于运行管理命令的管理容器以及反向代理。以下是一个涵盖这些服务的 Compose 文件:
version: '3.8'
services:
openclaw-gateway:
image: openclaw/openclaw:latest
container_name: openclaw-gateway
restart: unless-stopped
ports:
- "18789:18789"
- "18793:18793"
volumes:
- openclaw-config:/root/.openclaw
- openclaw-workspace:/root/workspace
environment:
- NODE_ENV=production
- OPENCLAW_STATE_DIR=/root/.openclaw
command: openclaw gateway
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '1'
memory: 1G
healthcheck:
test: ["CMD", "node", "dist/index.js", "health"]
interval: 30s
timeout: 10s
retries: 3
openclaw-cli:
image: openclaw/openclaw:latest
volumes_from: [openclaw-gateway]
entrypoint: openclaw
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- certs:/etc/nginx/certs
depends_on:
- openclaw-gateway
volumes:
openclaw-config:
openclaw-workspace:
certs:
这两个命名卷是关键所在。`<volume>`openclaw-config包含所有内容~/.openclaw:您的配置、凭据、会话等cron/jobs.json。` openclaw-workspace<volume>` 包含 MEMORY.md 文件、memory/目录、工具和技能。这两个卷都需要在容器重启后保留——如果您使用临时存储,每次重新部署都会丢失会话和内存。
该openclaw-cli服务与网关共享卷,并提供了一种简洁的方式来运行管理命令,而无需进入正在运行的网关执行操作:
docker compose run --rm openclaw-cli channels login
docker compose run --rm openclaw-cli status --all
docker compose exec openclaw-gateway openclaw status
对于需要 TTY(WhatsApp 二维码扫描、Telegram 登录)的频道设置任务,请使用docker compose run -it --rm openclaw-cli channels login。
特工沙盒
OpenClaw 的沙箱模式在由主机网关协调的隔离子容器中运行工具和会话。您可以使用`--sandbox-mode` agents.defaults.sandbox.mode: "non-main"(将除主代理之外的所有内容都隔离)或 `--sandbox -mode` 进行配置"all"。沙箱容器挂载一个/workspace目录,默认情况下以 ` network: none--sandbox-mode` 运行,并可为需要外部访问的工具启用可选的出口权限。闲置的沙箱会在 24 小时后自动清理,老化的沙箱会在 7 天后清理。在生产环境中启用此功能非常值得,因为它可以限制工具链出现异常行为时的影响范围。
部署到 Kubernetes
Docker Compose 适用于单主机环境。如果您需要多副本、自动故障转移、滚动部署和水平自动扩缩容,Kubernetes 才是您的理想之选。但权衡之下,Kubernetes 的运维复杂性不容忽视,对于不需要其全部功能的场景来说,它并不值得投入。如果您在LumaDock VPS上运行 OpenClaw ,并且单个资源充足的实例就足够了,那么继续使用即可。如果您正在运行具有正常运行时间 SLA 的生产环境部署,请继续阅读。
密钥和命名空间
首先使用命名空间来隔离 OpenClaw 资源,并将所有敏感值放在 Secret 中,而不是放在 ConfigMap 或清单中的环境变量中:
apiVersion: v1
kind: Namespace
metadata:
name: openclaw
---
apiVersion: v1
kind: Secret
metadata:
name: openclaw-secrets
namespace: openclaw
type: Opaque
data:
OPENCLAW_TELEGRAM_TOKEN: <base64-encoded>
ANTHROPIC_API_KEY: <base64-encoded>
DISCORD_BOT_TOKEN: <base64-encoded>
生成 base64 值echo -n 'your-value' | base64。在实际生产集群中,应使用类似 External Secrets Operator 的工具从合适的密钥存储中提取值,而不是直接将值写入清单。
部署清单
apiVersion: apps/v1
kind: Deployment
metadata:
name: openclaw-gateway
namespace: openclaw
spec:
replicas: 3
selector:
matchLabels:
app: openclaw-gateway
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: openclaw-gateway
spec:
containers:
- name: gateway
image: openclaw/openclaw:latest
ports:
- containerPort: 18789
envFrom:
- secretRef:
name: openclaw-secrets
volumeMounts:
- name: config
mountPath: /root/.openclaw
- name: workspace
mountPath: /root/workspace
resources:
limits:
cpu: "2"
memory: "2Gi"
requests:
cpu: "1"
memory: "1Gi"
livenessProbe:
httpGet:
path: /health
port: 18789
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 18789
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: config
persistentVolumeClaim:
claimName: openclaw-config-pvc
- name: workspace
persistentVolumeClaim:
claimName: openclaw-workspace-pvc
对于高可用性 (HA) 来说,三个副本是一个合理的起点:它允许一个 Pod 宕机(例如维护或崩溃),同时仍能保持两个 Pod 处于活动状态。存活探测会在网关停止响应时重启容器;就绪探测会将 Pod 从负载均衡器轮换中移除,直到它真正准备好处理流量。
持续性卷
这就是多副本 OpenClaw 部署的有趣之处。配置卷和工作区卷需要ReadWriteMany访问模式,以便多个 Pod 可以同时挂载它们。并非所有存储提供商都支持读写执行 (RWX)——本地路径配置器不支持,AWS EBS 不支持,但 NFS、CephFS 和 Longhorn 支持。如果您的集群没有支持 RWX 的存储类,那么添加 NFS 是最简便的选择:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: openclaw-config-pvc
namespace: openclaw
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs-client
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: openclaw-workspace-pvc
namespace: openclaw
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs-client
resources:
requests:
storage: 20Gi
如果您运行的是高级内存管理指南中讨论的高级内存后端(QMD、Cognee、Mem0),则这些服务应该各自拥有独立的持久性证书 (PVC),并且最好作为独立的部署运行,而不是与网关捆绑在一起。网关随后通过内部集群 DNS 连接到这些服务,这样可以分离存储问题,并使单独的扩展更加清晰。
服务和入口
apiVersion: v1
kind: Service
metadata:
name: openclaw-service
namespace: openclaw
spec:
selector:
app: openclaw-gateway
ports:
- name: gateway
port: 18789
targetPort: 18789
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: openclaw-ingress
namespace: openclaw
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
spec:
rules:
- host: openclaw.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: openclaw-service
port:
number: 18789
延长代理超时时间很重要,因为网关使用 WebSocket 进行一些通道通信,而 nginx 默认的 60 秒超时时间会断开这些连接。请将其设置为至少 3600 秒(一小时)。
水平舱自动扩缩器
一旦您在部署中定义了资源请求和限制,HPA 就可以根据 CPU 利用率向上或向下扩展副本:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: openclaw-hpa
namespace: openclaw
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: openclaw-gateway
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
将 CPU 利用率设为 70% 作为扩容触发条件较为保守,这是有意为之——您希望在资源饱和之前增加容量,而不是之后。至少 2 个副本可确保在某个 Pod 崩溃时始终有备用方案。
Pod 中断预算
PDB 可以防止 Kubernetes 在节点维护或集群升级期间一次性关闭过多副本:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: openclaw-pdb
namespace: openclaw
spec:
minAvailable: 2
selector:
matchLabels:
app: openclaw-gateway
有了minAvailable: 2三个副本,Kubernetes 永远不会一次主动关闭多个 pod,这意味着您的部署在集群维护窗口期间始终可用。
跨副本管理状态
运行多个 OpenClaw 网关实例时,状态管理是最棘手的部分。网关并非无状态——它需要维护会话、定时任务状态jobs.json、通道凭证和内存。当三个副本都写入同一个共享的 NFS 卷时,你需要考虑其中两个副本同时尝试写入同一个文件时会发生什么情况。
坦白说,OpenClaw 目前的架构是基于单网关模型设计的。通过 RWX PV 共享存储对于配置和凭据(这些文件大多是读取操作,很少写入)以及工作区内存文件(由各个会话按顺序写入)来说效果相当不错。需要特别注意的是cron/jobs.json:如果运行多个网关,并且所有副本都监视同一个作业文件,且各自独立调度运行,则可能会出现重复的 cron 作业执行。
目前可行的缓解方案有两种。第一种方案是指定一个副本作为 cron 领导者——仅配置一个 Pod 启用 cron(OPENCLAW_SKIP_CRON=0),并将其他 Pod 设置为跳过 cron(OPENCLAW_SKIP_CRON=1)。这比听起来要简单:为 cron 领导者 Pod 使用一个单独的 Kubernetes Deployment,并设置不同的环境变量。其他副本处理通道流量和会话,而一个副本负责调度。第二种方案是使用 Redis sidecar 或外部锁服务进行分布式 cron 协调,虽然这种方法更复杂,但在大规模部署时更加简洁。
对于 QMD、Cognee 和 Mem0 等内存后端,请将它们作为专用服务在集群内部运行。每个网关 Pod 都通过内部 DNS 连接到同一个内存服务端点,因此无论哪个 Pod 处理给定会话,所有副本的检索结果都保持一致。API代理设置涵盖了管理共享后端连接的相关模式。
高可用性:健康检查、滚动更新和故障转移
Kubernetes 会在部署配置正确后自动处理大部分工作。存活探针和就绪探针会在不健康的 Pod 开始接收流量之前将其重启并从轮换中移除。滚动更新意味着maxUnavailable: 1在部署期间始终至少有两个 Pod 在处理流量。PDB 则确保维护操作不会一次性关闭过多 Pod。
Kubernetes无法自动处理通道级故障转移。例如,如果您配置了 Telegram 机器人令牌,所有三个网关副本都将拥有相同的令牌,但 Telegram 一次只能将消息发送到一个活动的 Webhook 端点。您需要确保正确配置 Ingress 或负载均衡器,以便 Telegram 的 Webhook 能够访问到集群的稳定端点,而不是特定的 Pod IP。Discord Webhook 和 WhatsApp 回调也存在同样的问题。
另一个需要考虑的问题是凭证刷新。通过二维码建立的 WhatsApp 会话与手机状态绑定,可能会过期。如果存在多个副本,则需要一种不依赖于特定运行 Pod 的凭证刷新方法。这里的管理模式是使用单独的openclaw-cli作业或 Pod 来执行凭证操作,并将结果写入共享配置卷,以便所有网关 Pod 都能读取。
对于集群设置的监控和警报,监控指南涵盖了 Prometheus exporters 和正常运行时间检查,这些检查可以很好地转换为 Kubernetes 上下文。
容器化环境中的备份
命名卷和PVC并非备份策略。它们可以防止容器重启,但无法防止存储损坏、意外删除或集群级灾难。对于Docker Compose配置,请添加一个基于cron的备份容器,将卷快照保存到S3兼容的存储桶或远程存储。对于Kubernetes,Velero是用于PV快照和集群状态备份的标准工具。备份指南涵盖了需要备份的内容以及备份频率——无论您是在单个VPS上运行还是在Kubernetes集群上运行,这些原则都相同。
这适合你的配置吗?
坦白地说:对于大多数 OpenClaw 用户而言,这种架构过于复杂。一台配置良好的单台 VPS,配合 systemd、完善的监控和定期备份,就能处理绝大多数实际工作负载,而无需 Kubernetes 那样复杂的运维。只有当您确凿地感受到性能瓶颈时——例如内存溢出 (OOM) 导致的进程终止、持续的 CPU 饱和、以及造成实际损失的停机时间——才应该考虑容器和集群,而不是将其作为预防措施。
如果你还没达到那个阶段,那么多代理设置指南可能是更实际的下一步。多个代理在单个资源充足的实例上协同工作,可以满足很多吞吐量需求,而无需额外的基础设施开销。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)