Serverlessdb实例预热池管理和实例生命周期管理组件
ServerlessDB Operator
面向短生命周期、突发负载场景的 Serverless 数据库管控面 Operator。基于 Kubernetes Operator 扩展机制,维护预热数据库实例资源池,对外提供 REST 接口支持数据库计算实例的按需申请、释放与垂直扩缩容,并通过 Headless Service 保证连接地址在实例释放/重新申请后保持不变。
详细架构设计见 docs/ARCHITECTURE.md,设计提案见 docs/ofep-0056-Serverless DB Operator.md。
背景与动机
传统数据库基于长期稳态负载设计,而 Serverless 场景下数据库实例生命周期短(几分钟到几十分钟)、负载突发且不可预测,需要数据库扩缩容转变为运行时能力:按需创建、自动扩展、空闲释放。本 Operator 构建管控面能力,使数据库实例在 K8s 生态中实现快速启动与连接地址保持不变。
核心能力
- 预热资源池:通过
DBResourcePoolCR 维护指定数量/规格的预热 DB 实例,Reconciler 自动调谐补齐。 - 毫秒级申请:申请实例仅做 label/status 变更,从预热池中秒级分配,无需冷启动。
- 连接地址不变:每个
app_ref对应一个 Headless Service,实例释放后 DNS 地址保留,重新申请可复用。 - 垂直扩缩容:基于 K8s 1.32
Pod /resize子资源实现原地垂直扩缩容(无需重建 Pod)。 - 多租户认证鉴权:使用调用方 Bearer Token 透传 K8s API Server 认证,并通过
SelfSubjectRulesReview校验租户对目标 namespace 的 RBAC 权限。 - 高可用:基于 K8s Lease 选主,主故障自动切换备实例。
- 孤儿 Service 清理:定期清理无 backing Pod 且超过 TTL 的 Headless Service。
架构概览
graph LR
Admin["集群管理员"] -->|下发 DBResourcePool CR| OP["ServerlessDB Operator"]
OP -->|调谐创建 Pod/DBInstance| K8s["K8s API Server"]
K8s --> Warm["预热实例池 (WarmReady)"]
Client["DB Manager / 上层服务"] -->|REST 申请/释放/扩缩容| OP
OP -->|匹配预热实例 + label 关联| Warm
OP -->|创建/复用 Headless Service| K8s
App["业务应用"] -->|Service 域名连接| K8s
Operator 进程内同时运行两个组件(cmd/main.go):
- Controller Manager(controller-runtime):运行
DBResourcePoolReconciler,调谐资源池与实例状态。 - Gin HTTP Server:对外暴露 REST API,通过
TokenCache做认证鉴权后调用K8sInstanceService处理请求。
自定义资源 (CRD)
API Group:serverlessdb.openfuyao.cn/v1
DBResourcePool
数据库实例预热资源池,定义期望的实例数量、PG 版本与 Pod 模板。
apiVersion: serverlessdb.openfuyao.cn/v1
kind: DBResourcePool
metadata:
name: pool-small
namespace: serverlessdb
spec:
replicas: 5 # 维护的实例总数 (warm + allocated)
minAvailable: 2 # 最小预热可用实例数
pgVersion: 17 # PostgreSQL 主版本 (16 | 17)
controlPlaneUrl: "http://control-plane:8080"
podTemplate: # 完整 Pod 模板,compute 容器的资源用于池匹配
metadata:
labels:
app: compute
spec:
containers:
- name: compute # 第一个容器必须命名为 compute
image: "cr.openfuyao.cn/openfuyao/compute/compute:v17.4"
resizePolicy:
- resourceName: cpu
restartPolicy: NotRequired
- resourceName: memory
restartPolicy: NotRequired
ports:
- name: pg
containerPort: 5432
resources:
requests: { cpu: "1000m", memory: "1Gi" }
limits: { cpu: "2000m", memory: "2Gi" }
状态字段:totalInstances / warmInstances / availableInstances / allocatedInstances / labelSelector。支持 /scale 子资源。
DBInstance
单个数据库计算实例,由 Operator 在扩容时自动创建(通常无需用户直接管理)。
.status.phase |
含义 |
|---|---|
WarmReady |
预热就绪,待分配 |
Running |
已分配给某 app_ref,运行中 |
Scaling |
垂直扩缩容进行中 |
WakingUp |
Pod 启动中 |
Hibernated |
休眠 |
Failed |
异常 |
HTTP API
所有接口需在 Authorization 头携带 Bearer Token,并通过 namespace 查询参数指定目标命名空间。Operator 透传 Token 至 K8s API Server 完成认证,并校验该 Token 在目标 namespace 下对所需资源的 RBAC 权限。
申请实例
POST /api/v1/instances?namespace=serverlessdb
Authorization: Bearer <token>
{
"app_ref": "app1",
"pg_version": 17,
"resources": { "cpu": "1000m", "memory": "1Gi" }
}
响应 200:
{
"endpoint": "app1.serverlessdb.svc.cluster.local:5432",
"pod_name": "pool-small-abc12",
"pod_id": "4b295d49-7886-4dc7-a4b1-528886c5eb97"
}
释放实例
DELETE /api/v1/instances/app1?namespace=serverlessdb
Authorization: Bearer <token>
响应 204。删除 DBInstance CR(Pod 随 ownerRef 级联删除),Headless Service 保留以便复用连接地址。
垂直扩缩容
PATCH /api/v1/instances/app1?namespace=serverlessdb
Authorization: Bearer <token>
{
"containers": [
{ "name": "compute", "resources": { "cpu": "2000m", "memory": "2Gi" } }
]
}
Operator 在 DBInstance 上写入 resize-spec 注解并置 phase=Scaling,Reconciler 通过 pods/resize 子资源提交原地扩缩容请求,完成后恢复 Running。
错误码
| HTTP | 含义 |
|---|---|
| 400 | 请求参数非法 / 无匹配资源池 |
| 401 | Token 认证失败 |
| 403 | Token 鉴权失败(RBAC 不足) |
| 404 | 实例不存在 / 无可用预热实例 |
| 409 | 该 app_ref 已分配实例 |
部署
前置要求
- Kubernetes ≥ 1.32(需启用 Pod 原地垂直扩缩容特性以使用
/resize) - Helm 3
Helm 安装
# 1. 构建并推送镜像(见下方「构建」小节)
# 2. 安装 Chart
helm install serverlessdb-operator ./build/chart \
--set namespace=serverlessdb \
--set image.registry=<your-registry> \
--set image.repository=serverlessdb-operator \
--set image.tag=1.0.0
Chart 包含:CRD(dbresourcepool / dbinstance)、Deployment、ServiceAccount、ClusterRole/ClusterRoleBinding。可在 build/chart/values.yaml 中调整端口、选主参数、资源、TTL、QPS 等。
客户端证书认证(可选)
默认使用集群内 ServiceAccount Token。若需以客户端证书方式认证 Operator 与 API Server 的通信,设置:
clientCert:
enabled: true
secretName: "operator-tls"
certPath: /etc/serverlessdb/tls/tls.crt
keyPath: /etc/serverlessdb/tls/tls.key
username: "serverlessdb-operator" # 或 group,用于绑定 ClusterRole
调用方 RBAC 授权
上层 DB Manager 需持有目标 namespace 下对以下资源的权限,Operator 才能以该 Token 完成操作:
serverlessdb.openfuyao.cn组:dbinstances的 get/list/patch/delete、dbinstances/status的 patch- 核心 API:
pods的 get/patch、pods/resize的 patch、services的 get/create/delete
配置参数
Operator 启动参数(见 internal/config/config.go):
| 参数 | 默认值 | 说明 |
|---|---|---|
--gin-port |
8080 | REST API 端口 |
--metrics-port |
8081 | Prometheus 指标端口 |
--health-port |
8082 | 健康探针端口 (/healthz, /readyz) |
--log-file |
/var/log/serverlessdb/serverlessdb-operator.log |
日志文件路径 |
--leader-election |
true | 是否启用选主 |
--leader-election-id |
serverlessdb-operator.openfuyao.cn |
选主 Lease ID |
--lease-duration |
15s | Lease 时长 |
--renew-deadline |
10s | 续约截止 |
--retry-period |
2s | 重试周期 |
--service-ttl |
30m | 孤儿 Service 清理 TTL,0 表示禁用 |
--token-cache-ttl |
5m | Token 客户端与鉴权结果缓存时长 |
--tenant-client-qps |
100 | 单租户 K8s 客户端 QPS |
--tenant-client-burst |
200 | 单租户 K8s 客户端突发 |
--client-cert / --client-key |
空 | 客户端证书认证(可选) |
构建
# 本地编译
go build -o bin/serverlessdb-operator ./cmd
# 构建单架构 Docker 镜像
REGISTRY=<your-registry> TAG=1.0.0 ./build/build.sh
# 构建多架构 manifest(需先分别构建并 push 各架构镜像)
REGISTRY=<your-registry> TAG=1.0.0 ./build/build.sh manifest
支持 linux/amd64 与 linux/arm64。
开发
目录结构
api/v1/ # CRD 类型定义 (DBResourcePool, DBInstance) 与 deepcopy
cmd/main.go # 入口:启动 Manager + Gin Server
internal/
cache/ # PoolCache:资源池/实例内存缓存与 Allocate 分配逻辑
config/ # 启动参数解析与校验
controller/ # DBResourcePoolReconciler、Pod 构建、谓词
handler/ # Gin 路由与 HTTP handler、认证中间件
service/ # InstanceService:Create/Delete/Resize 业务编排
token/ # TokenCache:多租户 Token 认证鉴权缓存
types/ # 请求/响应类型与校验器
build/
chart/ # Helm Chart (CRD, Deployment, RBAC, values)
Dockerfile
build.sh # 多架构镜像构建脚本
docs/ # 架构文档、OFEP 提案、Swagger
运行测试
go test ./...
技术栈
- Go 1.26
- controller-runtime v0.21(K8s v0.33)
- Gin v1.10
- pflag、errgroup、validator/v10、
log/slog+logr