Blog
Thoughts on engineering, design, and building great products.
Hubble Bên Trong: Từ Sự Kiện eBPF Tới Luồng Mạng Toàn Cụm
Hubble cho ta xem mọi kết nối trong cụm Kubernetes theo tên pod, service, verdict policy — mà không cài sidecar vào pod nào. Bài này mổ cơ chế: datapath eBPF của Cilium (74 chương trình sched_cls ở Bài 12) gọi bpf_perf_event_output đẩy sự kiện vào một perf ring buffer tên cilium_events; cilium-agent đọc ra (cilium monitor cho thấy sự kiện thô với identity dạng số); rồi Hubble giàu hóa — biến identity 18203 thành kube-system/coredns — bằng cách tra kho identity-nhãn. Ta xem cả ba tầng chạy thật.
Kiểu Tetragon: Từ Quan Sát Đến Cưỡng Chế Bằng bpf_send_signal
Tetragon là công cụ an ninh runtime của hệ Cilium: nó quan sát bằng kprobe/tracepoint (đúng những hook Part II dùng) rồi cưỡng chế ngay trong nhân. Cơ chế cưỡng chế thật của nó là hai helper — bpf_send_signal gửi SIGKILL giết tiến trình, và bpf_override_return ghi đè giá trị trả về syscall. Bài này tự dựng đúng cơ chế đó: một tracepoint exec gọi bpf_send_signal(SIGKILL) để giết một tiến trình ngay khi nó chạy — binary cấm nhận exit 137, binary thường vẫn chạy. Không cần LSM hay reboot.
eBPF Từ Số Không: Chạy Chương Trình Trong Nhân Linux
Ngay lúc này, trên một worker của cụm Kubernetes ta dựng ở series trước, có 140 chương trình eBPF đang chạy bên trong nhân Linux — định tuyến từng gói tin, kiểm soát quyền truy cập thiết bị, gom metric. eBPF cho phép nạp mã vào nhân và chạy an toàn tại các điểm móc, không sửa mã nguồn nhân, không nạp module. Bài mở đầu series giải thích eBPF là gì, vì sao nó đổi cách mở rộng nhân, và một chương trình đi từ code tới mã máy chạy trong nhân ra sao.
Case-study: Một Gói Đi Qua Datapath eBPF Của Cilium
Mười chín bài đã mổ từng mảnh: verifier, maps, XDP, tc, tail call, perf ring, identity. Bài này ghép chúng lại thành một câu chuyện liền mạch — đi theo đúng một gói khi một pod gọi Service DNS của cụm, từ lúc rời pod nguồn tới lúc tới pod CoreDNS, qua từng chương trình eBPF và từng BPF map mà nó chạm vào. Không khái niệm mới; chỉ là thấy toàn bộ cỗ máy chạy như một thể thống nhất, với dữ liệu thật từ chính cụm đã dùng suốt series.
tc/sched_cls và Mổ Datapath Cilium Đang Chạy
Sau XDP là tc — hook nơi gói đã có sk_buff, thấy được cả ingress lẫn egress, và là nơi Cilium đặt gần như toàn bộ datapath của nó. Bài này không viết tc mẫu cho có; nó mổ thẳng 74 chương trình sched_cls đang chạy thật trên một node của cụm: chúng gắn vào đâu (card mạng, từng pod), gọi nhau qua tail call thế nào, và tra những BPF map nào để cân bằng tải một Service hay áp NetworkPolicy. Load balancing kube-proxy-less hóa ra chỉ là một lần tra map.
XDP: Xử Lý Gói Ở Điểm Sớm Nhất, Viết Một Firewall
XDP gắn chương trình eBPF vào driver mạng, chạy trên mỗi gói tới trước cả khi nhân cấp phát sk_buff — điểm sớm nhất có thể đụng vào một gói. Nó trả về một verdict: PASS, DROP, TX, REDIRECT. Bài này dựng một XDP firewall nhỏ drop ICMP trên một interface thật, gắn vào card mạng của node bằng bptool, rồi xem ping rớt từ 0% lên 100% loss trong khi SSH vẫn sống — và thấy nó nằm trước datapath tc của Cilium trên cùng interface ra sao.
LB IPAM và Traffic Policy
Bài 48 và 49 đều dừng ở chỗ Service LoadBalancer và Gateway treo external-IP <pending> — cụm tự dựng không có ai cấp địa chỉ. Bài này lấp chỗ đó bằng LB IPAM của Cilium: định nghĩa một dải IP, để Cilium gán cho Service, và Gateway của bài trước chuyển sang Programmed=True. Sau đó là externalTrafficPolicy — Cluster hay Local quyết định địa chỉ nguồn của client còn nguyên hay bị thay. Test thật trên cụm EC2, kèm phần nói rõ ranh giới giữa cấp IP và quảng bá IP.