Open sourcing kubenetmon: how we monitor data transfer in ClickHouse Cloud
Bài tóm tắt ClickHouse 2025 3. Quy mô lớn Độ khó: Khó
ClickHouse · 2025 · 3. Quy mô lớn · Độ khó: Khó — bài gốc
Bối cảnh
- ClickHouse Cloud chạy trên AWS, GCP, Azure, hàng chục region, mỗi region nhiều cụm Kubernetes, multi-tenant (nhiều khách trên cùng phần cứng).
- Mạng là mục chi phí thứ ba sau compute và storage, nhưng thường bị bỏ qua khi dự báo vì khó hiểu và khó đo: nhà cung cấp tính tiền NAT gateway, load balancer, lưu lượng giữa AZ, egress và ingress theo cặp region.
- Ba mục tiêu: forensics (từng kết nối L3/L4 thành chuỗi thời gian theo phút), attribution (kết nối thuộc workload, pod, AZ nào; đầu kia là gì), metering (tổng theo workload và theo loại chi phí, lưu lâu).
Các lựa chọn bị loại
- Cilium Hubble: hoặc có số byte mà thiếu ngữ cảnh endpoint, hoặc có ngữ cảnh mà không có số byte ("flow" của Cilium đếm theo cờ TCP, không theo băng thông).
- Flow log của nhà cung cấp cloud: đắt, mỗi nhà một kiểu, khó gắn nhãn workload Kubernetes, phải xử lý hậu kỳ riêng cho từng nhà.
- Công cụ FinOps (OpenCost...): tốt cho tổng chi phí nhưng không xem được hành vi từng kết nối theo thời gian.
- Đo ngay trong ClickHouse: không thấy lưu lượng của workload khác; theo dõi L3/L4 trong ứng dụng thì code rải khắp nơi; attribution không thuộc về codebase DB.
- Công cụ eBPF khác (Retina, system-probe của Datadog): lo ngại trộn nhiều hệ eBPF của các bên khác nhau khi đã chạy Cilium (và GKE dataplane v2 dựa trên Cilium); vùng ảnh hưởng nếu chúng tương tác sai quá rộng. Ngoài ra mô hình metric Prometheus đắt với cardinality cao.
Thay đổi chính
- Thu thập bằng conntrack: bảng theo dõi kết nối có sẵn của netfilter, chỉ cần bật accounting (
nf_conntrack_acct) là có số byte/gói mỗi chiều. Daemon đọc bảng định kỳ và yêu cầu kernel reset bộ đếm về 0 một cách nguyên tử sau mỗi lần đọc, nên giá trị là lưu lượng trong khoảng giữa hai lần đọc. Chấp nhận mất kết nối rất ngắn. Rủi ro conntrack đầy đã biết, nhưng cụm proxy tuyến đầu (nhiều kết nối nhất) không nằm trong phạm vi; cụm chạy workload khách chỉ dùng một phần nhỏ bảng. - Attribution: bản thử đầu hỏi Kubernetes API mỗi lần cần gắn nhãn: tốn RAM và tải nặng lên API server. Đổi sang informer (theo dõi event, giữ bản đồ cụm trong bộ nhớ): hết tải API nhưng RAM còn tệ hơn vì daemon trên mỗi node giữ trạng thái cả cụm lớn.
- Tách đôi:
kubenetmon-agenttrên mỗi node chỉ đọc conntrack và gửi qua gRPC (5–20 MB RAM);kubenetmon-serverkhông trạng thái, giữ informer và gắn nhãn, scale ngang được. Gắn nhãn cả đầu ngoài cụm (dải IP của dịch vụ AWS và region) để phân biệt lưu lượng trong/giữa region; xử lý chiều kết nối và NAT. - Lưu vào ClickHouse (LogHouse nội bộ): bảng
SummingMergeTreetự cộng byte/gói theo mọi tổ hợp nhãn, mốc thời gian làm tròn theo phút, nên đọc conntrack 5 giây một lần vẫn thành băng thông theo phút. Primary key tách khỏi sorting key (sorting key đổi được khi thêm cột, primary key thì không). TTL 90 ngày. - Insert: server gom lô trong bộ nhớ, flush khi lô quá cũ hoặc quá lớn, cộng async insert của ClickHouse (vẫn chờ xác nhận để không mất dữ liệu); nhiều worker cạnh tranh, mỗi worker giữ lô riêng. Lỗi đã gặp: chỉ kiểm tuổi lô khi có dữ liệu mới đến, nên ở môi trường ít tải lô không được flush đúng hạn. Đặt
insert_deduplication_tokenngẫu nhiên để hai lô trùng hệt nhau không bị ClickHouse coi là trùng lặp.
Kết quả (theo ClickHouse)
- Có môi trường ghi vài triệu quan sát kết nối mỗi phút. Một region: gần 400 tỉ dòng, 86,69 TiB chưa nén còn 2,66 TiB (khoảng 3%).
- Tìm ra: chính họ định kỳ tải dữ liệu S3 giữa region tốn kém; các cặp nói chuyện giữa AZ nhiều nhất; ước lượng băng thông cam kết cho workload; khách backup nhiều TB sang cloud khác nhiều lần mỗi ngày (egress đắt); chi phí của bảng "proxy" (MySQL engine) kéo dữ liệu từ xa.
Vì sao
- Không đo được thì không giảm được chi phí mạng; công cụ có sẵn hoặc có số mà thiếu ngữ cảnh, hoặc ngược lại (Chi phí hạ tầng và build vs buy).
- Dữ liệu cardinality cao hợp với kho cột hơn với mô hình metric (Observability và monitoring).
- Agent mỏng trên mỗi node + server không trạng thái giữ cache cụm là cách tránh nhân trạng thái theo số node.
Bài học cho SWE
- Trước khi thêm agent eBPF thứ hai, hỏi primitive có sẵn của kernel (conntrack) đã đủ chưa; ít thành phần trên đường dữ liệu thì ít rủi ro tương tác.
- Hỏi API server mỗi lần là tải lên control plane; informer giải tải nhưng chuyển chi phí sang RAM, nên đặt nó ở chỗ có ít bản sao.
- Gom lô theo cả tuổi lẫn kích thước, và kiểm tuổi bằng timer chứ không chỉ khi có dữ liệu mới (Batching và khấu hao round-trip).
- Đo chi phí mạng theo workload là điều kiện để thấy các đường egress mà không ai nghĩ là đắt.
Liên quan
#Network monitoring#Data transfer cost#conntrack#Kubernetes informers#eBPF#Cilium#SummingMergeTree#Async inserts#Egress#Cross-AZ
Được nhắc tới trong
Chủ đề (3)
Công ty (1)
Bài tóm tắt (2)