初始化提交

This commit is contained in:
chengcheng
2026-07-09 19:29:46 +08:00
commit 821ffe9e70
25 changed files with 2713 additions and 0 deletions
+426
View File
@@ -0,0 +1,426 @@
# EasyAI 本地 kind 部署指南
本目录用于在本机通过 kind 部署 EasyAI,验证 Kubernetes YAML 是否可以正常渲染、创建资源、拉起 Pod,并完成前端和核心接口访问。
本地部署会在 kind 集群中同时启动以下依赖:
| 依赖 | 说明 |
| --- | --- |
| MongoDB | 主服务本地业务数据 |
| Redis | 队列、缓存、WebSocket 集群状态 |
| RabbitMQ | 本地消息队列 |
| PostgreSQL/pgvector | Agent 治理和记忆服务数据库 |
本地数据使用 `emptyDir`,删除 Pod 或集群后数据可能丢失。本地部署只用于验证,不代表生产高可用方案。
## 1. 本机准备
以下命令均在仓库根目录执行。如果当前已经在仓库根目录,可以跳过这一步;如果当前在本 README 所在目录,执行:
```bash
cd ../../..
```
确认 Docker 正在运行:
```bash
docker version
```
确认已有 `kubectl`
```bash
kubectl version --client
```
安装 kind
```bash
brew install kind
```
确认 kind 可用:
```bash
kind version
```
建议本机至少预留:
| 资源 | 建议 |
| --- | --- |
| CPU | 4 核以上 |
| 内存 | 12 GB 以上 |
| 磁盘 | 20 GB 以上 |
如果本机是 Apple Silicon,且某些镜像没有 arm64 版本,可能出现 `ImagePullBackOff``exec format error` 或 Pod 无法启动。遇到这种情况,先查看失败镜像和 Pod 事件,生产环境请使用 amd64 节点池或多架构镜像。
## 2. 创建 kind 集群
如果本机还没有 `easyai` 集群,执行:
```bash
kind create cluster --name easyai
```
如果之前已经创建过同名集群,并且希望从干净环境重新部署,执行:
```bash
kind delete cluster --name easyai
kind create cluster --name easyai
```
切换到 kind 集群:
```bash
kubectl config use-context kind-easyai
```
确认当前 context 和节点:
```bash
kubectl config current-context
kubectl get nodes -o wide
```
当前 context 应该是:
```text
kind-easyai
```
## 3. 部署前检查
渲染本地 YAML
```bash
kubectl kustomize k8s/overlays/local > /tmp/easyai-local.yaml
```
检查资源类型:
```bash
grep '^kind:' /tmp/easyai-local.yaml
```
准备 dry-run 需要的 namespace
```bash
kubectl create namespace easyai-local --dry-run=client -o yaml | kubectl apply -f -
```
执行服务端 dry-run
```bash
kubectl apply --dry-run=server -f /tmp/easyai-local.yaml
```
如果只想检查 YAML 是否能被本地解析,也可以执行:
```bash
kubectl apply --dry-run=client -f /tmp/easyai-local.yaml
```
## 4. 部署 EasyAI
执行部署:
```bash
kubectl apply -k k8s/overlays/local
```
查看 namespace
```bash
kubectl get ns easyai-local
```
查看资源:
```bash
kubectl -n easyai-local get deploy,svc,pods
```
等待依赖和应用启动:
```bash
for d in mongo redis rabbitmq easyai-pgvector easyai-server easyai-web ws-gateway video-edit sandbox easyai-asg agent-memory; do
kubectl -n easyai-local rollout status deploy/$d --timeout=15m
done
```
确认 Pod 状态:
```bash
kubectl -n easyai-local get pods -o wide
```
所有核心 Pod 都应进入 `Running`,并且 `READY` 数量正常。
## 5. 本地端口转发
本地前端配置使用 `127.0.0.1`,因此需要在本机打开端口转发。
建议打开 5 个终端窗口,并分别保持以下命令运行。
终端 1
```bash
kubectl -n easyai-local port-forward svc/easyai-web 3010:3010
```
终端 2
```bash
kubectl -n easyai-local port-forward svc/easyai-server 3001:3001
```
终端 3
```bash
kubectl -n easyai-local port-forward svc/ws-gateway 3002:3002
```
终端 4
```bash
kubectl -n easyai-local port-forward svc/easyai-asg 3003:3003
```
终端 5
```bash
kubectl -n easyai-local port-forward svc/agent-memory 3004:3004
```
端口被占用时,先查看占用进程:
```bash
lsof -iTCP:3010 -sTCP:LISTEN
lsof -iTCP:3001 -sTCP:LISTEN
lsof -iTCP:3002 -sTCP:LISTEN
lsof -iTCP:3003 -sTCP:LISTEN
lsof -iTCP:3004 -sTCP:LISTEN
```
停止占用进程后,重新执行对应的 `port-forward`
## 6. 访问验证
确认主服务:
```bash
curl -i http://127.0.0.1:3001/health
```
确认 ASG
```bash
curl -i http://127.0.0.1:3003/health
```
确认 Agent Memory
```bash
curl -i http://127.0.0.1:3004/health
```
打开前端:
```bash
open http://127.0.0.1:3010
```
本地默认管理员账号:
```text
admin / 123456
```
如果页面可以打开,但接口失败,请先确认 `3001``3002``3003``3004``port-forward` 仍在运行。
## 7. 查看状态和日志
查看 Service
```bash
kubectl -n easyai-local get svc
```
查看 Endpoints
```bash
kubectl -n easyai-local get endpoints easyai-web easyai-server ws-gateway easyai-asg agent-memory mongo redis rabbitmq easyai-pgvector
```
查看应用日志:
```bash
kubectl -n easyai-local logs deploy/easyai-server --tail=200
kubectl -n easyai-local logs deploy/ws-gateway --tail=200
kubectl -n easyai-local logs deploy/easyai-asg --tail=200
kubectl -n easyai-local logs deploy/agent-memory --tail=200
```
查看集群事件:
```bash
kubectl -n easyai-local get events --sort-by=.lastTimestamp | tail -80
```
## 8. 更新本地部署
如果代码仓库或镜像更新后需要重新部署,执行:
```bash
git pull
kubectl apply -k k8s/overlays/local
kubectl -n easyai-local rollout restart \
deploy/easyai-web \
deploy/easyai-server \
deploy/ws-gateway \
deploy/video-edit \
deploy/sandbox \
deploy/easyai-asg \
deploy/agent-memory
for d in easyai-server easyai-web ws-gateway video-edit sandbox easyai-asg agent-memory; do
kubectl -n easyai-local rollout status deploy/$d --timeout=15m
done
```
说明:应用镜像使用 `latest`,远端镜像更新后需要 `rollout restart` 才会重新创建 Pod 并拉取镜像。
## 9. 常见问题
### kubectl 连接不到集群
检查 context
```bash
kubectl config get-contexts
kubectl config current-context
```
切换回本地 kind 集群:
```bash
kubectl config use-context kind-easyai
```
### Pod 一直 Pending
查看原因:
```bash
kubectl -n easyai-local describe pod <PodName>
```
常见原因:
- 本机 CPU 或内存不足。
- Docker 没有足够可用资源。
- 镜像架构和本机架构不匹配。
### ImagePullBackOff
查看具体镜像:
```bash
kubectl -n easyai-local get pod <PodName> -o jsonpath='{.spec.containers[*].image}'
```
查看事件:
```bash
kubectl -n easyai-local describe pod <PodName>
```
常见原因:
- 本机网络无法访问 `registry.cn-shanghai.aliyuncs.com`
- 镜像 tag 不存在。
- 镜像没有当前 CPU 架构版本。
### CrashLoopBackOff
查看日志:
```bash
kubectl -n easyai-local logs <PodName> --all-containers --previous --tail=200
kubectl -n easyai-local logs <PodName> --all-containers --tail=200
```
常见原因:
- 依赖服务还没 Ready。
- MongoDB、Redis、RabbitMQ 或 PostgreSQL 初始化较慢。
- 镜像启动时执行数据库迁移失败。
可以先等依赖 Ready,再重启应用 Pod:
```bash
kubectl -n easyai-local rollout restart deploy/easyai-server deploy/easyai-asg deploy/agent-memory
```
### easyai-server Mongo 认证失败
如果 `easyai-server` 日志出现:
```text
MongoServerError: Authentication failed
UserNotFound: Could not find user "username" for db "admin"
```
通常是 MongoDB 首次初始化账号过程中被重启,导致 `/data/db` 已经非空但 root 用户没有创建完成。本地 overlay 使用 `emptyDir`,可以直接重建 Mongo Pod,让它按当前 Secret 重新初始化:
```bash
kubectl -n easyai-local delete pod -l app.kubernetes.io/name=mongo
kubectl -n easyai-local wait --for=condition=Ready pod -l app.kubernetes.io/name=mongo --timeout=5m
kubectl -n easyai-local rollout restart deploy/easyai-server deploy/easyai-web
```
### 端口转发断开
`kubectl port-forward` 会受到本地网络、终端关闭和 Pod 重启影响,断开后重新执行即可。
如果重新执行仍失败,先确认 Service 有 endpoints
```bash
kubectl -n easyai-local get endpoints easyai-web easyai-server ws-gateway easyai-asg agent-memory
```
### 前端打开但接口不通
确认所有 `port-forward` 正在运行:
```bash
lsof -iTCP:3010 -sTCP:LISTEN
lsof -iTCP:3001 -sTCP:LISTEN
lsof -iTCP:3002 -sTCP:LISTEN
lsof -iTCP:3003 -sTCP:LISTEN
lsof -iTCP:3004 -sTCP:LISTEN
```
重新验证接口:
```bash
curl -i http://127.0.0.1:3001/health
curl -i http://127.0.0.1:3003/health
curl -i http://127.0.0.1:3004/health
```
## 10. 清理本地环境
删除 EasyAI 本地部署:
```bash
kubectl delete -k k8s/overlays/local
```
如果不再需要本地 kind 集群:
```bash
kind delete cluster --name easyai
```
+91
View File
@@ -0,0 +1,91 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: easyai-app-config
data:
NUXT_PUBLIC_BASE_APIURL: http://127.0.0.1:3001
NUXT_PUBLIC_BASE_SOCKETURL: ws://127.0.0.1:3002
NUXT_PUBLIC_SG_APIURL: http://127.0.0.1:3003
NUXT_APP_CDN_URL: ""
MALLOC_ARENA_MAX: "2"
MALLOC_TRIM_THRESHOLD_: "131072"
MALLOC_MMAP_THRESHOLD_: "131072"
MALLOC_TOP_PAD_: "131072"
SHARP_CACHE_ENABLED: "false"
SHARP_CONCURRENCY: "1"
CONFIG_COMFYUI_QUENE_REDIS_HOST: redis
CONFIG_COMFYUI_QUENE_REDIS_PORT: "6379"
CONFIG_COMFYUI_QUENE_REDIS_USERNAME: ""
CONFIG_COMFYUI_QUENE_REDIS_DB: "6"
CONFIG_COMFYUI_CACHE_REDIS_DB: "11"
LOG_LEVEL: log,error,warn,debug
WS_GATEWAY_LOG_LEVEL: log,error,warn
CONFIG_TOKEN_EXPIRE: "1800"
CONFIG_PROXY_URL: ""
CONFIG_DOCS_DISABLE: "false"
CONFIG_MQ_PROTOCOL: amqp
CONFIG_MQ_HOST: rabbitmq
CONFIG_MQ_PORT: "5672"
CONFIG_MQ_VHOST: /
CONFIG_TCP_HOST: 0.0.0.0
CONFIG_TCP_PORT: "4002"
GATEWAY_CLUSTER_REDIS_ENABLED: "true"
GATEWAY_CLUSTER_REDIS_CHANNEL: easyai:wsgateway:cluster
GATEWAY_CLUSTER_REDIS_ROUTE_PREFIX: easyai:wsgateway:route
GATEWAY_CLUSTER_REDIS_ROUTE_TTL_SEC: "120"
GATEWAY_CLUSTER_REDIS_RECONNECT_INTERVAL_MS: "5000"
GATEWAY_CLUSTER_REDIS_URL: ""
GATEWAY_CLUSTER_REDIS_HOST: redis
GATEWAY_CLUSTER_REDIS_PORT: "6379"
GATEWAY_CLUSTER_REDIS_USERNAME: ""
GATEWAY_CLUSTER_REDIS_DB: "0"
WS_GATEWAY_TCP_EVENT_PATTERN: gateway.event.publish
WS_GATEWAY_TCP_TIMEOUT_MS: "1500"
GATEWAY_INBOUND_TCP_PATTERN: gateway.inbound.command
GATEWAY_INBOUND_TIMEOUT_MS: "5000"
WS_AUTH_REQUIRED: "false"
WS_AUTH_TIMEOUT_MS: "6000"
WS_AUTH_METHODS: none,bearer
WS_AUTH_WS_TICKETS: ""
ASG_REDIS_HOST: redis
ASG_REDIS_PORT: "6379"
ASG_REDIS_DB: "8"
ASG_PORT: "3003"
ASG_TCP_HOST: 0.0.0.0
ASG_TCP_PORT: "4003"
ASG_DOCS_DISABLE: "false"
ASG_MAIN_BACKEND_URL: http://easyai-server:3001
AMS_PORT: "3004"
MEMORY_AI_BASE_URL: http://easyai-server:3001
MEMORY_EMBEDDINGS_PATH: /v1/embeddings
MEMORY_EMBEDDING_MODELS_PATH: /v1/embeddings/models
MEMORY_EMBEDDING_DIMENSION: "1024"
MEMORY_EMBEDDING_MODEL: Qwen3-Embedding-v4
MEMORY_SCORE_CONFIDENCE_BASE: "0.6"
MEMORY_SCORE_CONFIDENCE_GAIN: "0.4"
MEMORY_SCORE_IMPORTANCE_BASE: "0.7"
MEMORY_SCORE_IMPORTANCE_GAIN: "0.3"
MEMORY_DEDUP_MIN_SCORE: "0.92"
MEMORY_TEXT_DEDUP_MIN_SCORE: "0.9"
MEMORY_CHAT_COMPLETIONS_PATH: /v1/chat/completions
MEMORY_CHAT_MODELS_PATH: /v1/models
MEMORY_CHAT_MODEL: qwen-plus
MEMORY_COMPRESSION_ENABLED: "true"
MEMORY_COMPRESSION_MIN_LENGTH: "80"
MEMORY_MAINTENANCE_ENABLED: "true"
MEMORY_MAINTENANCE_DRY_RUN: "false"
MEMORY_MAINTENANCE_BATCH_SIZE: "200"
MEMORY_MAINTENANCE_LLM_ENABLED: "true"
MEMORY_MAINTENANCE_LLM_MAX_PAIRS: "20"
MEMORY_DOCS_DISABLE: "false"
OSS_REGION: us-east-1
OSS_DOMAIN: ""
+38
View File
@@ -0,0 +1,38 @@
apiVersion: v1
kind: Secret
metadata:
name: easyai-app-secret
type: Opaque
stringData:
CONFIG_DB_MONGO_URI: mongodb://mongo:27017
CONFIG_DB_MONGO_USERNAME: username
CONFIG_DB_MONGO_PASSWORD: password
MONGO_INITDB_ROOT_USERNAME: username
MONGO_INITDB_ROOT_PASSWORD: password
CONFIG_COMFYUI_QUENE_REDIS_PASSWORD: ""
GATEWAY_CLUSTER_REDIS_PASSWORD: ""
ASG_REDIS_PASSWORD: ""
CONFIG_MQ_USER: admin
CONFIG_MQ_PASSWORD: easyai2025
CONFIG_JWT_SECRET: this is a very secret secret
CONFIG_TOKEN_SIGN_SK: easyai2025easyai
WS_AUTH_BEARER_TOKENS: ""
ASG_DATABASE_URL: postgresql://easyai:easyai2025@easyai-pgvector:5432/agent_governance?schema=public
MEMORY_DATABASE_URL: postgresql://easyai:easyai2025@easyai-pgvector:5432/easyai_memory?schema=public
ASG_POSTGRES_USER: easyai
ASG_POSTGRES_PASSWORD: easyai2025
ASG_POSTGRES_DB: agent_governance
ASG_ADMIN_USERNAME: admin
ASG_ADMIN_PASSWORD: "123456"
MEMORY_AI_API_KEY: ""
SANDBOX_JUPYTER_TOKEN: easyaiisbest
OSS_ENDPOINT: ""
OSS_ACCESS_KEY_ID: ""
OSS_ACCESS_KEY_SECRET: ""
OSS_BUCKET: ""
+365
View File
@@ -0,0 +1,365 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-config
data:
redis.conf: |
port 6379
replicaof no one
daemonize no
appendonly yes
dir /data
timeout 300
maxclients 10000
tcp-keepalive 60
save ""
tcp-backlog 511
replica-read-only no
maxmemory 2gb
maxmemory-policy noeviction
databases 16
appendfsync everysec
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
slowlog-log-slower-than 10000
slowlog-max-len 128
---
apiVersion: v1
kind: ConfigMap
metadata:
name: pgvector-init
data:
02-init-pgvector.sql: |
\c agent_governance
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE DATABASE easyai_memory;
GRANT ALL PRIVILEGES ON DATABASE easyai_memory TO easyai;
\c easyai_memory
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pgcrypto;
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongo
labels:
app.kubernetes.io/name: mongo
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: mongo
template:
metadata:
labels:
app.kubernetes.io/name: mongo
spec:
containers:
- name: mongo
image: registry.cn-shanghai.aliyuncs.com/comfy-ai/mongo-aliyun:latest
imagePullPolicy: IfNotPresent
args:
- mongod
- --wiredTigerCacheSizeGB
- "1.5"
ports:
- name: mongo
containerPort: 27017
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: easyai-app-secret
key: MONGO_INITDB_ROOT_USERNAME
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: easyai-app-secret
key: MONGO_INITDB_ROOT_PASSWORD
volumeMounts:
- name: data
mountPath: /data/db
readinessProbe:
tcpSocket:
port: mongo
initialDelaySeconds: 20
periodSeconds: 10
startupProbe:
tcpSocket:
port: mongo
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 60
livenessProbe:
tcpSocket:
port: mongo
initialDelaySeconds: 60
periodSeconds: 30
resources:
requests:
cpu: 250m
memory: 1Gi
limits:
cpu: "1"
memory: 2500Mi
volumes:
- name: data
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: mongo
labels:
app.kubernetes.io/name: mongo
spec:
selector:
app.kubernetes.io/name: mongo
ports:
- name: mongo
port: 27017
targetPort: mongo
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
labels:
app.kubernetes.io/name: redis
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: redis
template:
metadata:
labels:
app.kubernetes.io/name: redis
spec:
containers:
- name: redis
image: registry.cn-shanghai.aliyuncs.com/comfy-ai/redis-aliyun:latest
imagePullPolicy: IfNotPresent
command:
- redis-server
- /etc/redis/redis.conf
ports:
- name: redis
containerPort: 6379
volumeMounts:
- name: config
mountPath: /etc/redis/redis.conf
subPath: redis.conf
readOnly: true
- name: data
mountPath: /data
readinessProbe:
tcpSocket:
port: redis
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: redis
initialDelaySeconds: 30
periodSeconds: 30
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: "1"
memory: 2Gi
volumes:
- name: config
configMap:
name: redis-config
- name: data
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: redis
labels:
app.kubernetes.io/name: redis
spec:
selector:
app.kubernetes.io/name: redis
ports:
- name: redis
port: 6379
targetPort: redis
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: rabbitmq
labels:
app.kubernetes.io/name: rabbitmq
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: rabbitmq
template:
metadata:
labels:
app.kubernetes.io/name: rabbitmq
spec:
containers:
- name: rabbitmq
image: registry.cn-shanghai.aliyuncs.com/easyaigc/mq:latest
imagePullPolicy: IfNotPresent
ports:
- name: amqp
containerPort: 5672
- name: management
containerPort: 15672
env:
- name: RABBITMQ_DEFAULT_USER
valueFrom:
secretKeyRef:
name: easyai-app-secret
key: CONFIG_MQ_USER
- name: RABBITMQ_DEFAULT_PASS
valueFrom:
secretKeyRef:
name: easyai-app-secret
key: CONFIG_MQ_PASSWORD
volumeMounts:
- name: data
mountPath: /var/lib/rabbitmq
readinessProbe:
tcpSocket:
port: amqp
initialDelaySeconds: 20
periodSeconds: 10
livenessProbe:
tcpSocket:
port: amqp
initialDelaySeconds: 60
periodSeconds: 30
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: "1"
memory: 1Gi
volumes:
- name: data
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: rabbitmq
labels:
app.kubernetes.io/name: rabbitmq
spec:
selector:
app.kubernetes.io/name: rabbitmq
ports:
- name: amqp
port: 5672
targetPort: amqp
- name: management
port: 15672
targetPort: management
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: easyai-pgvector
labels:
app.kubernetes.io/name: easyai-pgvector
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: easyai-pgvector
template:
metadata:
labels:
app.kubernetes.io/name: easyai-pgvector
spec:
containers:
- name: postgres
image: registry.cn-shanghai.aliyuncs.com/easyaigc/pgvector:0.8.2-pg18-trixie
imagePullPolicy: IfNotPresent
ports:
- name: postgres
containerPort: 5432
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: easyai-app-secret
key: ASG_POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: easyai-app-secret
key: ASG_POSTGRES_PASSWORD
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: easyai-app-secret
key: ASG_POSTGRES_DB
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
- name: init
mountPath: /docker-entrypoint-initdb.d/02-init-pgvector.sql
subPath: 02-init-pgvector.sql
readOnly: true
readinessProbe:
exec:
command:
- /bin/sh
- -c
- pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"
initialDelaySeconds: 15
periodSeconds: 10
livenessProbe:
exec:
command:
- /bin/sh
- -c
- pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"
initialDelaySeconds: 60
periodSeconds: 30
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: "1"
memory: 1Gi
volumes:
- name: data
emptyDir: {}
- name: init
configMap:
name: pgvector-init
---
apiVersion: v1
kind: Service
metadata:
name: easyai-pgvector
labels:
app.kubernetes.io/name: easyai-pgvector
spec:
selector:
app.kubernetes.io/name: easyai-pgvector
ports:
- name: postgres
port: 5432
targetPort: postgres
+48
View File
@@ -0,0 +1,48 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: easyai-local
resources:
- namespace.yaml
- ../../base
- app-config.yaml
- app-secret.yaml
- dependencies.yaml
patches:
- target:
kind: Deployment
name: easyai-web
patch: |-
- op: replace
path: /spec/replicas
value: 2
- target:
kind: Deployment
name: easyai-server
patch: |-
- op: replace
path: /spec/replicas
value: 2
- target:
kind: Deployment
name: ws-gateway
patch: |-
- op: replace
path: /spec/replicas
value: 1
- target:
kind: Deployment
name: easyai-asg
patch: |-
- op: replace
path: /spec/replicas
value: 1
- target:
kind: Deployment
name: agent-memory
patch: |-
- op: replace
path: /spec/replicas
value: 1
+7
View File
@@ -0,0 +1,7 @@
apiVersion: v1
kind: Namespace
metadata:
name: easyai-local
labels:
app.kubernetes.io/name: easyai-local
app.kubernetes.io/part-of: easyai
+91
View File
@@ -0,0 +1,91 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: easyai-app-config
data:
NUXT_PUBLIC_BASE_APIURL: /api
NUXT_PUBLIC_BASE_SOCKETURL: wss://easyai.example.com/socket.io
NUXT_PUBLIC_SG_APIURL: /asg-api
NUXT_APP_CDN_URL: ""
MALLOC_ARENA_MAX: "2"
MALLOC_TRIM_THRESHOLD_: "131072"
MALLOC_MMAP_THRESHOLD_: "131072"
MALLOC_TOP_PAD_: "131072"
SHARP_CACHE_ENABLED: "false"
SHARP_CONCURRENCY: "1"
CONFIG_COMFYUI_QUENE_REDIS_HOST: CHANGE_ME_REDIS_HOST
CONFIG_COMFYUI_QUENE_REDIS_PORT: "6379"
CONFIG_COMFYUI_QUENE_REDIS_USERNAME: ""
CONFIG_COMFYUI_QUENE_REDIS_DB: "6"
CONFIG_COMFYUI_CACHE_REDIS_DB: "11"
LOG_LEVEL: log,error,warn
WS_GATEWAY_LOG_LEVEL: log,error,warn
CONFIG_TOKEN_EXPIRE: "1800"
CONFIG_PROXY_URL: ""
CONFIG_DOCS_DISABLE: "true"
CONFIG_MQ_PROTOCOL: amqp
CONFIG_MQ_HOST: CHANGE_ME_RABBITMQ_HOST
CONFIG_MQ_PORT: "5672"
CONFIG_MQ_VHOST: /
CONFIG_TCP_HOST: 0.0.0.0
CONFIG_TCP_PORT: "4002"
GATEWAY_CLUSTER_REDIS_ENABLED: "true"
GATEWAY_CLUSTER_REDIS_CHANNEL: easyai:wsgateway:cluster
GATEWAY_CLUSTER_REDIS_ROUTE_PREFIX: easyai:wsgateway:route
GATEWAY_CLUSTER_REDIS_ROUTE_TTL_SEC: "120"
GATEWAY_CLUSTER_REDIS_RECONNECT_INTERVAL_MS: "5000"
GATEWAY_CLUSTER_REDIS_URL: ""
GATEWAY_CLUSTER_REDIS_HOST: CHANGE_ME_REDIS_HOST
GATEWAY_CLUSTER_REDIS_PORT: "6379"
GATEWAY_CLUSTER_REDIS_USERNAME: ""
GATEWAY_CLUSTER_REDIS_DB: "0"
WS_GATEWAY_TCP_EVENT_PATTERN: gateway.event.publish
WS_GATEWAY_TCP_TIMEOUT_MS: "1500"
GATEWAY_INBOUND_TCP_PATTERN: gateway.inbound.command
GATEWAY_INBOUND_TIMEOUT_MS: "5000"
WS_AUTH_REQUIRED: "false"
WS_AUTH_TIMEOUT_MS: "6000"
WS_AUTH_METHODS: none,bearer
WS_AUTH_WS_TICKETS: ""
ASG_REDIS_HOST: CHANGE_ME_REDIS_HOST
ASG_REDIS_PORT: "6379"
ASG_REDIS_DB: "8"
ASG_PORT: "3003"
ASG_TCP_HOST: 0.0.0.0
ASG_TCP_PORT: "4003"
ASG_DOCS_DISABLE: "true"
ASG_MAIN_BACKEND_URL: http://easyai-server:3001
AMS_PORT: "3004"
MEMORY_AI_BASE_URL: http://easyai-server:3001
MEMORY_EMBEDDINGS_PATH: /v1/embeddings
MEMORY_EMBEDDING_MODELS_PATH: /v1/embeddings/models
MEMORY_EMBEDDING_DIMENSION: "1024"
MEMORY_EMBEDDING_MODEL: Qwen3-Embedding-v4
MEMORY_SCORE_CONFIDENCE_BASE: "0.6"
MEMORY_SCORE_CONFIDENCE_GAIN: "0.4"
MEMORY_SCORE_IMPORTANCE_BASE: "0.7"
MEMORY_SCORE_IMPORTANCE_GAIN: "0.3"
MEMORY_DEDUP_MIN_SCORE: "0.92"
MEMORY_TEXT_DEDUP_MIN_SCORE: "0.9"
MEMORY_CHAT_COMPLETIONS_PATH: /v1/chat/completions
MEMORY_CHAT_MODELS_PATH: /v1/models
MEMORY_CHAT_MODEL: qwen-plus
MEMORY_COMPRESSION_ENABLED: "true"
MEMORY_COMPRESSION_MIN_LENGTH: "80"
MEMORY_MAINTENANCE_ENABLED: "true"
MEMORY_MAINTENANCE_DRY_RUN: "false"
MEMORY_MAINTENANCE_BATCH_SIZE: "200"
MEMORY_MAINTENANCE_LLM_ENABLED: "true"
MEMORY_MAINTENANCE_LLM_MAX_PAIRS: "20"
MEMORY_DOCS_DISABLE: "true"
OSS_REGION: us-east-1
OSS_DOMAIN: ""
+38
View File
@@ -0,0 +1,38 @@
apiVersion: v1
kind: Secret
metadata:
name: easyai-app-secret
type: Opaque
stringData:
CONFIG_DB_MONGO_URI: mongodb://CHANGE_ME_MONGO_HOST:27017
CONFIG_DB_MONGO_USERNAME: CHANGE_ME_MONGO_USERNAME
CONFIG_DB_MONGO_PASSWORD: CHANGE_ME_MONGO_PASSWORD
MONGO_INITDB_ROOT_USERNAME: CHANGE_ME_MONGO_USERNAME
MONGO_INITDB_ROOT_PASSWORD: CHANGE_ME_MONGO_PASSWORD
CONFIG_COMFYUI_QUENE_REDIS_PASSWORD: CHANGE_ME_REDIS_PASSWORD
GATEWAY_CLUSTER_REDIS_PASSWORD: CHANGE_ME_REDIS_PASSWORD
ASG_REDIS_PASSWORD: CHANGE_ME_REDIS_PASSWORD
CONFIG_MQ_USER: CHANGE_ME_RABBITMQ_USERNAME
CONFIG_MQ_PASSWORD: CHANGE_ME_RABBITMQ_PASSWORD
CONFIG_JWT_SECRET: CHANGE_ME_LONG_RANDOM_JWT_SECRET
CONFIG_TOKEN_SIGN_SK: CHANGE_ME_LONG_RANDOM_TOKEN_SIGN_KEY
WS_AUTH_BEARER_TOKENS: ""
ASG_DATABASE_URL: postgresql://CHANGE_ME_POSTGRES_USER:CHANGE_ME_POSTGRES_PASSWORD@CHANGE_ME_POSTGRES_HOST:5432/agent_governance?schema=public
MEMORY_DATABASE_URL: postgresql://CHANGE_ME_POSTGRES_USER:CHANGE_ME_POSTGRES_PASSWORD@CHANGE_ME_POSTGRES_HOST:5432/easyai_memory?schema=public
ASG_POSTGRES_USER: CHANGE_ME_POSTGRES_USER
ASG_POSTGRES_PASSWORD: CHANGE_ME_POSTGRES_PASSWORD
ASG_POSTGRES_DB: agent_governance
ASG_ADMIN_USERNAME: admin
ASG_ADMIN_PASSWORD: CHANGE_ME_EASYAI_ADMIN_PASSWORD
MEMORY_AI_API_KEY: ""
SANDBOX_JUPYTER_TOKEN: CHANGE_ME_DISABLE_PUBLIC_JUPYTER_OR_SET_TOKEN
OSS_ENDPOINT: ""
OSS_ACCESS_KEY_ID: ""
OSS_ACCESS_KEY_SECRET: ""
OSS_BUCKET: ""
+137
View File
@@ -0,0 +1,137 @@
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: easyai-web
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: easyai-web
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: easyai-server
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: easyai-server
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 75
behavior:
scaleDown:
stabilizationWindowSeconds: 300
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ws-gateway
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ws-gateway
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: video-edit
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: video-edit
minReplicas: 1
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 600
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: easyai-asg
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: easyai-asg
minReplicas: 2
maxReplicas: 8
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: agent-memory
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: agent-memory
minReplicas: 2
maxReplicas: 8
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300
+126
View File
@@ -0,0 +1,126 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: easyai-web
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
spec:
ingressClassName: nginx
tls:
- hosts:
- easyai.example.com
secretName: easyai-tls
rules:
- host: easyai.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: easyai-web
port:
number: 3010
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: easyai-api
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/proxy-body-size: 100m
nginx.ingress.kubernetes.io/proxy-buffering: "off"
nginx.ingress.kubernetes.io/proxy-read-timeout: "1200"
nginx.ingress.kubernetes.io/proxy-send-timeout: "1200"
spec:
ingressClassName: nginx
tls:
- hosts:
- easyai.example.com
secretName: easyai-tls
rules:
- host: easyai.example.com
http:
paths:
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: easyai-server
port:
number: 3001
- path: /asg-api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: easyai-asg
port:
number: 3003
- path: /ams-api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: agent-memory
port:
number: 3004
- path: /sandbox(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: sandbox
port:
number: 8000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: easyai-ws
annotations:
nginx.ingress.kubernetes.io/proxy-buffering: "off"
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
spec:
ingressClassName: nginx
tls:
- hosts:
- easyai.example.com
secretName: easyai-tls
rules:
- host: easyai.example.com
http:
paths:
- path: /socket.io
pathType: Prefix
backend:
service:
name: ws-gateway
port:
number: 3002
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: easyai-mcp
annotations:
nginx.ingress.kubernetes.io/proxy-buffering: "off"
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
spec:
ingressClassName: nginx
tls:
- hosts:
- easyai.example.com
secretName: easyai-tls
rules:
- host: easyai.example.com
http:
paths:
- path: /mcp
pathType: Prefix
backend:
service:
name: easyai-server
port:
number: 3001
+107
View File
@@ -0,0 +1,107 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: easyai
resources:
- namespace.yaml
- ../../base
- app-config.yaml
- app-secret.yaml
- shared-pvc.yaml
- ingress.yaml
- hpa.yaml
- pdb.yaml
images:
- name: registry.cn-shanghai.aliyuncs.com/comfy-ai/one-ai
newTag: latest
- name: registry.cn-shanghai.aliyuncs.com/comfy-ai/comfy-server
newTag: latest
- name: registry.cn-shanghai.aliyuncs.com/easyaigc/wsgateway
newTag: latest
- name: registry.cn-shanghai.aliyuncs.com/easyaigc/videoedit
newTag: latest
- name: registry.cn-shanghai.aliyuncs.com/easyaigc/sandbox
newTag: latest
- name: registry.cn-shanghai.aliyuncs.com/easyaigc/agent-governance
newTag: latest
- name: registry.cn-shanghai.aliyuncs.com/easyaigc/agent-memory
newTag: latest
patches:
- target:
kind: Deployment
name: easyai-server
patch: |-
- op: replace
path: /spec/template/spec/volumes/0
value:
name: shared-files
persistentVolumeClaim:
claimName: easyai-shared-files
- target:
kind: Deployment
name: easyai-web
patch: |-
- op: add
path: /spec/template/spec/topologySpreadConstraints
value:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: easyai-web
- target:
kind: Deployment
name: easyai-server
patch: |-
- op: add
path: /spec/template/spec/topologySpreadConstraints
value:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: easyai-server
- target:
kind: Deployment
name: ws-gateway
patch: |-
- op: add
path: /spec/template/spec/topologySpreadConstraints
value:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: ws-gateway
- target:
kind: Deployment
name: easyai-asg
patch: |-
- op: add
path: /spec/template/spec/topologySpreadConstraints
value:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: easyai-asg
- target:
kind: Deployment
name: agent-memory
patch: |-
- op: add
path: /spec/template/spec/topologySpreadConstraints
value:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: agent-memory
+7
View File
@@ -0,0 +1,7 @@
apiVersion: v1
kind: Namespace
metadata:
name: easyai
labels:
app.kubernetes.io/name: easyai
app.kubernetes.io/part-of: easyai
+49
View File
@@ -0,0 +1,49 @@
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: easyai-web
spec:
minAvailable: 1
selector:
matchLabels:
app.kubernetes.io/name: easyai-web
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: easyai-server
spec:
minAvailable: 1
selector:
matchLabels:
app.kubernetes.io/name: easyai-server
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: ws-gateway
spec:
minAvailable: 1
selector:
matchLabels:
app.kubernetes.io/name: ws-gateway
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: easyai-asg
spec:
minAvailable: 1
selector:
matchLabels:
app.kubernetes.io/name: easyai-asg
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: agent-memory
spec:
minAvailable: 1
selector:
matchLabels:
app.kubernetes.io/name: agent-memory
+13
View File
@@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: easyai-shared-files
labels:
app.kubernetes.io/name: easyai-shared-files
spec:
accessModes:
- ReadWriteMany
storageClassName: CHANGE_ME_RWX_STORAGE_CLASS
resources:
requests:
storage: 100Gi