Ceph+K8s 中间件实战 | 第 14 天:K8s 部署 ClickHouse 列式数据库集群(Ceph RBD + 架构设计)

第 14/15 天

引言:为什么选择 ClickHouse 作为 OLAP 引擎?

ClickHouse 是由 Yandex 开源的列式数据库管理系统(Columnar DBMS),专为实时分析场景设计。它具备惊人的写入吞吐量和亚秒级查询响应能力,广泛应用于日志分析、用户行为分析、监控指标存储、广告投放统计等 OLAP 场景。

在云原生架构中,将 ClickHouse 部署到 Kubernetes 集群上,可以利用 K8s 的弹性伸缩和滚动升级能力简化运维。而 Ceph RBD 块存储则为 ClickHouse 的数据文件提供了高可靠、低延迟的持久化卷,确保即使在 Pod 重建或节点故障时数据也不丢失。

K8s Logo

本篇将使用 Bitnami 官方维护的 bitnami/clickhouse Helm Chart,在已接入 Ceph RBD 存储的 K8s 集群上部署一个多分片多副本的 ClickHouse 分布式集群,并配置 ClickHouse Keeper(内置的 ZooKeeper 协调组件)实现副本同步与高可用。

一、设计架构

1.1 ClickHouse 集群拓扑

ClickHouse 的分布式集群由分片(Shard)和副本(Replica)两个维度构成。本方案部署 2 分片 × 2 副本共 4 个 ClickHouse 节点,外加 3 个 ClickHouse Keeper 节点用于协调:

组件 角色说明 副本数 存储需求
ClickHouse Shard-1 Replica-1 分片1主副本 1 Ceph RBD 持久卷
ClickHouse Shard-1 Replica-2 分片1备用副本 1 Ceph RBD 持久卷
ClickHouse Shard-2 Replica-1 分片2主副本 1 Ceph RBD 持久卷
ClickHouse Shard-2 Replica-2 分片2备用副本 1 Ceph RBD 持久卷
ClickHouse Keeper 分布式协调服务 3 Ceph RBD 持久卷

1.2 数据流向

ClickHouse 的数据写入与查询流程如下:

💻 代码示例

客户端写入 → Distributed 表(路由分发)

→ 分片1: 本地表写入 → MerkleTree 同步 → 副本2

→ 分片2: 本地表写入 → MerkleTree 同步 → 副本2

 

查询请求 → Distributed 表 → 聚合各分片局部结果 → 合并返回

  • 写入:数据按分片键(如 hash() )分发到不同分片,每个分片写入主副本后异步同步到备用副本
  • 查询:Distributed 表将查询扇出到所有分片的本地表,各节点并行计算后汇总返回
  • 副本同步:ClickHouse Keeper 维护复制日志队列,副本通过拉取日志实现数据同步

1.3 高可用机制

高可用维度 实现方式
数据冗余 每个分片 2 副本,任一副本宕机不影响读写
协调服务 Keeper 3 节点 Raft 共识,容忍 1 节点故障
存储高可用 Ceph RBD 块存储多副本(OSD 级别冗余)
查询容错 Distributed 表自动跳过不可用副本
服务发现 K8s Headless Service + StatefulSet 稳定 DNS

1.4 存储规划

数据类型 StorageClass 卷大小 访问模式
ClickHouse 数据卷 ceph-rbd 100Gi ReadWriteOnce
Keeper 数据卷 ceph-rbd 10Gi ReadWriteOnce

ClickHouse 的列式压缩通常能达到 5-10 倍压缩比,100Gi 原始卷可存储约 500Gi-1Ti 的原始数据。

二、部署实战

2.1 添加 Bitnami Helm 仓库

💻 代码示例

# 添加 Bitnami Chart 仓库

helm repo add bitnami https://charts.bitnami.com/bitnami

helm repo update

 

# 查看 ClickHouse Chart 可用版本

helm search repo bitnami/clickhouse –versions | head -10

 

# 拉取默认 values 以便自定义

helm show values bitnami/clickhouse > /tmp/clickhouse-default-values.yaml

2.2 编写 values.yaml 自定义配置

以下 values.yaml 配置了 2 分片 2 副本的 ClickHouse 集群,存储指向 Ceph RBD StorageClass:

💻 代码示例

# /tmp/clickhouse-values.yaml

## ClickHouse 集群配置

##

shards: 2

replicaCount: 2

 

## ClickHouse 认证配置

##

auth:

username: "admin"

password: "ClickHouse@2026"

existingSecret: ""

 

## ClickHouse Keeper(内置协调服务,替代外部 ZooKeeper)

##

keeper:

enabled: true

replicaCount: 3

auth:

client:

enabled: false

persistence:

enabled: true

storageClass: "ceph-rbd"

accessModes:

– ReadWriteOnce

size: 10Gi

 

## ClickHouse 持久化存储(核心数据卷)

##

persistence:

enabled: true

storageClass: "ceph-rbd"

accessModes:

– ReadWriteOnce

size: 100Gi

 

## 资源限制(按需调整)

##

resources:

requests:

cpu: "1000m"

memory: "2Gi"

limits:

cpu: "4000m"

memory: "8Gi"

 

## Service 配置

##

service:

type: ClusterIP

ports:

http: 8123

tcp: 9000

mysql: 9004

 

## 集群配置(分布式表 DDL)

##

clickhouse:

configmap:

## 远程服务器定义(自动由 Chart 根据 shards/replicas 生成)

remote_servers: ""

 

## 日志级别

##

logging:

level: "information"

2.3 Helm 安装部署

💻 代码示例

# 创建独立命名空间

kubectl create namespace middleware

 

# 部署 ClickHouse 集群

helm install clickhouse bitnami/clickhouse

–namespace middleware

–version 6.2.0

–values /tmp/clickhouse-values.yaml

–timeout 10m

 

# 观察 Pod 启动过程

kubectl get pods -n middleware -w

部署完成后,各 Pod 应进入 Running 状态:

💻 代码示例

# 查看 ClickHouse 与 Keeper Pod 状态

kubectl get pods -n middleware -l app.kubernetes.io/instance=clickhouse

 

# 预期输出:

# NAME READY STATUS RESTARTS AGE

# clickhouse-shard0-0 1/1 Running 0 3m

# clickhouse-shard0-1 1/1 Running 0 3m

# clickhouse-shard1-0 1/1 Running 0 3m

# clickhouse-shard1-1 1/1 Running 0 3m

# clickhouse-keeper-0 1/1 Running 0 4m

# clickhouse-keeper-1 1/1 Running 0 3m

# clickhouse-keeper-2 1/1 Running 0 2m

2.4 验证 PVC 与 Service

💻 代码示例

# 查看持久化卷声明(应全部 Bound)

kubectl get pvc -n middleware -l app.kubernetes.io/instance=clickhouse

 

# 查看 Service

kubectl get svc -n middleware -l app.kubernetes.io/instance=clickhouse

 

# 查看 StatefulSet

kubectl get sts -n middleware -l app.kubernetes.io/instance=clickhouse

确认所有 PVC 状态为 Bound,且 StorageClass 为 ceph-rbd,说明 Ceph RBD 块存储已正确挂载。

三、登录验证

3.1 通过 Port-Forward 本地连接

💻 代码示例

# 转发 ClickHouse TCP 端口(原生协议 9000)

kubectl port-forward -n middleware svc/clickhouse 9000:9000 &

 

# 使用 clickhouse-client 连接

clickhouse-client –host 127.0.0.1 –port 9000

–user admin –password 'ClickHouse@2026'

–query "SELECT version()"

 

# 预期输出:24.x.x

3.2 验证集群拓扑

💻 代码示例

— 进入 clickhouse-client 交互模式

— kubectl exec -it -n middleware clickhouse-shard0-0 — clickhouse-client –user admin –password 'ClickHouse@2026'

 

— 查看集群分片与副本信息

SELECT

shard_num,

replica_num,

host_name,

port

FROM system.clusters

WHERE cluster = 'default';

 

— 预期输出:4 行(2 分片 × 2 副本)

3.3 创建分布式表测试读写

💻 代码示例

— 在每个分片创建本地表(使用 ReplicatedMergeTree 引擎)

CREATE TABLE IF NOT EXISTS events_local ON CLUSTER 'default'

(

event_time DateTime,

event_id UInt64,

user_id String,

event_type String

)

ENGINE = ReplicatedMergeTree(

'/clickhouse/tables/{shard}/events_local',

'{replica}'

)

PARTITION BY toYYYYMM(event_time)

ORDER BY (event_id, event_time);

 

— 创建分布式表(写入与查询的统一入口)

CREATE TABLE IF NOT EXISTS events_distributed ON CLUSTER 'default'

AS events_local

ENGINE = Distributed('default', 'default', 'events_local', rand());

 

— 插入测试数据

INSERT INTO events_distributed VALUES

(now(), 1, 'user_001', 'click'),

(now(), 2, 'user_002', 'view'),

(now(), 3, 'user_003', 'purchase');

 

— 查询验证

SELECT count() FROM events_distributed;

— 预期:3

 

— 验证各分片数据分布

SELECT

hostName() AS node,

count() AS rows

FROM events_distributed

GROUP BY node;

四、日常巡检命令

4.1 集群健康检查

💻 代码示例

# 检查所有 Pod 运行状态

kubectl get pods -n middleware -l app.kubernetes.io/instance=clickhouse

 

# 检查 Keeper 集群状态(Raft 共识)

kubectl exec -n middleware clickhouse-keeper-0 —

clickhouse-keeper-client –host clickhouse-keeper-0 –port 9181

–query "ruok"

# 预期:imok

 

# 检查 PVC 绑定状态

kubectl get pvc -n middleware | grep clickhouse

4.2 数据库内部巡检

💻 代码示例

# 一键巡检脚本

kubectl exec -it -n middleware clickhouse-shard0-0 —

clickhouse-client –user admin –password 'ClickHouse@2026' –multiquery << 'SQL'

— 1. 查看活跃副本同步状态

SELECT database, table, is_leader, is_readonly, is_session_expired

FROM system.replicas;

 

— 2. 查看合并队列积压

SELECT database, table, count() AS pending_merges

FROM system.merges

GROUP BY database, table;

 

— 3. 查看磁盘使用情况

SELECT

name,

path,

formatReadableSize(free_space) AS free,

formatReadableSize(total_space) AS total

FROM system.disks;

 

— 4. 查看最近慢查询

SELECT

query_duration_ms,

formatReadableSize(read_bytes) AS read_bytes,

substring(query, 1, 80) AS query

FROM system.query_log

WHERE type = 'QueryFinish'

ORDER BY query_duration_ms DESC

LIMIT 5;

SQL

4.3 日志查看与性能监控

💻 代码示例

# 查看 ClickHouse 服务日志

kubectl logs -n middleware clickhouse-shard0-0 –tail=50

 

# 查看 Keeper 日志

kubectl logs -n middleware clickhouse-keeper-0 –tail=30

 

# 查看 HTTP 接口指标(Prometheus 格式)

kubectl exec -n middleware clickhouse-shard0-0 —

curl -s http://admin:ClickHouse%402026@localhost:8123/metrics | head -20

4.4 容量与存储巡检

💻 代码示例

# 查看各分片数据分区大小

kubectl exec -n middleware clickhouse-shard0-0 —

clickhouse-client –user admin –password 'ClickHouse@2026'

–query "

SELECT

database,

table,

partition,

formatReadableSize(sum(bytes_on_disk)) AS size

FROM system.parts

WHERE active = 1

GROUP BY database, table, partition

ORDER BY size DESC

LIMIT 10

"

 

# 查看 Ceph RBD 卷的实际使用量

kubectl exec -n middleware clickhouse-shard0-0 — df -h /bitnami/clickhouse/data

五、常见问题

Q1: 副本同步延迟过大怎么办?

A: 首先检查 Keeper 集群是否健康(ruok 返回 imok)。然后查看 system.replicas 表中的 log_pointer 和 absolute_delay 字段——如果 absolute_delay 持续增大,说明副本拉取日志落后。可能原因:网络带宽不足、合并操作过多。解决方案:限制后台合并并发数 background_pool_size,或临时暂停大表的 OPTIMIZE 操作。

Q2: ClickHouse Pod 启动失败,日志报 “Too many parts”?

A: 这通常是因为之前频繁写入小 batch 导致 parts 碎片过多。解决方案:先调大 max_parts_in_total 参数(在 users.xml 或 profiles 中设置),待 Pod 启动后手动执行 OPTIMIZE TABLE table FINAL 合并 parts,然后恢复大批量写入策略(建议单次写入不少于 1000 行)。

Q3: Ceph RBD 卷 I/O 延迟高影响查询性能?

A: ClickHouse 对存储 I/O 极其敏感。排查步骤:①在 Ceph 侧检查对应 RBD image 所在 OSD 的负载与延迟;②确认 Ceph 池副本数不要过高(2 副本通常足够);③在 ClickHouse 配置中启用 cache 磁盘策略,将热点数据缓存到本地 NVMe;④对于超高频查询场景,考虑使用本地 PV + Ceph 备份的混合方案。

六、总结

本篇使用 Bitnami 官方 Helm Chart 在 K8s 上部署了 2 分片 × 2 副本的 ClickHouse 分布式列式数据库集群,配合 ClickHouse Keeper 实现副本自动同步,所有数据卷挂载到 Ceph RBD StorageClass 实现持久化高可用。关键要点回顾:

  1. 架构设计:ClickHouse 采用分片+副本的双维度扩展,分片实现水平扩展写入,副本实现数据冗余高可用
  2. Chart 部署:bitnami/clickhouse Chart 内置 Keeper,无需额外部署 ZooKeeper,一键完成集群搭建
  3. 存储规划:Ceph RBD 提供低延迟块存储,结合列式压缩可达 5-10 倍存储效率
  4. 验证巡检:通过 system.clusters、system.replicas、system.merges 等系统表全面掌控集群状态

下期预告

明天是本系列的收官之作——第 15 天:K8s 中间件统一监控与运维巡检总结(Prometheus + Grafana 全景)。我们将搭建统一的监控平台,将前面 13 篇部署的所有中间件(MySQL、Redis、MongoDB、Kafka、ClickHouse 等)指标统一接入 Prometheus + Grafana,构建完整的云原生中间件运维监控全景图。

系列目录

微信二维码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像 - 恒星
欢迎您留下宝贵的见解!
提交
头像 - 恒星

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容