1. 项目概述从单点部署到规模化舰队管理如果你和我一样在团队里负责维护多个基于OpenClaw的智能体实例那你一定经历过这样的混乱服务器A上的配置改了忘了同步到B和C想升级一下镜像版本结果发现某个容器的认证令牌全丢了服务直接瘫痪或者更糟某个同事直接在容器里“热更新”了一个技能当时能用过两天重启容器修改全没了还得花半天时间排查。这种“配置漂移”、“升级恐惧”和“技能蔓延”的问题在管理超过5个实例时会从偶尔的麻烦演变成日常的噩梦。openclaw-fleet正是为了解决这些规模化运维的痛点而生的。它不是一个全新的平台而是一套经过实战检验的、声明式的舰队管理工具包。简单来说它让你能用一份YAML配置文件我们称之为“舰队清单”来定义你所有OpenClaw实例的期望状态——包括运行在哪个主机、用什么镜像、绑定哪些端口、挂载哪些数据卷、启用哪些技能。然后通过一组精心编写的Bash脚本这套工具能自动帮你完成从主机初始化、状态校验、安全升级到技能部署的全套工作。它的核心思想是“基础设施即代码”和“漂移检测”确保你的生产环境始终与你的设计蓝图保持一致。这套工具源自一个管理着18个以上OpenClaw实例、横跨5台主机的真实生产环境。它提炼出的最佳实践比如端口间隔规则、认证信息持久化策略、双向验证机制对于任何打算将OpenClaw从单点Demo推向稳定、可维护的团队服务的人来说都具有极高的参考价值。无论你是DevOps工程师、SRE还是负责技术架构的全栈开发者这套工具都能帮你把繁琐的重复劳动自动化把不确定性降到最低。2. 核心设计哲学与架构解析2.1 声明式配置单一可信源传统运维中我们经常通过一系列手动命令docker run ...或分散的脚本文件来管理容器。这种方式的问题在于“真实状态”分散在各个服务器的运行时和操作者的记忆里没有一份权威的、版本可控的“设计图”。openclaw-fleet强制要求将所有实例的配置集中定义在fleet.yml这个文件中。这份清单就是你的“单一可信源”。它不仅仅记录了容器在哪里运行更重要的是定义了“应该是什么样子”。工具的所有操作验证、升级、部署都以此文件为基准。这样做的好处显而易见版本控制fleet.yml可以放入Git仓库任何变更都有记录便于回滚和审计。团队协作新成员可以通过阅读这份文件快速理解整个系统的拓扑结构。消除歧义避免了“我以为你在那台机器上改了配置”的沟通成本。2.2 双向漂移检测不仅仅是“少了什么”更要发现“多了什么”大多数配置管理工具只做单向检查对比清单和现实报告哪些资源缺失或不符合规范。openclaw-fleet的fleet-verify.sh脚本实现了更强大的双向漂移检测。清单 - 现实检查清单中定义的每个容器是否都存在、运行正常、配置如端口、镜像版本是否正确。这是基础功能。现实 - 清单扫描宿主机上所有Docker容器找出那些没有被fleet.yml跟踪的“野容器”。这一点至关重要。它帮你发现那些可能由临时调试、遗忘的测试实例或未经授权的部署所创建的容器。这些“野容器”可能占用资源、带来安全风险或造成端口冲突。这种双向检测确保了环境的纯净性和可控性是生产环境稳定的基石。2.3 安全升级与数据持久化策略直接docker pull新镜像然后重启容器是导致服务中断和数据丢失的常见原因。OpenClaw容器内可能包含两类数据临时数据如安装的Chromium浏览器、临时下载的npm包。这些可以随容器销毁。持久化数据最核心的就是auth-profiles.json文件里面存储了OAuth令牌、API密钥等认证信息。这些数据必须存活于容器生命周期之外。fleet-upgrade.sh脚本实现了安全升级流程备份先行升级前自动对关键持久化数据卷进行备份。认证信息隔离通过Docker的bind mount或volume将~/.openclaw/agents/目录包含auth-profiles.json挂载到宿主机。这样无论容器如何重建认证状态都得以保留。滚动升级与回滚支持按主机逐个升级降低全局风险。一旦健康检查失败可以一键回滚到之前的镜像版本。干跑模式提供--dry-run参数在不执行任何实际操作的情况下模拟并打印出整个升级计划供你审核。2.4 技能部署的版本化管理OpenClaw的技能是其核心能力。在早期开发者可能会直接进入容器内部修改技能代码这带来了巨大的维护灾难。openclaw-fleet通过fleet-deploy-skills.sh引入了技能版本化部署的概念。其理念是将技能视为独立的、版本化的软件包。你可以将技能代码存放在独立的Git仓库中通过CI/CD流水线打包成特定版本如my-skill-1.2.3.tar.gz。部署脚本则负责将这个包安全地分发到舰队中指定的容器内并更新容器内的技能索引。同时它也提供--check功能对比当前运行的技能版本与期望版本是否一致防止未经授权的修改。3. 工具链深度拆解与实操指南3.1 舰队清单 (fleet.yml) 详解与配置实战fleet.yml是整个系统的核心。我们结合示例逐层解析其结构。# fleet.yml fleet: name: AI助手生产舰队 version: 1.0 # 清单格式版本用于未来兼容性判断 defaults: pa_image: ghcr.io/openclaw/openclaw:2026.2.22 # 默认使用的OpenClaw镜像 agent_data_root: /opt/agents # 宿主机上用于挂载Agent数据的根目录 profiles: # 1. 定义基础Profile base-pa: checks: - name: gateway-health # 健康检查网关服务 verify: curl -sf http://127.0.0.1:${PORT}/ # ${PORT} 会被容器实际端口替换 # 如果curl失败非2xx/3xx状态码则检查失败 - name: chromium # 检查容器内是否安装了Chromium用于浏览器自动化 verify: which chromium remediate: apt-get update apt-get install -y chromium # 如果缺失自动修复安装 critical: false # 非关键性依赖即使修复失败也不阻塞后续操作 - name: auth-profiles # 检查关键的认证文件是否存在 verify: test -f /home/node/.openclaw/agents/main/agent/auth-profiles.json critical: true # 关键性文件缺失意味着严重错误验证会失败 skills: # 此Profile默认启用的技能列表 - my-skill # 2. 定义继承自base-pa的管理员Profile admin-pa: inherits: base-pa # 继承所有base-pa的checks和skills skills: # 在继承的基础上增加或覆盖skills - team-router # 管理员独有的路由技能 droplets: # 定义物理或虚拟主机“水滴” prod-server-01: # 主机标识符 address: 192.168.1.101 # SSH可达的IP或域名 containers: # 在此主机上运行的容器列表 agent-customer-support: # 容器名称需唯一 port: 3001 # 容器映射到宿主机的端口 profile: base-pa # 使用的Profile domain: support.mycompany.com # 该Agent对外服务的域名用于Nginx配置参考 # 注意脚本不会自动配置Nginx这只是一个元数据字段 agent-internal-helper: port: 3006 # 注意端口间隔3001 - 3006相差5 profile: admin-pa # 未指定domain则可能仅内部访问实操要点与避坑指南端口规划是门艺术OpenClaw内部会使用网关端口 3的端口来运行一个浏览器中继服务。因此在同一台主机上部署多个实例时必须将它们的端口间隔至少设为5。例如第一个用3001第二个就必须用3006第三个用3011以此类推。否则会导致端口冲突浏览器中继服务无法启动。critical标志的智慧将auth-profiles.json这类绑定挂载的持久化数据标记为critical: true意味着如果它丢失系统核心功能就瘫痪了验证会直接失败。而将chromium这类容器层级的依赖标记为critical: false并配置remediate命令工具会尝试自动修复如重装修复失败也只是警告不影响主要服务。这体现了对“持久状态”和“临时环境”的区分管理。Profile继承减少重复通过inherits机制你可以构建一个配置层次。比如所有Agent都需要基础健康检查而只有部分需要管理技能。这避免了在几十个容器定义中复制粘贴相同的检查项极大提升了清单的可维护性。秘密信息绝不入清单fleet.yml可能会被提交到代码仓库。因此绝对不要在其中写入密码、密钥、令牌等敏感信息。这些应该通过环境变量在宿主机或CI/CD系统中设置或外部的密钥管理服务如HashiCorp Vault来注入。3.2 核心脚本工作流与内部机制3.2.1fleet-verify.sh环境的“纪律委员”这个脚本是你的第一道防线。让我们深入看看--full --remediate --json这个组合命令背后发生了什么解析清单脚本使用yq解析fleet.yml构建一个内部的对象模型包含所有主机、容器和其期望状态。SSH连接与发现通过SSH连接到清单中定义的每一台主机droplets。清单-现实检查对于清单中的每个容器执行docker ps过滤检查是否存在。如果存在检查其镜像标签是否匹配端口映射是否正确。遍历该容器Profile中的所有checks。通过docker exec在容器内执行verify命令。如果检查失败且定义了remediate命令并且critical: false则自动执行修复。记录所有成功、失败、已修复的项目。现实-清单检查审计在主机上执行docker ps -a获取所有容器列表。过滤掉那些名称与fleet.yml中定义的容器名匹配的。剩下的就是“未追踪的容器”会被标记为审计发现。生成报告根据--json标志将结果输出为结构化的JSON方便被CI系统如GitHub Actions解析并触发告警。一个常见的场景你运行./scripts/fleet-verify.sh --audit发现一台服务器上有一个名为old-test-agent的容器。你意识到这是两个月前的一次测试遗留物。这时你可以手动清理它或者将其正式纳入fleet.yml的管理。3.2.2fleet-upgrade.sh稳健的更新引擎升级是高风险操作。该脚本通过流程化将其风险可控化。# 一个完整的升级指令分解 ./scripts/fleet-upgrade.sh \ --image ghcr.io/openclaw/openclaw:2026.2.23 \ --droplet prod-server-01 \ --max-retries 2 \ --health-check-timeout 30内部执行顺序参数验证与计划确认新镜像存在确认目标主机和容器。预检对目标主机上的目标容器执行一次简化的健康检查使用其Profile中的gateway-health检查确保升级前状态是好的。数据备份识别容器中所有绑定挂载的卷特别是agent_data_root下的目录使用tar或rsync将其备份到宿主机的临时位置。备份文件名包含时间戳和容器名。执行升级停止旧容器。关键步骤使用与旧容器完全相同的docker run命令参数来自清单但仅替换镜像标签创建并启动新容器。这确保了所有环境变量、卷挂载、网络设置保持不变。后置健康检查等待新容器启动可配置超时时间然后重新运行Profile中的所有健康检查。如果--max-retries大于1会在失败后短暂等待并重试检查。决策点成功清理临时备份记录升级成功日志。失败触发自动回滚流程。停止新容器从备份中恢复数据用旧镜像重新启动原容器。然后发送失败告警。重要经验即使脚本支持全舰队升级在生产环境中也强烈建议使用--droplet参数进行分批次、分主机的滚动升级。先升级非关键或测试环境的实例观察一段时间后再升级核心生产实例。3.2.3fleet-deploy-skills.sh技能的CI/CD管道这个脚本假设你已经有一个技能打包和分发的体系。例如你的技能代码仓库在推送git tagv1.2.3时CI流程会构建一个技能包并上传到内部存储库。# 在CI流水线中或手动执行 ./scripts/fleet-deploy-skills.sh \ --version 1.2.3 \ --skill-repo-url https://pkg.internal.com/skills/my-skill-1.2.3.tar.gz \ --profile admin-pa脚本逻辑确定部署目标通过--profile指定只更新使用该Profile的容器或者不指定则更新所有容器。获取技能包从指定的URL下载对应版本的技能压缩包到本地或临时目录。分发与部署遍历所有目标容器通过SSH和Docker命令将技能包拷贝到容器内部解压到正确的技能目录例如/home/node/.openclaw/agents/main/agent/skills/。触发重载向容器的网关端口发送一个特定的HTTP请求如/reload-skills通知OpenClaw重新加载技能。这避免了重启整个容器。版本校验部署后可以再次运行--check模式连接每个容器并查询其内部技能版本确保与期望的1.2.3一致。3.3 自动化与监控GitHub Actions集成项目自带的.github/workflows/fleet-health.yml是一个开箱即用的持续监控方案。它每15分钟执行一次fleet-verify.sh --full --json。配置密钥FLEET_SSH_KEY存有能访问所有舰队主机的SSH私钥。TELEGRAM_BOT_TOKEN和TELEGRAM_CHAT_ID用于在检查失败时发送告警到Telegram群组。工作流价值主动发现在用户投诉之前就发现容器崩溃、配置漂移或健康检查失败。历史记录GitHub Actions的运行日志提供了系统健康状态的历史视图。可扩展你可以轻松修改这个工作流将告警集成到Slack、钉钉、企业微信或PagerDuty等系统。4. 生产环境部署全流程与避坑实录假设我们要从零开始在两台Ubuntu 22.04服务器上部署一个由3个OpenClaw Agent组成的小型舰队。4.1 阶段一准备与引导步骤1仓库准备git clone https://github.com/vibewrk/openclaw-fleet.git cd openclaw-fleet cp fleet.example.yml fleet.yml步骤2编写舰队清单 (fleet.yml)这是最关键的一步需要你详细了解你的基础设施。假设主机1 (host-prod-1): IP10.0.1.10 运行两个客服Agent。主机2 (host-prod-2): IP10.0.1.11 运行一个内部管理Agent。我们使用一个内部的镜像仓库my-registry.com/openclaw:2026.2.22。你的fleet.yml核心部分如下defaults: pa_image: my-registry.com/openclaw:2026.2.22 agent_data_root: /data/openclaw-agents profiles: base-pa: checks: - name: gateway-health verify: curl -sf http://127.0.0.1:${PORT}/health # 假设你的镜像有/health端点 - name: auth-profiles verify: test -f /home/node/.openclaw/agents/main/agent/auth-profiles.json critical: true droplets: host-prod-1: address: 10.0.1.10 containers: agent-cs-zh: port: 3001 profile: base-pa # 数据卷路径会自动拼接为 /data/openclaw-agents/agent-cs-zh agent-cs-en: port: 3006 # 注意间隔5 profile: base-pa host-prod-2: address: 10.0.1.11 containers: agent-internal-admin: port: 3001 profile: base-pa # 可以在这里覆盖agent_data_root # volumes: # - /mnt/ssd/openclaw/admin:/home/node/.openclaw/agents步骤3主机初始化在运行任何容器之前需要确保主机环境就绪。你可以手动设置也可以使用提供的bootstrap-droplet.sh脚本进行自动化初始化安装Docker、配置防火墙、设置Fail2ban等。务必先在测试环境验证此脚本。# 将脚本拷贝到主机并执行或通过Ansible等工具分发执行 scp scripts/bootstrap-droplet.sh user10.0.1.10:/tmp/ ssh user10.0.1.10 sudo bash /tmp/bootstrap-droplet.sh4.2 阶段二首次部署与验证步骤4手动创建容器首次由于fleet-upgrade.sh主要用于更新首次创建需要手动或通过简单脚本。根据清单我们需要在主机上创建对应的数据目录和容器。 以host-prod-1上的agent-cs-zh为例SSH登录后执行# 1. 创建持久化数据目录 sudo mkdir -p /data/openclaw-agents/agent-cs-zh sudo chown -R 1000:1000 /data/openclaw-agents/agent-cs-zh # 假设容器内用户UID为1000 # 2. 运行容器 docker run -d \ --name agent-cs-zh \ --restart unless-stopped \ -p 3001:3000 \ -v /data/openclaw-agents/agent-cs-zh:/home/node/.openclaw/agents \ -e NODE_ENVproduction \ my-registry.com/openclaw:2026.2.22注意你需要根据OpenClaw镜像的实际需求补充其他必要的环境变量或卷挂载。步骤5初始配置与认证容器启动后你需要通过其Web界面或API完成初始设置特别是OAuth认证。这个过程会在挂载卷/data/openclaw-agents/agent-cs-zh内生成auth-profiles.json等文件。这是持久化的关键。步骤6运行首次验证在所有容器都手动创建并配置好后回到你的管理机运行./scripts/fleet-verify.sh --full --json输出应该是绿色的显示所有检查通过。如果auth-profiles检查失败说明挂载可能有问题。如果gateway-health失败可能是容器没启动或端口不对。4.3 阶段三日常运维与升级场景升级到新镜像版本2026.2.23预发布检查先将新镜像推送到你的镜像仓库并在一个测试容器中验证基本功能。制定升级计划决定滚动升级顺序例如先host-prod-2再host-prod-1。执行升级# 升级 host-prod-2 上的单个容器 ./scripts/fleet-upgrade.sh --image my-registry.com/openclaw:2026.2.23 --droplet host-prod-2 --dry-run # 先干跑 ./scripts/fleet-upgrade.sh --image my-registry.com/openclaw:2026.2.23 --droplet host-prod-2观察监控查看GitHub Actions的监控流水线或你自己的监控系统确认升级后的实例健康状态稳定。继续升级如果稳定运行一段时间如30分钟再升级host-prod-1。因为有两台容器你可以选择一次升级一个也可以使用脚本批量升级该主机上的所有容器。# 升级 host-prod-1 上的所有容器 ./scripts/fleet-upgrade.sh --image my-registry.com/openclaw:2026.2.23 --droplet host-prod-1验证舰队状态升级全部完成后再次运行fleet-verify.sh --full确保整个舰队状态一致。5. 常见问题排查与经验沉淀即使有完善的工具在实际操作中仍会遇到各种问题。以下是我在实战中积累的一些排查经验和技巧。5.1 问题速查表问题现象可能原因排查步骤fleet-verify.sh报告 SSH 连接失败1. 网络不通/防火墙2. SSH密钥未添加或错误3. 主机地址/用户名错误1.ssh -i key.pem userhost手动测试连接。2. 检查fleet.yml中的address格式。3. 确保运行脚本的机器已将公钥添加到目标主机的~/.ssh/authorized_keys。健康检查 (gateway-health) 失败1. 容器未运行2. 端口映射错误3. 应用内部错误1.ssh 到主机执行docker ps和docker logs container_name。br2. 检查fleet.yml中port与docker run的-p 映射是否一致。3. 检查容器内应用日志看是否启动时报错。auth-profiles.json检查失败1. 数据卷未正确挂载2. 挂载点权限错误3. 文件尚未生成新实例1.ssh 到主机执行docker inspect container_name查看Mounts 字段。2. 检查宿主机挂载目录的权限是否属于容器用户。3. 对于新容器需要先通过Web界面完成一次认证流程。升级后服务不可用回滚成功1. 新镜像存在Bug2. 新镜像依赖环境变化3. 持久化数据与新版本不兼容1. 回滚后在测试环境深度测试新镜像。2. 对比新旧镜像的Dockerfile检查系统依赖。3. 查阅OpenClaw版本升级说明看是否有数据迁移要求。fleet-deploy-skills.sh部署后技能不生效1. 技能包路径错误2. 技能格式不符合要求3. 技能重载API调用失败1. 进入容器检查技能文件是否被解压到正确目录。2. 检查技能包的目录结构。3. 查看容器日志确认是否收到了重载请求及是否有错误。端口冲突错误1. 同一主机上容器端口间隔小于52. 存在未追踪的容器占用了端口1. 严格遵循端口间隔5的规则修改fleet.yml。2. 运行fleet-verify.sh --audit找出“野容器”并清理。5.2 深度避坑指南1. 关于数据持久化Bind Mount vs Volume脚本默认使用bind mount将宿主机目录挂载进容器因为它直观、易于备份和直接从宿主机访问。但在某些云环境或分布式存储场景Docker的Named Volume可能更合适因为它由Docker管理性能可能更好且更容易在不同容器间迁移。你可以修改fleet-upgrade.sh中构建docker run命令的逻辑将-v /host/path:/container/path替换为-v volume_name:/container/path。关键原则无论用哪种方式必须确保auth-profiles.json等关键数据存在于容器生命周期之外。2. 处理复杂的多环境配置你可能有开发、测试、生产多套环境。建议采用如下结构openclaw-fleet/ ├── fleet.example.yml ├── fleet.dev.yml # 覆盖部分配置指向开发服务器和镜像标签 ├── fleet.staging.yml ├── fleet.prod.yml └── scripts/然后通过环境变量FLEET_FILEfleet.prod.yml来指定使用的清单。在CI/CD流水线中根据分支自动选择对应的清单文件。3. 提升验证脚本的健壮性原版的verify命令可能比较简单。在生产中你可以定义更复杂的检查例如checks: - name: deep-health verify: | RESPONSE$(curl -s -o /dev/null -w %{http_code} http://127.0.0.1:${PORT}/api/status) if [ $RESPONSE -eq 200 ]; then # 进一步解析API返回的JSON检查关键组件状态 curl -s http://127.0.0.1:${PORT}/api/status | jq -e .components.database healthy /dev/null else exit 1 fi使用jq解析JSON响应可以做出更精细的健康状态判断。4. 备份策略的强化backup-pas.sh提供了基础的每日备份。对于核心生产数据你需要增加备份频率可能改为每小时或每6小时。异地备份将备份文件同步到另一个区域的对象存储如AWS S3、阿里云OSS。定期恢复演练定期随机抽取一个备份文件在隔离环境中尝试恢复确保备份的有效性。5. 密钥管理进阶将SSH私钥、Telegram token等直接放在GitHub Secrets是入门做法。对于更严格的安全要求可以考虑使用HashiCorp Vault或AWS Secrets Manager动态获取密钥。在GitHub Actions中使用OIDCOpenID Connect为工作流申请临时云凭证而不是存储长期的静态密钥。管理一个由多个智能体实例组成的舰队挑战不在于启动一两个容器而在于如何让整个系统随时间推移依然可靠、一致、可维护。openclaw-fleet提供了一套务实、自动化的答案。它没有追求大而全的复杂架构而是用一组简洁的脚本和一份声明式的清单抓住了运维中最关键的几个环节状态定义、偏差检测、安全变更和技能分发。从我个人的使用经验来看最大的收益并非来自某个炫酷的功能而是来自“心理安全感”。我知道我的环境状态被清晰地定义和监控着我知道升级可以一键回滚我知道不会有配置悄悄漂移。这让我能把更多精力花在构建业务逻辑上而不是焦头烂额地救火。如果你也正面临OpenClaw或多容器应用的管理规模挑战不妨从克隆这个仓库编写你的第一份fleet.yml开始逐步将你的运维工作纳入代码和自动化的轨道。