Files
ocdp-go/README.md
Ivan087 7f238a3168 refactor: full-stack restructure with multi-tenancy, workspace management, and K8s diagnostics
- Add Workspace domain (entity, repository, service, handler, DTO)
- Add multi-tenant K8s client with tenant binding and quota management
- Add K8s diagnostics client (instance diagnostics)
- Add authorization middleware (authz package)
- Restructure frontend to feature-based architecture (features/)
- Add User Management page in configuration
- Add AccessDenied page and route guards
- Refactor shared components (form inputs, layout, UI)
- Update Tailwind config for new design system
- Add comprehensive documentation (docs/, tasks/, plans)
- Improve cluster service with better kubeconfig handling
- Add tests for crypto, config, helm client, tenant binding
2026-05-12 16:15:14 +08:00

268 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# OCDP - Open Cloud Deployment Platform
OCDP 是一个面向 Kubernetes 的大模型推理部署平台。当前核心场景是:用户在页面选择 Harbor 中的 `vllm-serve` Helm Chart填写实例名称、命名空间和 values 后,后端从 Harbor 拉取封装好的 OCI Helm Chart并通过 Helm SDK 部署到已配置好的 Kubernetes 集群。
## 当前能力
- Registry 管理:保存 Harbor / OCI Registry 地址与凭据,敏感字段加密入库。
- Artifact 浏览:通过 Harbor v2.0 API 浏览当前凭据可见的项目、repositories 和 chart tags避免依赖 `/v2/_catalog` 全局 catalog 权限。
- 一键部署:从前端发起实例创建,后端拉取 Chart 并在目标集群执行 Helm install/upgrade/uninstall。
- 集群管理:保存 Kubernetes API Server、CA、客户端证书或 token用于后端连接集群。
- 实例管理查看部署状态、Helm revision、Service/Ingress 入口信息。
- 认证:内置 JWT 登录,首次启动可通过 bootstrap 注入管理员账号。
## 技术栈
- 后端Go 1.24Gorilla MuxHexagonal ArchitecturePostgreSQLORAS SDKHelm SDKKubernetes client-go。
- 前端React 18TypeScriptViteTailwindCSS。
- 部署Docker ComposeNginx 静态文件与 `/api` 反向代理PostgreSQL 持久化。
## 项目结构
```text
ocdp-go/
├── backend/ # Go 后端
│ ├── cmd/api/ # API 入口
│ ├── internal/adapter/input/ # HTTP REST handlers / DTO
│ ├── internal/adapter/output/ # PostgreSQL / ORAS / Helm / K8s 实现
│ ├── internal/domain/ # Entity / Repository interface / Service
│ └── internal/bootstrap/ # 首次启动数据注入
├── frontend/ # React + Vite 前端
├── infra/nginx/ # Nginx 网关配置和 TLS 证书
├── docker-compose.yml # 本地完整部署PostgreSQL + Backend + 前端 build + Nginx
├── backend/docker-compose.yml # PostgreSQL + Backend + pgAdmin
├── Makefile # 推荐入口install / run-2 / docker-dev / docker-down
└── tasks/ # Agent 工作记录
```
## 后端部署链路
1. 前端调用 `POST /api/v1/clusters/{clusterId}/instances`,提交 `name``namespace``registryId``repository``tag` 和可选 `values`
2. 后端 `InstanceService.CreateInstance` 校验集群、Registry 和实例名唯一性,创建 pending 记录。
3. Chart 浏览使用 Harbor v2.0 API实际部署时后端使用 ORAS SDK 访问 Harbor将指定 repository/tag 的 Helm Chart layer 下载到 `/tmp/charts/{chart}-{version}.tgz`
4. 后端用数据库中保存的集群凭据生成临时 kubeconfig。
5. Helm SDK 加载本地 chart 包,并对目标集群执行 `install`;后续通过 Helm status 同步实例状态。
6. 删除、升级和回滚实例同样通过 Helm SDK 操作目标集群。
## 部署前准备
需要本机已安装:
- Docker
- Docker Compose v2 或更高版本
- Make可选没有 Make 时可直接执行 Compose 命令
根目录 `.env` 用于开发环境启动时注入端口、数据库、初始账号、Harbor 和 Kubernetes 集群。它是开发/测试 bootstrap 数据,不是长期配置中心;系统启动后建议在页面里维护 Registry 和 Cluster。不要提交真实 `.env`
关键变量如下,实际值以你的 `.env` 为准:
```dotenv
# 登录账号 bootstrap
BOOTSTRAP_ADMIN_USER=admin
BOOTSTRAP_ADMIN_PASS=change-me
BOOTSTRAP_ADMIN_EMAIL=admin@example.com
# Harbor bootstrap
BOOTSTRAP_REGISTRY_NAME=harbor
BOOTSTRAP_REGISTRY_URL=https://harbor.example.com
BOOTSTRAP_REGISTRY_DESC=Harbor Registry
# 推荐使用 Harbor robot 账号,只授予目标项目 pull/read 权限
BOOTSTRAP_REGISTRY_ROBOT_USER='robot$project+ocdp'
BOOTSTRAP_REGISTRY_ROBOT_PASS='robot-token'
# 可选 fallback未配置 ROBOT 变量时才会使用
BOOTSTRAP_REGISTRY_USER=admin-or-user
BOOTSTRAP_REGISTRY_PASS=change-me
BOOTSTRAP_REGISTRY_INSECURE=false
# Kubernetes 集群 bootstrap名称列表用逗号分隔
BOOTSTRAP_CLUSTERS=cluster1,cluster2
BOOTSTRAP_CLUSTER_CLUSTER1_HOST=https://x.x.x.x:6443
BOOTSTRAP_CLUSTER_CLUSTER1_DESC=GPU Cluster 1
BOOTSTRAP_CLUSTER_CLUSTER1_CA=base64-ca-data
BOOTSTRAP_CLUSTER_CLUSTER1_CERT=base64-client-cert-data
BOOTSTRAP_CLUSTER_CLUSTER1_KEY=base64-client-key-data
# 如使用 token可配置 TOKENCERT/KEY 可按实际鉴权方式留空
BOOTSTRAP_CLUSTER_CLUSTER2_HOST=https://x.x.x.x:6443
BOOTSTRAP_CLUSTER_CLUSTER2_TOKEN=token-value
# 服务端口,默认使用高位端口避免和本机其他项目冲突
WEB_HTTP_PORT=18080
WEB_HTTPS_PORT=18443
BACKEND_PORT=18081
POSTGRES_PORT=15432
# 安全与数据库
JWT_SECRET=replace-with-a-strong-secret
ENCRYPTION_KEY=replace-with-32-byte-key
POSTGRES_DB=ocdp
POSTGRES_USER=postgres
POSTGRES_PASSWORD=replace-me
# 可选Docker 构建后端时使用的 Go module proxy。
# 国内网络建议保留默认值;如公司网络要求,也可改回 https://proxy.golang.org,direct。
GOPROXY=https://goproxy.cn,direct
GOSUMDB=sum.golang.google.cn
```
说明:
- `BOOTSTRAP_CONFIG_JSON` 优先级最高,适合把完整 bootstrap 配置作为 JSON 注入。
- 没有 `BOOTSTRAP_CONFIG_JSON` 时,后端会读取 `BOOTSTRAP_*` 变量生成初始账号、Registry 和 Cluster。
- 没有任何显式 bootstrap 配置时后端不会预注入用户、Registry 或 Cluster代码中不再保留真实 Harbor、admin 或集群 fallback。
- 初始管理员必须显式配置 `BOOTSTRAP_ADMIN_USER``BOOTSTRAP_ADMIN_PASS`。如果只配置 Registry/Cluster 而未配置管理员账号,系统不会自动创建默认账号。
- Registry bootstrap 凭据优先级为 `BOOTSTRAP_REGISTRY_ROBOT_USER/PASS`,然后才是 `BOOTSTRAP_REGISTRY_USER/PASS`。Harbor robot 账号需要能访问目标项目的 repositories 和 artifacts。
- Harbor robot 用户名通常包含 `$`。本项目 Compose 已使用 raw `env_file` 传给后端;如果你在 shell 里临时 `export BOOTSTRAP_REGISTRY_ROBOT_USER=...`,请用单引号包住值,避免 shell 展开 `$project`
- 已存在同名用户、Registry 或 Cluster 时bootstrap 会跳过,不会覆盖数据库里的记录。
- `ENCRYPTION_KEY` 用于加密保存 Harbor 密码和集群凭据;生产环境首次启动后不要随意更换,否则旧数据无法解密。
## 推荐部署流程
当前推荐使用根目录 Makefile。`docker-dev``docker-prod``docker-up` 都是兼容旧文档的别名,实际会启动同一套完整 Docker Compose 栈PostgreSQL、Backend、前端静态构建和 Nginx。
```bash
# 1. 在根目录检查 .env
ls .env
# 2. 可选:安装本地依赖。只部署 Docker 栈时不是必须,但这个命令可用。
make install
# 3. 如果默认高位端口仍被其他项目占用,再临时换端口
export WEB_HTTP_PORT=18080
export WEB_HTTPS_PORT=18443
export BACKEND_PORT=18081
export POSTGRES_PORT=15432
# 4. 构建并后台启动完整栈
make run-2
# 兼容旧文档,也可以执行:
make docker-dev
make docker-prod
# 5. 查看服务
make docker-ps
```
访问地址:
- 前端入口http://localhost:${WEB_HTTP_PORT:-18080}
- 后端健康检查http://localhost:${BACKEND_PORT:-18081}/health
- Swagger UIhttp://localhost:${BACKEND_PORT:-18081}/api/docs
- Nginx 健康检查http://localhost:${WEB_HTTP_PORT:-18080}/healthz
没有 Make 时,直接用根目录 Compose 文件即可。注意要加 `--build`,因为后端镜像和前端静态资源需要构建:
```bash
docker compose up --build -d postgres backend nginx
docker compose ps
```
如果直接执行 `docker compose up`Compose 也会使用同一个完整栈;但在代码或 Dockerfile 改动后建议显式加 `--build`,避免复用旧镜像。
## 验证部署
```bash
# 健康检查
curl http://localhost:${BACKEND_PORT:-18081}/health
curl http://localhost:${WEB_HTTP_PORT:-18080}/healthz
# 登录,返回 token。把 password 替换成 .env 里的 BOOTSTRAP_ADMIN_PASS。
curl -s -X POST http://localhost:${BACKEND_PORT:-18081}/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"<BOOTSTRAP_ADMIN_PASS>"}'
# 查看 bootstrap 是否生效,需要带 Bearer token
curl http://localhost:${BACKEND_PORT:-18081}/api/v1/registries \
-H "Authorization: Bearer <token>"
curl http://localhost:${BACKEND_PORT:-18081}/api/v1/clusters \
-H "Authorization: Bearer <token>"
```
页面验证:
1. 打开前端入口并登录。
2. 进入 Chart Browser确认能看到 Harbor 中的 `vllm-serve` 或 nginx chart repository。当前默认只展示可部署 Helm chart。
3. 选择 chart tag点击 Launch。
4. 选择目标集群、命名空间,填写实例名和 values。values 支持 schema 表单或 YAMLYAML 会在前端校验,并由后端解析为 Helm values map。
5. 提交后到实例页面查看状态;后端会异步安装并同步 Helm 状态。
命令行 smoke test
```bash
# 只验证登录、Registry health、Harbor chart 浏览和 values schema
BASE_URL=http://localhost:${BACKEND_PORT:-18081}/api/v1 \
ADMIN_USER="${BOOTSTRAP_ADMIN_USER:-admin}" \
ADMIN_PASS="<BOOTSTRAP_ADMIN_PASS>" \
./test/current-platform-smoke.sh
# 允许真实部署时,会创建测试 release 并在结束后调用平台删除
RUN_DEPLOY_TEST=true \
TEST_NAMESPACE=ocdp-smoke \
TEST_RELEASE=ocdp-smoke-nginx \
BASE_URL=http://localhost:${BACKEND_PORT:-18081}/api/v1 \
ADMIN_PASS="<BOOTSTRAP_ADMIN_PASS>" \
./test/current-platform-smoke.sh
```
## 常用运维命令
```bash
# 查看日志
make docker-logs
# 重启后端
docker compose restart backend
# 如果后端容器被重建过Nginx 可能仍缓存旧 upstream IP只需重启本项目 Nginx
docker compose restart nginx
# 停止本项目服务,但保留数据卷
make docker-down
# 清理本项目容器和数据卷,谨慎使用
make clean-2
```
## 本地开发与测试
后端:
```bash
cd backend
go test ./...
go run cmd/api/main.go
```
前端:
```bash
cd frontend
npm ci
npm run build
```
Mock 后端仍可通过 `backend/docker-compose.yml``mock` profile 启动:
```bash
docker compose -f backend/docker-compose.yml --profile mock up -d backend-mock
```
## 注意事项
- 不要为了端口冲突停止其他项目;优先通过 `WEB_HTTP_PORT``WEB_HTTPS_PORT``BACKEND_PORT``POSTGRES_PORT` 换端口。当前默认端口已经是 `18080/18443/18081/15432`
- 如果旧文档提到 `make docker-dev``make docker-prod`,现在这些命令仍可用,都会启动同一套 Docker 栈。
- 如果之前用旧配置启动失败过PostgreSQL 卷里可能残留旧的加密数据,表现为 `/api/v1/clusters``/api/v1/registries` 解密失败。开发/重装环境可执行 `make clean-2 && make docker-dev` 重新初始化;生产环境不要直接删卷,应先备份数据库。
- `vllm-serve` 必须以 Helm Chart OCI artifact 的形式存在于 Harbor 中;后端会寻找 Helm Chart layer 并保存为 `.tgz`
- Harbor 浏览使用 `/api/v2.0/projects`、project repositories 和 artifacts API。若 robot 账号无法列项目或 artifacts页面会显示明确错误请检查 Harbor 项目成员/robot 权限,而不是给普通用户开放全局 catalog。
- values YAML 已按 YAML 解析;顶层必须是 mapping例如 `replicaCount: 1`
- Nginx 默认同时监听 HTTP 和 HTTPS证书位于 `infra/nginx/certs/`,生产环境应替换为正式证书。
- `make clean-2` 会删除本项目 Compose 卷,包括 PostgreSQL 数据;只想停服务时使用 `docker compose ... down --remove-orphans`
## API 文档
- OpenAPI YAML[backend/docs/openapi.yaml](./backend/docs/openapi.yaml)
- 运行后 Swagger UI`/api/docs`