Update
This commit is contained in:
193
4 - Resources/HomeLab/Xiaohongshu MCP - K8s Infrastructure.md
Normal file
193
4 - Resources/HomeLab/Xiaohongshu MCP - K8s Infrastructure.md
Normal file
@@ -0,0 +1,193 @@
|
||||
---
|
||||
created: "2026-03-22"
|
||||
type: resource
|
||||
tags: [resource, kubernetes, infrastructure, devops, drone-ci, argocd, mcp, homelab]
|
||||
source: "xiaohongshu-mcp 项目部署实践"
|
||||
---
|
||||
|
||||
# Xiaohongshu MCP - K8s 基础设施
|
||||
|
||||
## 概述
|
||||
|
||||
小红书 MCP (Model Context Protocol) 服务器的 Kubernetes 部署。通过 go-rod 浏览器自动化让 AI 助手直接操作小红书平台(发帖、搜索、评论、点赞等)。
|
||||
|
||||
- 上游仓库: [xpzouying/xiaohongshu-mcp](https://github.com/xpzouying/xiaohongshu-mcp)
|
||||
- Gitea 仓库: `ssh://git@git.colacoder.com:2200/kai/xiaohongshu-mcp.git`
|
||||
- 本地路径: `C:\Users\yaoji\git\OpenSource\xiaohongshu-mcp`
|
||||
|
||||
## 架构
|
||||
|
||||
```
|
||||
AI 助手 → MCP 协议 → Go 服务 (Gin + go-rod) → 无头 Chrome → 小红书网页版
|
||||
```
|
||||
|
||||
核心技术栈:
|
||||
- Go 1.24 + Gin HTTP 框架
|
||||
- go-rod (Chrome DevTools Protocol) 浏览器自动化
|
||||
- go-rod/stealth 反检测插件
|
||||
- MCP Go SDK v0.7.0
|
||||
|
||||
## 部署方案
|
||||
|
||||
### 镜像选择
|
||||
|
||||
由于集群节点内存有限(每节点 ~2GB),**无法在集群内用 Kaniko 构建镜像**(Go 编译 + Chrome 安装会 OOM,Exit Code 137)。直接使用 Docker Hub 预构建镜像:
|
||||
|
||||
```
|
||||
xpzouying/xiaohongshu-mcp:latest
|
||||
```
|
||||
|
||||
### K8s Manifests (k8s/base/)
|
||||
|
||||
| 文件 | 作用 |
|
||||
|------|------|
|
||||
| `namespace.yaml` | `xiaohongshu-mcp` 命名空间 |
|
||||
| `pvc.yaml` | 持久卷: cookies 数据 (1Gi) + 图片存储 (5Gi) |
|
||||
| `deployment.yaml` | Deployment + Chrome 共享内存 + 健康检查 |
|
||||
| `service.yaml` | ClusterIP Service (18060) |
|
||||
| `ingress.yaml` | Ingress: `xiaohongshu-mcp.k8s.home` |
|
||||
| `drone-rbac.yaml` | Drone CI RBAC 权限 |
|
||||
| `kustomization.yaml` | Kustomize 资源索引 |
|
||||
|
||||
### Deployment 关键配置
|
||||
|
||||
```yaml
|
||||
image: xpzouying/xiaohongshu-mcp:latest
|
||||
ports: [18060]
|
||||
env:
|
||||
ROD_BROWSER_BIN: /usr/bin/google-chrome
|
||||
COOKIES_PATH: /app/data/cookies.json
|
||||
TZ: Asia/Shanghai
|
||||
resources:
|
||||
requests: { cpu: 200m, memory: 512Mi }
|
||||
limits: { cpu: "1", memory: 2Gi }
|
||||
volumes:
|
||||
- /app/data → PVC xiaohongshu-mcp-data (1Gi, cookies 持久化)
|
||||
- /app/images → PVC xiaohongshu-mcp-images (5Gi, 图片上传)
|
||||
- /dev/shm → emptyDir Memory (256Mi, Chrome 共享内存)
|
||||
```
|
||||
|
||||
Chrome 无头浏览器需要 `/dev/shm` 共享内存,否则会崩溃。通过 `emptyDir: { medium: Memory }` 挂载。
|
||||
|
||||
### Ingress
|
||||
|
||||
```yaml
|
||||
host: xiaohongshu-mcp.k8s.home
|
||||
annotations:
|
||||
proxy-body-size: "50m" # 支持图片/视频上传
|
||||
proxy-read-timeout: "300" # 浏览器操作耗时长
|
||||
proxy-send-timeout: "300"
|
||||
```
|
||||
|
||||
DNS 通过路由器通配符 `*.k8s.home → 192.168.68.240` (MetalLB) 自动解析,无需额外配置。
|
||||
|
||||
### 健康检查
|
||||
|
||||
```
|
||||
GET /health → {"success":true,"data":{"status":"healthy"},"message":"服务正常"}
|
||||
livenessProbe: initialDelay=30s, period=30s
|
||||
readinessProbe: initialDelay=10s, period=10s
|
||||
```
|
||||
|
||||
## Git Remote 配置
|
||||
|
||||
```
|
||||
origin → ssh://git@git.colacoder.com:2200/kai/xiaohongshu-mcp.git (Gitea, 主仓库)
|
||||
upstream → (已移除,需要时手动添加 GitHub 上游)
|
||||
```
|
||||
|
||||
## CI/CD
|
||||
|
||||
### Drone CI (.drone.yml)
|
||||
|
||||
由于不在集群内构建镜像,Drone 只负责触发 rollout restart:
|
||||
|
||||
```yaml
|
||||
kind: pipeline
|
||||
type: kubernetes
|
||||
name: deploy
|
||||
trigger:
|
||||
branch: [main]
|
||||
event: [push, custom]
|
||||
steps:
|
||||
- name: restart-deployment
|
||||
image: bitnami/kubectl:latest
|
||||
commands:
|
||||
- kubectl rollout restart deploy/xiaohongshu-mcp -n xiaohongshu-mcp
|
||||
```
|
||||
|
||||
### ArgoCD (k8s/argocd-app.yaml)
|
||||
|
||||
```yaml
|
||||
source:
|
||||
repoURL: https://git.colacoder.com/kai/xiaohongshu-mcp.git
|
||||
targetRevision: main
|
||||
path: k8s/base
|
||||
syncPolicy:
|
||||
automated: { prune: true, selfHeal: true }
|
||||
syncOptions: [CreateNamespace=true]
|
||||
```
|
||||
|
||||
### 部署流程
|
||||
|
||||
```
|
||||
git push origin main
|
||||
↓
|
||||
Gitea webhook → Drone CI
|
||||
↓
|
||||
kubectl rollout restart (拉取最新镜像)
|
||||
↓
|
||||
ArgoCD 自动同步 k8s/base/ 配置变更
|
||||
```
|
||||
|
||||
镜像更新依赖 Docker Hub 上游作者发布新版本,本地只做配置变更和重启。
|
||||
|
||||
## 初始部署步骤
|
||||
|
||||
```bash
|
||||
# 1. 添加 Gitea remote
|
||||
git remote add origin ssh://git@git.colacoder.com:2200/kai/xiaohongshu-mcp.git
|
||||
|
||||
# 2. 首次手动部署(Drone SA 无权创建命名空间)
|
||||
kubectl apply -k k8s/base/
|
||||
|
||||
# 3. 验证
|
||||
curl -sk https://xiaohongshu-mcp.k8s.home/health
|
||||
|
||||
# 4. 推送代码到 Gitea(后续由 Drone + ArgoCD 自动化)
|
||||
git push -u origin main
|
||||
|
||||
# 5. 在 Drone UI 中 Sync 仓库列表并 Activate
|
||||
```
|
||||
|
||||
## 踩坑记录
|
||||
|
||||
- **Kaniko OOM (Exit Code 137)**: 节点仅 2GB 内存,Go 编译 + Chrome 安装超出限制。解决: 直接用 Docker Hub 预构建镜像。
|
||||
- **Drone RBAC 权限不足**: Drone SA 只有 `invest-api` 命名空间的权限,新命名空间需手动 `kubectl apply` 创建资源后,Drone 才能操作。
|
||||
- **SSH Agent 问题**: Git 内置 SSH 客户端无法连接 1Password SSH Agent,需通过终端手动 push 或配置 `core.sshCommand` 指向 Windows OpenSSH。
|
||||
- **Chrome /dev/shm**: 容器内 Chrome 默认 `/dev/shm` 仅 64MB,不够用会崩溃。必须挂载 `emptyDir: { medium: Memory }`。
|
||||
|
||||
## MCP 功能
|
||||
|
||||
| 功能 | 说明 |
|
||||
|------|------|
|
||||
| 登录 | QR 码扫码 + Cookie 持久化 |
|
||||
| 发图文 | 多图上传、定时发布、话题标签 |
|
||||
| 发视频 | 本地视频上传 |
|
||||
| 搜索 | 关键词 + 多维筛选 |
|
||||
| 互动 | 点赞/收藏/评论/回复 |
|
||||
| 用户 | 获取个人资料和推荐 Feed |
|
||||
|
||||
## 访问地址
|
||||
|
||||
| 服务 | URL |
|
||||
|------|-----|
|
||||
| MCP 服务 | `https://xiaohongshu-mcp.k8s.home` |
|
||||
| 健康检查 | `https://xiaohongshu-mcp.k8s.home/health` |
|
||||
| MCP 端点 | `https://xiaohongshu-mcp.k8s.home/mcp` |
|
||||
| API | `https://xiaohongshu-mcp.k8s.home/api/v1/` |
|
||||
|
||||
## Related
|
||||
|
||||
- [[OpenBB Invest API - K8s Infrastructure]]
|
||||
- [[HomeLab Infrastructure]]
|
||||
239
4 - Resources/OpenClaw/OpenClaw Agent 创建指南.md
Normal file
239
4 - Resources/OpenClaw/OpenClaw Agent 创建指南.md
Normal file
@@ -0,0 +1,239 @@
|
||||
---
|
||||
created: "2026-03-22"
|
||||
updated: "2026-03-22"
|
||||
type: resource
|
||||
tags: [resource, openclaw, ai-agent, discord, howto, homelab]
|
||||
source: "实际创建 xhs-creator agent 的过程总结 + skill review 后改进"
|
||||
---
|
||||
|
||||
# OpenClaw Agent 创建指南
|
||||
|
||||
## 概述
|
||||
|
||||
基于创建小红书 agent (xhs-creator) 的实际经验,总结 OpenClaw agent 创建的完整流程。Claude Code 有对应的自动化 skill (`openclaw-create-agent`),说"创建一个 xxx agent"即可触发。
|
||||
|
||||
## 前置准备
|
||||
|
||||
### 1. 创建 Discord Bot
|
||||
|
||||
1. 访问 [Discord Developer Portal](https://discord.com/developers/applications)
|
||||
2. New Application > 命名 > Create
|
||||
3. Bot 页面 > Reset Token > 复制 token
|
||||
4. 开启 **Message Content Intent**(Privileged Gateway Intents 下)
|
||||
5. 生成邀请链接:OAuth2 > URL Generator > 勾选 `bot` > 权限选择 Send Messages, Read Message History, Add Reactions
|
||||
6. 用链接把 bot 邀请到目标 Discord 服务器
|
||||
|
||||
### 2. 获取 Discord ID
|
||||
|
||||
需要开启开发者模式(用户设置 > 高级 > 开发者模式):
|
||||
|
||||
| 信息 | 获取方式 |
|
||||
|------|---------|
|
||||
| Guild ID | 右键服务器图标 > 复制服务器 ID |
|
||||
| Channel ID | 右键文字频道 > 复制频道 ID |
|
||||
| Bot User ID | Base64 解码 token 第一段(`.` 之前)|
|
||||
| Owner User ID | `964122056163721286`(固定值) |
|
||||
|
||||
Bot User ID 解码方法:
|
||||
|
||||
```bash
|
||||
echo "TOKEN第一段" | base64 -d
|
||||
# 例如: echo "MTQ4NTMwNTQyOTcxMzA5NjkzNw" | base64 -d
|
||||
# 输出: 1485305429713096937
|
||||
```
|
||||
|
||||
## 创建步骤
|
||||
|
||||
### Step 1: Pre-flight 检查
|
||||
|
||||
验证 agent ID 是否已被占用:
|
||||
|
||||
```bash
|
||||
ssh yiukai@192.168.68.108 'node -e "
|
||||
const cfg = JSON.parse(require(\"fs\").readFileSync(\"/home/yiukai/.openclaw/openclaw.json\", \"utf8\"));
|
||||
const exists = cfg.agents.list.some(a => a.id === \"AGENT_ID\");
|
||||
console.log(exists ? \"CONFLICT\" : \"OK\");
|
||||
"'
|
||||
```
|
||||
|
||||
### Step 2: 创建目录
|
||||
|
||||
```bash
|
||||
ssh yiukai@192.168.68.108 "mkdir -p ~/.openclaw/workspace-{agent-id} ~/.openclaw/agents/{agent-id}/agent"
|
||||
```
|
||||
|
||||
### Step 3: 编写 Bootstrap 文件
|
||||
|
||||
在 `~/.openclaw/agents/{agent-id}/agent/` 下创建:
|
||||
|
||||
**AGENTS.md** -- 操作指令、能力定义、工作流程。必须包含:
|
||||
|
||||
1. 身份声明 -- 一句话说明 agent 是谁、专注什么
|
||||
2. 核心能力 -- 3-5 个编号章节,具体描述
|
||||
3. 工作流程/输出模板 -- agent 产出的结构化格式
|
||||
4. 约束条件 -- 明确不做什么
|
||||
|
||||
**SOUL.md** -- 人格、语气、边界。保持简短(20-30行):
|
||||
|
||||
1. 身份 -- 一行角色描述
|
||||
2. 语气 -- 3-4 条沟通风格
|
||||
3. 语言 -- 主要使用的语言
|
||||
4. 边界 -- 3-4 条拒绝做的事
|
||||
|
||||
可选文件:
|
||||
- `TOOLS.md` -- 用户自定义工具说明
|
||||
- `BOOTSTRAP.md` -- 一次性引导(运行后自动删除)
|
||||
- `IDENTITY.md` -- 名称/风格
|
||||
- `USER.md` -- 用户画像
|
||||
|
||||
### Step 4: 更新 openclaw.json(三部分)
|
||||
|
||||
使用 Node.js 脚本通过 SSH 原子更新,确保 JSON 有效性:
|
||||
|
||||
#### 4a. Agent 条目 (`agents.list`)
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "agent-id",
|
||||
"name": "agent-id",
|
||||
"workspace": "/home/yiukai/.openclaw/workspace-agent-id",
|
||||
"agentDir": "/home/yiukai/.openclaw/agents/agent-id/agent",
|
||||
"model": "kimi-coding/k2p5",
|
||||
"identity": { "name": "显示名称" },
|
||||
"groupChat": {
|
||||
"mentionPatterns": ["<@!?BOT_USER_ID>", "中文名称", "英文简称", "BOT_USER_ID"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `id` | Yes | 唯一标识符,用于 binding 和命令引用 |
|
||||
| `workspace` | Yes | agent 的工作目录,存放会话数据 |
|
||||
| `agentDir` | Yes | AGENTS.md/SOUL.md 所在目录 |
|
||||
| `model` | No | 覆盖 `agents.defaults.model.primary` |
|
||||
| `identity.name` | Yes | 在消息中显示的名称 |
|
||||
| `groupChat.mentionPatterns` | No | 群聊中触发 agent 的模式 |
|
||||
| `subagents.allowAgents` | No | 允许调用的子 agent 列表 |
|
||||
|
||||
#### 4b. Discord 账户 (`channels.discord.accounts`)
|
||||
|
||||
```json
|
||||
"account-id": {
|
||||
"name": "显示名称",
|
||||
"enabled": true,
|
||||
"token": "DISCORD_BOT_TOKEN",
|
||||
"groupPolicy": "open",
|
||||
"streaming": "off",
|
||||
"guilds": {
|
||||
"GUILD_ID": {
|
||||
"requireMention": false,
|
||||
"users": ["964122056163721286", "BOT_USER_ID"],
|
||||
"channels": { "CHANNEL_ID": { "allow": true } }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `groupPolicy` | `open` = 允许所有,`allowlist` = 仅白名单,`disabled` = 禁用 |
|
||||
| `requireMention` | `true` = 共享频道需 @mention,`false` = 独占频道直接响应 |
|
||||
| `users` | 白名单,必须包含 owner ID 和 bot 自身 ID |
|
||||
| `streaming` | `off` / `partial` / `full` |
|
||||
|
||||
#### 4c. Binding (`bindings`)
|
||||
|
||||
```json
|
||||
{ "agentId": "agent-id", "match": { "channel": "discord", "accountId": "account-id" } }
|
||||
```
|
||||
|
||||
### Step 5: 验证
|
||||
|
||||
配置支持热重载,保存后自动生效。检查日志:
|
||||
|
||||
```bash
|
||||
ssh yiukai@192.168.68.108 'journalctl --user -u openclaw-gateway --since "30 sec ago" --no-pager | grep -iE "agent-id|error|reload"'
|
||||
```
|
||||
|
||||
三个成功指标(全部出现才算成功):
|
||||
|
||||
1. `[reload] config change detected` -- 热重载触发
|
||||
2. `[discord] [agent-id] starting provider` -- bot 连接 Discord
|
||||
3. `channels resolved: GUILD_ID/CHANNEL_ID` -- 频道解析成功
|
||||
|
||||
如果热重载未触发:
|
||||
|
||||
```bash
|
||||
ssh yiukai@192.168.68.108 'systemctl --user restart openclaw-gateway'
|
||||
```
|
||||
|
||||
## 可选扩展
|
||||
|
||||
### 添加 Skills
|
||||
|
||||
```bash
|
||||
ssh yiukai@192.168.68.108 "mkdir -p ~/.openclaw/skills/skill-name"
|
||||
# 然后写 SKILL.md(含 frontmatter: name, description, requires, install)
|
||||
```
|
||||
|
||||
### 添加 Cron 定时任务
|
||||
|
||||
通过 Node.js 脚本添加到 `cron.entries`,或使用 CLI:
|
||||
|
||||
```bash
|
||||
openclaw cron add --agent agent-id --schedule "0 8 * * 1-5" \
|
||||
--message "任务内容" --deliver discord:CHANNEL_ID
|
||||
```
|
||||
|
||||
### 启用 Agent 间通信
|
||||
|
||||
1. 添加 agent ID 到 `tools.agentToAgent.allow` 列表
|
||||
2. 在调用方 agent 设置 `subagents.allowAgents`
|
||||
3. 共享频道中所有协作 agent 设置 `requireMention: true`
|
||||
|
||||
## 实际案例
|
||||
|
||||
### xhs-creator(2026-03-22)
|
||||
|
||||
| 项目 | 值 |
|
||||
|------|-----|
|
||||
| Agent ID | `xhs-creator` |
|
||||
| 显示名称 | 小红薯 |
|
||||
| Discord Bot | @小红书牛马 |
|
||||
| Guild | 小红书 (`1485305839379021871`) |
|
||||
| Channel | general (`1485305839828074620`) |
|
||||
| Bot User ID | `1485305429713096937` |
|
||||
| 模型 | kimi-coding/k2p5 |
|
||||
| requireMention | false(独占频道) |
|
||||
| 用途 | 小红书内容创作、话题分析、笔记撰写 |
|
||||
|
||||
## 排障指南
|
||||
|
||||
### Bot 无响应
|
||||
|
||||
1. 检查 bot 是否已邀请到服务器
|
||||
2. 检查 Message Content Intent 是否开启
|
||||
3. 检查 `enabled: true`
|
||||
4. 检查 users 白名单是否包含你的 ID (`964122056163721286`)
|
||||
5. 查看日志:`journalctl --user -u openclaw-gateway -f`
|
||||
6. 检查 token 是否有效(可能已过期需重新生成)
|
||||
|
||||
### 多 Agent 协作
|
||||
|
||||
- 在同一 Guild 的同一频道放多个 agent
|
||||
- 所有 agent 设置 `requireMention: true` 避免同时响应
|
||||
- 配置 `subagents.allowAgents` 允许 agent 间通信
|
||||
- 配置 `tools.agentToAgent.allow` 列表
|
||||
|
||||
## Claude Code 自动化
|
||||
|
||||
对应 skill: `~/.claude/skills/openclaw-create-agent/SKILL.md`
|
||||
|
||||
触发方式:告诉 Claude "创建一个 xxx agent" / "add agent" / "new bot",提供 token、Guild ID、Channel ID 即可自动完成全部步骤。
|
||||
|
||||
## Related
|
||||
|
||||
- [[OpenClaw-Skill-Reference]]
|
||||
- [[OpenClaw 部署配置分析]]
|
||||
- [[OpenClaw Stock Agent 配置详情]]
|
||||
Reference in New Issue
Block a user