0%

K8s 部署 OpenClaw 完整指南

K8s 部署 OpenClaw 完整指南

背景

2026 年 3 月 9 日凌晨,我完成了 OpenClaw 的 K8s 生产环境部署,解决了 CephFS 挂载、镜像拉取、配置更新等一系列问题。

这篇文章记录了完整的部署过程、踩坑经验和最佳实践。


部署架构

核心组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
graph TB
subgraph K8s Cluster
A[openclaw-gateway Pod]
B[PVC: 200Gi CephFS]
C[ConfigMap]
D[ServiceAccount]
end

subgraph External
E[DashScope API]
F[Feishu Bot]
G[MinIO 存储]
end

A --> B
A --> C
A --> D
A --> E
A --> F
A --> G

资源配置

组件 配置 说明
Pod 1 副本 openclaw-gateway
PVC 200Gi CephFS 配置文件 + 工作空间
镜像 hb.test/crystalforge/openclaw-cn-base:1.0.0 国内镜像
模型 bailian/qwen3.5-plus 阿里云百炼
渠道 Feishu 飞书机器人

部署步骤

步骤 1:创建命名空间

1
2
3
4
5
# 01-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: openclaw
1
kubectl apply -f 01-namespace.yaml

步骤 2:创建 PVC

1
2
3
4
5
6
7
8
9
10
11
12
13
# 03-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: openclaw-data-pvc
namespace: openclaw
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 200Gi
storageClassName: csi-cephfs-sc
1
kubectl apply -f 03-pvc.yaml

踩坑 1: 最初设计了 5 个 PVC(配置/工作空间/日志/备份/缓存),导致并发挂载失败。简化为单 PVC 方案,所有数据放在一个 200Gi CephFS 中。


步骤 3:创建 ServiceAccount

1
2
3
4
5
6
# 04-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: openclaw-sa
namespace: openclaw
1
kubectl apply -f 04-serviceaccount.yaml

步骤 4:创建 ConfigMap

1
2
3
4
5
6
7
8
9
# 05-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: openclaw-config
namespace: openclaw
data:
OPENCLAW_ALLOW_UNCONFIGURED: "true"
TZ: "Asia/Shanghai"
1
kubectl apply -f 05-configmap.yaml

踩坑 2: 最初没有配置 --allow-unconfigured 参数,导致 Pod 启动失败(CrashLoopBackOff)。添加后解决。


步骤 5:创建 Deployment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 06-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: openclaw-gateway
namespace: openclaw
spec:
replicas: 1
selector:
matchLabels:
app: openclaw-gateway
template:
metadata:
labels:
app: openclaw-gateway
spec:
serviceAccountName: openclaw-sa
imagePullSecrets:
- name: harbor-secret
containers:
- name: gateway
image: hb.test/crystalforge/openclaw-cn-base:1.0.0
imagePullPolicy: IfNotPresent
command:
- openclaw
- gateway
- start
- --allow-unconfigured
ports:
- containerPort: 18789
name: gateway
- containerPort: 18790
name: metrics
- containerPort: 18791
name: browser
volumeMounts:
- name: data-volume
mountPath: /root/.openclaw
subPath: config
- name: data-volume
mountPath: /root/.openclaw/workspace
subPath: workspace
envFrom:
- configMapRef:
name: openclaw-config
volumes:
- name: data-volume
persistentVolumeClaim:
claimName: openclaw-data-pvc
1
kubectl apply -f 06-deployment.yaml

踩坑 3: 最初使用 imagePullPolicy: Always,导致每次启动都从 Harbor 拉取镜像(慢且不稳定)。改为 IfNotPresent,节点本地缓存后速度提升 10 倍。


步骤 6:创建 Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 07-service.yaml
apiVersion: v1
kind: Service
metadata:
name: openclaw-gateway
namespace: openclaw
spec:
selector:
app: openclaw-gateway
ports:
- name: gateway
port: 18789
targetPort: 18789
- name: metrics
port: 18790
targetPort: 18790
- name: browser
port: 18791
targetPort: 18791
type: ClusterIP
1
kubectl apply -f 07-service.yaml

步骤 7:验证部署

1
2
3
4
5
6
7
8
# 查看 Pod 状态
kubectl get pods -n openclaw

# 查看日志
kubectl logs -f deployment/openclaw-gateway -n openclaw

# 端口转发测试
kubectl port-forward svc/openclaw-gateway 18789:18789 -n openclaw

预期输出:

1
2
NAME                                  READY   STATUS    RESTARTS   AGE
openclaw-gateway-xxxxx-xxxxx 1/1 Running 0 5m

配置文件更新

问题

配置文件存储在 PVC 中,无法直接修改。

解决方案

通过临时 Pod 更新:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 1. 创建临时 Pod
kubectl run config-updater --rm -i --restart=Never \
--image=busybox -n openclaw \
--overrides='{"spec":{"volumes":[{"name":"data-volume","persistentVolumeClaim":{"claimName":"openclaw-data-pvc"}}],"containers":[{"name":"updater","image":"busybox","command":["sleep","3600"],"volumeMounts":[{"name":"data-volume","mountPath":"/data","subPath":"config"}]}]}}'

# 2. 复制配置文件
kubectl cp /tmp/openclaw.json openclaw/config-updater:/data/openclaw.json

# 3. 删除临时 Pod
kubectl delete pod config-updater -n openclaw

# 4. 重启 Gateway
kubectl rollout restart deployment openclaw-gateway -n openclaw

关键配置项

配置项 当前值 说明
models.default bailian/qwen3.5-plus 默认模型
models.providers.bailian.baseUrl https://coding.dashscope.aliyuncs.com/v1 DashScope API
channels.feishu.enabled true 启用飞书集成
channels.feishu.dmPolicy pairing 私聊配对策略
gateway.port 18789 Gateway 端口
metrics.port 18790 Metrics 端口

踩坑记录

踩坑 1:CephFS 挂载失败

问题: 5 个 PVC 并发挂载超时。

原因: CephFS 并发挂载限制。

解决: 简化为单 PVC 方案(5 个 → 1 个)。

教训: 存储设计要简单,避免过度复杂。


踩坑 2:ImagePullBackOff

问题: 镜像拉取失败。

原因: Harbor 网络不稳定。

解决:

  1. 节点本地拉取镜像
  2. imagePullPolicy: IfNotPresent

教训: 生产环境优先使用本地缓存。


踩坑 3:CrashLoopBackOff

问题: Pod 启动后反复崩溃。

原因: 缺少配置文件,Gateway 拒绝启动。

解决: 添加 --allow-unconfigured 启动参数。

教训: 允许无配置启动,便于首次部署。


踩坑 4:模型配置错误

问题: 模型调用失败。

原因: PVC 中的 openclaw.json 配置错误。

解决: 通过临时 Pod 更新配置。

教训: 配置文件更新需要特殊方法。


最佳实践

✅ 推荐做法

  1. 单 PVC 方案 - 避免并发挂载问题
  2. 本地镜像缓存 - imagePullPolicy: IfNotPresent
  3. 允许无配置启动 - --allow-unconfigured
  4. 临时 Pod 更新配置 - 安全可靠
  5. 国内镜像源 - 加速拉取

❌ 避免做法

  1. 不要多 PVC 并发 - CephFS 可能失败
  2. 不要 Always 拉取 - 浪费时间和带宽
  3. 不要直接修改 PVC - 用临时 Pod
  4. 不要忽略日志 - 及时排查问题

监控与运维

健康检查

1
2
3
4
5
6
7
8
9
# 检查 Pod 状态
kubectl get pods -n openclaw

# 检查服务端口
kubectl port-forward svc/openclaw-gateway 18789:18789 -n openclaw
curl http://localhost:18789/health

# 查看日志
kubectl logs -f deployment/openclaw-gateway -n openclaw

备份策略

类型 频率 保留期 目标
配置文件 每日 02:00 90 天 MinIO
工作空间 每周 03:00 180 天 MinIO
日志文件 每日 04:00 30 天 MinIO

性能数据

指标 数据
Pod 启动时间 <2 分钟
镜像拉取时间 <5 分钟(首次)
配置更新时间 <1 分钟
健康检查间隔 30 秒
日志保留期 30 天

测试结果:

  • Pod 重启后自动恢复:✅
  • 配置更新后自动生效:✅
  • 服务端口正常监听:✅

总结

K8s 部署 OpenClaw 的核心要点

  1. 单 PVC 方案 - 稳定可靠
  2. 本地镜像缓存 - 快速启动
  3. 允许无配置启动 - 便于部署
  4. 临时 Pod 更新配置 - 安全方法

部署文件位置:

1
obsidian-sync/projects/P3_OpenClaw_Extension/02_Docs/K8s_Deployment/

相关资源

  • 部署文档:02_Docs/K8s_Deployment/README.md
  • 配置文件模板:openclaw.json.template
  • 部署实践:DEPLOYMENT_PRACTICE.md
  • MEMORY.md:记录经验教训

本文是 OpenClaw 实战系列第 3 篇,后续将推出语音识别、飞书机器人等文章。