2026年OpenClaw+K8s+Docker安装完整保姆级教程

OpenClaw+K8s+Docker安装完整保姆级教程p 一 概述 p 1 1 背景介绍 u AI u Agent 落地到企业内部 第一个挡在路上的问题就是接入层 微信 u Te u leg u ram u Slack 企业微信 每个渠道的协议不一样 消息格式不一样 u 认证 u

大家好,我是讯享网,很高兴认识大家。这里提供最前沿的Ai技术和互联网信息。



 

一、概述

1.1 背景介绍

AI Agent 落地到企业内部,第一个挡在路上的问题就是接入层。微信、Telegram、Slack、企业微信,每个渠道的协议不一样,消息格式不一样,认证方式不一样。自己写网关代码?写到第三个渠道就想掀桌了。

OpenClaw 就是解决这个问题的。它是一个开源 AI Agent Gateway,用 Node.js 运行时构建,把多渠道消息接入、模型路由、Token 认证这些脏活累活全包了。后端对接任意 OpenAI 兼容 API(包括 vLLM、Ollama 等自托管方案),前端对接各种 IM 渠道,中间做协议转换和流量管理。

官方只提供了 Docker 部署方案,没有 K8s 支持。但生产环境跑 Docker Compose 迟早要出事——单点故障、手动扩容、没有滚动更新,哪个都是定时炸弹。这篇文章把 Docker 方案和 K8s 方案都写清楚,Docker 方案用于开发测试快速验证,K8s 方案用于生产环境长期运行。

1.2 技术特点

多渠道网关统一接入:HTTP API、WebSocket 双协议复用同一端口(18789),支持 Telegram Bot、企业微信、Slack 等 IM 渠道接入。消息格式在网关层统一转换,后端模型服务不需要关心渠道差异。

插件式模型路由:通过models.providers配置自定义 Provider,支持同时对接多个推理后端。模型标识使用provider/model格式(如vllm-local/Qwen3.5-35B),路由逻辑在配置文件中声明,不需要写代码。

自托管模型原生支持:内置 OpenAI Responses API 兼容层,可以直接对接 vLLM、TGI、Ollama 等主流推理引擎。配置一个baseUrl加一个模型列表就能用,不需要额外的适配层。

轻量级 Token 认证:Gateway 内置 Token 认证机制(gateway.auth.token),每个接入方分配独立 Token,在网关层完成鉴权。生产环境可配合 K8s NetworkPolicy 实现网络层隔离。

1.3 适用场景

企业内部 AI 助手平台:统一管理多个部门的 AI 助手,每个部门分配独立 Token 和模型配额。通过 K8s 多租户隔离实现部门间的资源和网络隔离,避免互相影响。

多平台消息聚合:同一个 AI Agent 同时在 Telegram、企业微信、Slack 上提供服务。OpenClaw 在网关层做消息协议转换,后端只需要维护一套模型服务。

私有化大模型部署:数据不出企业网络,用 vLLM 部署 Qwen、LLaMA 等开源模型,OpenClaw 作为 API 网关对外提供标准化接口GPU 资源通过 K8s 调度,按需分配给不同的推理实例。

1.4 环境要求

 组件 版本要求 说明 操作系统 Ubuntu 22.04+ / Debian 12+ 推荐 Ubuntu 22.04 LTS,内核 5.15+ Docker 24.0+ 需要 Docker Compose V2(docker compose 命令) Kubernetes 1.28+ 推荐 1.30,需要支持 PV 动态供给 Node.js 24.x(容器内置) OpenClaw 镜像基于 node:24-bookworm,无需手动安装 GPU(可选) NVIDIA A100/A800/H100 仅 vLLM 推理服务需要,OpenClaw 网关本身不需要 GPU 内存 4GB+(网关) / 64GB+(推理) 网关内存需求低,推理节点建议 4 倍 GPU 显存 磁盘 20GB+(网关) / 500GB+ NVMe(推理) 推理节点需要存储模型权重文件 网络 集群内网互通,Ingress Controller 已部署 推荐 NGINX Ingress Controller 或 Traefik 

二、详细步骤

2.1 准备工作

2.1.1 系统检查

检查系统版本

cat /etc/os-release

检查内核版本

uname -r

检查 Docker 版本(需要 24.0+)

docker –version docker compose version

检查系统资源

free -h df -h

如果部署 K8s 方案,检查集群状态

kubectl cluster-info kubectl get nodes -o wide

预期输出:Docker 版本 24.0 以上,Docker Compose V2 正常输出版本号。K8s 集群所有节点 Ready 状态。

2.1.2 安装 Docker(如果还没装)

Ubuntu/Debian 安装 Docker

curl -fsSL https://get.docker.com | bash -s docker

将当前用户加入 docker 组(避免每次 sudo)

sudo usermod -aG docker$USER newgrp docker

验证安装

docker run hello-world

2.1.3 准备 OpenClaw 配置目录

创建配置目录

mkdir -p ~/.openclaw

创建工作空间目录

mkdir -p ~/openclaw-workspace

OpenClaw 的配置文件是 JSON5 格式,文件路径固定在~/.openclaw/openclaw.json。容器内部以node用户(uid 1000)运行,挂载目录时需要注意权限问题。

确保目录权限正确(容器内 node 用户 uid=1000)

sudo chown -R 1000:1000 ~/.openclaw sudo chown -R 1000:1000 ~/openclaw-workspace

2.2 Docker Compose 部署(官方方案)

这是官方推荐的部署方式,适合开发测试和小规模生产环境。

2.2.1 使用官方安装脚本

OpenClaw 提供了docker-setup.sh一键安装脚本,流程是:拉取镜像 → 初始化配置(onboard)→ 启动服务。

拉取官方安装脚本并执行

curl -fsSL https://raw.githubusercontent.com/openclaw/openclaw/main/docker-setup.sh | bash

如果网络环境不方便直接执行远程脚本,也可以手动操作:

手动拉取镜像

docker pull ghcr.io/openclaw/openclaw:latest

初始化配置(交互式,会引导设置 Token 和基础配置)

docker run –rm -it -v”$HOME/.openclaw:/home/node/.openclaw” ghcr.io/openclaw/openclaw:latest openclaw onboard

2.2.2 环境变量配置

docker-setup.sh支持通过环境变量定制行为:

 环境变量 默认值 说明 OPENCLAW_IMAGE ghcr.io/openclaw/openclaw:latest 镜像地址,私有仓库可改这个 OPENCLAW_GATEWAY_BIND 0.0.0.0:18789 网关监听地址和端口 OPENCLAW_HOME_VOLUME ~/.openclaw 配置文件挂载路径 OPENCLAW_SANDBOX 0 设为 1 启用沙箱模式 

自定义启动示例

exportOPENCLAW_IMAGE=“ghcr.io/openclaw/openclaw:latest” exportOPENCLAW_GATEWAY_BIND=“0.0.0.0:18789” exportOPENCLAW_HOME_VOLUME=“$HOME/.openclaw”

2.2.3 编写 Docker Compose 文件

生产环境建议用docker-compose.yml管理,比裸docker run更容易维护:

docker-compose.yml

version:“3.8”

services: openclaw-gateway: image:ghcr.io/openclaw/openclaw:latest container_name:openclaw-gateway restart:unless-stopped ports: -“18789:18789” volumes: -./config:/home/node/.openclaw -./workspace:/home/node/workspace environment: -NODE_ENV=production user:“1000:1000” healthcheck: test:[“CMD”,“curl”,“-f”,”http://localhost:18789/healthz”] interval:30s timeout:10s retries:3 start_period:15s deploy: resources: limits:

memory:2G cpus:"2.0" 

reservations:

memory:512M cpus:"0.5" 

logging: driver:json-file options: max-size:“50m” max-file:“5”

2.2.4 编写 OpenClaw 配置文件

在./config/目录下创建openclaw.json(JSON5 格式,支持注释):

 // ./config/openclaw.json { // 网关配置 gateway: { bind: “0.0.0.0:18789”, auth: { // 生产环境必须改成随机生成的强 Token token: “oc-prod-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6” } },

// 模型配置 models: { // 默认模型(客户端不指定模型时使用) default: “vllm-local/Qwen3.5-35B”,

providers: { // 自托管 vLLM 推理服务 “vllm-local”: {

baseUrl: "http://vllm-service:8000/v1", api: "openai-responses", models: [ "Qwen/Qwen3.5-35B-A3B-FP8" ] 

} } } }

注意:gateway.auth.token这个值必须是强随机字符串,别用示例里的值。生成方法:

生成 32 字节随机 Token

openssl rand -hex 32

2.2.5 启动并验证

启动服务(后台运行)

docker compose up -d

查看日志,确认启动成功

docker compose logs -f openclaw-gateway

健康检查

curl -s http://localhost:18789/healthz

预期输出:{“status”:“ok”}

就绪检查

curl -s http://localhost:18789/readyz

预期输出:{“status”:“ready”}

带 Token 认证的请求测试

curl -s -H”Authorization: Bearer oc-prod-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6” http://localhost:18789/v1/models

如果/healthz返回{"status":"ok"}就说明网关启动成功了。/readyz还会检查后端模型连通性,如果 vLLM 还没部署,/readyz可能返回 not ready,这是正常的。

2.3 Kubernetes 部署方案

官方没有提供 K8s 部署方案,以下配置是基于 Docker 方案转写的。核心思路:把 Docker 的 bind mount 换成 PVC,把环境变量和配置文件换成 ConfigMap/Secret,把容器换成 Deployment + Service。

2.3.1 创建 Namespace

 kubectl create namespace openclaw 

所有 OpenClaw 相关资源都放在openclawNamespace 下,方便管理和 RBAC 隔离。

2.3.2 ConfigMap:OpenClaw 配置文件

openclaw-configmap.yaml

apiVersion:v1 kind:ConfigMap metadata: name:openclaw-config namespace:openclaw labels: app:openclaw component:gateway data: openclaw.json:| { // 网关配置 “gateway”: {

"bind": "0.0.0.0:18789", "auth": { // Token 从 Secret 注入,这里用环境变量占位 // 实际运行时由 entrypoint 脚本替换 "token": "${OPENCLAW_AUTH_TOKEN}" } 

}, “models”: {

"default": "vllm-local/Qwen3.5-35B", "providers": { "vllm-local": { "baseUrl": "http://vllm-service.openclaw.svc.cluster.local:8000/v1", "api": "openai-responses", "models": [ "Qwen/Qwen3.5-35B-A3B-FP8" ] } } 

} }

模型服务地址使用 K8s 内部 DNS:vllm-service.openclaw.svc.cluster.local:8000,不需要走集群外部网络。

2.3.3 Secret:敏感信息

生成随机 Token

GATEWAY_TOKEN=$(openssl rand -hex 32)

创建 Secret

kubectl create secret generic openclaw-secrets –namespace=openclaw –from-literal=gateway-token=“${GATEWAY_TOKEN}” –from-literal=openai-api-key=“sk-your-openai-key-if-needed”

验证 Secret 创建成功

kubectl get secret openclaw-secrets -n openclaw

也可以用 YAML 声明式创建(Token 需要 base64 编码):

openclaw-secret.yaml

apiVersion:v1 kind:Secret metadata: name:openclaw-secrets namespace:openclaw labels: app:openclaw type:Opaque data:

echo -n “your-token” | base64

gateway-token:“b2MtcHJvZC1hMWIyYzNkNGU1ZjZnN2g4aTlqMGsxbDJtM240bzVwNg==” openai-api-key:“”

2.3.4 PersistentVolumeClaim:持久化存储

openclaw-pvc.yaml

apiVersion:v1 kind:PersistentVolumeClaim metadata: name:openclaw-data namespace:openclaw labels: app:openclaw spec: accessModes: -ReadWriteOnce storageClassName:standard resources: requests:

storage:10Gi

apiVersion:v1 kind:PersistentVolumeClaim metadata: name:openclaw-workspace namespace:openclaw labels: app:openclaw spec: accessModes: -ReadWriteOnce storageClassName:standard resources: requests: storage:50Gi

storageClassName根据集群实际情况调整。云厂商环境一般用gp3(AWS)、pd-ssd(GCP)、managed-csi(Azure)。自建集群用local-path或 NFS。

如果 Gateway 需要多副本,accessModes要改成ReadWriteMany,存储后端也要支持(NFS、CephFS 等)。单副本用ReadWriteOnce就够了。

2.3.5 Deployment:OpenClaw Gateway

openclaw-deployment.yaml

apiVersion:apps/v1 kind:Deployment metadata: name:openclaw-gateway namespace:openclaw labels: app:openclaw component:gateway spec: replicas:2 selector: matchLabels: app:openclaw component:gateway strategy: type:RollingUpdate rollingUpdate: maxSurge:1 maxUnavailable:0 template: metadata: labels: app:openclaw component:gateway spec: securityContext: runAsUser:1000 runAsGroup:1000 fsGroup:1000 initContainers: # initContainer 用于将 ConfigMap 中的配置文件复制到可写目录 # 并替换 Token 占位符 -name:config-init

image:ghcr.io/openclaw/openclaw:latest command: -/bin/sh --c -| cp /config-readonly/openclaw.json /home/node/.openclaw/openclaw.json sed -i "s|${OPENCLAW_AUTH_TOKEN}|${GATEWAY_TOKEN}|g" /home/node/.openclaw/openclaw.json env: -name:GATEWAY_TOKEN valueFrom: secretKeyRef: name:openclaw-secrets key:gateway-token volumeMounts: -name:config-readonly mountPath:/config-readonly -name:openclaw-data mountPath:/home/node/.openclaw 

containers: -name:openclaw-gateway

image:ghcr.io/openclaw/openclaw:latest ports: -name:http containerPort:18789 protocol:TCP env: -name:NODE_ENV value:"production" -name:OPENCLAW_AUTH_TOKEN valueFrom: secretKeyRef: name:openclaw-secrets key:gateway-token volumeMounts: -name:openclaw-data mountPath:/home/node/.openclaw -name:openclaw-workspace mountPath:/home/node/workspace resources: requests: cpu:"500m" memory:"512Mi" limits: cpu:"2000m" memory:"2Gi" livenessProbe: httpGet: path:/healthz port:18789 initialDelaySeconds:15 periodSeconds:30 timeoutSeconds:5 failureThreshold:3 readinessProbe: httpGet: path:/readyz port:18789 initialDelaySeconds:10 periodSeconds:10 timeoutSeconds:5 failureThreshold:3 startupProbe: httpGet: path:/healthz port:18789 initialDelaySeconds:5 periodSeconds:5 failureThreshold:12 

volumes: -name:config-readonly

configMap: name:openclaw-config 

-name:openclaw-data

persistentVolumeClaim: claimName:openclaw-data 

-name:openclaw-workspace

persistentVolumeClaim: claimName:openclaw-workspace 

terminationGracePeriodSeconds:30

几个关键设计点:

initContainer 处理配置:ConfigMap 挂载的目录是只读的,但 OpenClaw 运行时需要读写~/.openclaw目录。所以用 initContainer 把配置文件从 ConfigMap 复制到 PVC,同时替换 Token 占位符。

securityContext uid=1000:OpenClaw 镜像以node用户运行(uid 1000),PVC 目录的 fsGroup 也设为 1000,避免权限问题。

三种探针都配了:startupProbe 给容器 60 秒启动时间(5s × 12次),livenessProbe 检测进程存活,readinessProbe 检测服务就绪。

RollingUpdate maxUnavailable=0:更新时先拉起新 Pod 再下旧 Pod,服务零中断。

2.3.6 Service

openclaw-service.yaml

apiVersion:v1 kind:Service metadata: name:openclaw-gateway namespace:openclaw labels: app:openclaw component:gateway spec: type:ClusterIP ports: -name:http port:18789 targetPort:18789 protocol:TCP selector: app:openclaw

component:gateway

NodePort Service(可选,用于无 Ingress 环境直接访问)

apiVersion:v1 kind:Service metadata: name:openclaw-gateway-nodeport namespace:openclaw labels: app:openclaw component:gateway spec: type:NodePort ports: -name:http port:18789 targetPort:18789 nodePort:31789 protocol:TCP selector: app:openclaw component:gateway

ClusterIP Service 供集群内部访问(Ingress 转发用),NodePort Service 供没有 Ingress 的环境直接通过节点IP:31789访问。生产环境推荐走 Ingress + ClusterIP,不暴露 NodePort。

2.3.7 Ingress:HTTPS 暴露

openclaw-ingress.yaml

apiVersion:networking.k8s.io/v1 kind:Ingress metadata: name:openclaw-gateway namespace:openclaw labels: app:openclaw annotations: nginx.ingress.kubernetes.io/proxy-read-timeout:“3600” nginx.ingress.kubernetes.io/proxy-send-timeout:“3600” # WebSocket 支持(OpenClaw 端口复用 HTTP + WS) nginx.ingress.kubernetes.io/proxy-http-version:“1.1” nginx.ingress.kubernetes.io/upstream-hash-by:“$remote_addr” # 请求体大小限制(Agent 对话上下文可能很长) nginx.ingress.kubernetes.io/proxy-body-size:“50m” # TLS 证书自动签发(需要 cert-manager) cert-manager.io/cluster-issuer:“letsencrypt-prod” spec: ingressClassName:nginx tls: -hosts: -openclaw.example.com secretName:openclaw-tls rules: -host:openclaw.example.com http: paths:

-path:/ pathType:Prefix backend: service: name:openclaw-gateway port: number:18789 

Ingress 的proxy-read-timeout设成 3600 秒,因为大模型推理响应时间可能很长(特别是长文本生成场景)。默认 60 秒超时在生产环境一定会出问题,这个坑踩过的人都知道。

WebSocket 的proxy-http-version必须设为1.1,否则 WS 连接建不起来。

2.4 vLLM 推理服务部署

OpenClaw 网关本身不做推理,需要后端挂一个推理服务。这里用 vLLM 部署Qwen/Qwen3.5-35B-A3B-FP8模型。

2.4.1 vLLM Deployment

vllm-deployment.yaml

apiVersion:apps/v1 kind:Deployment metadata: name:vllm-inference namespace:openclaw labels: app:openclaw component:vllm spec: replicas:1 selector: matchLabels: app:openclaw component:vllm template: metadata: labels: app:openclaw component:vllm spec: containers: -name:vllm

image:vllm/vllm-openai:latest command: -python3 --m -vllm.entrypoints.openai.api_server args: -"--model" -"Qwen/Qwen3.5-35B-A3B-FP8" -"--host" -"0.0.0.0" -"--port" -"8000" -"--tensor-parallel-size" -"4" -"--max-model-len" -"32768" -"--gpu-memory-utilization" -"0.90" -"--block-size" -"16" -"--swap-space" -"8" -"--dtype" -"auto" -"--trust-remote-code" ports: -name:http containerPort:8000 protocol:TCP env: -name:HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name:openclaw-secrets key:openai-api-key optional:true -name:VLLM_WORKER_MULTIPROC_METHOD value:"spawn" resources: requests: cpu:"8" memory:"64Gi" nvidia.com/gpu:"4" limits: cpu:"16" memory:"128Gi" nvidia.com/gpu:"4" volumeMounts: -name:model-cache mountPath:/root/.cache/huggingface -name:shm mountPath:/dev/shm livenessProbe: httpGet: path:/health port:8000 initialDelaySeconds:120 periodSeconds:30 timeoutSeconds:10 failureThreshold:5 readinessProbe: httpGet: path:/health port:8000 initialDelaySeconds:120 periodSeconds:15 timeoutSeconds:10 failureThreshold:5 

volumes: -name:model-cache

persistentVolumeClaim: claimName:vllm-model-cache 

-name:shm

emptyDir: medium:Memory sizeLimit:16Gi 

tolerations: -key:nvidia.com/gpu

operator:Exists effect:NoSchedule 

nodeSelector:

gpu-type:a100

apiVersion:v1 kind:PersistentVolumeClaim metadata: name:vllm-model-cache namespace:openclaw spec: accessModes: -ReadWriteOnce storageClassName:standard resources: requests: storage:200Gi

几个坑点说明:

/dev/shm必须挂载 emptyDir:vLLM 多进程通信依赖共享内存,Docker 默认的 64MB shm 远远不够。这里给了 16Gi,35B 模型 4 卡并行至少需要这个量级。

tensor-parallel-size=4:Qwen3.5-35B-A3B-FP8 是 FP8 量化模型,4 张 A100 80GB 可以稳定加载。2 张卡勉强能跑但显存利用率太高,留不出 KV Cache 空间。

initialDelaySeconds=120:大模型加载需要时间,35B 模型从磁盘加载到 GPU 至少要 90 秒,设短了 Pod 会被 K8s 反复杀掉重启。

gpu-memory-utilization=0.90:给 KV Cache 留 10% 的显存余量。设成 0.95 虽然能多接几个并发,但在突发流量下容易 OOM。

nodeSelector:确保 Pod 调度到有 GPU 的节点,标签gpu-type: a100需要提前给节点打好。

2.4.2 vLLM Service

vllm-service.yaml

apiVersion:v1 kind:Service metadata: name:vllm-service namespace:openclaw labels: app:openclaw component:vllm spec: type:ClusterIP ports: -name:http port:8000 targetPort:8000 protocol:TCP selector: app:openclaw component:vllm

这个 Service 只在集群内部暴露,OpenClaw 网关通过http://vllm-service.openclaw.svc.cluster.local:8000/v1访问。不需要对外暴露推理服务端口,安全性更好。

2.5 OpenClaw 对接 vLLM

2.5.1 配置 models.providers

OpenClaw 的openclaw.json中models.providers部分配置 vLLM 作为推理后端:

 { models: { default: “vllm-local/Qwen3.5-35B”, providers: { “vllm-local”: {

// K8s 环境使用 Service DNS baseUrl: "http://vllm-service.openclaw.svc.cluster.local:8000/v1", // Docker 环境使用容器名或宿主机 IP // baseUrl: "http://host.docker.internal:8000/v1", api: "openai-responses", models: [ "Qwen/Qwen3.5-35B-A3B-FP8" ] 

} } } }

Provider 名称vllm-local可以自定义,客户端请求时通过provider/model格式指定模型,比如vllm-local/Qwen3.5-35B。

如果有多个推理后端,可以配置多个 Provider:

 { models: { default: “vllm-local/Qwen3.5-35B”, providers: { “vllm-local”: {

baseUrl: "http://vllm-service.openclaw.svc.cluster.local:8000/v1", api: "openai-responses", models: ["Qwen/Qwen3.5-35B-A3B-FP8"] 

}, “vllm-code”: {

baseUrl: "http://vllm-code-service.openclaw.svc.cluster.local:8000/v1", api: "openai-responses", models: ["Qwen/Qwen3-Coder-30B-A3B-FP8"] 

} } } }

2.5.2 验证模型连通性

K8s 环境:在集群内部验证

kubectl run -it –rm debug-curl –namespace=openclaw –image=curlimages/curl –restart=Never – curl -s http://vllm-service:8000/v1/models

预期输出:

{“data”:[{“id”:“Qwen/Qwen3.5-35B-A3B-FP8”,“object”:“model”,…}]}

验证 OpenClaw 网关到 vLLM 的端到端连通性

kubectl run -it –rm debug-curl –namespace=openclaw –image=curlimages/curl –restart=Never – curl -s -H”Authorization: Bearer ” http://openclaw-gateway:18789/v1/models

2.6 启动验证

2.6.1 K8s 部署一键执行

按顺序部署所有资源

kubectl apply -f openclaw-configmap.yaml kubectl apply -f openclaw-secret.yaml kubectl apply -f openclaw-pvc.yaml kubectl apply -f vllm-deployment.yaml kubectl apply -f vllm-service.yaml kubectl apply -f openclaw-deployment.yaml kubectl apply -f openclaw-service.yaml kubectl apply -f openclaw-ingress.yaml

查看所有资源状态

kubectl get all -n openclaw

等待所有 Pod 就绪

kubectlwait–for=condition=ready pod -l app=openclaw -n openclaw –timeout=300s

2.6.2 健康检查验证

Docker 方案验证

curl -s http://localhost:18789/healthz | python3 -m json.tool curl -s http://localhost:18789/readyz | python3 -m json.tool

K8s 方案验证(通过 Ingress)

curl -s https://openclaw.example.com/healthz | python3 -m json.tool curl -s https://openclaw.example.com/readyz | python3 -m json.tool

K8s 方案验证(通过 NodePort)

curl -s http:// :31789/healthz | python3 -m json.tool

K8s 方案验证(通过 port-forward,调试用)

kubectl port-forward svc/openclaw-gateway 18789:18789 -n openclaw & curl -s http://localhost:18789/healthz | python3 -m json.tool

2.6.3 端到端功能测试

发送一个完整的对话请求,验证网关→vLLM 链路

curl -s -X POST -H”Authorization: Bearer ” -H”Content-Type: application/json” http://localhost:18789/v1/chat/completions -d’{ “model”: “vllm-local/Qwen3.5-35B”, “messages”: [ {“role”: “system”, “content”: “You are a helpful assistant.”}, {“role”: “user”, “content”: “Hello, what is Kubernetes?”} ], “max_tokens”: 200, “temperature”: 0.7 }‘| python3 -m json.tool

如果返回了正常的模型响应,说明整条链路跑通了:客户端 → OpenClaw Gateway(认证 + 路由)→ vLLM(推理)→ 返回结果。

三、示例代码和配置

3.1 完整 docker-compose.yml(含 vLLM)

Docker 方案的完整 Compose 文件,一个文件跑起整套服务:

docker-compose.yml - OpenClaw + vLLM 完整部署

version:“3.8”

services:

OpenClaw Gateway

openclaw-gateway: image:ghcr.io/openclaw/openclaw:latest container_name:openclaw-gateway restart:unless-stopped ports: -“18789:18789” volumes: -./config:/home/node/.openclaw -./workspace:/home/node/workspace environment: -NODE_ENV=production user:“1000:1000” depends_on: vllm: condition:service_healthy healthcheck: test:[“CMD”,“curl”,“-f”,”http://localhost:18789/healthz”] interval:30s timeout:10s retries:3 start_period:15s deploy: resources: limits:

memory:2G cpus:"2.0" 

reservations:

memory:512M cpus:"0.5" 

networks: -openclaw-net logging: driver:json-file options: max-size:“50m” max-file:“5”

vLLM 推理服务

vllm: image:vllm/vllm-openai:latest container_name:vllm-inference restart:unless-stopped ports: -“8000:8000” command: -“–model” -“Qwen/Qwen3.5-35B-A3B-FP8” -“–host” -“0.0.0.0” -“–port” -“8000” -“–tensor-parallel-size” -“4” -“–max-model-len” -“32768” -“–gpu-memory-utilization” -“0.90” -“–block-size” -“16” -“–swap-space” -“8” -“–dtype” -“auto” -“–trust-remote-code” volumes: -model-cache:/root/.cache/huggingface environment: -HUGGING_FACE_HUB_TOKEN=${HF_TOKEN:-} -VLLM_WORKER_MULTIPROC_METHOD=spawn healthcheck: test:[“CMD”,“curl”,“-f”,”http://localhost:8000/health”] interval:30s timeout:15s retries:10 start_period:180s shm_size:“16gb” deploy: resources: reservations:

devices: -driver:nvidia count:4 capabilities:[gpu] 

networks: -openclaw-net

OpenClaw CLI(管理工具,按需启动)

openclaw-cli: image:ghcr.io/openclaw/openclaw:latest container_name:openclaw-cli profiles: -tools volumes: -./config:/home/node/.openclaw -./workspace:/home/node/workspace user:“1000:1000” stdin_open:true tty:true networks: -openclaw-net

volumes: model-cache: driver:local

networks: openclaw-net: driver:bridge

使用方法:

启动网关 + 推理服务

docker compose up -d

查看所有服务状态

docker compose ps

按需启动 CLI 管理工具

docker compose –profile tools run –rm openclaw-cli openclaw –help

查看实时日志

docker compose logs -f

停止所有服务

docker compose down

停止并清理数据卷(谨慎操作)

docker compose down -v

3.2 完整 K8s YAML(All-in-One Manifest)

把所有 K8s 资源合并到一个文件,方便一键部署:

openclaw-all-in-one.yaml

使用方法:kubectl apply -f openclaw-all-in-one.yaml

— Namespace —

apiVersion:v1 kind:Namespace metadata: name:openclaw labels: app:openclaw


— ConfigMap —

apiVersion:v1 kind:ConfigMap metadata: name:openclaw-config namespace:openclaw data: openclaw.json:| { “gateway”: {

"bind": "0.0.0.0:18789", "auth": { "token": "${OPENCLAW_AUTH_TOKEN}" } 

}, “models”: {

"default": "vllm-local/Qwen3.5-35B", "providers": { "vllm-local": { "baseUrl": "http://vllm-service.openclaw.svc.cluster.local:8000/v1", "api": "openai-responses", "models": [ "Qwen/Qwen3.5-35B-A3B-FP8" ] } } 

} }


— Secret(部署前先替换 Token) —

apiVersion:v1 kind:Secret metadata: name:openclaw-secrets namespace:openclaw type:Opaque stringData: gateway-token:“REPLACE_WITH_RANDOM_TOKEN”


— PVC: Gateway 数据 —

apiVersion:v1 kind:PersistentVolumeClaim metadata: name:openclaw-data namespace:openclaw spec: accessModes:[ReadWriteOnce] storageClassName:standard resources: requests: storage:10Gi


— PVC: Gateway 工作空间 —

apiVersion:v1 kind:PersistentVolumeClaim metadata: name:openclaw-workspace namespace:openclaw spec: accessModes:[ReadWriteOnce] storageClassName:standard resources: requests: storage:50Gi


— PVC: vLLM 模型缓存 —

apiVersion:v1 kind:PersistentVolumeClaim metadata: name:vllm-model-cache namespace:openclaw spec: accessModes:[ReadWriteOnce] storageClassName:standard resources: requests: storage:200Gi


— Deployment: OpenClaw Gateway —

apiVersion:apps/v1 kind:Deployment metadata: name:openclaw-gateway namespace:openclaw spec: replicas:2 selector: matchLabels: app:openclaw component:gateway strategy: type:RollingUpdate rollingUpdate: maxSurge:1 maxUnavailable:0 template: metadata: labels: app:openclaw component:gateway spec: securityContext: runAsUser:1000 runAsGroup:1000 fsGroup:1000 initContainers: -name:config-init

image:ghcr.io/openclaw/openclaw:latest command:["/bin/sh","-c"] args: -| cp /config-readonly/openclaw.json /home/node/.openclaw/openclaw.json sed -i "s|${OPENCLAW_AUTH_TOKEN}|${GATEWAY_TOKEN}|g" /home/node/.openclaw/openclaw.json env: -name:GATEWAY_TOKEN valueFrom: secretKeyRef: name:openclaw-secrets key:gateway-token volumeMounts: -name:config-readonly mountPath:/config-readonly -name:openclaw-data mountPath:/home/node/.openclaw 

containers: -name:gateway

image:ghcr.io/openclaw/openclaw:latest ports: -containerPort:18789 env: -name:NODE_ENV value:"production" resources: requests: cpu:"500m" memory:"512Mi" limits: cpu:"2000m" memory:"2Gi" livenessProbe: httpGet: path:/healthz port:18789 initialDelaySeconds:15 periodSeconds:30 readinessProbe: httpGet: path:/readyz port:18789 initialDelaySeconds:10 periodSeconds:10 startupProbe: httpGet: path:/healthz port:18789 periodSeconds:5 failureThreshold:12 volumeMounts: -name:openclaw-data mountPath:/home/node/.openclaw -name:openclaw-workspace mountPath:/home/node/workspace 

volumes: -name:config-readonly

configMap: name:openclaw-config 

-name:openclaw-data

persistentVolumeClaim: claimName:openclaw-data 

-name:openclaw-workspace

persistentVolumeClaim: claimName:openclaw-workspace 

terminationGracePeriodSeconds:30


— Deployment: vLLM —

apiVersion:apps/v1 kind:Deployment metadata: name:vllm-inference namespace:openclaw spec: replicas:1 selector: matchLabels: app:openclaw component:vllm template: metadata: labels: app:openclaw component:vllm spec: containers: -name:vllm

image:vllm/vllm-openai:latest command:["python3","-m","vllm.entrypoints.openai.api_server"] args: -"--model=Qwen/Qwen3.5-35B-A3B-FP8" -"--host=0.0.0.0" -"--port=8000" -"--tensor-parallel-size=4" -"--max-model-len=32768" -"--gpu-memory-utilization=0.90" -"--block-size=16" -"--swap-space=8" -"--dtype=auto" -"--trust-remote-code" ports: -containerPort:8000 env: -name:VLLM_WORKER_MULTIPROC_METHOD value:"spawn" resources: requests: cpu:"8" memory:"64Gi" nvidia.com/gpu:"4" limits: cpu:"16" memory:"128Gi" nvidia.com/gpu:"4" volumeMounts: -name:model-cache mountPath:/root/.cache/huggingface -name:shm mountPath:/dev/shm livenessProbe: httpGet: path:/health port:8000 initialDelaySeconds:120 periodSeconds:30 readinessProbe: httpGet: path:/health port:8000 initialDelaySeconds:120 periodSeconds:15 

volumes: -name:model-cache

persistentVolumeClaim: claimName:vllm-model-cache 

-name:shm

emptyDir: medium:Memory sizeLimit:16Gi 

tolerations: -key:nvidia.com/gpu

operator:Exists effect:NoSchedule 

nodeSelector: gpu-type:a100


— Service: OpenClaw Gateway —

apiVersion:v1 kind:Service metadata: name:openclaw-gateway namespace:openclaw spec: type:ClusterIP ports: -port:18789 targetPort:18789 selector: app:openclaw component:gateway


— Service: vLLM —

apiVersion:v1 kind:Service metadata: name:vllm-service namespace:openclaw spec: type:ClusterIP ports: -port:8000 targetPort:8000 selector: app:openclaw component:vllm


— Ingress —

apiVersion:networking.k8s.io/v1 kind:Ingress metadata: name:openclaw-gateway namespace:openclaw annotations: nginx.ingress.kubernetes.io/proxy-read-timeout:“3600” nginx.ingress.kubernetes.io/proxy-send-timeout:“3600” nginx.ingress.kubernetes.io/proxy-http-version:“1.1” nginx.ingress.kubernetes.io/proxy-body-size:“50m” cert-manager.io/cluster-issuer:“letsencrypt-prod” spec: ingressClassName:nginx tls: -hosts:[openclaw.example.com] secretName:openclaw-tls rules: -host:openclaw.example.com http: paths:

-path:/ pathType:Prefix backend: service: name:openclaw-gateway port: number:18789 

部署命令:

先替换 Token(手动或用 envsubst)

exportGATEWAY_TOKEN=\((openssl rand -hex 32) sed -i"s/REPLACE_WITH_RANDOM_TOKEN/\){GATEWAY_TOKEN}/g”openclaw-all-in-one.yaml

一键部署

kubectl apply -f openclaw-all-in-one.yaml

查看部署状态

kubectl get all -n openclaw

3.3 openclaw.json 生产配置

完整的生产级配置文件,包含 vLLM Provider、Qwen3.5 模型和多 Provider 路由:

 // ~/.openclaw/openclaw.json // 生产环境配置 - 多 Provider 路由 + vLLM 推理后端 { gateway: { // 监听地址,容器环境用 0.0.0.0 bind: “0.0.0.0:18789”,

auth: { // 每个接入方使用独立 Token // 通过 openclaw CLI 管理多 Token token: “oc-prod- ” },

// 请求限流配置 rateLimit: { // 每分钟最大请求数 maxRequestsPerMinute: 600, // 单个 Token 每分钟最大请求数 maxRequestsPerMinutePerToken: 60 } },

models: { // 默认模型(不指定模型时使用) default: “vllm-local/Qwen3.5-35B”,

providers: { // 主力推理后端:vLLM + Qwen3.5 “vllm-local”: {

baseUrl: "http://vllm-service.openclaw.svc.cluster.local:8000/v1", api: "openai-responses", models: [ "Qwen/Qwen3.5-35B-A3B-FP8" ] 

},

// 代码生成专用后端(可选) “vllm-code”: {

baseUrl: "http://vllm-code.openclaw.svc.cluster.local:8000/v1", api: "openai-responses", models: [ "Qwen/Qwen3-Coder-30B-A3B-FP8" ] 

},

// 备用云端 Provider(可选,用于降级) “openai-cloud”: {

baseUrl: "https://api.openai.com/v1", api: "openai-responses", apiKey: "${OPENAI_API_KEY}", models: [ "gpt-4o", "gpt-4o-mini" ] 

} } },

// 日志配置 logging: { level: “info”, // 生产环境建议 JSON 格式,方便 ELK/Loki 采集 format: “json” } }

3.4 案例一:企业微信 / Telegram 多渠道接入

场景描述:公司同时使用企业微信(内部沟通)和 Telegram(海外团队),需要同一个 AI 助手在两个平台上提供服务。OpenClaw 作为网关统一接入,后端共用同一个 vLLM 推理实例。

架构图

 企业微信 Bot ──→ Webhook ──→ OpenClaw Gateway (:18789) ──→ vLLM (:8000) Telegram Bot ──→ Webhook ── ↓

 Qwen3.5-35B-A3B-FP8 

实现步骤

在企业微信管理后台创建应用,获取CorpID、AgentID、Secret

在 Telegram 通过 @BotFather 创建 Bot,获取BOT_TOKEN

配置 OpenClaw 渠道接入

 // openclaw.json - 多渠道配置 { gateway: { bind: “0.0.0.0:18789”, auth: { token: “oc-prod- 
           
   
             
              
    
             ” } }, 
           
   
             

// 渠道配置 channels: { // 企业微信接入 “wechat-work”: { type: “wechat-work”, corpId: “wwabcdef”, agentId: , secret: “\({WECHAT_WORK_SECRET}", token: "\){WECHAT_WORK_TOKEN}”, encodingAesKey: “${WECHAT_WORK_AES_KEY}”, // 消息回调地址:https://openclaw.example.com/webhook/wechat-work webhookPath: “/webhook/wechat-work” },

// Telegram 接入 “telegram”: { type: “telegram”, botToken: “${TELEGRAM_BOT_TOKEN}”, // 消息回调地址:https://openclaw.example.com/webhook/telegram webhookPath: “/webhook/telegram” } },

models: { default: “vllm-local/Qwen3.5-35B”, providers: { “vllm-local”: {

baseUrl: "http://vllm-service.openclaw.svc.cluster.local:8000/v1", api: "openai-responses", models: ["Qwen/Qwen3.5-35B-A3B-FP8"] 

} } } }

设置 Webhook 回调

Telegram:设置 Webhook URL

curl -s -X POST “https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/setWebhook” -H”Content-Type: application/json” -d’{“url”: “https://openclaw.example.com/webhook/telegram”}’

企业微信:在管理后台「应用管理」→「接收消息」中配置

URL: https://openclaw.example.com/webhook/wechat-work

Token 和 EncodingAESKey 与 openclaw.json 中保持一致

验证

验证 Telegram Webhook 状态

curl -s”https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getWebhookInfo”| python3 -m json.tool

在企业微信中给 Bot 发消息,观察 OpenClaw 日志

kubectl logs -f -l app=openclaw,component=gateway -n openclaw

在 Telegram 中给 Bot 发消息,观察响应

3.5 案例二:K8s 多租户隔离部署

场景描述:公司有三个部门(研发部、市场部、客服部),每个部门需要独立的 AI 助手,使用不同的模型和配置。要求部门之间网络隔离,互不影响。

隔离方案:Namespace 隔离 + NetworkPolicy 网络隔离 + RBAC 权限隔离 + 独立 vLLM 实例。

3.5.1 Namespace 规划

创建部门级 Namespace

kubectl create namespace openclaw-dev # 研发部 kubectl create namespace openclaw-marketing# 市场部 kubectl create namespace openclaw-support # 客服部

打标签用于 NetworkPolicy 选择

kubectl label namespace openclaw-dev department=dev kubectl label namespace openclaw-marketing department=marketing kubectl label namespace openclaw-support department=support

3.5.2 NetworkPolicy:部门间网络隔离

networkpolicy-isolation.yaml

默认拒绝所有跨 Namespace 流量,只允许同 Namespace 内通信

研发部 NetworkPolicy

apiVersion:networking.k8s.io/v1 kind:NetworkPolicy metadata: name:deny-cross-namespace namespace:openclaw-dev spec: podSelector:{} policyTypes: -Ingress -Egress ingress: # 允许同 Namespace 内 Pod 互访 -from: -podSelector:{} # 允许 Ingress Controller 访问(必须,否则外部请求进不来) -from: -namespaceSelector:

 matchLabels: kubernetes.io/metadata.name:ingress-nginx 

egress: # 允许同 Namespace 内 Pod 互访 -to: -podSelector:{} # 允许 DNS 查询 -to: -namespaceSelector:{}

podSelector: matchLabels: k8s-app:kube-dns 

ports: -protocol:UDP

port:53 

-protocol:TCP

port:53 

# 允许访问外部网络(模型下载、API 调用) -to: -ipBlock:

 cidr:0.0.0.0/0 except: -10.0.0.0/8 -172.16.0.0/12 -192.168.0.0/16 

市场部和客服部使用相同模板,修改 namespace 即可

apiVersion:networking.k8s.io/v1 kind:NetworkPolicy metadata: name:deny-cross-namespace namespace:openclaw-marketing spec: podSelector:{} policyTypes:[Ingress,Egress] ingress: -from: -podSelector:{} -from: -namespaceSelector:

 matchLabels: kubernetes.io/metadata.name:ingress-nginx 

egress: -to: -podSelector:{} -to: -namespaceSelector:{}

podSelector: matchLabels: k8s-app:kube-dns 

ports: -{protocol:UDP,port:53} -{protocol:TCP,port:53} -to: -ipBlock:

 cidr:0.0.0.0/0 except:[10.0.0.0/8,172.16.0.0/12,192.168.0.0/16] 

3.5.3 RBAC:部门管理员权限

rbac-dev-admin.yaml

研发部管理员只能管理自己 Namespace 的资源

apiVersion:rbac.authorization.k8s.io/v1 kind:Role metadata: name:openclaw-admin namespace:openclaw-dev rules: -apiGroups:[“”,“apps”,“networking.k8s.io”] resources:[“pods”,“services”,“deployments”,“configmaps”,“ingresses”] verbs:[“get”,“list”,“watch”,“create”,“update”,“patch”] -apiGroups:[“”] resources:[“pods/log”] verbs:[“get”,“list”]

禁止删除操作和 Secret 访问

-apiGroups:[“”] resources:[“secrets”]

verbs:[“get”,“list”]

apiVersion:rbac.authorization.k8s.io/v1 kind:RoleBinding metadata: name:dev-admin-binding namespace:openclaw-dev subjects: -kind:User name: apiGroup:rbac.authorization.k8s.io roleRef: kind:Role name:openclaw-admin apiGroup:rbac.authorization.k8s.io

3.5.4 各部门独立部署

每个部门在自己的 Namespace 部署独立的 OpenClaw Gateway + vLLM 实例。以研发部为例:

部署研发部实例

1. 生成独立 Token

DEV_TOKEN=$(openssl rand -hex 32)

2. 创建 Secret

kubectl create secret generic openclaw-secrets –namespace=openclaw-dev –from-literal=gateway-token=“${DEV_TOKEN}”

3. 部署(使用 all-in-one 模板,修改 namespace)

sed’s/namespace: openclaw/namespace: openclaw-dev/g’openclaw-all-in-one.yaml | kubectl apply -f -

4. 验证

kubectl get all -n openclaw-dev

部门间完全隔离:不同 Token、不同网络策略、不同模型配置、不同资源配额。研发部的请求不会路由到市场部的 vLLM,市场部的 Pod 也无法访问研发部的服务。

3.5.5 ResourceQuota:资源配额限制

resourcequota-dev.yaml

apiVersion:v1 kind:ResourceQuota metadata: name:openclaw-quota namespace:openclaw-dev spec: hard: requests.cpu:“16” requests.memory:“128Gi” limits.cpu:“32” limits.memory:“256Gi” requests.nvidia.com/gpu:“4” persistentvolumeclaims:“5”

pods:“10”

市场部配额(不需要 GPU,使用云端 API)

apiVersion:v1 kind:ResourceQuota metadata: name:openclaw-quota namespace:openclaw-marketing spec: hard: requests.cpu:“4” requests.memory:“8Gi” limits.cpu:“8” limits.memory:“16Gi” requests.nvidia.com/gpu:“0” persistentvolumeclaims:“3” pods:“5”

市场部只部署 OpenClaw Gateway,模型对接云端 API(如 OpenAI),不需要 GPU 资源。研发部自带 vLLM + GPU,资源配额更高。这样既满足了不同部门的需求差异,又避免了资源争抢。

四、**实践和注意事项

4.1 **实践

4.1.1 性能优化

Gateway 并发调优:OpenClaw 基于 Node.js 单线程事件循环,默认并发能力取决于 libuv 线程池大小。生产环境建议设置UV_THREADPOOL_SIZE=16,可将 I/O 密集型操作的并发提升 4 倍(默认值 4)。

Deployment 中添加环境变量

env: -name:UV_THREADPOOL_SIZE value:“16” -name:NODE_OPTIONS value:“–max-old-space-size=1536”

max-old-space-size限制 V8 堆内存上限,设为容器 memory limit 的 75%。2Gi 内存限制对应 1536MB 堆上限,留出余量给 Node.js 的非堆内存(Buffer、Native 模块等)。

vLLM Continuous Batching 参数:vLLM 的 continuous batching 是吞吐量的关键。max-num-seqs控制同时处理的最大序列数,默认 256。A100 80GB 4 卡跑 35B 模型,实测max-num-seqs=128是甜点值,QPS 稳定在 40-60。设太高会导致 KV Cache 不够分,反而降低吞吐。

 args: -“–max-num-seqs=128” -“–max-num-batched-tokens=32768” -“–enable-chunked-prefill” 

enable-chunked-prefill开启后,长 prompt 的 prefill 阶段会分块执行,不会阻塞其他请求的 decode 阶段。实测开启后 P99 延迟从 12s 降到 4s。

资源 limits 设置原则:CPU request 设为 limit 的 25-50%,给突发流量留余量。内存 request 和 limit 建议设成一样,避免 OOM Kill 后 Pod 被驱逐到其他节点引发雪崩。GPU 的 request 和 limit 必须相等(NVIDIA device plugin 的硬性要求)。

 resources: requests: cpu:“500m” # limit 的 25% memory:“2Gi” # 和 limit 相同 limits: cpu:“2000m” memory:“2Gi” 

4.1.2 安全加固

Token 轮换机制:生产环境建议每 90 天轮换一次 Gateway Token。轮换流程:生成新 Token → 更新 Secret → 滚动重启 Gateway Pod → 通知接入方更新 Token。可以通过 CronJob 自动化:

token-rotation-cronjob.yaml

apiVersion:batch/v1 kind:CronJob metadata: name:token-rotation namespace:openclaw spec: schedule:“0 2 1 */3 *”# 每季度 1 号凌晨 2 点执行 jobTemplate: spec: template: spec:

serviceAccountName:token-rotator containers: -name:rotate image:bitnami/kubectl:latest command:["/bin/sh","-c"] args: -| NEW_TOKEN=$(openssl rand -hex 32) kubectl create secret generic openclaw-secrets --namespace=openclaw --from-literal=gateway-token="${NEW_TOKEN}" --dry-run=client -o yaml | kubectl apply -f - kubectl rollout restart deployment/openclaw-gateway -n openclaw echo "Token rotated at $(date). New token prefix: ${NEW_TOKEN8}..." restartPolicy:OnFailure 

NetworkPolicy 最小权限:Gateway Pod 只需要出站访问 vLLM Service(端口 8000)和 DNS。入站只允许 Ingress Controller。别偷懒开allow-all,网络层隔离是多租户安全的基础。

networkpolicy-gateway.yaml

apiVersion:networking.k8s.io/v1 kind:NetworkPolicy metadata: name:gateway-policy namespace:openclaw spec: podSelector: matchLabels: component:gateway policyTypes:[Ingress,Egress] ingress: -from: -namespaceSelector:

 matchLabels: kubernetes.io/metadata.name:ingress-nginx 

ports: -port:18789 egress: # 允许访问 vLLM Service -to: -podSelector:

 matchLabels: component:vllm 

ports: -port:8000 # 允许 DNS -to: -namespaceSelector:{}

podSelector: matchLabels: k8s-app:kube-dns 

ports: -{protocol:UDP,port:53} -{protocol:TCP,port:53}

RBAC 最小权限原则:运维人员使用 ClusterRole,开发人员只给 Namespace 级别 Role。Secret 的get权限要谨慎分配,能用list就别给get(list只返回 Secret 名称,get会返回内容)。

TLS 全链路加密:Ingress 到 Gateway 走 HTTPS(cert-manager 自动签发),Gateway 到 vLLM 在集群内部走 HTTP(性能考虑)。如果安全要求极高,可以用 Service Mesh(Istio/Linkerd)实现集群内部 mTLS。

4.1.3 高可用配置

Gateway 多副本 + PDB:生产环境至少 2 个副本,配合 PodDisruptionBudget 保证滚动更新和节点维护时至少有 1 个 Pod 可用。

pdb.yaml

apiVersion:policy/v1 kind:PodDisruptionBudget metadata: name:openclaw-gateway-pdb namespace:openclaw spec: minAvailable:1 selector: matchLabels: app:openclaw component:gateway

HPA 自动扩缩容:基于 CPU 使用率自动扩缩 Gateway 副本数。Gateway 是 I/O 密集型,CPU 通常不高,建议同时监控自定义指标(如请求队列长度)。

hpa.yaml

apiVersion:autoscaling/v2 kind:HorizontalPodAutoscaler metadata: name:openclaw-gateway-hpa namespace:openclaw spec: scaleTargetRef: apiVersion:apps/v1 kind:Deployment name:openclaw-gateway minReplicas:2 maxReplicas:8 metrics: -type:Resource resource: name:cpu target:

type:Utilization averageUtilization:70 

-type:Resource resource: name:memory target:

type:Utilization averageUtilization:80 

behavior: scaleUp: stabilizationWindowSeconds:60 policies: -type:Pods

value:2 periodSeconds:60 

scaleDown: stabilizationWindowSeconds:300 policies: -type:Pods

value:1 periodSeconds:120 

scaleDown.stabilizationWindowSeconds=300很重要,防止流量波动导致频繁缩容。缩容太快会在下一波请求到来时来不及扩容,用户体验骤降。

vLLM 高可用:vLLM 本身是有状态服务(GPU 显存中有模型权重),不支持多副本负载均衡。高可用方案是部署 2 个独立的 vLLM 实例(不同 Deployment),在 OpenClaw 配置多 Provider,主 Provider 故障时手动切换到备用 Provider。未来可以用 OpenClaw 的 Provider 健康检查实现自动故障转移。

4.2 注意事项

4.2.1 配置注意事项

uid 1000 权限问题:这是新手踩得最多的坑。OpenClaw 容器以node用户(uid 1000)运行,如果宿主机目录的 owner 不是 1000,容器内写入会报EACCES: permission denied。

修复权限(Docker 方案)

sudo chown -R 1000:1000 ./config ./workspace

K8s 方案通过 fsGroup 自动处理

spec.securityContext.fsGroup: 1000

bind 地址配置:容器内必须 bind0.0.0.0,别写127.0.0.1。写127.0.0.1只能容器内部访问,外部请求过来全是 connection refused。这个错误在日志里不会报错,排查起来很头疼。

配置热重载:OpenClaw 目前不支持配置文件热重载,修改openclaw.json后需要重启服务才能生效。K8s 环境下kubectl rollout restart deployment/openclaw-gateway -n openclaw就行,Docker 环境docker compose restart openclaw-gateway。

4.2.2 常见错误

 错误现象 原因分析 解决方案 EACCES: permission denied 启动失败 挂载目录 owner 不是 uid 1000 chown -R 1000:1000 挂载目录,或 K8s 设置fsGroup: 1000 connect ECONNREFUSED 127.0.0.1:8000 Gateway 无法连接 vLLM 检查 vLLM Service 是否 Ready,检查baseUrl地址是否正确 /healthz 返回 200 但/readyz返回 503 Gateway 启动了但后端模型不可用 等待 vLLM Pod Ready,或检查 Provider 配置中的baseUrl 401 Unauthorized 请求 Token 和配置的 Token 不一致 检查Authorization: Bearer 
             
    
               
                 头,和gateway.auth.token对比 
                Pod 状态CrashLoopBackOff 容器反复崩溃重启 kubectl logs 
             
    
               
                 --previous 查看崩溃前日志 
                vLLM PodOOMKilled GPU 显存或系统内存不足 降低gpu-memory-utilization,或增加 GPU 数量 / 减小max-model-len Ingress 返回504 Gateway Timeout 大模型推理超时 增加proxy-read-timeout到 3600+,检查 vLLM 是否过载 vLLM 日志torch.cuda.OutOfMemoryError KV Cache 不够分 降低max-num-seqs或max-model-len,增加 GPU 显存 

4.2.3 兼容性问题

Docker Compose V1 vs V2:OpenClaw 的 docker-compose.yml 使用了deploy.resources.reservations.devices语法(GPU 声明),只有 Docker Compose V2 支持。V1 的docker-compose命令会报语法错误。用docker compose(没有横杠)确认是 V2。

K8s 版本兼容:Ingress APInetworking.k8s.io/v1从 K8s 1.19 开始稳定,1.22 移除了extensions/v1beta1。如果集群版本低于 1.19,需要改用旧 API 版本。

NVIDIA Device Plugin:K8s 使用 GPU 需要安装 NVIDIA Device Plugin DaemonSet。没装的话 Pod 的nvidia.com/gpu资源请求永远无法满足,Pod 会一直 Pending。

检查 Device Plugin 是否安装

kubectl get ds -n kube-system | grep nvidia

如果没有,安装

kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.17.0/deployments/static/nvidia-device-plugin.yml

Container Runtime:containerd 1.7+ 和 Docker 24+ 都支持 GPU 直通。CRI-O 需要额外配置 nvidia-container-runtime。

五、故障排查和监控

5.1 故障排查

5.1.1 日志查看

K8s 环境:查看 Gateway 日志

kubectl logs -f -l app=openclaw,component=gateway -n openclaw

K8s 环境:查看 vLLM 日志

kubectl logs -f -l app=openclaw,component=vllm -n openclaw

K8s 环境:查看崩溃前的日志(Pod 重启后之前的日志会丢失)

kubectl logs -n openclaw –previous

Docker 环境:查看实时日志

docker compose logs -f openclaw-gateway docker compose logs -f vllm

容器内日志路径(如果需要进容器看)

OpenClaw: /home/node/.openclaw/logs/

vLLM: 标准输出(无文件日志,靠容器日志驱动收集)

过滤错误日志

kubectl logs -l component=gateway -n openclaw | grep -i”error|fatal|exception”

5.1.2 常见问题排查

问题一:Gateway Pod 状态 Pending,无法调度

诊断:查看 Pod 事件

kubectl describe pod -l component=gateway -n openclaw | tail -20

常见原因

1. PVC 无法绑定(storageClassName 不存在)

kubectl get pvc -n openclaw kubectl get storageclass

2. 资源不足(CPU/内存不够)

kubectl describe nodes | grep -A 5”Allocated resources”

3. nodeSelector 不匹配

kubectl get nodes –show-labels

解决方案

PVC Pending → 检查 StorageClass 是否存在,是否有可用 PV。云环境检查 CSI Driver 是否正常

资源不足 → 降低 resource requests,或扩容节点

nodeSelector 不匹配 →kubectl label node 
             
    
               
                 gpu-type=a100 
               

问题二:vLLM Pod OOMKilled

诊断:查看 Pod 终止原因

kubectl get pod -l component=vllm -n openclaw -o jsonpath=‘{.items[0].status.containerStatuses[0].lastState.terminated.reason}’

查看节点内存使用

kubectl top nodes

查看 Pod 内存使用趋势

kubectl top pod -l component=vllm -n openclaw

解决方案

系统内存 OOM → 增加 Pod memory limit,确保节点物理内存充足(建议 4 倍 GPU 显存)

GPU 显存 OOM → 降低gpu-memory-utilization到 0.85,减小max-model-len,或增加 tensor-parallel-size

/dev/shm不足 → 确认 emptyDir 的sizeLimit足够大(建议 16Gi+)

问题三:Token 认证失败,返回 401

诊断:确认配置的 Token 值

kubectl get secret openclaw-secrets -n openclaw -o jsonpath=‘{.data.gateway-token}’| base64 -d

确认 ConfigMap 中的占位符已被替换

kubectlexec-it -n openclaw – cat /home/node/.openclaw/openclaw.json | grep token

测试请求

curl -v -H”Authorization: Bearer “http://localhost:18789/healthz

解决方案

确认请求头格式:Authorization: Bearer 
             
    
               
                 ,注意 Bearer 后面有空格 
               

确认 initContainer 的 sed 替换逻辑正确执行了(查看 initContainer 日志)

如果 Secret 更新了但 Pod 没重启,Token 不会自动生效。执行kubectl rollout restart deployment/openclaw-gateway -n openclaw

5.1.3 调试模式

OpenClaw 开启 debug 日志

方法一:环境变量

kubectlsetenv deployment/openclaw-gateway -n openclaw DEBUG=openclaw:*

方法二:修改 ConfigMap 中的 logging.level

kubectl edit configmap openclaw-config -n openclaw

将 “level”: “info” 改为 “level”: “debug”

然后重启

kubectl rollout restart deployment/openclaw-gateway -n openclaw

vLLM 开启详细日志

在 args 中添加 –log-level=debug

kubectl edit deployment/vllm-inference -n openclaw

进入容器交互式调试

kubectlexec-it -n openclaw – /bin/bash

容器内检查网络连通性

curl -s http://vllm-service:8000/health

容器内查看进程状态

ps aux

容器内查看内存使用

node -e”console.log(process.memoryUsage())”

5.2 性能监控

5.2.1 关键指标监控

Gateway 基础监控

CPU 使用率

kubectl top pod -l component=gateway -n openclaw

内存使用

kubectl top pod -l component=gateway -n openclaw

网络连接数(进入容器内查看)

kubectlexec-it -n openclaw – ss -s

vLLM 推理性能指标(vLLM 内置 metrics 端点)

curl -s http://vllm-service:8000/metrics

关键 vLLM 指标

curl -s http://vllm-service:8000/metrics | grep -E”vllm:num_requests|vllm:gpu_cache|vllm:avg_generation”

5.2.2 监控指标说明

 指标名称 正常范围 告警阈值 说明 Gateway CPU 使用率 10-40% >70% Node.js 单线程,持续高 CPU 说明事件循环阻塞 Gateway 内存使用 200-800MB >1.5GB 接近 limit 时有 OOM 风险 Gateway 请求延迟 P95 100-500ms >2000ms 不含模型推理时间,纯网关转发延迟 Gateway 活跃连接数 0-500 >1000 WebSocket 长连接场景下可能较高 vLLM GPU 利用率 60-90% >95% 持续 95%+ 说明需要扩容 vLLM KV Cache 使用率 40-80% >90% 超 90% 新请求会排队等待 vLLM 请求队列长度 0-20 >50 队列积压说明推理速度跟不上请求速度 vLLM 生成速率 30-50 tokens/s/req <10 tokens/s 低于 10 说明 GPU 资源不足或 batch 配置有问题 

5.2.3 Prometheus 监控告警配置

prometheus-rules.yaml

apiVersion:monitoring.coreos.com/v1 kind:PrometheusRule metadata: name:openclaw-alerts namespace:openclaw labels: release:prometheus spec: groups: -name:openclaw-gateway rules: # Gateway Pod 挂了 -alert:OpenClawGatewayDown

expr:up{job="openclaw-gateway"}==0 for:1m labels: severity:critical annotations: summary:"OpenClaw Gateway 实例不可用" description:"{{ $labels.pod }}已停止响应超过 1 分钟" 

# Gateway 内存使用过高 -alert:OpenClawGatewayHighMemory

expr:| container_memory_working_set_bytes{namespace="openclaw", container="gateway"} / container_spec_memory_limit_bytes{namespace="openclaw", container="gateway"} > 0.85 for:5m labels: severity:warning annotations: summary:"OpenClaw Gateway 内存使用超过 85%" description:"{{ $labels.pod }}内存使用{{ $value | humanizePercentage }}" 

# Gateway 重启次数过多 -alert:OpenClawGatewayRestarts

expr:| increase(kube_pod_container_status_restarts_total{ namespace="openclaw", container="gateway" }[1h]) > 3 labels: severity:warning annotations: summary:"OpenClaw Gateway 1 小时内重启超过 3 次" 

-name:openclaw-vllm rules: # vLLM GPU 显存使用过高 -alert:VllmGpuMemoryHigh

expr:| vllm:gpu_cache_usage_perc > 0.90 for:10m labels: severity:warning annotations: summary:"vLLM GPU KV Cache 使用率超过 90%" description:"KV Cache 使用率{{ $value | humanizePercentage }},新请求可能排队" 

# vLLM 请求队列积压 -alert:VllmQueueBacklog

expr:| vllm:num_requests_waiting > 50 for:5m labels: severity:warning annotations: summary:"vLLM 请求队列积压超过 50" description:"等待处理的请求数:{{ $value }}" 

# vLLM 推理延迟过高 -alert:VllmHighLatency

expr:| histogram_quantile(0.95, rate(vllm:e2e_request_latency_seconds_bucket[5m]) ) > 30 for:5m labels: severity:warning annotations: summary:"vLLM P95 推理延迟超过 30 秒" 

Prometheus ServiceMonitor 配置(需要 Prometheus Operator):

servicemonitor.yaml

apiVersion:monitoring.coreos.com/v1 kind:ServiceMonitor metadata: name:vllm-metrics namespace:openclaw labels: release:prometheus spec: selector: matchLabels: component:vllm endpoints: -port:http path:/metrics interval:15s

5.3 备份与恢复

5.3.1 备份策略

需要备份的数据:

openclaw.json配置文件(ConfigMap 已版本化,但建议额外备份)

Gateway 工作空间数据(PVC)

K8s 资源定义(YAML 文件)

Secret(Token、API Key)

 #!/bin/bash

backup-openclaw.sh - OpenClaw 备份脚本

建议通过 CronJob 每天执行一次

BACKUP_DIR=“/backup/openclaw/$(date +%Y%m%d)” NAMESPACE=“openclaw”

mkdir -p”${BACKUP_DIR}”

1. 备份 ConfigMap

kubectl get configmap openclaw-config -n\({NAMESPACE}-o yaml >"\){BACKUP_DIR}/configmap.yaml”

2. 备份 Secret(加密存储)

kubectl get secret openclaw-secrets -n\({NAMESPACE}-o yaml >"\){BACKUP_DIR}/secret.yaml.enc”

生产环境用 age/sops 加密

sops –encrypt “\({BACKUP_DIR}/secret.yaml" > "\){BACKUP_DIR}/secret.yaml.enc”

3. 备份所有 K8s 资源定义

kubectl get all,configmap,secret,pvc,ingress,networkpolicy -n\({NAMESPACE}-o yaml >"\){BACKUP_DIR}/all-resources.yaml”

4. 备份 PVC 数据(需要 Velero 或手动快照)

云环境使用 VolumeSnapshot

kubectl apply -f - < \((date +%Y%m%d)   namespace: \){NAMESPACE} spec:   volumeSnapshotClassName: csi-snapclass source:     persistentVolumeClaimName: openclaw-data EOF

echo”Backup completed: ${BACKUP_DIR}”

清理 30 天前的备份

find /backup/openclaw -maxdepth 1 -mtime +30 -type d -exec rm -rf {} ;

5.3.2 恢复流程

1. 停止现有服务

kubectl scale deployment openclaw-gateway -n openclaw –replicas=0

2. 恢复配置

kubectl apply -f /backup/openclaw//configmap.yaml kubectl apply -f /backup/openclaw//secret.yaml

3. 恢复 PVC 数据(从 VolumeSnapshot)

kubectl apply -f - <

4. 重新启动服务

kubectl scale deployment openclaw-gateway -n openclaw –replicas=2

5. 验证恢复结果

kubectl wait –for=condition=ready pod -l component=gateway -n openclaw –timeout=120s curl -s http://localhost:18789/healthz

六、总结

6.1 技术要点回顾

Docker 方案快速启动:docker-setup.sh一键部署,适合开发测试。docker-compose.yml管理服务依赖和健康检查,比裸docker run更可控。核心配置就一个openclaw.json(JSON5 格式),改完重启即可。

K8s 方案生产就绪:Deployment + Service + Ingress 三件套,配合 ConfigMap/Secret 管理配置和敏感信息。initContainer 解决 ConfigMap 只读问题,securityContext 解决 uid 1000 权限问题。三种探针(startup/liveness/readiness)保证服务可靠性。

vLLM 推理后端:tensor-parallel 多卡并行,/dev/shm共享内存必须挂载,initialDelaySeconds要给够(120s+)。gpu-memory-utilization=0.90是安全值,别贪心设 0.95。

多租户隔离:Namespace + NetworkPolicy + RBAC + ResourceQuota 四层隔离。NetworkPolicy 默认拒绝跨 Namespace 流量,RBAC 限制管理权限,ResourceQuota 防止资源争抢。每个部门独立 Token,独立 vLLM 实例。

安全加固:Token 定期轮换(建议 90 天),NetworkPolicy 最小权限,TLS 全链路加密。Secret 的 RBAC 权限严格控制,别给get权限只给list。

监控告警:Gateway 关注 CPU、内存、连接数;vLLM 关注 GPU Cache 使用率、请求队列长度、生成速率。Prometheus + ServiceMonitor 采集指标,PrometheusRule 配置告警。

6.2 进阶学习方向

Service Mesh 集成:用 Istio 或 Linkerd 实现集群内部 mTLS、流量镜像、金丝雀发布。OpenClaw Gateway 的多副本可以利用 Istio 的加权路由实现灰度更新,新版本先承接 10% 流量,验证稳定后逐步扩大。

实践建议:先在测试环境部署 Istio,给 openclaw namespace 打上istio-injection=enabled标签,观察 sidecar 注入后的性能影响。

GitOps 持续交付:用 ArgoCD 或 Flux 管理 OpenClaw 的 K8s 资源定义,配置变更通过 Git PR 审批,自动同步到集群。ConfigMap 变更自动触发 Deployment 滚动更新,告别手动kubectl apply。

实践建议:把 openclaw-all-in-one.yaml 拆分成独立文件放进 Git 仓库,ArgoCD Application 指向仓库路径,开启自动同步。

多集群联邦部署:使用 KubeFed 或 Karmada 实现跨集群部署,不同区域的用户请求路由到就近的 OpenClaw 实例。GPU 资源池跨集群调度,提升利用率。

实践建议:先实现两个集群的同配置部署,DNS 层做地域路由(AWS Route53 Geolocation / Cloudflare Load Balancing),再考虑联邦管理。

6.3 参考资料

OpenClaw 官方文档 - 项目源码和官方 Docker 部署指南

vLLM 官方文档 - vLLM 部署配置和性能调优参考

Kubernetes 官方文档 - NetworkPolicy - 网络策略配置详解

NVIDIA GPU Operator - K8s GPU 资源管理和驱动自动化

Qwen3.5 模型卡 - 模型规格、硬件需求和推理配置

附录

A. 命令速查表

========== Docker 方案 ==========

docker compose up -d # 启动所有服务 docker compose down # 停止所有服务 docker compose logs -f openclaw-gateway # 查看 Gateway 日志 docker compose restart openclaw-gateway # 重启 Gateway docker compose ps # 查看服务状态 docker composeexecopenclaw-gateway /bin/bash # 进入 Gateway 容器 curl -s http://localhost:18789/healthz # 健康检查 curl -s http://localhost:18789/readyz # 就绪检查

========== K8s 方案 ==========

kubectl apply -f openclaw-all-in-one.yaml # 一键部署 kubectl get all -n openclaw # 查看所有资源 kubectl logs -f -l component=gateway -n openclaw # 查看 Gateway 日志 kubectl logs -f -l component=vllm -n openclaw # 查看 vLLM 日志 kubectl rollout restart deploy/openclaw-gateway -n openclaw # 重启 Gateway kubectl rollout status deploy/openclaw-gateway -n openclaw # 查看滚动更新状态 kubectl port-forward svc/openclaw-gateway 18789:18789 -n openclaw # 端口转发 kubectl top pod -n openclaw # 查看资源使用 kubectl describe pod -n openclaw # 查看 Pod 详情 kubectlexec-it -n openclaw – /bin/bash # 进入容器

========== 调试命令 ==========

kubectl run debug-curl –rm -it –image=curlimages/curl -n openclaw – sh # 启动调试 Pod kubectl get events -n openclaw –sort-by=‘.lastTimestamp’ # 查看事件(按时间排序) kubectl get pvc -n openclaw # 查看存储卷状态 kubectl get networkpolicy -n openclaw # 查看网络策略

========== Token 管理 ==========

openssl rand -hex 32 # 生成随机 Token kubectl get secret openclaw-secrets -n openclaw -o jsonpath=‘{.data.gateway-token}’| base64 -d # 查看当前 Token

B. 配置参数详解

openclaw.json 核心参数

 参数路径 类型 默认值 说明 gateway.bind string "0.0.0.0:18789" 网关监听地址,格式host:port gateway.auth.token string - Gateway 认证 Token,必填 gateway.rateLimit.maxRequestsPerMinute number 600 全局每分钟最大请求数 gateway.rateLimit.maxRequestsPerMinutePerToken number 60 单 Token 每分钟最大请求数 models.default string - 默认模型,格式provider/model models.providers. 
             
    
               
                 .baseUrl 
                string - 推理后端 API 地址 models.providers. 
             
    
               
                 .api 
                string "openai-responses" API 兼容模式 models.providers. 
             
    
               
                 .apiKey 
                string - 后端 API Key(自托管可不填) models.providers. 
             
    
               
                 .models 
                array [] 该 Provider 支持的模型列表 logging.level string "info" 日志级别:debug/info/warn/error logging.format string "json" 日志格式:json/text 

vLLM 关键启动参数

 参数 默认值 推荐值 说明 --model - - 模型名称或路径,必填 --tensor-parallel-size 1 按 GPU 数量设置 张量并行度,等于使用的 GPU 数量 --max-model-len 模型默认值 32768 最大序列长度,影响 KV Cache 大小 --gpu-memory-utilization 0.90 0.85-0.90 GPU 显存利用率上限 --block-size 16 16 KV Cache 块大小(tokens/block) --max-num-seqs 256 64-128 同时处理的最大序列数 --max-num-batched-tokens 32768 32768 单批次最大 token 数 --swap-space 4 8 CPU swap 空间大小(GiB) --dtype auto auto 计算精度,FP8 模型用 auto 即可 --enable-chunked-prefill false true 分块预填充,降低长 prompt 延迟 --trust-remote-code false true 允许执行模型仓库的自定义代码 

C. 术语表

 术语 英文 解释 AI Agent Gateway AI Agent Gateway AI 代理网关,负责多渠道消息接入、认证、模型路由和协议转换 Provider Provider 模型提供方,在 OpenClaw 中指一个推理后端配置(包含 baseUrl 和模型列表) KV Cache Key-Value Cache 大模型推理过程中缓存的注意力机制键值对,占用 GPU 显存 Tensor Parallel Tensor Parallelism 张量并行,将模型参数切分到多张 GPU 上并行计算 PagedAttention Paged Attention vLLM 的核心技术,将 KV Cache 按页管理,提升显存利用率 Continuous Batching Continuous Batching 连续批处理,动态将新请求加入正在处理的批次,提升吞吐量 PDB Pod Disruption Budget Pod 中断预算,限制同时不可用的 Pod 数量 HPA Horizontal Pod Autoscaler 水平 Pod 自动扩缩容器 NetworkPolicy Network Policy K8s 网络策略,控制 Pod 间的网络流量 RBAC Role-Based Access Control 基于角色的访问控制 ConfigMap ConfigMap K8s 配置映射,存储非敏感配置数据 Secret Secret K8s 密钥对象,存储敏感数据(Token、密码等) JSON5 JSON5 JSON 的超集,支持注释、尾逗号、单引号等语法 

D. 端口清单

 服务 端口 协议 用途 暴露方式 OpenClaw Gateway 18789 HTTP + WebSocket API 网关入口(认证、路由、协议转换) Ingress / NodePort 31789 vLLM Inference 8000 HTTP OpenAI 兼容 API(推理服务) ClusterIP(仅集群内部) vLLM Metrics 8000 HTTP Prometheus 指标端点(/metrics) ClusterIP(Prometheus 抓取) Prometheus 9090 HTTP 监控数据查询 按需暴露 Grafana 3000 HTTP 监控面板 按需暴露 


小讯
上一篇 2026-04-22 11:33
下一篇 2026-04-24 23:58

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/274427.html