0%

OpenClaw K8S 一键安装指南

OpenClaw 一键安装最佳实践

通过 Jenkins 自动部署到 K8S 集群

📋 目录

  1. 前置准备
  2. 环境要求
  3. 资源准备
  4. Jenkins 流水线配置
  5. K8S 部署配置
  6. 一键安装脚本
  7. 验证与测试
  8. 故障排查

🚨 前置准备

1. 环境检查清单

  • K8S 集群可用(v1.20+)
  • Jenkins 已安装(v2.553+)
  • GitLab 已配置
  • Docker 镜像仓库可用
  • kubectl 已安装并配置
  • Helm v3(可选)

2. 权限准备

  • K8S ServiceAccount(部署权限)
  • Jenkins K8S 凭证
  • GitLab API Token
  • Docker Registry 凭证

💻 环境要求

硬件要求

组件 CPU 内存 存储
K8S 集群 4 核 + 8GB+ 50GB+
Jenkins 2 核 + 4GB+ 20GB+
OpenClaw 2 核 + 4GB+ 10GB+

软件要求

软件 版本 说明
Kubernetes v1.20+ K8S 集群
Jenkins v2.553+ CI/CD 平台
Docker v20.10+ 容器引擎
kubectl v1.20+ K8S 命令行工具
Helm v3.0+ K8S 包管理(可选)
Git v2.30+ 版本控制

📦 资源准备

1. GitLab 仓库结构

1
2
3
4
5
6
7
8
openclaw/
├── openclaw-core/ # 核心代码
├── openclaw-gateway/ # 网关服务
├── openclaw-agent/ # Agent 服务
├── openclaw-ui/ # 前端界面
├── k8s-manifests/ # K8S 部署配置
└── jenkins/
└── Jenkinsfile

2. Docker 镜像

1
2
3
4
5
6
镜像仓库:registry.example.com/openclaw
镜像列表:
- openclaw-core:latest
- openclaw-gateway:latest
- openclaw-agent:latest
- openclaw-ui:latest

🔧 Jenkins 流水线配置

Jenkinsfile

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
pipeline {
agent any

environment {
KUBECONFIG = credentials('k8s-kubeconfig')
DOCKER_REGISTRY = 'registry.example.com'
DOCKER_IMAGE_PREFIX = 'openclaw'
K8S_NAMESPACE = 'openclaw'
}

parameters {
string(name: 'VERSION', defaultValue: 'latest', description: '部署版本')
booleanParam(name: 'FORCE_REBUILD', defaultValue: false, description: '强制重新构建镜像')
}

stages {
stage('Checkout') {
steps {
echo '📦 拉取代码...'
git branch: 'main',
url: 'https://gitlab.example.com/openclaw.git',
credentialsId: 'gitlab-credentials'
}
}

stage('Build & Push Images') {
when {
expression { return params.FORCE_REBUILD }
}
parallel {
stage('Build Core') {
steps {
echo '🔨 构建 Core 镜像...'
dir('openclaw-core') {
sh """
docker build -t ${DOCKER_REGISTRY}/${DOCKER_IMAGE_PREFIX}/openclaw-core:${VERSION} .
docker push ${DOCKER_REGISTRY}/${DOCKER_IMAGE_PREFIX}/openclaw-core:${VERSION}
"""
}
}
}

stage('Build Gateway') {
steps {
echo '🔨 构建 Gateway 镜像...'
dir('openclaw-gateway') {
sh """
docker build -t ${DOCKER_REGISTRY}/${DOCKER_IMAGE_PREFIX}/openclaw-gateway:${VERSION} .
docker push ${DOCKER_REGISTRY}/${DOCKER_IMAGE_PREFIX}/openclaw-gateway:${VERSION}
"""
}
}
}

stage('Build Agent') {
steps {
echo '🔨 构建 Agent 镜像...'
dir('openclaw-agent') {
sh """
docker build -t ${DOCKER_REGISTRY}/${DOCKER_IMAGE_PREFIX}/openclaw-agent:${VERSION} .
docker push ${DOCKER_REGISTRY}/${DOCKER_IMAGE_PREFIX}/openclaw-agent:${VERSION}
"""
}
}
}

stage('Build UI') {
steps {
echo '🔨 构建 UI 镜像...'
dir('openclaw-ui') {
sh """
docker build -t ${DOCKER_REGISTRY}/${DOCKER_IMAGE_PREFIX}/openclaw-ui:${VERSION} .
docker push ${DOCKER_REGISTRY}/${DOCKER_IMAGE_PREFIX}/openclaw-ui:${VERSION}
"""
}
}
}
}
}

stage('Deploy to K8S') {
steps {
echo '🚀 部署到 K8S 集群...'

script {
// 创建命名空间
sh """
kubectl apply -f k8s-manifests/openclaw-namespace.yaml
"""

// 创建 Secrets(使用 Kubernetes Secrets 管理敏感信息)
sh """
kubectl create secret generic openclaw-db-secret \\
--from-literal=root-password='<DB_ROOT_PASSWORD>' \\
--from-literal=username='<DB_USERNAME>' \\
--from-literal=password='<DB_PASSWORD>' \\
-n ${K8S_NAMESPACE} \\
--dry-run=client -o yaml | kubectl apply -f -
"""

// 部署所有资源
sh """
kubectl apply -f k8s-manifests/ -n ${K8S_NAMESPACE}
"""

// 更新镜像版本
sh """
kubectl set image deployment/openclaw-core \\
openclaw-core=${DOCKER_REGISTRY}/${DOCKER_IMAGE_PREFIX}/openclaw-core:${VERSION} \\
-n ${K8S_NAMESPACE}

kubectl set image deployment/openclaw-gateway \\
openclaw-gateway=${DOCKER_REGISTRY}/${DOCKER_IMAGE_PREFIX}/openclaw-gateway:${VERSION} \\
-n ${K8S_NAMESPACE}

kubectl set image deployment/openclaw-agent \\
openclaw-agent=${DOCKER_REGISTRY}/${DOCKER_IMAGE_PREFIX}/openclaw-agent:${VERSION} \\
-n ${K8S_NAMESPACE}

kubectl set image deployment/openclaw-ui \\
openclaw-ui=${DOCKER_REGISTRY}/${DOCKER_IMAGE_PREFIX}/openclaw-ui:${VERSION} \\
-n ${K8S_NAMESPACE}
"""
}
}
}

stage('Health Check') {
steps {
echo '⏳ 等待部署完成...'
script {
timeout(time: 5, unit: 'MINUTES') {
sh """
kubectl rollout status deployment/openclaw-core -n ${K8S_NAMESPACE}
kubectl rollout status deployment/openclaw-gateway -n ${K8S_NAMESPACE}
kubectl rollout status deployment/openclaw-agent -n ${K8S_NAMESPACE}
kubectl rollout status deployment/openclaw-ui -n ${K8S_NAMESPACE}
"""
}
}

echo '✅ 健康检查...'
script {
timeout(time: 2, unit: 'MINUTES') {
sh """
kubectl wait --for=condition=available deployment/openclaw-gateway -n ${K8S_NAMESPACE} --timeout=120s
"""
}
}
}
}
}

post {
success {
echo '✅ 部署成功!'

// 获取访问地址
sh """
NODE_PORT=\$(kubectl get svc openclaw-gateway -n ${K8S_NAMESPACE} -o jsonpath='{.spec.ports[0].nodePort}')
NODE_IP=\$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[0].address}')
echo "===================================="
echo "✅ OpenClaw 部署成功!"
echo "===================================="
echo "访问地址:http://\\${NODE_IP}:\\${NODE_PORT}"
echo "===================================="
"""
}

failure {
echo '❌ 部署失败!'

// 收集错误日志
sh """
echo "=== Core Logs ==="
kubectl logs -l app=openclaw-core -n ${K8S_NAMESPACE} --tail=50

echo "=== Gateway Logs ==="
kubectl logs -l app=openclaw-gateway -n ${K8S_NAMESPACE} --tail=50

echo "=== Agent Logs ==="
kubectl logs -l app=openclaw-agent -n ${K8S_NAMESPACE} --tail=50
"""
}
}
}

📝 一键安装脚本

install-openclaw.sh

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/bin/bash
set -e

echo "======================================"
echo " OpenClaw 一键安装脚本"
echo "======================================"

# 配置变量
K8S_NAMESPACE="openclaw"
DOCKER_REGISTRY="registry.example.com"
DOCKER_IMAGE_PREFIX="openclaw"
VERSION="latest"

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# 检查前置条件
check_prerequisites() {
echo -e "${YELLOW}📋 检查前置条件...${NC}"

# 检查 kubectl
if ! command -v kubectl &> /dev/null; then
echo -e "${RED}❌ kubectl 未安装${NC}"
exit 1
fi

# 检查 K8S 连接
if ! kubectl cluster-info &> /dev/null; then
echo -e "${RED}❌ 无法连接到 K8S 集群${NC}"
exit 1
fi

# 检查 Docker
if ! command -v docker &> /dev/null; then
echo -e "${RED}❌ Docker 未安装${NC}"
exit 1
fi

echo -e "${GREEN}✅ 前置检查通过${NC}"
}

# 创建命名空间
create_namespace() {
echo -e "${YELLOW}📦 创建命名空间...${NC}"
kubectl create namespace ${K8S_NAMESPACE} --dry-run=client -o yaml | kubectl apply -f -
echo -e "${GREEN}✅ 命名空间创建完成${NC}"
}

# 创建 Secrets
create_secrets() {
echo -e "${YELLOW}🔐 创建 Secrets...${NC}"
kubectl create secret generic openclaw-db-secret \\
--from-literal=root-password='<DB_ROOT_PASSWORD>' \\
--from-literal=username='<DB_USERNAME>' \\
--from-literal=password='<DB_PASSWORD>' \\
-n ${K8S_NAMESPACE} \\
--dry-run=client -o yaml | kubectl apply -f -
echo -e "${GREEN}✅ Secrets 创建完成${NC}"
}

# 部署 K8S 资源
deploy_k8s() {
echo -e "${YELLOW}🚀 部署 K8S 资源...${NC}"
kubectl apply -f k8s-manifests/ -n ${K8S_NAMESPACE}
echo -e "${GREEN}✅ K8S 资源部署完成${NC}"
}

# 等待部署完成
wait_deployment() {
echo -e "${YELLOW}⏳ 等待部署完成...${NC}"

kubectl rollout status deployment/openclaw-core -n ${K8S_NAMESPACE}
kubectl rollout status deployment/openclaw-gateway -n ${K8S_NAMESPACE}
kubectl rollout status deployment/openclaw-agent -n ${K8S_NAMESPACE}
kubectl rollout status deployment/openclaw-ui -n ${K8S_NAMESPACE}

echo -e "${GREEN}✅ 所有部署完成${NC}"
}

# 健康检查
health_check() {
echo -e "${YELLOW}⏳ 执行健康检查...${NC}"
sleep 10
kubectl get pods -n ${K8S_NAMESPACE}
kubectl get svc -n ${K8S_NAMESPACE}
echo -e "${GREEN}✅ 健康检查通过${NC}"
}

# 获取访问信息
get_access_info() {
echo -e "${YELLOW}📊 获取访问信息...${NC}"

NODE_PORT=$(kubectl get svc openclaw-gateway -n ${K8S_NAMESPACE} -o jsonpath='{.spec.ports[0].nodePort}')
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[0].address}')

echo ""
echo -e "${GREEN}======================================"
echo " ✅ OpenClaw 部署成功!"
echo "======================================${NC}"
echo "访问地址:http://${NODE_IP}:${NODE_PORT}"
echo "命名空间:${K8S_NAMESPACE}"
echo "======================================"
echo ""
}

# 主流程
main() {
check_prerequisites
create_namespace
create_secrets
deploy_k8s
wait_deployment
health_check
get_access_info

echo -e "${GREEN}🎉 安装完成!${NC}"
}

# 执行
main "$@"

✅ 验证与测试

1. 检查 Pod 状态

1
kubectl get pods -n openclaw

预期输出

1
2
3
4
5
6
NAME                              READY   STATUS    RESTARTS   AGE
openclaw-core-xxxxx-xxxxx 1/1 Running 0 5m
openclaw-gateway-xxxxx-xxxxx 1/1 Running 0 5m
openclaw-agent-xxxxx-xxxxx 1/1 Running 0 5m
openclaw-ui-xxxxx-xxxxx 1/1 Running 0 5m
mysql-xxxxx-xxxxx 1/1 Running 0 5m

2. 检查服务状态

1
kubectl get svc -n openclaw

预期输出

1
2
3
4
5
NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
openclaw-core ClusterIP 10.x.x.x <none> 80/TCP 5m
openclaw-gateway NodePort 10.x.x.x <none> 80:32080/TCP 5m
openclaw-agent ClusterIP 10.x.x.x <none> 5000/TCP 5m
mysql ClusterIP 10.x.x.x <none> 3306/TCP 5m

3. 测试访问

1
2
3
4
5
6
# 获取 NodePort
NODE_PORT=$(kubectl get svc openclaw-gateway -n openclaw -o jsonpath='{.spec.ports[0].nodePort}')
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[0].address}')

# 测试访问
curl http://${NODE_IP}:${NODE_PORT}/health

预期输出

1
{"status":"ok","message":"OpenClaw Gateway is running"}

🔧 故障排查

问题 1:Pod 无法启动

症状

1
2
3
kubectl get pods -n openclaw
NAME READY STATUS RESTARTS AGE
openclaw-core-xxxxx-xxxxx 0/1 ImagePullBackOff 0 5m

解决方案

1
2
3
4
5
6
7
8
# 检查 Pod 事件
kubectl describe pod openclaw-core-xxxxx-xxxxx -n openclaw

# 检查镜像拉取凭证
kubectl get secrets -n openclaw

# 手动拉取镜像测试
docker pull registry.example.com/openclaw/openclaw-core:latest

问题 2:数据库连接失败

症状

1
Error: connect ECONNREFUSED 10.x.x.x:3306

解决方案

1
2
3
4
5
6
7
8
9
# 检查 MySQL Pod
kubectl get pods -l app=mysql -n openclaw

# 检查 MySQL 日志
kubectl logs -l app=mysql -n openclaw

# 测试数据库连接
kubectl run -it --rm mysql-client --image=mysql:8.0 --restart=Never -n openclaw -- \\
mysql -h mysql -u <DB_USERNAME> -p

问题 3:服务无法访问

症状

1
curl: (7) Failed to connect to <IP> port <PORT>: Connection refused

解决方案

1
2
3
4
5
6
7
8
9
10
11
12
# 检查 Service 配置
kubectl get svc openclaw-gateway -n openclaw -o yaml

# 检查 Endpoint
kubectl get endpoints openclaw-gateway -n openclaw

# 检查 Pod 标签是否匹配
kubectl get pods --show-labels -n openclaw

# 测试集群内访问
kubectl run -it --rm test --image=curlimages/curl --restart=Never -n openclaw -- \\
curl http://openclaw-gateway/health

📖 参考链接


架构师点评:一键安装只是起点,生产化才是重点

OpenClaw 这类 Agent 平台跑在 K8s 上,安装成功只能说明“组件启动了”,不能说明“平台可生产使用”。生产化部署至少要补齐配置治理、密钥管理、网络访问、持久化、监控告警、备份恢复、灰度升级和权限审计。否则一键安装越方便,越容易让团队忽略后续治理成本。

生产部署时要特别关注:

  1. 配置与密钥:数据库、模型 API、Feishu/GitLab/Jenkins 等凭证必须用 Secret/External Secrets 管理,不能散落在脚本中。
  2. 数据持久化:记忆、日志、向量库、任务状态和用户配置要明确备份策略。
  3. 网络边界:Agent 能访问哪些内部系统、外部 API 和文件路径,必须通过网关和策略控制。
  4. 升级回滚:镜像版本、数据库迁移、配置变更要支持灰度和快速回滚。
  5. 运行时审计:工具调用、命令执行、权限拒绝、人工审批都要可追溯。

企业落地建议

推荐把 OpenClaw K8s 部署拆成三层交付:

  • 开发验证环境:快速安装,验证 Agent 能力、工具接入和业务流程。
  • 预生产环境:补齐监控、日志、备份、权限和发布流程,模拟真实业务负载。
  • 生产环境:引入高可用、灰度发布、审计合规、容量规划和应急预案。

如果企业计划把 OpenClaw 用于 AI Coding、PR 审查、知识库问答或自动化运维,建议先从一个低风险流程试点,再逐步扩大工具权限和自动化范围。

相关入口:

  • OpenClaw 专题:了解 OpenClaw 平台化部署、记忆、工具和多 Agent 协作。
  • AI Agent 专题:理解 Agent 系统架构、执行循环和安全边界。
  • 企业 AI 落地咨询:适合需要 OpenClaw 私有化部署、K8s 生产化和企业 AI 工作流落地的团队。

一键安装,自动部署,快速上线!🚀

提示:实际部署时请将 <DB_ROOT_PASSWORD><DB_USERNAME><DB_PASSWORD> 等占位符替换为真实配置。