WEBKT

日均百亿级:基于 ClickHouse 的 eBPF 安全日志存储与高并发检索架构演进实践

10 0 0 0

当安全审计的粒度下沉到内核级(eBPF),系统吞吐量会迎来指数级爆发。一次普通的内核态系统调用捕获(如 sys_enter_execvesys_enter_connect),在百万级 QPS 的 Kubernetes 集群中,会产生每秒数十万条的结构化安全日志。

传统的 ELK (Elasticsearch) 架构在此类场景下,常因写入放大严重、全文索引开销巨大而导致机器成本失控。ClickHouse 凭借其列式存储引擎与极强的向量化执行能力,成为承载 eBPF 海量安全日志的黄金选择。但在高并发检索、实时告警与 PB 级存储的实际生产中,若没有合理的架构设计与调优,ClickHouse 极易被高频写入压垮,或在并发查询时遭遇 CPU 耗尽。

本文将分享一套经过生产验证的 基于 ClickHouse 的 eBPF 安全日志海量存储与高并发检索架构方案


一、 系统架构蓝图

整套数据链路遵循 “轻量采集 -> 削峰聚合 -> 极速写入 -> 分层检索” 的原则。

+------------------+     +---------------+     +--------------------+
| K8s Nodes        |     | Kafka Cluster |     | Flink / Vector     |
| (Tetragon/eBPF)  | --> | (Ingress Log) | --> | (Enrich & Batch)   |
+------------------+     +---------------+     +--------------------+
                                                          | (Batch HTTP)
                                                          v
                                               +--------------------+
                                               | chproxy / LB       |
                                               +--------------------+
                                                          |
                                      +-------------------+-------------------+
                                      |                                       |
                                      v                                       v
                             +-----------------+                     +-----------------+
                             | ClickHouse Shard1|                    | ClickHouse Shard2|
                             |  (MergeTree)    |                     |  (MergeTree)    |
                             +-----------------+                     +-----------------+
  1. 采集层 (Data Collection):使用基于 eBPF 的安全工具(如 Cilium Tetragon 或自研 eBPF Probe)监控进程行为、文件读写、网络连接等,以 JSON / Protobuf 格式输出。
  2. 缓冲层 (Queueing):Kafka 承载高并发写入,提供削峰填谷能力。
  3. 清洗与分批层 (Ingress Pipe):使用 Vector 或 Flink 消费 Kafka 数据,进行元数据补全(例如将 Pod IP 转化为 PodName、Namespace、Owner 等 K8s 标签),并保证单次写入 ClickHouse 的 Batch 大小在 10万条以上时间窗口达到 5-10 秒
  4. 路由与查询代理 (Proxy):使用 chproxy 进行查询限流、合并和路由,保护后端 ClickHouse 集群不被高并发查询击垮。

二、 ClickHouse Schema 极致优化设计

eBPF 安全日志字段多、基数大,包含大量长字符串(如进程路径、命令行参数、K8s 标签)。如果采用默认建表配置,存储空间和检索性能将大打折扣。

1. 生产级 DDL 模板

以下是一个针对 eBPF 进程执行行为日志(Process Exec Events)深度优化后的表结构设计:

CREATE TABLE security_audit.ebpf_process_log_local ON CLUSTER cluster_3shards_2replicas
(
    -- 1. 时间与基础元数据(DoubleDelta+LZ4 极度压缩时间戳)
    event_time DateTime64(3, 'Asia/Shanghai') CODEC(DoubleDelta, LZ4),
    event_type LowCardinality(String) CODEC(ZSTD(1)),
    trace_id String CODEC(ZSTD(1)),
    
    -- 2. 进程上下文(整型使用 T64 / DoubleDelta 压缩)
    pid UInt32 CODEC(T64, ZSTD(1)),
    ppid UInt32 CODEC(T64, ZSTD(1)),
    tgid UInt32 CODEC(T64, ZSTD(1)),
    uid UInt32 CODEC(T64, ZSTD(1)),
    user_name LowCardinality(String) CODEC(ZSTD(1)),
    
    -- 3. 进程核心载荷(高频查询列使用 LowCardinality 降低字典基数)
    proc_name LowCardinality(String) CODEC(ZSTD(1)),
    binary_path String CODEC(ZSTD(3)),
    arguments String CODEC(ZSTD(3)),
    
    -- 4. K8s 元数据上下文
    namespace LowCardinality(String) CODEC(ZSTD(1)),
    pod_name String CODEC(ZSTD(1)),
    container_id FixedString(64) CODEC(ZSTD(1)),
    image_name String CODEC(ZSTD(3)),
    
    -- 5. 动态扩展属性(使用 Map 存储非常规审计元数据)
    extensions Map(String, String) CODEC(ZSTD(1)),
    
    -- 跳数索引:加速对命令行参数等大文本的模糊检索
    INDEX idx_args arguments TYPE tokenbf_v1(30720, 2, 0) GRANULARITY 1
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/ebpf_process_log_local', '{replica}')
PARTITION BY toYYYYMMDD(event_time)
ORDER BY (namespace, event_type, proc_name, event_time)
SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1;

2. DDL 核心设计要点解析

  • LowCardinality(低基数类型)
    对于 namespaceevent_typeproc_name 等字段,其全局去重后的总数通常小于 1 万个。使用 LowCardinality(String) 会将其在内部转换为整数索引,不仅极大节省了存储空间,还能让 WHERE 过滤过滤速度提升一个数量级。
  • Codec 链式压缩
    • 时间戳event_time 连续性极强,使用 DoubleDelta 编码后,再用 LZ4 压缩,几乎不占用存储。
    • 数字型(PID/UID):使用 T64 编码,它会剔除高位连续的 0,非常适合大整型。
    • 长文本(Arguments/BinaryPath):使用 ZSTD(3)。eBPF 命令行参数重复率高且体积大,ZSTD 的高压缩比在此优势显著。
  • 物理排序键 (ORDER BY)
    ClickHouse 的物理检索依赖稀疏索引。我们将最常用、基数相对较低的过滤条件放至 ORDER BY 最前列(如 namespaceevent_type)。时间戳 event_time 必须放在最后,否则会导致稀疏索引文件过大,失去索引过滤效果。
  • 布隆过滤器跳数索引 (tokenbf_v1)
    安全分析常需要通过 LIKE '%sh -i%' 检索异常命令行。在 arguments 字段上建立 tokenbf_v1(分词布隆过滤器),能直接在 Merge 阶段过滤掉 90% 不包含关键字的 Data Part,避免全表扫描。

三、 高并发检索架构破局

ClickHouse 的底层设计初衷是大宽表、低并发、大查询。如果前端控制台有 100 个安全分析师同时刷新仪表盘,或者告警引擎每秒发起数百次策略匹配检索,ClickHouse 的 CPU 会瞬间打满。

为了解决高并发查询的短板,我们必须在存储引擎之上加入查询网关与分层路由

                       [ 客户端检索请求 ]
                               |
                               v
                       +---------------+
                       |  chproxy 网关  |
                       +---------------+
                         /           \
         (命中缓存 / 简单点查) /             \ (大范围聚合/报表)
                       v               v
             +---------------+   +-------------------+
             |  Redis 缓存层  |   | ClickHouse 副本集群 |
             +---------------+   +-------------------+

1. 使用 chproxy 做并发控制与流控

chproxy 作为一个专为 ClickHouse 打造的 HTTP 代理,可以完美解决恶意/无序的高并发冲击:

# chproxy 关键配置片段
users:
  - name: security_fe
    max_execution_time: 10 # 限制单个查询最大执行时间 10 秒
    max_concurrent_queries: 20 # 限制该用户最大并发数为 20
    queue_max_wait_time: 5s # 超过并发后在队列中等待 5 秒
    queries_path_regexp: "^SELECT.*" # 仅允许执行查询语句

# 开启查询缓存(Query Cache)
cache:
  - name: memcached
    size: 2048MB
    expire: 30s # 对安全分析大屏等常见重复查询进行 30s 缓存

2. 读写分离与副本负载均衡

ClickHouse 的 Distributed 引擎在执行查询时,会自动分发到不同的 Shard 和 Replica。为避免写入操作影响查询体验,建议将读写流量彻底分离:

  • 写入路径:向 Local 表直接写入,不通过 Distributed 表。Flink 采用轮询(Round-robin)方式直接向各分片的 Local 表进行 HTTP Batch 写入。
  • 读取路径:通过 Distributed 表或使用 Chproxy 的 load_balancing 策略,将查询分发到专门的 Read-Only 副本(读取节点不参与 MergeTree 的后台 Merge 合并计算)。

3. 物化视图(Materialized View)异步预聚合

安全仪表盘(如“当前命名空间下 Top 10 异常进程”)不需要每次都扫描明细表。通过物化视图将数据秒级预聚合,查询时只需访问聚合后的高度精简表。

-- 创建目标聚合表
CREATE TABLE security_audit.process_summary_hourly
(
    event_hour DateTime,
    namespace LowCardinality(String),
    proc_name LowCardinality(String),
    exec_count UInt64
) ENGINE = SummingMergeTree()
ORDER BY (event_hour, namespace, proc_name);

-- 创建物化视图,将明细表增量注入聚合表
CREATE MATERIALIZED VIEW security_audit.mv_process_summary_hourly
TO security_audit.process_summary_hourly AS 
SELECT 
    toStartOfHour(event_time) AS event_hour,
    namespace,
    proc_name,
    count() AS exec_count
FROM security_audit.ebpf_process_log_local
GROUP BY event_hour, namespace, proc_name;

通过这一层优化,大屏和报表等高频聚合查询的 QPS 能够从数十提升至数千,响应时间从秒级缩短至毫秒级。


四、 存储生命周期管理 (TTL) 与冷热分层

eBPF 安全数据具有极明显的“时效性”。通常情况下:

  • 0 - 3天 的日志属于“热数据”,需要极速检索用于应急响应;
  • 4 - 30天 的日志属于“温数据”,用于追踪溯源,检索频率降低;
  • 31 - 180天 的日志作为“冷数据”,用于合规审计,极少查询。

冷热分层配置

ClickHouse 支持多级存储介质(SSD/HDD/对象存储)的分层转移。在 config.xml 中配置存储策略:

<storage_configuration>
    <disks>
        <fast_ssd>
            <path>/clickhouse/data/ssd/</path>
        </fast_ssd>
        <cold_hdd>
            <path>/clickhouse/data/hdd/</path>
        </cold_hdd>
    </disks>
    <policies>
        <tier_policy>
            <volumes>
                <hot_volume>
                    <disk>fast_ssd</disk>
                    <max_data_part_size_bytes>10737418240</max_data_part_size_bytes> <!-- 超过 10GB 优先存 HDD -->
                </hot_volume>
                <cold_volume>
                    <disk>cold_hdd</disk>
                </cold_volume>
            </volumes>
        </tier_policy>
    </policies>
</storage_configuration>

并在建表 DDL 的末尾加上基于时间的移动与删除策略:

-- 修改前文 DDL 的 SETTINGS 部分
SETTINGS storage_policy = 'tier_policy'
TTL event_time + INTERVAL 3 DAY TO VOLUME 'cold_volume', -- 3天后自动移动到 HDD 磁盘
    event_time + INTERVAL 180 DAY DELETE; -- 180天后自动物理删除

五、 总结与生产实测表现

在某大型 Kubernetes 集群环境(约 2000 个节点,峰值安全日志写入约 350k EPS / 日均 300 亿条)中落地此架构后,取得了以下显著成果:

  1. 存储成本降低 75%:得益于 LowCardinalityDoubleDelta 以及 ZSTD 的精细化配置,整表物理压缩比达到了 11.2:1。相比原有 Elasticsearch 架构,服务器节点数量从 36 台缩减至 8 台(三沙箱双副本+2代理)。
  2. 查询吞吐量跃升:通过 chproxy 查询限流与 Redis 物化视图缓存,秒级点查(TraceID 追踪)QPS 稳定在 1200+,未发生 CPU 过载报警。
  3. P99 查询延迟:对 1 亿行数据进行模糊匹配(如含有 /etc/ld.so.preload 的文件篡改行为),检索耗时控制在 1.2 秒 以内。

对于 eBPF 这类结构高度确定、体量极度庞大的安全审计日志,ClickHouse 配合合理的数据流设计,毫无疑问是当前性价比与技术先进性的最优解。

架构之眼 ClickHouseeBPF大数据存储

评论点评