可观测性数据落进对象存储:Proscia 案例拆解与 ClickHouse 自托管配置

SaaS 可观测性平台的按量计费,痛点从来不是单价,是数据量涨上去之后那句"要不要限制保留期"。多数团队的日志和指标只留 15 天,不是不想留,是留不起。

AWS 存储博客上个月发了一个案例,讲病理 AI 公司 Proscia 怎么把自托管可观测性跑起来的。数字值得一看:遥测数据保留从 15 天改成无限期,每月记录量从约 24 亿涨到约 337 亿,存储成本反而从每 TB 500 美元以上降到 5 美元左右。在超过 25 TB 的数据上,部分查询的 p95 延迟刚过 250 毫秒。

这类案例文容易读成"AWS 又秀肌肉"。但把架构拆开看,真正扛住成本的不是哪朵云,是两个通用设计:ClickHouse 用 TTL 把冷数据卸到对象存储,clickhouse-backup 把备份也压到对象存储上。这两个设计不绑定任何云,自托管侧可以原样复刻。这篇就把这两块配一遍,对象存储用 RustFS。

Proscia 搭了什么

Proscia 的数字病理平台要处理千兆像素级医学影像,客户里有前 20 大制药公司中的 16 家,接入的实验室每年处理约 1200 万患者病例。这套可观测性系统跑了 10 多个 K8s 集群、550 多个节点,6 个月从验证走到生产。

架构用一句话概括:应用通过 OpenTelemetry 上报日志、指标和 span,经三层 Collector 汇到 ClickHouse 集群;ClickHouse 用 Altinity 的 Kubernetes Operator 管理,单 shard 三副本跨可用区,配三节点 ClickHouse Keeper 做共识;查询和告警走 Grafana。

跟存储有关的是两条链路:

热冷分层。 数据先落本地 SSD,TTL 规则到期后自动移到 S3。官方给出的整体压缩比是 40:1------这是 ClickHouse 列存加编码的功劳,不是换存储换出来的,后面还会说到这点。

备份。 用 clickhouse-backup 工具把全量和增量备份写到 S3,做灾难恢复。

至于跨账户 IAM、Cognito 联合身份、KMS 这些云专属件,自托管场景各有等价物,不在本文展开。

起一个桶

对象存储这块,自托管用 RustFS 就一行 docker 命令的事,按官方文档:

bash 复制代码
docker run -d \
  --name rustfs \
  --restart unless-stopped \
  -p 9000:9000 \
  -p 9001:9001 \
  -v rustfs-data:/data \
  -e RUSTFS_ACCESS_KEY="<your-access-key>" \
  -e RUSTFS_SECRET_KEY="<your-secret-key>" \
  -e RUSTFS_ADDRESS=":9000" \
  -e RUSTFS_CONSOLE_ADDRESS=":9001" \
  -e RUSTFS_CONSOLE_ENABLE=true \
  rustfs/rustfs:latest \
  /data

建两个桶,一个放冷数据,一个放备份:

bash 复制代码
export AWS_ACCESS_KEY_ID=<your-access-key>
export AWS_SECRET_ACCESS_KEY=<your-secret-key>
aws --endpoint-url http://<rustfs-host>:9000 s3 mb s3://clickhouse-cold
aws --endpoint-url http://<rustfs-host>:9000 s3 mb s3://clickhouse-backup

两个桶都不要叠 lifecycle expiration 规则:冷数据桶里的对象由 ClickHouse 自己删(part 过期移除时连远端对象一起删),备份桶由 clickhouse-backup 的保留策略管。外部规则再插一手,等于两套删除逻辑抢方向盘。

数据面:S3 disk 与 TTL

ClickHouse 的存储策略机制允许一块表的数据分散在多块盘上,S3 兼容存储可以直接声明成一块盘。在 config.d 下的配置文件里写:

xml 复制代码
<storage_configuration>
    <disks>
        <local>
            <path>/var/lib/clickhouse/disks/local/</path>
        </local>
        <s3_cold>
            <type>s3</type>
            <endpoint>http://<rustfs-host>:9000/clickhouse-cold/data/</endpoint>
            <access_key_id><your-access-key></access_key_id>
            <secret_access_key><your-secret-key></secret_access_key>
        </s3_cold>
    </disks>
    <policies>
        <hot_cold>
            <volumes>
                <hot>
                    <disk>local</disk>
                </hot>
                <cold>
                    <disk>s3_cold</disk>
                </cold>
            </volumes>
            <move_factor>0.1</move_factor>
        </hot_cold>
    </policies>
</storage_configuration>

几个容易理解偏的地方:

endpoint 里要包含桶名和根路径,官方示例和惯例都带尾斜杠;ClickHouse 按 path-style 寻址,这对自托管端点是天然匹配的。

move_factor 是空间触发,不是时间触发。 默认 0.1 的含义是:本地盘剩余空间低于 10% 时,后台才开始把 part 按大小从大到小往下一个 volume 搬。它不负责"数据满 7 天就搬",那是 TTL 的职责,两者是互补关系。示例里显式写 0.1 只是为了把行为写明白。

TTL 在后台 merge 时评估,不是插入时逐行判断,所以 TTL 表达式只能用确定性的列值。表这么建:

sql 复制代码
CREATE TABLE logs
(
    ts DateTime,
    service LowCardinality(String),
    message String
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(ts)
ORDER BY ts
TTL ts + INTERVAL 7 DAY TO VOLUME 'cold'
SETTINGS storage_policy = 'hot_cold'

已有表用 ALTER TABLE ... MODIFY TTL 改规则,用 ALTER TABLE ... MODIFY SETTING storage_policy 换策略,注意换策略时新策略必须包含原来的磁盘和同名 volume,否则改不动。

还有两个开关值得知道:perform_ttl_move_on_insert 默认会让插入时就已过期的 part 立刻往慢速目标搬,写入高峰期可以禁掉它避免拖慢插入;排查数据落在哪块盘时,看 system.parts 的 disk_name 列,后台搬动在 system.part_log 里对应 MovePart 事件类型。想手动搬,ALTER TABLE ... MOVE PART ... TO VOLUME 'cold' 随时可用。

备份面:clickhouse-backup

工具选型不用纠结,Proscia 用的就是社区里事实标准的 clickhouse-backup,当前版本 v2.8.3。工作原理是对本地 part 做硬链接快照再流式压缩上传,所以它必须跟 clickhouse-server 跑在同一台主机或同一个 Pod 里,只支持 MergeTree 家族的表(22.7 以上配 USE_EMBEDDED_BACKUP_RESTORE=true 可支持更多表类型)------这两条对可观测性场景都不算限制。

/etc/clickhouse-backup/config.yml 核心就三段:

yaml 复制代码
general:
  remote_storage: s3
  backups_to_keep_remote: 3

clickhouse:
  username: default
  password: "<your-password>"

s3:
  access_key: "<your-access-key>"
  secret_key: "<your-secret-key>"
  bucket: clickhouse-backup
  endpoint: http://<rustfs-host>:9000
  path: clickhouse
  region: us-east-1
  force_path_style: true

force_path_style 打开后走 path-style 寻址,别让 SDK 拿桶名去拼虚拟主机域名,自托管端点基本都要开。backups_to_keep_remote: 3 让远端自动滚动保留最近 3 份备份,桶里不会无限堆积。压缩格式默认 tar,想要更高的压缩比可以换成 zstd。

日常就三条命令:

bash 复制代码
clickhouse-backup create_remote   # 本地建快照并直传
clickhouse-backup list remote     # 看远端有哪些备份
clickhouse-backup restore_remote  # 恢复:下载并 ATTACH 回来

不想手点的话,watch 子命令能定时跑增量加全量混合备份,调度方式二选一:固定间隔配 watch_interval 和 full_interval,或者 cron 配 watch_schedules(命令行写法 --schedule=name=...,full=<cron>,increment=<cron>),README 明确标注两种方式互斥,别一起配。

一个安全细节顺带提一句:/var/lib/clickhouse/backup 目录里是硬链接,权限动一下可能连坐正在使用的数据文件,运维清理时别碰这个目录的权限。

和案例的差距在哪

诚实说三件事,免得照抄之后期望错位。

40:1 的压缩比别归功给对象存储。 那是 ClickHouse 列存加编码算法的收益,数据落在本地盘还是对象存储都一样。自托管方案的成本优势来自"压缩后体积小 + 对象存储单价低"的乘积,两半都成立,但没有哪一半是魔法。

案例里的云侧组件要自己找等价物。 跨账户隔离对应网络分段加最小权限的访问密钥,KMS 加密对应自托管端的 SSE 想法(RustFS 支持 SSE-S3、SSE-C 和 SSE-KMS),Athena 直查 Iceberg 导出对应 RustFS 内置的 S3 Tables 能力(官方文档标注目前为预览功能,客户端兼容性限于文档列出的工作流,排期前先核对)。对齐得起来,但每一项都是要动手配的活,不是开箱即得。

那组数字是 Proscia 规模的个案。 每月 337 亿条记录、每 TB 5 美元的月成本,前提是他们有自己的运维投入和数据规模摊薄。自托管省的是按量计费的溢价,付的是运维工时,这笔账每个团队要自己算。

值不值得照抄

案例文末给了三条自建的前提:有能运维 K8s 有状态系统的团队、需要长期甚至无限期保留遥测数据、希望对整个管线有完全控制。原文的判断很干脆:三条都满足,自建才成立;占不全,就走混合方案,一部分留在托管服务上,自建只做真正需要控制的那一段。

我的看法是,这套架构里对象存储是最薄的一层:热冷分层和备份两件事,ClickHouse 和 clickhouse-backup 把机制都做好了,对象存储只需要老老实实做一个 S3 兼容的持久层。RustFS 单二进制部署加 S3 全兼容,把这一层补上的成本很低,剩下的决定权在你们团队手里。

相关推荐
SL_staff44 分钟前
制造订单交付闭环实践:用跨部门计划模板解决缺料-停机-返工三角死循环
java·开源·产品
方便面不加香菜1 小时前
Docker Image-- 镜像命令详解与使用示例
运维·docker·容器
日日大王学编程2 小时前
deerflow-memory-design-blog
python·langchain·开源
天远API2 小时前
零信任架构实战:基于天远劳动仲裁信息查询构建自动化灵活用工劳务派遣人员准入背调网关
运维·人工智能·架构·自动化
fb_123452 小时前
K8s动态卷供应实战_StorageClass与LocalPath_NFS双Provisioner
云原生·容器·kubernetes
miofly2 小时前
MIT 团队用 GPT-6 Astra 改写小模型权重,跳过梯度训练提升指令遵循能力
开源·github
程序员大雄学编程2 小时前
Linux 磁盘满了怎么排查?df / du / find 三步定位大文件
linux·运维·php
AI日报派送佬2 小时前
2026年11月02日 AI 行业日报|商汤开源 Loop-9B、Pika 发布 H3 Flex 音视频模型、Meta× 傅利叶推出人形机器人 Max
人工智能·微软·开源·音视频·openai·1024程序员节·ai日报
Bruce_Liuxiaowei2 小时前
前端校验登录态,等于没校验——一次应急广播终端高危漏洞的发现与报送
运维·前端·安全