Files
ocdp-go/backend/docs/architecture.md
mangomqy c5e51ed069 ocdp v1
2025-11-13 02:54:06 +00:00

1306 lines
43 KiB
Markdown
Raw Permalink 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.

# 🏗️ 架构文档
## 目录
- [2.1.1 需求描述](#211-需求描述)
- [项目背景](#项目背景)
- [核心需求](#核心需求)
- [功能需求](#功能需求)
- [非功能需求](#非功能需求)
- [2.1.2 业务建模](#212-业务建模)
- [业务领域](#业务领域)
- [核心实体](#核心实体)
- [业务流程](#业务流程)
- [用例场景](#用例场景)
- [2.1.3 技术建模](#213-技术建模)
- [2.1.3.1 六边形架构](#2131-六边形架构)
- [2.1.3.2 技术选型](#2132-技术选型)
---
# 2.1.1 需求描述
## 项目背景
### 问题陈述
在云原生时代Kubernetes 已成为容器编排的事实标准Helm 是 Kubernetes 的包管理工具。然而,当前企业在使用 Helm 进行应用部署时面临以下挑战:
1. **多集群管理复杂** - 企业通常有多个 Kubernetes 集群(开发、测试、生产),需要统一的管理界面
2. **制品仓库分散** - Helm Chart 可能分布在多个 OCI RegistryHarbor、Docker Hub、GHCR难以统一浏览
3. **部署流程繁琐** - 需要手动编写 `helm install` 命令,配置复杂的 values.yaml
4. **缺乏可视化** - 命令行操作对非技术人员不友好,缺少直观的 UI
5. **版本管理困难** - 应用升级需要记住历史版本,容易出错
6. **监控信息分散** - 需要单独访问 Kubernetes Dashboard 查看应用状态
### 解决方案
OCDP Backend 提供统一的后端 API 服务,实现:
-**统一管理** - 集中管理多个 Kubernetes 集群和 OCI Registry
-**可视化部署** - 通过 API 简化 Helm Chart 的浏览和部署流程
-**版本控制** - 完整的应用生命周期管理(安装、升级、卸载)
-**实时监控** - 集成 Kubernetes API实时获取应用状态和资源使用情况
-**安全认证** - 支持用户认证和敏感数据加密存储
---
## 核心需求
### 业务需求
| 需求 ID | 需求描述 | 优先级 |
|---------|---------|--------|
| BR-001 | 支持管理多个 Kubernetes 集群 | P0 |
| BR-002 | 支持管理多个 OCI Registry | P0 |
| BR-003 | 浏览和搜索 Helm Chart 制品 | P0 |
| BR-004 | 部署 Helm Chart 到 Kubernetes 集群 | P0 |
| BR-005 | 升级已部署的应用 | P0 |
| BR-006 | 查看应用实时状态和资源使用 | P1 |
| BR-007 | 用户认证和权限管理 | P1 |
| BR-008 | 审计日志记录 | P2 |
### 用户角色
1. **平台管理员** - 管理集群、Registry、用户
2. **开发者** - 部署和管理自己的应用
3. **运维人员** - 监控和维护应用状态
4. **访客** - 只读查看应用列表和状态
---
## 功能需求
### F1. 集群管理
**描述**: 管理多个 Kubernetes 集群的连接配置
**功能点**:
- 添加集群(配置 API Server 地址、证书)
- 查看集群列表和详情
- 测试集群连接健康状态
- 更新和删除集群配置
- 查看集群资源使用情况CPU、内存、节点数
**验收标准**:
- ✅ 支持证书认证和 Token 认证
- ✅ 敏感信息(证书、密钥)加密存储
- ✅ 连接失败时给出清晰的错误提示
- ✅ 支持测试连接功能
---
### F2. Registry 管理
**描述**: 管理多个 OCI Registry 的连接配置
**功能点**:
- 添加 RegistryHarbor、Docker Hub、GHCR 等)
- 配置认证信息(用户名/密码)
- 查看 Registry 列表和详情
- 测试 Registry 连接健康状态
- 更新和删除 Registry 配置
**验收标准**:
- ✅ 支持 Basic Auth 和 Bearer Token
- ✅ 密码加密存储
- ✅ 支持 HTTP/HTTPS 和自签名证书
- ✅ 连接测试返回响应时间
---
### F3. Artifact 浏览
**描述**: 浏览和搜索 OCI Registry 中的 Helm Chart
**功能点**:
- 列出 Registry 中的所有仓库
- 列出仓库中的所有制品tags
- 查看制品详情大小、创建时间、annotations
- 自动识别制品类型Helm Chart、Docker Image
- 获取 Helm Chart 的 values schema
**验收标准**:
- ✅ 符合 OCI Distribution Specification
- ✅ 支持 URL 编码的仓库名称(如 `charts/app`
- ✅ 正确解析 manifest 和 config
- ✅ 计算制品总大小(包含所有 layers
---
### F4. 应用部署
**描述**: 部署 Helm Chart 到 Kubernetes 集群
**功能点**:
- 选择集群、Registry、Chart 和版本
- 配置 valuesJSON 或 YAML
- 安装应用到指定 namespace
- 查看安装进度和状态
- 获取应用访问端点
**验收标准**:
- ✅ 支持自定义 Release 名称
- ✅ 支持 JSON 和 YAML 格式的 values
- ✅ 记录部署历史
---
### F5. 应用生命周期管理
**描述**: 管理已部署应用的完整生命周期
**功能点**:
- 查看应用列表和详情
- 升级应用到新版本
- 查看部署历史
- 卸载应用
**验收标准**:
- ✅ 升级时保留配置
- ✅ 卸载时可选保留历史
- ✅ 显示每次部署的描述信息
---
### F6. 监控和状态
**描述**: 实时监控应用和集群状态
**功能点**:
- 查看应用实时状态Running、Failed 等)
- 查看应用资源使用CPU、内存
- 查看集群整体监控
- 查看节点资源使用
- 监控摘要统计
**验收标准**:
- ✅ 实时获取 Kubernetes 资源状态
- ✅ 支持 Prometheus 指标集成
- ✅ 显示 Pod 状态和事件
- ✅ 资源使用百分比显示
---
### F7. 认证和授权
**描述**: 用户身份认证和访问控制
**功能点**:
- 用户注册和登录
- JWT Token 认证
- Token 刷新机制
- 密码加密存储
**验收标准**:
- ✅ 使用 bcrypt 哈希密码
- ✅ JWT Token 有效期配置
- ✅ Refresh Token 支持
- ✅ 密码强度验证
---
## 非功能需求
### NFR1. 性能要求
| 指标 | 要求 |
|------|------|
| API 响应时间 | P95 < 500ms |
| 并发用户数 | 支持 100+ 并发 |
| 数据库连接池 | 25 个连接 |
| Helm 操作超时 | 5 分钟 |
### NFR2. 可用性
- **系统可用性**: 99.5%
- **故障恢复时间**: < 5 分钟
- **数据备份**: 每日备份
- **健康检查**: 提供 `/health` 端点
### NFR3. 安全性
- **数据加密**: AES-256 加密敏感数据
- **传输安全**: 支持 HTTPS
- **认证方式**: JWT Token
- **密码策略**: 最小长度 8
- **审计日志**: 记录所有操作未来
### NFR4. 可扩展性
- **水平扩展**: 支持多实例部署
- **数据库**: PostgreSQL 支持主从复制
- **无状态设计**: API 服务无状态
- **缓存策略**: 支持 Redis未来
### NFR5. 可维护性
- **代码质量**: 遵循 Go 最佳实践
- **测试覆盖**: > 70%
- **文档完整**: API 文档、架构文档、部署文档
- **日志记录**: 结构化日志
- **监控指标**: Prometheus 指标(未来)
### NFR6. 兼容性
- **Kubernetes 版本**: 1.24+
- **Helm 版本**: 3.x
- **OCI Registry**: 符合 OCI Distribution Spec
- **数据库**: PostgreSQL 15+
- **Go 版本**: 1.21+
---
# 2.1.2 业务建模
## 业务领域
OCDP Backend 属于**云原生应用管理**领域,主要涉及以下子域:
1. **制品管理域** - OCI Registry、Helm Chart、Docker Image
2. **集群管理域** - Kubernetes Cluster、Node、Namespace
3. **应用部署域** - Helm Release、Application Instance
4. **监控运维域** - Metrics、Logs、Events
---
## 核心实体
### 领域模型图
```
┌─────────────────────────────────────────────────────────────┐
│ Core Domain Entities │
└─────────────────────────────────────────────────────────────┘
┌──────────┐ ┌──────────┐ ┌──────────┐
│ User │─────────│ Cluster │─────────│ Instance │
└──────────┘ └──────────┘ └──────────┘
│ │ │
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Auth │ │ Health │ │ Status │
│ Token │ │ Check │ │ Resource │
└──────────┘ └──────────┘ └──────────┘
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Registry │─────────│Artifact │─────────│ Chart │
└──────────┘ └──────────┘ └──────────┘
│ │ │
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Health │ │Repository│ │ Values │
│ Check │ │ │ │ Schema │
└──────────┘ └──────────┘ └──────────┘
```
### 实体详解
#### 1. User用户
**职责**: 表示系统用户,负责身份认证
**属性**:
- `ID`: 唯一标识符
- `Username`: 用户名(唯一)
- `Email`: 邮箱
- `PasswordHash`: 密码哈希bcrypt
- `CreatedAt`: 创建时间
- `UpdatedAt`: 更新时间
**业务规则**:
- 用户名唯一
- 邮箱格式验证
- 密码最小长度 8 位
---
#### 2. Cluster集群
**职责**: 表示 Kubernetes 集群连接配置
**属性**:
- `ID`: 唯一标识符
- `Name`: 集群名称
- `Host`: API Server 地址
- `Description`: 描述
- `CAData`: CA 证书(加密存储)
- `CertData`: 客户端证书(加密存储)
- `KeyData`: 客户端密钥(加密存储)
- `Token`: Bearer Token可选
- `CreatedAt`: 创建时间
- `UpdatedAt`: 更新时间
**业务规则**:
- 集群名称唯一
- 必须提供证书或 Token
- Host 必须是有效的 HTTPS URL
---
#### 3. Registry镜像仓库
**职责**: 表示 OCI Registry 连接配置
**属性**:
- `ID`: 唯一标识符
- `Name`: Registry 名称
- `URL`: Registry URL
- `Description`: 描述
- `Username`: 用户名
- `Password`: 密码(加密存储)
- `Insecure`: 是否跳过 SSL 验证
- `CreatedAt`: 创建时间
- `UpdatedAt`: 更新时间
**业务规则**:
- Registry 名称唯一
- URL 必须是有效的 HTTP/HTTPS URL
- 密码加密存储
---
#### 4. Instance应用实例
**职责**: 表示部署在 Kubernetes 中的 Helm Release
**属性**:
- `ID`: 唯一标识符
- `Name`: Release 名称
- `Namespace`: Kubernetes namespace
- `ClusterID`: 所属集群
- `RegistryID`: Chart 来源 Registry
- `Repository`: Chart 仓库名
- `Chart`: Chart 名称
- `Version`: Chart 版本
- `Status`: 部署状态
- `Revision`: 当前版本号
- `Values`: 配置值JSON
- `Description`: 描述
- `CreatedAt`: 创建时间
- `UpdatedAt`: 更新时间
**业务规则**:
- 同一集群和 namespace 下 Release 名称唯一
- 必须关联有效的 Cluster 和 Registry
- Values 必须是有效的 JSON 或 YAML
---
#### 5. Artifact制品
**职责**: 表示 OCI Registry 中的制品Helm Chart、Docker Image 等)
**属性**:
- `RepositoryName`: 仓库名称
- `Tag`: 标签
- `Digest`: SHA256 摘要
- `Type`: 制品类型helm、docker、oci
- `Size`: 总大小
- `MediaType`: 媒体类型
- `Annotations`: 元数据
- `CreatedAt`: 创建时间
**业务规则**:
- Tag 或 Digest 至少提供一个
- 自动识别制品类型
- 计算所有 layers 的总大小
---
## 业务流程
### 流程 1: 用户注册和登录
```
┌──────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ User │ │ Handler │ │ Service │ │ Repo │
└──┬───┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │ │
│ Register │ │ │
├────────────>│ │ │
│ │ Create User │ │
│ ├──────────────>│ │
│ │ │ Hash Password │
│ │ ├──────┐ │
│ │ │<─────┘ │
│ │ │ Save User │
│ │ ├──────────────>│
│ │ │<──────────────┤
│ │<──────────────┤ │
│<────────────┤ │ │
│ │ │ │
│ Login │ │ │
├────────────>│ │ │
│ │ Authenticate │ │
│ ├──────────────>│ │
│ │ │ Verify Pwd │
│ │ ├──────┐ │
│ │ │<─────┘ │
│ │ │ Gen JWT │
│ │ ├──────┐ │
│ │ │<─────┘ │
│ │<──────────────┤ │
│<────────────┤ Return Token │ │
│ │ │ │
```
---
### 流程 2: 部署应用
```
┌──────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ User │ │ Handler │ │ Service │ │HelmClient│ │Kubernetes│
└──┬───┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │ │ │
│ Deploy App │ │ │ │
├────────────>│ │ │ │
│ │ Create Inst │ │ │
│ ├──────────────>│ │ │
│ │ │ Validate │ │
│ │ ├──────┐ │ │
│ │ │<─────┘ │ │
│ │ │ Pull Chart │ │
│ │ ├──────────────>│ │
│ │ │<──────────────┤ │
│ │ │ Install Chart │ │
│ │ ├──────────────>│ │
│ │ │ │ Apply K8s │
│ │ │ ├──────────────>│
│ │ │ │<──────────────┤
│ │ │<──────────────┤ │
│ │ │ Save Instance │ │
│ │ ├──────┐ │ │
│ │ │<─────┘ │ │
│ │<──────────────┤ │ │
│<────────────┤ Return Status │ │ │
│ │ │ │ │
```
---
### 流程 3: 浏览制品
```
┌──────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ User │ │ Handler │ │ Service │ │OCIClient │ │ Registry │
└──┬───┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │ │ │
│List Repos │ │ │ │
├────────────>│ │ │ │
│ │ Get Repos │ │ │
│ ├──────────────>│ │ │
│ │ │ List Catalog │ │
│ │ ├──────────────>│ │
│ │ │ │ GET _catalog │
│ │ │ ├──────────────>│
│ │ │ │<──────────────┤
│ │ │<──────────────┤ │
│ │<──────────────┤ │ │
│<────────────┤ │ │ │
│ │ │ │ │
│List Tags │ │ │ │
├────────────>│ │ │ │
│ │ Get Artifacts │ │ │
│ ├──────────────>│ │ │
│ │ │ List Tags │ │
│ │ ├──────────────>│ │
│ │ │ │ GET tags/list │
│ │ │ ├──────────────>│
│ │ │ │<──────────────┤
│ │ │ Get Manifest │ │
│ │ ├──────────────>│ │
│ │ │ │ GET manifest │
│ │ │ ├──────────────>│
│ │ │ │<──────────────┤
│ │ │<──────────────┤ │
│ │<──────────────┤ │ │
│<────────────┤ │ │ │
│ │ │ │ │
```
---
## 用例场景
### UC1: 开发者部署测试应用
**主角**: 开发者 Alice
**前置条件**:
- Alice 已登录系统
- 系统中已配置开发环境集群
- 系统中已配置 Harbor Registry
**基本流程**:
1. Alice 选择"开发集群"
2. Alice 浏览 Harbor 中的"charts/nginx"仓库
3. Alice 选择 nginx 1.0.0 版本
4. Alice 配置 values: `{"replicaCount": 2}`
5. Alice 点击"部署"
6. 系统显示部署进度
7. 部署成功,显示应用访问地址
**后置条件**:
- nginx 应用成功部署到开发集群
- 应用状态为 "deployed"
- Alice 可以访问应用
**异常流程**:
- 3a. Chart 版本不存在 → 显示错误提示
- 5a. 部署失败 → 显示错误日志
---
### UC2: 运维人员升级生产应用
**主角**: 运维 Bob
**前置条件**:
- Bob 已登录系统
- 生产环境有运行中的 nginx 应用(版本 1.0.0
**基本流程**:
1. Bob 进入"生产集群"应用列表
2. Bob 选择 nginx 应用
3. Bob 查看当前版本和配置
4. Bob 点击"升级"
5. Bob 选择新版本 1.1.0
6. Bob 更新配置: `{"replicaCount": 3}`
7. Bob 添加升级说明
8. Bob 确认升级
9. 系统执行滚动升级
10. 升级成功Revision 增加到 2
**后置条件**:
- nginx 应用升级到 1.1.0
- 副本数增加到 3
- 历史记录中保留了 Revision 1
**异常流程**:
- 9a. 升级失败 → 显示错误信息,保持原状态
- 9b. 超时 → 取消升级,保持原状态
---
### UC3: 管理员添加新集群
**主角**: 管理员 Charlie
**前置条件**:
- Charlie 已登录系统
- Charlie 有集群的 kubeconfig 文件
**基本流程**:
1. Charlie 进入"集群管理"页面
2. Charlie 点击"添加集群"
3. Charlie 填写集群信息:
- 名称: "Production Cluster"
- API Server: "https://k8s.prod.com:6443"
- 描述: "生产环境集群"
4. Charlie 从 kubeconfig 提取证书数据
5. Charlie 粘贴 CA、Cert、Key 数据
6. Charlie 点击"测试连接"
7. 系统显示"连接成功"
8. Charlie 保存配置
**后置条件**:
- 新集群添加到系统
- 集群证书加密存储
- 其他用户可以使用此集群
**异常流程**:
- 6a. 连接失败 → 显示具体错误信息
- 6b. 证书格式错误 → 提示正确的格式
---
# 2.1.3 技术建模
## 2.1.3.1 六边形架构
### 架构概述
OCDP Backend 采用**六边形架构**Hexagonal Architecture也称为端口和适配器架构这是一种分层架构模式强调业务逻辑与外部依赖的分离。
### 核心原则
1. **依赖倒置** - 所有层依赖 DomainDomain 无外部依赖
2. **端口和适配器** - 通过接口Port定义交互协议通过适配器Adapter实现具体技术
3. **可测试性** - 业务逻辑可独立测试,无需外部依赖
4. **可替换性** - 适配器可轻松替换Mock ↔ Production
### 架构分层图
```
┌─────────────────────────────────────────────────────────────┐
│ Input Adapters │
│ (HTTP REST API) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Auth Handler │ │Cluster Handl │ │Instance Handl│ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
└──────────────────────┬──────────────────────────────────────┘
│ DTO / Request
┌─────────────────────────────────────────────────────────────┐
│ Domain Layer │
│ (Business Logic) │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Entities │ │
│ │ User | Cluster | Registry | Instance | Artifact │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Services │ │
│ │ AuthService | ClusterService | InstanceService │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Repository Interfaces (Ports) │ │
│ │ UserRepo | ClusterRepo | OCIClient | HelmClient │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└──────────────────────┬──────────────────────────────────────┘
│ Interface Contract
┌─────────────────────────────────────────────────────────────┐
│ Output Adapters │
│ (Infrastructure Implementations) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Database │ │ OCI Client │ │ Helm Client │ │
│ │ │ │ │ │ │ │
│ ├──────────────┤ ├──────────────┤ ├──────────────┤ │
│ │ Mock: Memory │ │ Mock: Static │ │ Mock: Fake │ │
│ │ Prod:Postgres│ │ Prod: ORAS │ │ Prod: Helm │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
```
### 目录结构
```
internal/
├── domain/ # 🎯 领域层(核心)
│ ├── entity/ # 领域实体
│ │ ├── user.go
│ │ ├── cluster.go
│ │ ├── registry.go
│ │ ├── instance.go
│ │ └── artifact.go
│ │
│ ├── service/ # 业务逻辑服务
│ │ ├── auth_service.go
│ │ ├── cluster_service.go
│ │ ├── registry_service.go
│ │ ├── artifact_service.go
│ │ ├── instance_service.go
│ │ └── monitoring_service.go
│ │
│ └── repository/ # 接口定义Output Ports
│ ├── user_repository.go
│ ├── cluster_repository.go
│ ├── registry_repository.go
│ ├── instance_repository.go
│ ├── oci_client.go
│ ├── helm_client.go
│ └── metrics_client.go
├── adapter/
│ ├── input/ # 📥 输入适配器
│ │ └── http/
│ │ ├── rest/ # REST API Handlers
│ │ │ ├── auth_handler.go
│ │ │ ├── cluster_handler.go
│ │ │ ├── registry_handler.go
│ │ │ ├── artifact_handler.go
│ │ │ ├── instance_handler.go
│ │ │ ├── monitoring_handler.go
│ │ │ └── utils.go
│ │ │
│ │ └── dto/ # 数据传输对象
│ │ ├── auth_dto.go
│ │ ├── cluster_dto.go
│ │ ├── registry_dto.go
│ │ └── instance_dto.go
│ │
│ └── output/ # 📤 输出适配器
│ ├── persistence/
│ │ ├── mock/ # ✅ Mock 实现
│ │ │ ├── user_repository_mock.go
│ │ │ ├── cluster_repository_mock.go
│ │ │ ├── registry_repository_mock.go
│ │ │ └── instance_repository_mock.go
│ │ │
│ │ └── postgres/ # 🐘 PostgreSQL 实现
│ │ ├── user_repository.go
│ │ ├── cluster_repository.go
│ │ ├── registry_repository.go
│ │ └── instance_repository.go
│ │
│ ├── oci/
│ │ ├── mock/ # ✅ Mock OCI Client
│ │ │ └── oci_client_mock.go
│ │ └── oras_client.go # ORAS SDK 实现
│ │
│ ├── helm/
│ │ ├── mock/ # ✅ Mock Helm Client
│ │ │ └── helm_client_mock.go
│ │ └── helm_client.go # Helm SDK 实现
│ │
│ ├── metrics/
│ │ ├── mock/ # ✅ Mock Metrics Client
│ │ │ └── metrics_client_mock.go
│ │ └── prometheus_client.go
│ │
│ └── factory.go # 🏭 适配器工厂
├── bootstrap/ # Bootstrap 预注入模块
│ ├── config.go
│ └── seeder.go
└── pkg/ # 🔧 工具包
├── jwt/ # JWT 工具
├── password/ # 密码哈希
└── encryption/ # AES 加密
```
### 数据流
```
1. HTTP Request
2. [REST Handler] (Input Adapter)
- 验证请求参数
- 转换为 Domain 对象Entity
3. [Domain Service] (Business Logic)
- 执行业务逻辑
- 调用 Repository 接口Port
4. [Repository Implementation] (Output Adapter)
- Mock: 操作内存数据
- PostgreSQL: 操作数据库
- ORAS: 与 OCI Registry 交互
- Helm: 与 Kubernetes 交互
5. Response
- 返回结果到 Service
- Service 返回到 Handler
- Handler 转换为 HTTP 响应
```
### 依赖注入
`cmd/api/main.go` 中组装所有组件:
```go
func main() {
// 1. 加载配置
config := loadConfig()
// 2. 创建适配器工厂
factory := output.NewAdapterFactory(
config.AdapterMode,
config.DatabaseURL,
)
// 3. 创建 Output Adapters
repos, _ := factory.CreateAllRepositories()
ociClient, _ := factory.CreateOCIClient()
helmClient, _ := factory.CreateHelmClient()
// 4. 创建工具类
hasher := password.NewBcryptHasher()
jwtGen := jwt.NewJWTGenerator(config.JWTSecret)
// 5. 创建 Domain Services
authService := service.NewAuthService(repos.UserRepo, hasher, jwtGen)
clusterService := service.NewClusterService(repos.ClusterRepo)
registryService := service.NewRegistryService(repos.RegistryRepo)
instanceService := service.NewInstanceService(
repos.InstanceRepo,
repos.ClusterRepo,
repos.RegistryRepo,
helmClient,
)
// 6. 创建 Input Adapters (REST Handlers)
authHandler := rest.NewAuthHandler(authService)
clusterHandler := rest.NewClusterHandler(clusterService)
instanceHandler := rest.NewInstanceHandler(instanceService)
// 7. 设置路由
router := setupRouter(
authHandler,
clusterHandler,
instanceHandler,
)
// 8. 启动服务器
http.ListenAndServe(":8080", router)
}
```
### 适配器模式
#### 适配器工厂
```go
// internal/adapter/output/factory.go
type AdapterMode string
const (
ModeMock AdapterMode = "mock"
ModeProduction AdapterMode = "production"
)
type AdapterFactory struct {
mode AdapterMode
dbConnString string
}
func (f *AdapterFactory) CreateUserRepository() (repository.UserRepository, error) {
switch f.mode {
case ModeMock:
return mock.NewUserRepositoryMock(), nil
case ModeProduction:
return postgres.NewUserRepository(f.dbConnString)
default:
return nil, fmt.Errorf("unknown adapter mode: %s", f.mode)
}
}
```
#### Mock vs Production
| 接口 | Mock 模式 | Production 模式 |
|------|----------|----------------|
| UserRepository | ✅ 内存 map | 🐘 PostgreSQL |
| ClusterRepository | ✅ 内存 map | 🐘 PostgreSQL |
| RegistryRepository | ✅ 内存 map | 🐘 PostgreSQL |
| InstanceRepository | ✅ 内存 map | 🐘 PostgreSQL |
| OCIClient | ✅ 静态数据 | 🌐 ORAS SDK v2 |
| HelmClient | ✅ 模拟部署 | ☸️ Helm SDK |
| MetricsClient | ✅ 假数据 | 📊 Prometheus |
---
## 2.1.3.2 技术选型
### 编程语言
**Go 1.21+**
**选型理由**:
- ✅ 高性能,原生并发支持
- ✅ 静态类型,编译时检查
- ✅ 丰富的云原生生态Kubernetes client-go、Helm SDK、ORAS
- ✅ 简单易维护,部署方便(单一二进制文件)
- ✅ 广泛应用于云原生领域
**替代方案**: Java/Spring Boot, Python/FastAPI
---
### Web 框架
**gorilla/mux**
**选型理由**:
- ✅ 轻量级,性能好
- ✅ 灵活的路由匹配(支持正则表达式)
- ✅ 与标准库 `net/http` 完美兼容
- ✅ 活跃的社区支持
**使用示例**:
```go
router := mux.NewRouter()
api := router.PathPrefix("/api/v1").Subrouter()
api.HandleFunc("/clusters", handler.CreateCluster).Methods(http.MethodPost)
api.HandleFunc("/clusters/{clusterId}", handler.GetCluster).Methods(http.MethodGet)
```
**替代方案**: Gin, Echo, Fiber
---
### 数据库
**PostgreSQL 15+**
**选型理由**:
- ✅ 开源、成熟、可靠
- ✅ 支持复杂查询和事务
- ✅ JSONB 类型适合存储动态配置
- ✅ 主从复制、高可用支持
- ✅ 与 Go 生态集成良好
**数据库驱动**: `lib/pq``pgx`
**替代方案**: MySQL, MongoDB
---
### OCI Registry 客户端
**ORAS Go SDK v2**
**选型理由**:
- ✅ 符合 OCI Distribution Specification
- ✅ 官方维护,质量可靠
- ✅ 支持所有 OCI 兼容的 Registry
- ✅ 完整的 manifest、blob 操作
**使用示例**:
```go
repo, err := remote.NewRepository("harbor.example.com/charts/nginx")
repo.Client = &auth.Client{
Credential: auth.StaticCredential("username", "password"),
}
tags, err := repo.Tags(ctx)
manifest, err := repo.FetchReference(ctx, "1.0.0")
```
**官网**: https://oras.land/
**替代方案**: containerd, go-containerregistry
---
### Kubernetes 客户端
**client-go**
**选型理由**:
- ✅ Kubernetes 官方 Go 客户端
- ✅ 完整的 API 支持
- ✅ 动态客户端支持
- ✅ 与 Helm SDK 集成
**使用示例**:
```go
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
clientset, err := kubernetes.NewForConfig(config)
pods, err := clientset.CoreV1().Pods("default").List(ctx, metav1.ListOptions{})
```
**替代方案**: 无(标准库)
---
### Helm 客户端
**Helm SDK (helm.sh/helm/v3)**
**选型理由**:
- ✅ Helm 官方 SDK
- ✅ 完整的 Helm 操作支持
- ✅ Chart 解析和渲染
- ✅ Release 生命周期管理
**使用示例**:
```go
actionConfig := new(action.Configuration)
actionConfig.Init(settings.RESTClientGetter(), namespace, os.Getenv("HELM_DRIVER"), log.Printf)
install := action.NewInstall(actionConfig)
install.ReleaseName = "my-release"
install.Namespace = "default"
chart, err := loader.Load(chartPath)
release, err := install.Run(chart, values)
```
**替代方案**: 命令行调用 helm不推荐
---
### 认证和授权
**JWT (golang-jwt/jwt)**
**选型理由**:
- ✅ 无状态,易扩展
- ✅ 标准化RFC 7519
- ✅ 支持过期时间和刷新
- ✅ 广泛应用
**使用示例**:
```go
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"user_id": user.ID,
"exp": time.Now().Add(time.Hour * 24).Unix(),
})
tokenString, err := token.SignedString([]byte(jwtSecret))
```
**替代方案**: OAuth 2.0, Session
---
### 密码哈希
**bcrypt (golang.org/x/crypto/bcrypt)**
**选型理由**:
- ✅ 安全、抗暴力破解
- ✅ 自动加盐
- ✅ 计算成本可调
- ✅ Go 标准扩展库
**使用示例**:
```go
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
err = bcrypt.CompareHashAndPassword(hash, []byte(password))
```
**替代方案**: argon2, scrypt
---
### 数据加密
**AES-256 (crypto/aes + crypto/cipher)**
**选型理由**:
- ✅ 对称加密,性能好
- ✅ 256 位密钥,安全性高
- ✅ Go 标准库支持
- ✅ 适合敏感数据加密(证书、密码)
**使用模式**: GCMGalois/Counter Mode
**使用示例**:
```go
block, err := aes.NewCipher(key) // 32 bytes key
gcm, err := cipher.NewGCM(block)
nonce := make([]byte, gcm.NonceSize())
ciphertext := gcm.Seal(nonce, nonce, plaintext, nil)
```
**替代方案**: RSA (非对称加密,性能较差)
---
### 容器化
**Docker + Docker Compose**
**选型理由**:
- ✅ 标准化容器技术
- ✅ 简化部署和环境一致性
- ✅ 丰富的镜像生态
- ✅ Docker Compose 简化多容器编排
**Dockerfile 示例**:
```dockerfile
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o ocdp-backend cmd/api/main.go
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/ocdp-backend .
EXPOSE 8080
CMD ["./ocdp-backend"]
```
**替代方案**: Podman, containerd
---
### 日志记录
**标准库 log + 结构化日志未来zerolog/zap**
**当前实现**:
```go
log.Printf("✅ User created: %s", user.Username)
log.Printf("⚠️ Warning: %v", err)
log.Printf("❌ Error: %v", err)
```
**未来优化**:
```go
logger.Info().
Str("user_id", user.ID).
Str("username", user.Username).
Msg("User created")
```
---
### 测试框架
**testify**
**选型理由**:
- ✅ 丰富的断言函数
- ✅ Mock 支持
- ✅ 测试套件支持
- ✅ 活跃的社区
**使用示例**:
```go
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCreateUser(t *testing.T) {
user, err := service.CreateUser(ctx, "test", "password")
require.NoError(t, err)
assert.NotEmpty(t, user.ID)
assert.Equal(t, "test", user.Username)
}
```
---
### 热重载(开发)
**Air**
**选型理由**:
- ✅ Go 项目热重载
- ✅ 监听文件变化自动重启
- ✅ 配置简单
**配置文件**: `.air.toml`
```toml
[build]
cmd = "go build -o ./tmp/main cmd/api/main.go"
bin = "./tmp/main"
include_ext = ["go", "yaml", "json"]
exclude_dir = ["tmp", "vendor"]
```
**启动**: `air -c .air.toml`
---
### 技术栈总结表
| 组件 | 技术 | 版本 | 用途 |
|------|------|------|------|
| **语言** | Go | 1.21+ | 主要编程语言 |
| **Web 框架** | gorilla/mux | latest | HTTP 路由 |
| **数据库** | PostgreSQL | 15+ | 持久化存储 |
| **数据库驱动** | lib/pq 或 pgx | latest | Go 数据库驱动 |
| **OCI 客户端** | ORAS Go SDK | v2 | OCI Registry 操作 |
| **Kubernetes** | client-go | latest | K8s API 交互 |
| **Helm** | Helm SDK | v3 | Helm 操作 |
| **JWT** | golang-jwt/jwt | v5 | 认证 Token |
| **密码哈希** | bcrypt | latest | 密码加密 |
| **数据加密** | AES-256 | stdlib | 敏感数据加密 |
| **容器化** | Docker | latest | 应用容器化 |
| **编排** | Docker Compose | latest | 多容器编排 |
| **测试** | testify | latest | 单元测试 |
| **热重载** | Air | latest | 开发环境 |
---
### Bootstrap 预注入
**概述**: 在应用启动时自动初始化用户、Registry、Cluster 等数据。
**配置文件**: `config/bootstrap.json`
```json
{
"enabled": true,
"users": [
{
"username": "admin",
"password": "admin123",
"email": "admin@example.com"
}
],
"registries": [
{
"name": "Harbor Production",
"url": "https://harbor.example.com",
"username": "admin",
"password": "secret"
}
],
"clusters": [
{
"name": "Production Cluster",
"host": "https://k8s.example.com:6443",
"caData": "LS0tLS...",
"certData": "LS0tLS...",
"keyData": "LS0tLS..."
}
]
}
```
**特性**:
- ✅ 自动加密敏感数据
- ✅ 幂等性(重复启动不会重复创建)
- ✅ 可通过环境变量配置
- ✅ 支持禁用
**从 kubeconfig 提取证书**:
```bash
kubectl config view --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}'
kubectl config view --raw -o jsonpath='{.users[0].user.client-certificate-data}'
kubectl config view --raw -o jsonpath='{.users[0].user.client-key-data}'
```
---
### 开发指南
#### 添加新功能的步骤
1. **定义 Entity** (`internal/domain/entity/`)
2. **定义 Repository 接口** (`internal/domain/repository/`)
3. **实现 Domain Service** (`internal/domain/service/`)
4. **实现 Mock Adapter** (`internal/adapter/output/persistence/mock/`)
5. **实现 Production Adapter** (`internal/adapter/output/persistence/postgres/`)
6. **添加到 Factory** (`internal/adapter/output/factory.go`)
7. **创建 REST Handler** (`internal/adapter/input/http/rest/`)
8. **注册路由** (`cmd/api/main.go`)
#### 依赖方向规则
- ✅ Input Adapters → Domain Layer
- ✅ Domain Layer → Repository Interfaces
- ✅ Output Adapters → Domain Layer (实现接口)
- ❌ Domain Layer → Output Adapters禁止
#### 测试策略
- **单元测试**: 测试 Domain Service使用 Mock Repository
- **集成测试**: 测试 Handler + Service使用 Mock Adapters
- **E2E 测试**: 完整流程测试,使用真实环境
---
## 相关文档
- [API 与测试](api-and-test.md)
- [部署文档](deployment.md)
- [主 README](../README.md)
---
**Last Updated**: 2025-11-09