开源自托管GitOps平台OpenRun这周把Litestream复制能力直接塞进了平台内核:给SQLite应用的数据库文件持续同步到AWS S3或Cloudflare R2、MinIO这类兼容对象存储,一旦检测到应用卷为空或被重建,启动前自动从副本拉回数据。Docker、Podman和Kubernetes用同一套配置,开发者不用装Litestream、不用改镜像、不用自己写恢复脚本。
这确实省事。但把"自动复制+自动恢复"读成"SQLite现在生产级了",是把配置自动化和架构突破混在了一起——Litestream的单活跃写入节点模型一寸都没变,OpenRun只是把这道坎藏得更深。
一套配置,两种落地方式
在openrun.toml里把Litestream配置写一次,给SQLite服务和应用绑定后就能用,新应用接入不需要任何Litestream专属设置。openrun apply走的是GitOps路数,像Kubernetes apply一样只改变化的部分。
真正的差异藏在运行时。Docker/Podman上,每个SQLite应用配一个Litestream伴生容器共享数据卷,应用启动前先跑恢复容器把副本拉回来;Kubernetes上换成恢复init容器+原生Litestream sidecar,而sidecar这个特性要求集群跑在Kubernetes 1.29及以上版本——这是一条容易被忽略的版本门槛。OpenRun自己的元数据库和审计数据库也能复制,因为Litestream被直接嵌进了Go二进制,不用额外起进程。
一秒钟窗口是估算,不是承诺
sync_interval默认1秒,是Litestream给出的一个近似值,意思是灾难性崩溃后大概会丢失最近一秒还没同步到对象存储的写入。这句话的关键词是"大概"。复制本身是异步的,如果那一刻S3恰好不可达,或者进程在同步前被强杀,丢的可能不止一秒。
openrun replication status能看到healthy、pending、error这些状态,解决的是"事后能不能发现问题",不是"事前能不能防止问题"。这条命令值得所有跑SQLite应用的团队养成习惯性查看,但它改变不了复制的异步本质。
没解决的老问题:写入还是只能有一个
Litestream官方文档写得很清楚:SQLite必须跑在WAL模式下,不能放在NFS或SMB这类锁语义不可靠的文件系统上;手动执行VACUUM、手动checkpoint、或者在Litestream运行时直接跑restore覆盖数据,都可能悄悄弄坏复制链。OpenRun把这些细节全部藏在平台层背后,开发者省心,但一旦踩中,排查起来会变成一个新的黑箱——你甚至不知道该往哪个方向查。
更根本的一条:Kubernetes上绑定了SQLite的OpenRun应用只能跑单副本,更新策略强制用Recreate,防止多个Pod同时写同一个数据卷。这不是OpenRun的疏漏,是SQLite本身从来不支持多写入节点水平扩展的老账——Litestream解决的是"数据丢了能不能找回来",不是"能不能多个节点同时写"。
自动化配置的便利,不该被读成架构天花板已经消失。
- 风险.单副本加Recreate更新策略意味着应用升级或扩缩容时会有一段服务中断窗口,被平台自动化盖住之后容易被低估。
跟Fly.io原生托管Litestream、Turso/libSQL的多写复制、或者干脆上一套Postgres加Operator比,OpenRun+Litestream的定位始终清楚:轻量、单写入、异地容灾,不是分布式集群的替代品。对内部工具和小型自托管应用的独立开发者,这套东西是实打实减负;真正需要多写扩展或强一致性的场景,该换的还是要换,别被"看起来已经生产级"迷惑。
