初始化提交
This commit is contained in:
@@ -0,0 +1,421 @@
|
||||
# EasyAI Kubernetes 部署指南
|
||||
|
||||
本仓库用于将 EasyAI 部署到客户自己的 Kubernetes 环境中。客户拿到仓库后,只需要按本文准备外部依赖、修改生产配置并执行 `kubectl apply`,即可完成部署。
|
||||
|
||||
生产部署只使用以下目录:
|
||||
|
||||
```text
|
||||
k8s/overlays/production
|
||||
```
|
||||
|
||||
本地部署验证可参考:
|
||||
|
||||
```text
|
||||
k8s/overlays/local/README.md
|
||||
```
|
||||
|
||||
镜像版本默认使用 `latest`。EasyAI 发布新版本后,客户拉取本仓库最新内容并按“更新到最新版本”执行即可升级。
|
||||
|
||||
## 部署内容
|
||||
|
||||
| 服务 | Kubernetes 资源 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| 前端 | `easyai-web` | Web 页面入口 |
|
||||
| 主服务 | `easyai-server` | API、核心业务服务 |
|
||||
| WebSocket 网关 | `ws-gateway` | `/socket.io` 长连接入口 |
|
||||
| 视频编辑 | `video-edit` | 视频编辑能力 |
|
||||
| 沙箱 | `sandbox` | 代码执行/Notebook 沙箱 |
|
||||
| Agent 服务治理 | `easyai-asg` | Agent 治理服务 |
|
||||
| Agent 记忆服务 | `agent-memory` | Agent 记忆与检索服务 |
|
||||
|
||||
生产环境建议将 Redis、MongoDB、RabbitMQ、PostgreSQL 等基础组件使用云厂商托管服务,不在本仓库中部署。
|
||||
|
||||
## 部署前准备
|
||||
|
||||
### Kubernetes 集群
|
||||
|
||||
请先确认集群满足以下条件:
|
||||
|
||||
| 项目 | 要求 |
|
||||
| --- | --- |
|
||||
| Kubernetes | 可正常使用 `kubectl` 连接 |
|
||||
| Worker 节点 | 建议不少于 3 个节点,生产环境建议跨可用区 |
|
||||
| Metrics Server | 已启用,用于 HPA 自动扩缩容 |
|
||||
| Ingress Controller | 已安装,当前配置默认使用 NGINX Ingress |
|
||||
| 共享存储 | 有支持 `ReadWriteMany` 的 StorageClass |
|
||||
| 镜像拉取 | 节点可以访问 `registry.cn-shanghai.aliyuncs.com` |
|
||||
|
||||
检查命令:
|
||||
|
||||
```bash
|
||||
kubectl config current-context
|
||||
kubectl get nodes -o wide
|
||||
kubectl top nodes
|
||||
kubectl get ingressclass
|
||||
kubectl get storageclass
|
||||
```
|
||||
|
||||
如果 `kubectl top nodes` 不可用,请先启用 Metrics Server。
|
||||
|
||||
### 外部依赖
|
||||
|
||||
部署前需要准备以下云服务,并保证 Kubernetes 节点所在 VPC 可以访问:
|
||||
|
||||
以下版本为当前生产部署推荐版本。使用云厂商托管服务时,请固定主版本;大版本升级前先在测试环境完成回归验证。
|
||||
|
||||
| 依赖 | 推荐版本 | 用途 | 需要准备的信息 |
|
||||
| --- | --- | --- | --- |
|
||||
| MongoDB | `7.x` | 主服务业务数据 | 内网地址、端口、用户名、密码、连接参数 |
|
||||
| Redis | `7.x`,需支持至少 `16` 个逻辑 DB | 队列、缓存、WebSocket 集群状态 | 内网地址、端口、密码,需支持多个逻辑 DB |
|
||||
| RabbitMQ | `3.13.x`,需支持 AMQP `0-9-1` | 消息队列 | AMQP 地址、端口、用户名、密码、vhost |
|
||||
| PostgreSQL + pgvector | PostgreSQL `18` + pgvector `0.8.2` | Agent 治理和记忆服务 | 地址、端口、用户名、密码、数据库、扩展 |
|
||||
| RWX 共享存储 | 与 Kubernetes 集群版本兼容的 CSI/存储插件 | 上传、备份、恢复文件共享 | 支持 `ReadWriteMany` 的 StorageClass |
|
||||
| OSS/S3 对象存储 | 兼容 AWS S3 Signature V4 或云厂商 OSS/S3 当前 API,可选 | 文件存储,可选 | Endpoint、Bucket、Access Key |
|
||||
|
||||
本地验证环境中的 PostgreSQL/pgvector 镜像为:
|
||||
|
||||
```text
|
||||
registry.cn-shanghai.aliyuncs.com/easyaigc/pgvector:0.8.2-pg18-trixie
|
||||
```
|
||||
|
||||
外部依赖版本核对示例:
|
||||
|
||||
```bash
|
||||
mongosh --eval 'db.version()'
|
||||
redis-cli INFO server | grep '^redis_version:'
|
||||
rabbitmqctl status | grep '{rabbit,'
|
||||
psql "$ASG_DATABASE_URL" -c 'SHOW server_version;'
|
||||
psql "$ASG_DATABASE_URL" -c "SELECT extversion FROM pg_extension WHERE extname = 'vector';"
|
||||
kubectl get storageclass
|
||||
```
|
||||
|
||||
PostgreSQL 需要创建两个数据库,并启用扩展:
|
||||
|
||||
```sql
|
||||
CREATE DATABASE agent_governance;
|
||||
\c agent_governance
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
|
||||
CREATE DATABASE easyai_memory;
|
||||
\c easyai_memory
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
```
|
||||
|
||||
最终需要准备两个连接串:
|
||||
|
||||
```text
|
||||
postgresql://USER:PASSWORD@HOST:5432/agent_governance?schema=public
|
||||
postgresql://USER:PASSWORD@HOST:5432/easyai_memory?schema=public
|
||||
```
|
||||
|
||||
## 修改生产配置
|
||||
|
||||
所有生产配置都在:
|
||||
|
||||
```text
|
||||
k8s/overlays/production
|
||||
```
|
||||
|
||||
### 1. 修改非敏感配置
|
||||
|
||||
编辑:
|
||||
|
||||
```text
|
||||
k8s/overlays/production/app-config.yaml
|
||||
```
|
||||
|
||||
至少替换以下内容:
|
||||
|
||||
```yaml
|
||||
NUXT_PUBLIC_BASE_SOCKETURL: wss://你的域名/socket.io
|
||||
CONFIG_COMFYUI_QUENE_REDIS_HOST: 你的Redis内网地址
|
||||
GATEWAY_CLUSTER_REDIS_HOST: 你的Redis内网地址
|
||||
ASG_REDIS_HOST: 你的Redis内网地址
|
||||
CONFIG_MQ_HOST: 你的RabbitMQ内网地址
|
||||
```
|
||||
|
||||
如果使用统一域名访问,以下配置通常保持默认:
|
||||
|
||||
```yaml
|
||||
NUXT_PUBLIC_BASE_APIURL: /api
|
||||
NUXT_PUBLIC_SG_APIURL: /asg-api
|
||||
```
|
||||
|
||||
### 2. 修改敏感配置
|
||||
|
||||
编辑:
|
||||
|
||||
```text
|
||||
k8s/overlays/production/app-secret.yaml
|
||||
```
|
||||
|
||||
至少替换以下内容:
|
||||
|
||||
```yaml
|
||||
CONFIG_DB_MONGO_URI: mongodb://你的Mongo内网地址:27017
|
||||
CONFIG_DB_MONGO_USERNAME: 你的Mongo用户名
|
||||
CONFIG_DB_MONGO_PASSWORD: 你的Mongo密码
|
||||
MONGO_INITDB_ROOT_USERNAME: 你的Mongo用户名
|
||||
MONGO_INITDB_ROOT_PASSWORD: 你的Mongo密码
|
||||
|
||||
CONFIG_COMFYUI_QUENE_REDIS_PASSWORD: 你的Redis密码
|
||||
GATEWAY_CLUSTER_REDIS_PASSWORD: 你的Redis密码
|
||||
ASG_REDIS_PASSWORD: 你的Redis密码
|
||||
|
||||
CONFIG_MQ_USER: 你的RabbitMQ用户名
|
||||
CONFIG_MQ_PASSWORD: 你的RabbitMQ密码
|
||||
|
||||
CONFIG_JWT_SECRET: 一段足够长的随机字符串
|
||||
CONFIG_TOKEN_SIGN_SK: 一段足够长的随机字符串
|
||||
|
||||
ASG_DATABASE_URL: postgresql://USER:PASSWORD@HOST:5432/agent_governance?schema=public
|
||||
MEMORY_DATABASE_URL: postgresql://USER:PASSWORD@HOST:5432/easyai_memory?schema=public
|
||||
|
||||
ASG_POSTGRES_USER: 你的PostgreSQL用户名
|
||||
ASG_POSTGRES_PASSWORD: 你的PostgreSQL密码
|
||||
ASG_ADMIN_PASSWORD: EasyAI管理员密码
|
||||
|
||||
SANDBOX_JUPYTER_TOKEN: 一段足够长的随机字符串
|
||||
```
|
||||
|
||||
生成随机密钥示例:
|
||||
|
||||
```bash
|
||||
openssl rand -base64 48
|
||||
```
|
||||
|
||||
如果使用 OSS/S3,请同时替换:
|
||||
|
||||
```yaml
|
||||
OSS_ENDPOINT: ""
|
||||
OSS_ACCESS_KEY_ID: ""
|
||||
OSS_ACCESS_KEY_SECRET: ""
|
||||
OSS_BUCKET: ""
|
||||
```
|
||||
|
||||
生产密钥不要提交到公共 Git 仓库。正式环境建议接入 External Secrets、Sealed Secrets 或云厂商 Secret Manager。
|
||||
|
||||
### 3. 修改域名和证书
|
||||
|
||||
编辑:
|
||||
|
||||
```text
|
||||
k8s/overlays/production/ingress.yaml
|
||||
```
|
||||
|
||||
将所有 `easyai.example.com` 替换为客户真实域名。
|
||||
|
||||
如果集群的 IngressClass 不是 `nginx`,同步修改:
|
||||
|
||||
```yaml
|
||||
ingressClassName: nginx
|
||||
```
|
||||
|
||||
创建 TLS Secret:
|
||||
|
||||
```bash
|
||||
kubectl create namespace easyai --dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
kubectl -n easyai create secret tls easyai-tls \
|
||||
--cert=/path/to/tls.crt \
|
||||
--key=/path/to/tls.key
|
||||
```
|
||||
|
||||
如果使用 cert-manager,请按客户集群规范在 `ingress.yaml` 中添加证书签发 annotation。
|
||||
|
||||
### 4. 修改共享存储
|
||||
|
||||
编辑:
|
||||
|
||||
```text
|
||||
k8s/overlays/production/shared-pvc.yaml
|
||||
```
|
||||
|
||||
将占位符替换为真实的 RWX StorageClass:
|
||||
|
||||
```yaml
|
||||
storageClassName: 你的RWX_StorageClass
|
||||
```
|
||||
|
||||
默认 PVC 容量为 `100Gi`,可按客户实际文件量调整:
|
||||
|
||||
```yaml
|
||||
storage: 100Gi
|
||||
```
|
||||
|
||||
## 部署前检查
|
||||
|
||||
确认没有未替换的占位符:
|
||||
|
||||
```bash
|
||||
grep -R -nE 'CHANGE_ME|easyai.example.com|你的' k8s/overlays/production
|
||||
```
|
||||
|
||||
如果还有输出,请先完成配置替换。
|
||||
|
||||
渲染生产 YAML:
|
||||
|
||||
```bash
|
||||
kubectl kustomize k8s/overlays/production > /tmp/easyai-production.yaml
|
||||
```
|
||||
|
||||
检查资源类型:
|
||||
|
||||
```bash
|
||||
grep '^kind:' /tmp/easyai-production.yaml
|
||||
```
|
||||
|
||||
执行服务端 dry-run:
|
||||
|
||||
```bash
|
||||
kubectl create namespace easyai --dry-run=client -o yaml | kubectl apply -f -
|
||||
kubectl apply --dry-run=server -f /tmp/easyai-production.yaml
|
||||
```
|
||||
|
||||
如果 dry-run 报 IngressClass、Ingress annotation 或权限相关错误,请先按客户集群规范调整 `ingress.yaml`。
|
||||
|
||||
## 部署
|
||||
|
||||
执行部署:
|
||||
|
||||
```bash
|
||||
kubectl apply -k k8s/overlays/production
|
||||
```
|
||||
|
||||
查看资源:
|
||||
|
||||
```bash
|
||||
kubectl -n easyai get deploy,svc,pvc,ingress,hpa,pdb
|
||||
kubectl -n easyai get pods -o wide
|
||||
```
|
||||
|
||||
等待服务发布完成:
|
||||
|
||||
```bash
|
||||
for d in easyai-web easyai-server ws-gateway video-edit sandbox easyai-asg agent-memory; do
|
||||
kubectl -n easyai rollout status deploy/$d --timeout=15m
|
||||
done
|
||||
```
|
||||
|
||||
如果某个 Deployment 超时,查看 Pod 状态和日志:
|
||||
|
||||
```bash
|
||||
kubectl -n easyai get pods -o wide
|
||||
kubectl -n easyai describe pod <PodName>
|
||||
kubectl -n easyai logs <PodName> --all-containers --tail=200
|
||||
```
|
||||
|
||||
## DNS 和访问验证
|
||||
|
||||
查看 Ingress 地址:
|
||||
|
||||
```bash
|
||||
kubectl -n easyai get ingress
|
||||
```
|
||||
|
||||
将客户域名解析到 Ingress 暴露的公网 IP 或 CNAME。
|
||||
|
||||
DNS 生效前,可以先用 `curl --resolve` 验证:
|
||||
|
||||
```bash
|
||||
curl -i --resolve 你的域名:443:Ingress公网IP https://你的域名/api/health
|
||||
```
|
||||
|
||||
DNS 生效后验证:
|
||||
|
||||
```bash
|
||||
curl -i https://你的域名/api/health
|
||||
curl -i https://你的域名/asg-api/health
|
||||
curl -i https://你的域名/ams-api/health
|
||||
```
|
||||
|
||||
浏览器访问:
|
||||
|
||||
```text
|
||||
https://你的域名
|
||||
```
|
||||
|
||||
重点确认:
|
||||
|
||||
| 检查项 | 预期结果 |
|
||||
| --- | --- |
|
||||
| Web 页面 | 可以正常打开 |
|
||||
| `/api/health` | 返回健康状态,不是 404/502 |
|
||||
| `/asg-api/health` | 返回健康状态 |
|
||||
| `/ams-api/health` | 返回健康状态 |
|
||||
| `/socket.io` | WebSocket 可以正常连接 |
|
||||
|
||||
## 更新到最新版本
|
||||
|
||||
本仓库默认使用 `latest` 镜像标签,并且工作负载已配置 `imagePullPolicy: Always`。
|
||||
|
||||
当 EasyAI 发布新版本后,客户在本仓库目录执行以下命令。即使 `git pull` 没有拉到新的 YAML 变更,只要 EasyAI 已发布新的 `latest` 镜像,也需要执行后面的 `rollout restart`:
|
||||
|
||||
```bash
|
||||
git pull
|
||||
kubectl apply -k k8s/overlays/production
|
||||
|
||||
kubectl -n easyai 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-web easyai-server ws-gateway video-edit sandbox easyai-asg agent-memory; do
|
||||
kubectl -n easyai rollout status deploy/$d --timeout=15m
|
||||
done
|
||||
```
|
||||
|
||||
说明:`latest` 标签更新后,Kubernetes 不会仅因为远端镜像变化就自动重建 Pod,所以更新时必须执行 `rollout restart`。
|
||||
|
||||
## 回滚
|
||||
|
||||
如果是配置变更导致问题,可回到上一份配置后重新部署:
|
||||
|
||||
```bash
|
||||
git checkout <上一个可用提交>
|
||||
kubectl apply -k k8s/overlays/production
|
||||
```
|
||||
|
||||
如果是镜像版本问题,请使用 EasyAI 提供的回滚版本或回滚仓库版本后重新执行部署。
|
||||
|
||||
查看发布历史:
|
||||
|
||||
```bash
|
||||
kubectl -n easyai rollout history deploy/easyai-server
|
||||
```
|
||||
|
||||
回滚单个服务:
|
||||
|
||||
```bash
|
||||
kubectl -n easyai rollout undo deploy/easyai-server
|
||||
kubectl -n easyai rollout status deploy/easyai-server --timeout=10m
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
| 现象 | 优先检查 |
|
||||
| --- | --- |
|
||||
| `ImagePullBackOff` | 节点是否能访问镜像仓库,镜像仓库是否需要额外拉取凭证 |
|
||||
| Pod 一直 `Pending` | 节点资源、PVC 是否 Bound、StorageClass 是否支持 RWX |
|
||||
| HPA 显示 `unknown` | Metrics Server 是否可用,`kubectl top pods` 是否正常 |
|
||||
| `/api/health` 返回 404/502 | IngressClass、rewrite annotation、后端服务是否 Ready |
|
||||
| WebSocket 频繁断开 | `/socket.io` 是否路由到 `ws-gateway:3002`,Ingress 超时时间是否足够 |
|
||||
| 文件上传后多副本不可见 | `easyai-shared-files` PVC 是否正确挂载到 `easyai-server` |
|
||||
| 连接数据库或中间件失败 | VPC、安全组、白名单、端口、用户名密码、TLS 要求 |
|
||||
| `video-edit` 无法创建 | 集群 PodSecurity/PSA 是否禁止 `SYS_ADMIN` capability |
|
||||
|
||||
查看事件和日志:
|
||||
|
||||
```bash
|
||||
kubectl -n easyai get events --sort-by=.lastTimestamp | tail -80
|
||||
kubectl -n easyai logs deploy/easyai-server --tail=200
|
||||
kubectl -n easyai logs deploy/ws-gateway --tail=200
|
||||
kubectl -n easyai logs deploy/easyai-asg --tail=200
|
||||
kubectl -n easyai logs deploy/agent-memory --tail=200
|
||||
```
|
||||
Reference in New Issue
Block a user