Compare commits

...

25 Commits

Author SHA1 Message Date
updsv7
cc000c2055 openviking k8s: mount ov.conf via ConfigMap volume
- 03-configmap.yaml: add ov.conf key with embedding/vlm JSON template
- 01-deployment.yaml: add volume mount to /app/.openviking/ov.conf
2026-06-06 11:53:11 +09:00
98478a34a7 更新 AI/openviking/k8s/01-deployment.yaml 2026-06-06 02:25:49 +00:00
512eb5ab62 更新 AI/openviking/k8s/01-deployment.yaml 2026-06-06 02:25:10 +00:00
836a06a382 更新 AI/openviking/k8s/04-pvc.yaml 2026-06-06 01:52:09 +00:00
90889aa730 更新 AI/openviking/k8s/03-configmap.yaml 2026-06-06 01:51:16 +00:00
8b9a9d1ec6 更新 AI/openviking/k8s/02-service.yaml 2026-06-06 01:51:00 +00:00
8a8a77fe29 更新 AI/openviking/k8s/05-ingress.yaml 2026-06-06 01:50:51 +00:00
2f320b69b3 更新 AI/openviking/k8s/02-service.yaml 2026-06-06 01:50:25 +00:00
hermes-bot
766e6e640d docs: 更新 README,匹配实际目录结构 2026-06-05 13:40:37 +00:00
updsv7
3d8c62c12e AI/openviking/k8s: update namespace from openviking to tei 2026-06-05 13:35:56 +09:00
updsv7
3333dba7e6 AI/openviking: add k8s manifest (Kustomize) and remove redundant Dockerfile 2026-06-05 12:59:02 +09:00
hermes-bot
1ef1ceb384 add openviking Dockerfile 2026-06-04 14:10:39 +00:00
hermes-bot
567fc2c180 docs: 增加外部镜像同步到本地 registry 的操作流程 2026-06-04 12:25:28 +00:00
hermes-bot
042a377143 fix: add mem0-ui container and init container patch for sentence_transformers 2026-06-01 16:05:38 +00:00
hermes-bot
ed054da5d8 fix: sentence_transformers import error workaround 2026-06-01 15:37:47 +00:00
hermes-bot
893839c7a8 mem0 faq: remove ingress recommendation 2026-05-31 05:38:26 +00:00
hermes-bot
fb80480a22 mem0 faq: correct - single admin user mode, not per-email 2026-05-31 05:37:20 +00:00
hermes-bot
21e3e33da9 mem0 faq: add security note about Swagger UI registration 2026-05-31 05:36:16 +00:00
hermes-bot
9159cdf83c mem0: remove probes (no health endpoint), add functional test script 2026-05-31 04:12:56 +00:00
hermes-bot
df5c412c7b mem0: add POSTGRES_PASSWORD from dify-prod-db-secret to migrate Job 2026-05-31 03:45:15 +00:00
hermes-bot
2ea8964b7c mem0: add alembic migration Job, PVC, update APP_DB_NAME to mem0 2026-05-31 03:35:49 +00:00
hermes-bot
7f2a609914 mem0: update APP_DB_NAME to mem0 2026-05-31 03:16:32 +00:00
hermes-bot
a72b1faf11 mem0: add PVC for SQLite history persistence 2026-05-31 02:30:42 +00:00
hermes-bot
3180fb0ee8 add linux users commands 2026-05-30 15:40:35 +00:00
hermes-bot
24905d501f update mem0 deployment yaml 2026-05-30 14:18:17 +00:00
12 changed files with 642 additions and 18 deletions

View File

@@ -74,4 +74,8 @@ A: 不需要。TEI 只做向量生成(文本→向量),不存储任何数
A: 可能网络问题。可以尝试:
- 使用断点续传:`curl -C - -L -o file.tar.gz URL`
- 使用国内镜像或代理
- 通过 Gitea 等国内 Git 服务托管
- 通过 Gitea 等国内 Git 服务托管
## Q: Swagger UI 可以随意注册用户,生产环境安全吗?
A: Mem0 系统级别的单用户模式——注册第一个 admin 用户后,系统禁止再注册新用户。

View File

@@ -20,8 +20,7 @@ ccr.ccs.tencentyun.com/tei_agent/mem0:latest
| 变量 | 值 | 说明 |
|---|---|---|
| DATABASE_URL | postgres://gitlab:gitlab@192.168.3.49:5432/mem0 | 连接字串 |
| APP_DB_NAME | mem0_app | 数据库名 |
| APP_DB_NAME | mem0 | 数据库名 |
| QDRANT_HOST | qdrant | Qdrant 服务地址 |
| QDRANT_PORT | 6333 | Qdrant 端口 |
| QDRANT_COLLECTION_NAME | mem0 | 集合名 |
@@ -33,6 +32,7 @@ ccr.ccs.tencentyun.com/tei_agent/mem0:latest
| AUTH_DISABLED | false | 启用认证 |
| MEM0_TELEMETRY | false | 关闭遥测 |
| REQUEST_LOG_RETENTION_DAYS | 30 | 日志保留天数 |
| HISTORY_DB_PATH | /app/data/mem0_history.db | SQLite 历史数据库路径 |
### Secret (mem0-secrets)
@@ -42,24 +42,364 @@ ccr.ccs.tencentyun.com/tei_agent/mem0:latest
| ADMIN_API_KEY | 管理后台 API key |
| POSTGRES_PASSWORD | PostgreSQL 密码 |
## 部署清单
## 数据库迁移 (Alembic)
mem0 server 使用 Alembic 管理 PostgreSQL schema。**首次部署前必须先执行迁移**,创建 `request_logs` 等表。
### 迁移 Job
```yaml
# mem0 deployment + configmap + secret + service
apiVersion: batch/v1
kind: Job
metadata:
name: mem0-migrate
namespace: tei
spec:
ttlSecondsAfterFinished: 300 # 完成后5分钟自动清理
template:
spec:
restartPolicy: OnFailure
containers:
- name: alembic
image: ccr.ccs.tencentyun.com/tei_agent/mem0:latest
command: ["alembic", "upgrade", "head"]
envFrom:
- configMapRef:
name: mem0-env
- secretRef:
name: mem0-secrets
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: dify-prod-db-secret
key: password
resources:
limits:
memory: "512Mi"
cpu: "500m"
```
### 迁移部署步骤
```bash
# 1. 先跑迁移(只执行一次)
kubectl apply -f mem0-migrate-job.yaml
# 2. 确认迁移完成
kubectl get job mem0-migrate -n tei -w
# 3. 确认成功后再部署 mem0
kubectl apply -f mem0-deployment.yaml
# 4. 如果迁移失败,查看原因
kubectl logs job/mem0-migrate -n tei
```
**重要**:迁移 Job 只跑一次。Pod 重启时不需要重新迁移PostgreSQL schema 不会天天变。
## 前置要求
1. **pgvector 扩展** — PostgreSQL 需要安装 pgvector
2. **mem0_app 数据库** — 需要提前创建
3. **Qdrant collection** — mem0 启动时自动创建(首次调用时)
2. **mem0 数据库** — 需要提前创建
3. **mem0-migrate Job** — 首次部署前必须先执行迁移
4. **mem0-history PVC** — 必须提前创建
5. **Qdrant collection** — mem0 启动时自动创建(首次调用时)
## 部署清单
### PVC + ConfigMap + Secret + Deployment + Service
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mem0-history
namespace: tei
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: standard # 根据你的 StorageClass 调整
---
apiVersion: v1
kind: ConfigMap
metadata:
name: mem0-env
namespace: tei
data:
APP_DB_NAME: "mem0"
QDRANT_HOST: "qdrant"
QDRANT_PORT: "6333"
QDRANT_COLLECTION_NAME: "mem0"
EMBEDDER_PROVIDER: "tei"
TEI_ENDPOINT: "http://tei:8080"
LLM_PROVIDER: "openai"
OPENAI_API_KEY: "YOUR_MINIMAX_KEY"
OPENAI_BASE_URL: "https://api.minimax.chat/v1"
AUTH_DISABLED: "false"
MEM0_TELEMETRY: "false"
REQUEST_LOG_RETENTION_DAYS: "30"
HISTORY_DB_PATH: "/app/data/mem0_history.db"
---
apiVersion: v1
kind: Secret
metadata:
name: mem0-secrets
namespace: tei
type: Opaque
stringData:
JWT_SECRET: "your-jwt-secret-change-me"
ADMIN_API_KEY: "your-admin-key-change-me"
POSTGRES_PASSWORD: "gitlab"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mem0
namespace: tei
spec:
replicas: 1
selector:
matchLabels:
app: mem0
template:
metadata:
labels:
app: mem0
spec:
containers:
- name: mem0
image: ccr.ccs.tencentyun.com/tei_agent/mem0:latest
ports:
- containerPort: 8000
name: http
envFrom:
- configMapRef:
name: mem0-env
- secretRef:
name: mem0-secrets
volumeMounts:
- name: mem0-history
mountPath: /app/data
resources:
limits:
cpu: "2"
memory: "4Gi"
requests:
cpu: "500m"
memory: "1Gi"
volumes:
- name: mem0-history
persistentVolumeClaim:
claimName: mem0-history
---
apiVersion: v1
kind: Service
metadata:
name: mem0
namespace: tei
spec:
ports:
- port: 8000
name: http
selector:
app: mem0
```
## 验证
```bash
# 检查 PVC
kubectl get pvc -n tei mem0-history
# 检查 Pod
kubectl get pods -n tei -l app=mem0
# 查看日志
kubectl logs -n tei -l app=mem0 --tail=50
# 健康检查
curl http://mem0:8000/health
```
## History SQLite 说明
mem0 的对话历史存储在 SQLite位于 `/app/data/mem0_history.db`。**必须用 PVC 持久化**emptyDir 挂载重启后数据丢失。
如果 PVC 空间不足或不需要历史功能,可以改用空目录(数据丢失但不影响核心记忆功能):
```yaml
# 测试/轻量级环境用 emptyDir
volumes:
- name: mem0-history
emptyDir: {}
```
## Dashboard 部署
mem0 dashboard 是 Next.js 应用,需要单独部署。
### 环境变量
```yaml
NEXT_PUBLIC_API_URL=http://mem0.tei.svc.cluster.local:8000 # 浏览器调用(通过 Ingress
API_INTERNAL_URL=http://mem0.tei.svc.cluster.local:8000 # 服务端内部调用K8s 内部直连)
NEXT_PUBLIC_INSTANCE_NAME=Mem0
```
**`API_INTERNAL_URL`**K8s 内部服务间通信,直接使用 Service DNS不需要暴露到外部。浏览器无法解析 `mem0.tei.svc.cluster.local`,所以前端用 `NEXT_PUBLIC_API_URL` 通过 Ingress 访问。
两者可以相同,但分离部署时:
- `NEXT_PUBLIC_API_URL` = 对外域名Ingress
- `API_INTERNAL_URL` = 集群内部 `mem0.tei.svc.cluster.local:8000`
### CORS 配置
mem0 server 使用 CORSMiddleware需要通过环境变量配置允许的来源
```yaml
DASHBOARD_URL=https://mem0.your-domain.com # dashboard 的外部访问地址
```
mem0 server 启动时读取 `DASHBOARD_URL`,设置 `allow_origins=[DASHBOARD_URL]`
**常见问题**
- 浏览器访问 dashboard 登录页时,返回 `400 Bad Request`
- OPTIONS 预检请求失败,因为 `allow_origins` 为空
- Swagger 能正常登录(同域请求,无 CORS 问题)
确保 `DASHBOARD_URL` 设为 dashboard 的外部访问地址(与 `NEXT_PUBLIC_API_URL` 的域名部分一致)。
## sentence_transformers 导入错误(永久修复)
mem0 的 `huggingface.py` 在文件顶部执行 `from sentence_transformers import SentenceTransformer`,即使走 `huggingface_base_url` 路径(用 OpenAI 客户端调用 TEI不需要本地模型也会尝试加载造成 `ModuleNotFoundError`
通过 init container + emptyDir 挂载实现持久修复pod recreate 不丢失:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mem0
namespace: tei
spec:
replicas: 1
selector:
matchLabels:
app: mem0
template:
metadata:
labels:
app: mem0
spec:
initContainers:
- name: patch-mem0
image: ccr.ccs.tencentyun.com/tei_agent/mem0:latest
command:
- sh
- -c
- |
cp -r /usr/local/lib/python3.12/site-packages/mem0 /tmp/mem0-patch/
sed -i 's/from sentence_transformers import SentenceTransformer/# from sentence_transformers import SentenceTransformer/' /tmp/mem0-patch/embeddings/huggingface.py
echo "patch done"
volumeMounts:
- name: mem0-code
mountPath: /tmp/mem0-patch
containers:
- name: mem0-ui
image: ccr.ccs.tencentyun.com/tei_agent/mem0-ui:latest
ports:
- containerPort: 3000
name: http
env:
- name: NEXT_PUBLIC_API_URL
value: "https://api.mem0.violin-work.online"
- name: API_INTERNAL_URL
value: "http://mem0.tei.svc.cluster.local:8000"
- name: NEXT_PUBLIC_INSTANCE_NAME
value: Mem0
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 100m
memory: 250Mi
- name: mem0
image: ccr.ccs.tencentyun.com/tei_agent/mem0:latest
ports:
- containerPort: 8000
name: http
envFrom:
- configMapRef:
name: mem0-env
- secretRef:
name: mem0-secrets
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: dify-prod-db-secret
key: password
volumeMounts:
- name: mem0-history
mountPath: /app/data
- name: mem0-code
mountPath: /usr/local/lib/python3.12/site-packages/mem0
resources:
limits:
cpu: "2"
memory: 4Gi
requests:
cpu: "500m"
memory: 1Gi
volumes:
- name: mem0-history
persistentVolumeClaim:
claimName: mem0-history
- name: mem0-code
emptyDir: {}
```
**原理**init container 先于主容器启动,把镜像里的 mem0 代码复制到 emptyDirsed 补丁打在 emptyDir 里。主容器挂载 emptyDir 到 site-packages覆盖镜像原有文件实现补丁持久化recreate 不丢)。
## 功能测试
mem0 未为 K8s 做适配,无健康检查端点。手动测试核心 API
```bash
cat > /tmp/test_mem0.py << 'TESTEOF'
import urllib.request, json, uuid
BASE = "http://mem0:8000"
def req(method, path, data=None):
url = BASE + path
body = json.dumps(data).encode() if data else None
headers = {"Content-Type": "application/json"}
try:
r = urllib.request.urlopen(urllib.request.Request(url, data=body, headers=headers, method=method), timeout=10)
return json.loads(r.read()), r.status
except urllib.error.HTTPError as e:
return json.loads(e.read()), e.code
except Exception as e:
return str(e), 0
uid = str(uuid.uuid4())
print("=== 1. 创建用户 ===")
print(req("POST", "/api/v1/users", {"user_id": uid, "email": f"{uid}@test.com"}))
print("=== 2. 添加记忆 ===")
print(req("POST", "/api/v1/memories", {"text": "我叫张三我喜欢Python", "user_id": uid}))
print("=== 3. 搜索记忆 ===")
print(req("GET", f"/api/v1/memories?query=python&user_id={uid}"))
print("=== 4. 获取历史 ===")
print(req("GET", f"/api/v1/history?user_id={uid}"))
TESTEOF
kubectl exec -n tei deploy/mem0 -- python3 /tmp/test_mem0.py
```

View File

@@ -0,0 +1,7 @@
apiVersion: v1
kind: Namespace
metadata:
name: tei
labels:
app.kubernetes.io/name: tei
app.kubernetes.io/managed-by: kubectl

View File

@@ -0,0 +1,61 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: openviking
namespace: tei
labels:
app: openviking
spec:
replicas: 1
selector:
matchLabels:
app: openviking
template:
metadata:
labels:
app: openviking
spec:
containers:
- name: openviking
image: ccr.ccs.tencentyun.com/tei_agent/openviking:latest
ports:
- containerPort: 1933
protocol: TCP
envFrom:
- configMapRef:
name: openviking-config
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 1Gi
livenessProbe:
httpGet:
path: /ready
port: 1933
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /ready
port: 1933
initialDelaySeconds: 5
periodSeconds: 10
volumeMounts:
- name: data
mountPath: /app/data
- name: openviking-config
mountPath: /app/.openviking
readOnly: true
volumes:
- name: data
persistentVolumeClaim:
claimName: openviking-data
- name: openviking-config
configMap:
name: openviking-config
items:
- key: ov.conf
path: ov.conf

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: openviking
namespace: tei
labels:
app: openviking
spec:
type: ClusterIP
ports:
- port: 1933
targetPort: 1933
protocol: TCP
name: http
selector:
app: openviking

View File

@@ -0,0 +1,32 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: openviking-config
namespace: tei
data:
OVIKING_PORT: "1933"
OVIKING_HOST: "0.0.0.0"
# 日志级别: debug, info, warn, error
OVIKING_LOG_LEVEL: "info"
# 数据存储路径(容器内)
OVIKING_DATA_DIR: "/app/data"
# 向量模型(可选,注释掉则使用默认模型)
# OVIKING_EMBED_MODEL: "text-embedding-3-large"
ov.conf: |
{
"embedding": {
"dense": {
"api_base": "<api-endpoint>",
"api_key": "<your-api-key>",
"provider": "<provider-type>",
"dimension": 1024,
"model": "<model-name>"
}
},
"vlm": {
"api_base": "<api-endpoint>",
"api_key": "<your-api-key>",
"provider": "<provider-type>",
"model": "<model-name>"
}
}

View File

@@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: openviking-data
namespace: tei
labels:
app: openviking
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi

View File

@@ -0,0 +1,22 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: openviking
namespace: tei
labels:
app: openviking
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
spec:
ingressClassName: nginx
rules:
- host: openviking.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: openviking
port:
number: 1933

View File

@@ -0,0 +1,16 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: tei
resources:
- 00-namespace.yaml
- 01-deployment.yaml
- 02-service.yaml
- 03-configmap.yaml
- 04-pvc.yaml
- 05-ingress.yaml
commonLabels:
app.kubernetes.io/name: openviking
app.kubernetes.io/managed-by: kustomize

View File

@@ -99,6 +99,53 @@ git clone https://github.com/torvalds/linux
---
## 外部镜像同步到本地 Registry
### 场景
东京服务器能访问 `ghcr.io`/`docker.io`,需要同步到本地 `localhost:5000` registry供国内 K8s 节点拉取。
### 拉取外部镜像
```bash
docker pull ghcr.io/volcengine/openviking:latest
```
### 同步到本地 Registry推荐保留原始路径
```bash
# 打 tag路径保留原始仓库路径
docker tag ghcr.io/volcengine/openviking:latest localhost:5000/ghcr.io/volcengine/openviking:latest
# 推送
docker push localhost:5000/ghcr.io/volcengine/openviking:latest
```
### 国内 K8s 节点拉取
```bash
docker pull 43.130.228.226:5000/ghcr.io/volcengine/openviking:latest
```
### 用 skopeo 跳过本地存储直接同步(多架构镜像推荐)
```bash
apt update && apt install -y skopeo
skopeo copy --dest-tls-verify=false \
docker://ghcr.io/volcengine/openviking:latest \
docker://localhost:5000/ghcr.io/volcengine/openviking:latest
```
### 查看本地 Registry 内容
```bash
curl -s http://localhost:5000/v2/_catalog
curl -s http://localhost:5000/v2/ghcr.io/volcengine/openviking/tags/list
```
### 路径说明
- `localhost:5000/library/alpine` = Docker 官方镜像路径
- `localhost:5000/ghcr.io/volcengine/openviking` = 保留原始来源路径(推荐)
保留原始路径好处:一目了然知道镜像来源。
---
## 注意事项
- 东京服务器带宽低1-2MbpsDocker 拉大镜像较慢
- Git 流量小,代理无压力

36
Linux/linux-users.md Normal file
View File

@@ -0,0 +1,36 @@
# Linux 用户基础操作
## 查看用户
```bash
# 查看所有用户
cat /etc/passwd
# 查看当前在线用户
who
# 显示谁在登录
w
```
## 切换用户
```bash
su - postgres # 切换到 postgres 用户(带登录 shell
sudo su - postgres # 用 sudo 切换(需要 root 权限)
```
## PostgreSQL 进数据库
```bash
su - postgres # 先切到 postgres 用户
psql # 直接进数据库
```
或者不切换用户直接进:
```bash
psql -U postgres -h 192.168.3.49 -p 5432
```
输入密码后进入 SQL 操作界面quit 用 `\q`

View File

@@ -1,21 +1,51 @@
# 知识库
个人知识仓库,存储 AI 相关技术知识
个人技术知识仓库, AI Agent (Hermes) 根据对话整理
## 目录结构
```
AI/
├── mem0/ # Mem0 自托管部署、架构、运维知识
│ ├── 01-basics.md
│ ├── 02-architecture.md
│ ├── 03-deployment.md
│ ├── 04-your-infra.md
└── 05-faq.md
└── tokyo-proxy/ # 东京云服务器代理GitHub + Docker 流量转发
└── 01-proxy.md
knowledge-base/
├── AGENT.md # Agent 说明
├── AI/
│ ├── mem0/ # Mem0 自托管部署、架构、运维
│ ├── 01-basics.md # 基础概念
│ ├── 02-architecture.md # 架构详解
│ ├── 03-deployment.md # 部署方案
│ │ ├── 04-your-infra.md # 你的基础设施
│ ├── 05-faq.md # 常见问题
│ │ └── deploy.md # 完整部署配置
│ ├── tokyo-proxy/ # 东京云服务器代理GitHub + Docker 流量转发
│ │ └── 01-proxy.md
│ └── openviking/ # OpenViking Dockerfile
│ └── Dockerfile
└── Linux/
└── linux-users.md # Linux 用户基础操作
```
## 主要内容
### AI/mem0
Mem0 自托管部署知识库,包含:
- 基础概念Mem0 vs OpenMemory
- 架构详解TEI + Qdrant + PostgreSQL + LLM
- K8s 部署方案ConfigMap + Secret + PVC + Deployment + Service
- 数据库迁移Alembic Job
- Dashboard 部署CORS 配置)
- sentence_transformers 导入错误修复init container + emptyDir 补丁)
- 功能测试脚本
依赖服务TEI (BGE-M3)、Qdrant、PostgreSQLtei namespace
### AI/tokyo-proxy
东京云服务器代理方案:
- Squid HTTP 代理(密码认证)
- 国内 Docker/K3s 代理配置
- 外部镜像同步到本地 Registryskopeo
### Linux
Linux 用户基础操作查看用户、切换用户、PostgreSQL 连接。
## 来源
本知识库由 AI Agent (Hermes) 根据对话整理。
本知识库由 AI Agent (Hermes) 根据对话整理,托管于 Gitea支持 git-sync sidecar 自动同步