-
Notifications
You must be signed in to change notification settings - Fork 4
Open
Description
1. 背景 (Background)
API7 开发者门户由两部分组成:
- Portal API(后端):
api7/api7-ee-developer-portal,监听端口 4321,已经作为api7umbrella chart 的一部分部署在 Kubernetes 中 - Developer Portal FE(前端):
api7/api7-ee-developer-portal-fe,监听端口 3001,基于 api7-portal-boilerplate 构建的 Next.js 应用,目前只有 Docker Compose 部署方式
本 PRD 的目标是为 Developer Portal FE 创建一个独立的 Helm Chart,使其可以在 Kubernetes 集群中部署。
参考文档:使用提供方门户设置开发者门户
2. 架构概览
┌─────────────────────────────────────────────────┐
│ api7 umbrella chart (已有) │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Dashboard │ │DP Manager│ │ Portal API │ │
│ │ :7443 │ │ :7900 │ │ (后端) :4321 │ │
│ └──────────┘ └──────────┘ └──────┬───────┘ │
│ │ │
│ PostgreSQL │
│ (共享 api7ee) │
└──────────────────────────────────────┼───────────┘
│ portal.url + portal.token
│
┌──────────────────────────────────────┼───────────┐
│ developer-portal-fe chart (新建) │ │
│ ┌──────────────────┐ │ │
│ │ Developer Portal │◄──────────────┘ │
│ │ FE (Next.js) │ │
│ │ :3001 │ │
│ └────────┬─────────┘ │
│ │ │
│ PostgreSQL │
│ (独立,用于 Better Auth 用户管理) │
└──────────────────────────────────────────────────┘
关键区分:
- Portal API 后端(已有 chart)和 Developer Portal FE 前端(本 chart)使用不同的 PostgreSQL 数据库
- FE 通过
portal.url+portal.token连接后端 Portal API - FE 有自己的用户认证系统(Better Auth),数据存储在自己的 PostgreSQL 中
3. 应用运行时画像
3.1 Docker 镜像信息
| 属性 | 值 |
|---|---|
| 镜像 | api7/api7-ee-developer-portal-fe |
| 最新版本 | v0.5.7 |
| 架构 | linux/amd64, linux/arm64 (~85-86 MB) |
| 基础镜像 | Node.js 22 Alpine |
| 容器端口 | 3001 |
| 配置文件路径 | /app/apps/site/config.yaml |
| 入口 | ./docker-entrypoint.sh → node apps/site/server.js |
3.2 启动流程
docker-entrypoint.sh
└─ preflight.js # 验证数据库连通性 + Portal API 可用性
└─ node apps/site/server.js # 启动 Next.js 服务
3.3 Health Check
| 探针类型 | 路径 | 端口 | 协议 |
|---|---|---|---|
| Liveness | /healthz |
3001 | HTTP |
| Readiness | /healthz |
3001 | HTTP |
3.4 环境变量
| 变量 | 必需 | 说明 |
|---|---|---|
NODE_ENV |
是 | 设为 production |
PORT |
是 | 服务端口(默认 3001) |
HOSTNAME |
是 | 监听地址(默认 0.0.0.0) |
NODE_TLS_REJECT_UNAUTHORIZED |
仅自签名证书场景 | 设为 0 跳过 TLS 验证 |
PORTAL_URL |
是 | API7 Portal API endpoint |
PORTAL_TOKEN |
是 | 从 Provider Portal 生成的 Token |
3.5 配置文件 Schema
config.yaml 支持 ${VAR} 和 ${VAR:default} 环境变量模板语法。
完整 schema(来自 apps/site/config.yaml.example):
# 必需 - Portal API 连接
portal:
url: ${PORTAL_URL:http://provider-portal.api.local}
token: ${PORTAL_TOKEN:}
# 必需 - 数据库
db:
url: "" # PostgreSQL 连接字符串
# pool: # 可选连接池配置
# max: 20
# min: 0
# idleTimeout: 30000
# ssl: false
# 必需 - 认证
auth:
secret: "" # 至少 32 字符
# session:
# expiresIn: 604800 # 7 天(秒)
# updateAge: 86400 # 1 天
# emailAndPassword:
# enabled: true
# socialProviders: # GitHub, Google 等
# 可选 - 应用设置
app:
name: "Developer Portal"
baseURL: "http://localhost:3001"
trustedOrigins:
- "*"3.6 依赖
| 依赖 | 版本 | 用途 |
|---|---|---|
| PostgreSQL | 15+ | 用户/组织数据存储(通过 Drizzle ORM) |
| API7 Portal API | - | 后端 REST API(端口 4321) |
4. Docker Compose → Helm Chart 映射
| Docker Compose 组件 | Helm Chart 资源 | 说明 |
|---|---|---|
developer-portal service |
Deployment + Service + Ingress | 镜像 api7/api7-ee-developer-portal-fe:v0.5.7 |
postgres service |
子依赖 (bitnami/postgresql) 或外部连接 | 可选内置 PostgreSQL |
config.yaml 挂载 |
ConfigMap(非敏感)+ Secret(敏感值通过环境变量注入) | 挂载到 /app/apps/site/config.yaml |
ports: "80:3001" |
Service port 80 → containerPort 3001 | |
NODE_TLS_REJECT_UNAUTHORIZED env |
env in Deployment spec | |
volumes: postgres_data |
PVC(通过 postgresql subchart 管理) |
5. Chart 设计
5.1 Chart 元数据
# charts/developer-portal-fe/Chart.yaml
apiVersion: v2
name: developer-portal-fe
description: A Helm chart for API7 Developer Portal Frontend
type: application
version: 0.1.0
appVersion: "0.5.7"
maintainers:
- name: API7
email: support@api7.ai
url: https://api7.ai
dependencies:
- name: postgresql
condition: postgresql.builtin
version: "12.12.10"
repository: "https://charts.bitnami.com/bitnami"5.2 values.yaml 结构
# ============================================================
# 应用配置
# ============================================================
developerPortal:
replicaCount: 1
image:
repository: api7/api7-ee-developer-portal-fe
pullPolicy: IfNotPresent
tag: "v0.5.7"
resources: {}
extraEnvVars: []
extraVolumes: []
extraVolumeMounts: []
podLabels: {}
podAnnotations: {}
topologySpreadConstraints: []
# 针对自签名证书的 Portal API(仅开发环境使用)
tlsRejectUnauthorized: true # 设 false 则 NODE_TLS_REJECT_UNAUTHORIZED=0
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 10
readinessProbe:
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
# ============================================================
# Portal API 连接配置
# ============================================================
portal:
# Portal API 的 endpoint(即 api7 chart 中部署的 developer portal 后端)
url: "https://api7-developer-portal:4321"
# 从 Provider Portal 生成的 Token(明文,优先级低于 existingSecret)
token: ""
# 引用已有 Secret(生产环境推荐)
existingSecret: ""
existingSecretKey: "portal-token"
# ============================================================
# 数据库配置
# ============================================================
db:
# PostgreSQL 连接字符串
url: "postgres://portal:portal123@developer-portal-fe-postgresql:5432/portal"
# 引用已有 Secret(生产环境推荐)
existingSecret: ""
existingSecretKey: "db-url"
# ============================================================
# Auth 配置
# ============================================================
auth:
# Better Auth secret key(至少 32 字符,可用 openssl rand -base64 32 生成)
secret: ""
existingSecret: ""
existingSecretKey: "auth-secret"
# ============================================================
# 应用 URL 配置
# ============================================================
app:
baseURL: "http://localhost"
trustedOrigins:
- "http://localhost"
# ============================================================
# Service 配置
# ============================================================
service:
type: ClusterIP
port: 80
containerPort: 3001
annotations: {}
# ============================================================
# Ingress 配置
# ============================================================
ingress:
enabled: false
className: ""
annotations: {}
hosts:
- host: developer-portal.local
paths:
- path: /
pathType: ImplementationSpecific
tls: []
# ============================================================
# 内置 PostgreSQL
# ============================================================
postgresql:
builtin: true
fullnameOverride: "developer-portal-fe-postgresql"
image:
registry: docker.io
repository: postgres
tag: "16"
auth:
username: portal
password: portal123
database: portal
primary:
persistence:
size: 10Gi
service:
ports:
postgresql: 5432
# ============================================================
# 通用配置
# ============================================================
imagePullSecret: ""
nameOverride: ""
fullnameOverride: ""
serviceAccount:
create: true
annotations: {}
name: ""
nodeSelector: {}
tolerations: []
affinity: {}5.3 Templates 清单
| 文件 | 说明 |
|---|---|
_helpers.tpl |
名称、标签、selector 等 helper 函数,遵循现有 chart 风格 |
configmap.yaml |
生成 config.yaml(敏感字段使用 ${ENV_VAR} 占位符) |
secret.yaml |
包含 portal.token、auth.secret、db.url(支持 existingSecret 时跳过创建) |
deployment.yaml |
Developer Portal FE Deployment |
service.yaml |
ClusterIP/NodePort/LoadBalancer Service |
ingress.yaml |
可选 Ingress |
serviceaccount.yaml |
可选 ServiceAccount |
NOTES.txt |
安装后提示信息 |
5.4 敏感数据策略
config.yaml 支持 ${VAR} 环境变量模板语法,因此采用以下策略:
- ConfigMap 中的 config.yaml 使用环境变量占位符:
# ConfigMap 中的 config.yaml
portal:
url: {{ .Values.portal.url }}
token: ${PORTAL_TOKEN}
db:
url: ${DB_URL}
auth:
secret: ${AUTH_SECRET}
app:
baseURL: {{ .Values.app.baseURL }}
trustedOrigins:
{{- toYaml .Values.app.trustedOrigins | nindent 4 }}- Secret 存储实际敏感值(
PORTAL_TOKEN、DB_URL、AUTH_SECRET) - Deployment 通过
envFrom.secretRef将 Secret 挂载为环境变量 - 支持
existingSecret引用外部管理的 Secret(Vault、Sealed Secrets 等)
5.5 Deployment 关键设计
containers:
- name: developer-portal-fe
image: "{{ image }}"
ports:
- containerPort: 3001
name: http
protocol: TCP
env:
- name: NODE_ENV
value: "production"
- name: PORT
value: "3001"
- name: HOSTNAME
value: "0.0.0.0"
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: "{{ if .Values.developerPortal.tlsRejectUnauthorized }}1{{ else }}0{{ end }}"
- name: PORTAL_TOKEN
valueFrom:
secretKeyRef:
name: {{ secret name }}
key: portal-token
- name: DB_URL
valueFrom:
secretKeyRef:
name: {{ secret name }}
key: db-url
- name: AUTH_SECRET
valueFrom:
secretKeyRef:
name: {{ secret name }}
key: auth-secret
volumeMounts:
- name: config
mountPath: /app/apps/site/config.yaml
subPath: config.yaml
livenessProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 10
readinessProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
volumes:
- name: config
configMap:
name: {{ fullname }}-config6. 安全考虑
| 项目 | 策略 |
|---|---|
| Portal Token | 存储在 Kubernetes Secret 中,支持 existingSecret 引用外部管理的 Secret |
| Auth Secret | 同上 |
| DB Password | 通过 db.url 连接字符串中包含,整个 URL 存储在 Secret |
| TLS | 支持 Ingress TLS 终结;支持 NODE_TLS_REJECT_UNAUTHORIZED 配置(仅开发环境) |
| PostgreSQL | 生产环境建议设 postgresql.builtin: false 使用外部托管数据库 |
7. 目录结构
charts/developer-portal-fe/
├── .helmignore
├── Chart.yaml
├── charts/ # postgresql subchart(helm dependency update 生成)
├── README.md
├── templates/
│ ├── _helpers.tpl
│ ├── configmap.yaml
│ ├── deployment.yaml
│ ├── ingress.yaml
│ ├── NOTES.txt
│ ├── secret.yaml
│ ├── service.yaml
│ └── serviceaccount.yaml
└── values.yaml
8. 实现步骤
- 创建
charts/developer-portal-fe/目录结构 - 编写
Chart.yaml和values.yaml - 编写
_helpers.tpl(参考现有 chart 的 helper 模式) - 编写
configmap.yaml(config.yaml 使用环境变量占位符) - 编写
secret.yaml(portal token, auth secret, db url;支持 existingSecret) - 编写
deployment.yaml - 编写
service.yaml - 编写
ingress.yaml - 编写
serviceaccount.yaml - 编写
NOTES.txt - 编写
.helmignore helm lint+helm template验证- 编写
README.md - 提交 PR 到 https://github.com/api7/api7-helm-chart
9. 已有参考资源
| 资源 | 路径/链接 | 用途 |
|---|---|---|
| 现有 api7 chart 的 developer-portal 模板 | charts/api7/templates/developer-portal-*.yaml |
参考模板风格和 helper 函数 |
| boilerplate 仓库的 K8s 示例 | dev-tools/devportal.yaml (GitHub) |
参考 ConfigMap + Deployment 结构 |
| Docker Compose 部署文档 | getting-started | 需求来源 |
| config.yaml.example | apps/site/config.yaml.example (GitHub) |
完整配置 schema |
10. 决策记录
| 决策点 | 决策 | 理由 |
|---|---|---|
| Chart 独立 vs 集成到 umbrella chart | 独立 chart | FE 和后端是不同的应用,有独立的数据库和生命周期 |
| 敏感数据注入方式 | 环境变量 + config.yaml 占位符 | 应用原生支持 ${VAR} 语法,无需额外工具 |
| PostgreSQL 依赖 | 可选内置 (bitnami subchart) | 开发/测试用内置,生产环境用外部数据库 |
| Chart 版本策略 | 独立版本(从 0.1.0 开始) | appVersion 跟随 Docker 镜像 tag |
| PostgreSQL 版本 | 16(跟随官方文档 Docker Compose 示例) | 文档示例使用 postgres:16 |
Reactions are currently unavailable