教程·阅读约 2 分钟·
从零搭建 PlanetScale:基础设施篇

从零搭建 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 处理。

最终用户的操作流程大概是这样:

code
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 的数据库创建分支时,不需要复制任何数据——只需要元数据和后续差异部分的存储空间。

code
postgres-base (image) → dev-db (writable) → dev-db@feature-login (snapshot) → feature-login (writable)

Ceph RBD 实现

在块存储层,Ceph 的 RADOS Block Device(RBD) 提供了所需的所有原语。

RBD 镜像是分布在 RADOS 对象上的虚拟块设备(默认每个对象 4MB)。三个关键操作:

  1. Snapshot(快照) — RBD 镜像的只读时间点视图
  2. Clone(克隆) — 引用快照不可变数据的可写 RBD 镜像(Ceph 称之为 snapshot layering
  3. Protect(保护) — 快照被克隆后,需要保护防止被意外删除

直接操作 RBD 的流程:

code
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 — 定义存储后端

整个技术栈:

code
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: 3failureDomain: host 复制策略

Homescale 的 operator 使用相同的 reconciliation 逻辑,无论在什么规模下部署。

下一步:构建核心服务

基础设施层搭建完成后,接下来需要构建 Homescale 的实际服务:

  1. API — 接收 CLI 请求并协调资源
  2. Controllers — 管理数据库实例的生命周期
  3. Postgres Adapter — 初始化 Postgres 卷 → 捕获为不可变 VolumeSnapshot → 克隆快照 → 启动 Postgres → 返回连接信息

整个分支流程:

  1. 准备源容器进行快照(确保数据一致性)
  2. 创建中间状态快照
  3. 记录沿袭关系
  4. 启动新的可写容器

适合谁读

这篇文章适合对以下内容感兴趣的开发者:

  • 了解 PlanetScale 分支功能的内部原理
  • 想在自己的基础设施上搭建类似服务
  • 对 Ceph RBD 和 Kubernetes VolumeSnapshot 的实际应用感兴趣
  • 正在设计数据库即服务(DBaaS)平台

参考

分享到
微博Twitter

© 2026 四月

原文链接:https://www.aprilzz.com/tutorials/building-planetscale-from-scratch-infrastructure