
从零搭建 PlanetScale:基础设施篇
用 Ceph RBD 和 Kubernetes 实现数据库分支与快照克隆的完整架构
原文来源:Let's Build PlanetScale from Scratch: Infrastructure — 用 Ceph RBD 的写时复制(COW)功能,在自家服务器上搭建类似 PlanetScale 的数据库分支服务
数据库分支——像 Git 分支一样创建数据库副本——是 PlanetScale 最让人印象深刻的功能。开发者可以秒级创建一个完整数据库的独立副本,在上面改 schema、跑迁移,用完就删,完全不影响主库。
但 PlanetScale 是商业产品,不开源。如果你想在自己的服务器上搭一套类似的呢?
这就是 Homescale 项目在做的事:用 Ceph RBD 的写时复制(Copy-on-Write)和 Kubernetes 编排,从零搭建一套数据库分支系统。
核心思路:把 Docker 的镜像/容器模型搬到数据库上
Homescale 的核心抽象借鉴了 Docker:
- Image(镜像) — 一个不可变的数据库快照,相当于启动起点
- Container(容器) — 从镜像创建的可写数据库实例
- Branch(分支) — 从现有容器当前状态创建的新可写实例
这套模型是数据库无关的——只要数据库引擎把持久化状态保存在块存储文件系统上,就能工作。引擎特定的初始化、恢复和快照逻辑由 adapter 处理。
最终用户的操作流程大概是这样:
homescale image create --engine postgres postgres-base
homescale container create --image postgres-base dev-db
homescale container connect dev-db
homescale branch create --container dev-db feature-login
homescale container connect feature-login—— 广告 ——
存储架构:计算与存储分离
关键架构决策是把存储和计算分开。数据库进程读写的是一个块设备上的文件系统,这个块设备的生命周期独立于进程。
分支发生在存储层,数据库引擎完全不知道自己在被分支。这避免了引擎级的分支逻辑——不需要懂 Postgres 或 MySQL 的内部机制。
写时复制(COW)
写时复制是实现高效克隆的关键:
- 新容器初始时与父容器共享所有数据
- 写入的数据只存储在子容器中
- 未修改的数据仍然从父容器读取
一个 100GB 的数据库创建分支时,不需要复制任何数据——只需要元数据和后续差异部分的存储空间。
postgres-base (image) → dev-db (writable) → dev-db@feature-login (snapshot) → feature-login (writable)
Ceph RBD 实现
在块存储层,Ceph 的 RADOS Block Device(RBD) 提供了所需的所有原语。
RBD 镜像是分布在 RADOS 对象上的虚拟块设备(默认每个对象 4MB)。三个关键操作:
- Snapshot(快照) — RBD 镜像的只读时间点视图
- Clone(克隆) — 引用快照不可变数据的可写 RBD 镜像(Ceph 称之为 snapshot layering)
- Protect(保护) — 快照被克隆后,需要保护防止被意外删除
直接操作 RBD 的流程:
rbd snap create homescale/dev-db@feature-login
rbd snap protect homescale/dev-db@feature-login
rbd clone homescale/dev-db@feature-login homescale/feature-login在 Homescale 中,这整个序列被抽象成一条 homescale branch create 命令。
Ceph 架构速览
Ceph 的对象存储层(RADOS)通过在 OSD(每个磁盘对应一个 OSD)上分布对象来实现高可用。对象 → 归置组(Placement Groups)→ OSD,没有中央对象表。Pool 定义了复制策略(副本数和 CRUSH 规则)。
Kubernetes 控制平面
Homescale 不直接管理进程或挂载点。它通过 Kubernetes 资源抽象所有操作:
- PVC(PersistentVolumeClaim)— 声明存储
- VolumeSnapshot — Kubernetes 的快照 API
- StorageClass — 定义存储后端
整个技术栈:
Homescale CLI → Homescale API → Kubernetes (PVCs, VolumeSnapshots)
→ Ceph CSI → RBD 操作
→ Rook → Ceph 守护进程
其中 Ceph CSI 将 Kubernetes 存储资源转换为 RBD 操作,Rook 负责运维 Ceph 集群(管理 CephCluster、CephBlockPool、OSD)。
部署规模
| 环境 | 配置 |
|---|---|
| 本地开发 | 单节点 Kubernetes(Colima/Lima),一个 OSD |
| 生产环境 | 多节点 Talos 集群,独立 Ceph 节点池;size: 3,failureDomain: host 复制策略 |
Homescale 的 operator 使用相同的 reconciliation 逻辑,无论在什么规模下部署。
下一步:构建核心服务
基础设施层搭建完成后,接下来需要构建 Homescale 的实际服务:
- API — 接收 CLI 请求并协调资源
- Controllers — 管理数据库实例的生命周期
- Postgres Adapter — 初始化 Postgres 卷 → 捕获为不可变 VolumeSnapshot → 克隆快照 → 启动 Postgres → 返回连接信息
整个分支流程:
- 准备源容器进行快照(确保数据一致性)
- 创建中间状态快照
- 记录沿袭关系
- 启动新的可写容器
适合谁读
这篇文章适合对以下内容感兴趣的开发者:
- 了解 PlanetScale 分支功能的内部原理
- 想在自己的基础设施上搭建类似服务
- 对 Ceph RBD 和 Kubernetes VolumeSnapshot 的实际应用感兴趣
- 正在设计数据库即服务(DBaaS)平台
参考
© 2026 四月
原文链接:https://www.aprilzz.com/tutorials/building-planetscale-from-scratch-infrastructure