eBPF (extended Berkeley Packet Filter)
1. Tổng quan
Định nghĩa: eBPF là công nghệ thực thi nhẹ bên trong nhân (kernel), cho phép gắn và chạy một cách an toàn các chương trình do người dùng định nghĩa — đã vượt qua bộ kiểm chứng (Verifier) — vào những sự kiện cụ thể bên trong kernel (lời gọi hệ thống, gói tin mạng, điểm vào hàm, v.v.) mà không cần biên dịch lại kernel hay nạp mô-đun kernel mới.
Gốc rễ của eBPF là BPF (Berkeley Packet Filter, sau đây gọi là cBPF) ra đời năm 1992 nhằm lọc gói tin.
cBPF là một máy ảo nhỏ giúp tcpdump lọc ngay trong kernel chỉ những gói tin quan tâm để đưa lên không gian người dùng, nhưng có cấu trúc hạn chế: chỉ có 2 thanh ghi và không dùng được vào việc gì ngoài lọc gói tin.
eBPF, được đưa vào Linux kernel 3.15 năm 2014, đã mở rộng mạnh mẽ ý tưởng này, tái sinh nó thành môi trường thực thi đa năng bên trong kernel với 11 thanh ghi 64 bit, cấu trúc dữ liệu (map) và khả năng gọi hàm trợ giúp (helper function).
Kết quả là ngày nay eBPF đã vượt khỏi vai trò bộ lọc gói tin đơn thuần để trở thành công nghệ nền tảng bao trùm mạng, khả năng quan sát (Observability), bảo mật và phân tích hiệu năng.
Lý do eBPF quan trọng từ góc nhìn của Kỹ sư chuyên nghiệp (Professional Engineer) là vì nó mở ra một mô hình mở rộng mới: "thay đổi hành vi của kernel mà không thay đổi kernel". Theo truyền thống, muốn thay đổi hoạt động của kernel thì phải sửa mã nguồn kernel rồi chờ chu kỳ phát hành, hoặc chấp nhận rủi ro nạp mô-đun kernel. Cách thứ nhất mất nhiều năm, còn cách thứ hai nếu sai có thể gây kernel panic làm dừng toàn bộ hệ thống. eBPF đưa ra con đường thứ ba giữa hai lựa chọn đó: chương trình sandbox được bộ kiểm chứng bảo đảm an toàn, và đây chính là cốt lõi đưa Linux tiến hóa thành "kernel có thể lập trình".
1.1 Bối cảnh ra đời và sự cần thiết
Thứ nhất, do nhu cầu đo lường (instrumentation) bùng nổ trong môi trường cloud native. Khi container và microservice lan rộng, hàng trăm tiến trình xuất hiện rồi biến mất trên một nút, và nhu cầu quan sát các lời gọi hệ thống và luồng mạng mà chúng trao đổi qua kernel — mà không cần sửa mã ứng dụng — ngày càng lớn. Cách cài agent và đo lường mã cho từng ứng dụng kém khả năng mở rộng vì ngôn ngữ và framework mỗi nơi một khác, nhưng nếu đo lường một lần tại kernel — nơi mọi tiến trình đều phải đi qua — thì có thể quan sát toàn bộ bất kể ngôn ngữ.
Thứ hai, do rủi ro và gánh nặng bảo trì của mô-đun kernel. Mô-đun kernel chạy trong cùng không gian địa chỉ với kernel với quyền hạn không giới hạn, nên một lỗi có thể làm sập toàn hệ thống, và mỗi lần nâng phiên bản kernel lại phải viết lại, kiểm chứng lại. Chương trình eBPF được bộ kiểm chứng chặn trước vòng lặp vô hạn và truy cập bộ nhớ sai ngay tại thời điểm nạp, nên có thể triển khai chức năng cấp kernel một cách tương đối an toàn.
Thứ ba, do yêu cầu tối thiểu hóa chi phí hiệu năng. Nếu sao chép gói tin lên không gian người dùng để xử lý nhằm quan sát hay thực thi chính sách, chi phí chuyển ngữ cảnh và sao chép sẽ tích lũy. eBPF có thể hoàn tất xử lý ngay trong kernel, thậm chí ở tầng driver mạng (XDP), giúp giảm mạnh độ trễ và mức tiêu thụ CPU.
1.2 Đặc điểm cốt lõi
Bản chất của eBPF được tóm gọn trong bốn đặc điểm. Tính an toàn là việc bộ kiểm chứng bảo đảm tĩnh tính kết thúc và an toàn bộ nhớ của chương trình, còn hiệu năng là việc bytecode được chuyển thành mã máy gốc qua biên dịch JIT rồi thực thi. Khả năng mở rộng động là việc có thể gắn và gỡ chương trình để thay đổi hành vi kernel mà không cần khởi động lại hệ thống, còn khả năng lập trình là việc người dùng có thể tự do kết nối logic mong muốn với các sự kiện kernel. Bốn đặc điểm này kết hợp giúp eBPF đạt được mục tiêu "mở rộng kernel vừa an toàn vừa nhanh" — điều trước đây khó dung hòa.
2. Cấu trúc thực thi và nguyên lý hoạt động
Vòng đời của chương trình eBPF đi theo luồng viết–biên dịch–nạp–kiểm chứng–thực thi–trao đổi dữ liệu.
Lập trình viên viết chương trình bằng cú pháp C bị giới hạn, và LLVM/Clang biên dịch nó thành bytecode eBPF.
Bytecode này được nạp vào kernel qua lời gọi hệ thống bpf(), và ngay lúc đó bộ kiểm chứng duyệt mọi đường thực thi của chương trình để xác nhận tính an toàn.
Chỉ chương trình vượt qua kiểm chứng mới được trình biên dịch JIT chuyển thành mã gốc của kiến trúc CPU tương ứng và gắn vào điểm móc (Hook) đã chỉ định.
flowchart TD
A["Lập trình viên: viết mã C giới hạn"] --> B["Biên dịch LLVM/Clang"]
B --> C["Bytecode eBPF"]
C -->|"lời gọi hệ thống bpf()"| D{"Bộ kiểm chứng (Verifier)<br/>phân tích tĩnh tính an toàn"}
D -->|"Từ chối (lặp vô hạn·truy cập trái phép)"| E["Nạp thất bại"]
D -->|"Vượt qua"| F["Biên dịch JIT → mã gốc"]
F --> G["Gắn vào điểm móc"]
G --> H["Thực thi khi có sự kiện kernel"]
H -->|"Map eBPF"| I["Daemon không gian người dùng"]
I --> J["Kết quả quan sát·chính sách·phân tích"]
Hai trục quan trọng nhất trong nguyên lý hoạt động là bộ kiểm chứng và map. Để bảo đảm chương trình chắc chắn kết thúc trong thời gian hữu hạn, trước đây bộ kiểm chứng cấm nhảy lùi (vòng lặp), còn hiện nay chỉ cho phép vòng lặp có giới hạn (bounded loop) có thể kiểm chứng được. Ngoài ra, nó theo dõi phạm vi của các phép toán con trỏ để chặn truy cập vào vùng tùy ý của bộ nhớ kernel, và kiểm tra cả các hàm trợ giúp được phép truy cập cùng kiểu tham số. Nhờ phân tích tĩnh này, chương trình viết sai bị từ chối ở giai đoạn nạp trước khi được thực thi, nên rủi ro kernel panic trong vận hành giảm đáng kể.
Map là cấu trúc dữ liệu khóa-giá trị dùng để chia sẻ trạng thái giữa chương trình eBPF trong kernel với chương trình không gian người dùng, và giữa nhiều chương trình eBPF với nhau. Chương trình eBPF chạy ngắn và kết thúc mỗi khi có sự kiện, nên không thể tự duy trì trạng thái lâu dài; map giúp lưu trữ bền vững trạng thái này trong kernel. Ví dụ, chương trình đếm số lời gọi hệ thống sẽ cộng dồn bộ đếm vào hash map, và daemon không gian người dùng định kỳ đọc map này để chuyển thành chỉ số. Có nhiều loại như hash map, mảng, ring buffer, LRU map, đáp ứng rộng rãi từ truyền phát sự kiện tần suất cao đến tra cứu bảng chính sách.
2.1 Các loại điểm móc (Hook)
Phạm vi ứng dụng của eBPF được quyết định bởi nơi có thể gắn chương trình, tức là điểm móc. Điểm móc chia thành hai nhóm lớn: nhóm mạng và nhóm truy vết (tracing). Trong nhóm mạng, XDP (eXpress Data Path) chạy ngay khi driver mạng nhận gói tin, tức là trước khi vào ngăn xếp mạng của kernel, nên có thể cho qua, loại bỏ hoặc chuyển hướng gói tin nhanh nhất. Ngược lại, điểm móc TC (Traffic Control) nằm sau khi vào ngăn xếp nên xử lý được siêu dữ liệu phong phú hơn XDP và kiểm soát cả chiều gửi. Trong nhóm truy vết, kprobe/kretprobe gắn vào điểm vào và trả về của hàm kernel, uprobe gắn vào hàm của chương trình người dùng, và tracepoint gắn vào các điểm sự kiện tĩnh mà kernel công khai một cách ổn định.
| Phân loại | Điểm móc | Vị trí | Công dụng chính |
|---|---|---|---|
| Mạng | XDP | Ngay sau khi driver nhận | Lọc siêu tốc·chống DDoS·cân bằng tải |
| Mạng | TC | Ngăn xếp mạng | Chính sách gửi·nhận, điều khiển lưu lượng |
| Truy vết | kprobe | Hàm kernel bất kỳ | Đo lường động hoạt động kernel |
| Truy vết | tracepoint | Sự kiện tĩnh | Quan sát ổn định sự kiện kernel |
| Truy vết | uprobe | Hàm người dùng | Truy vết bên trong ứng dụng |
| Bảo mật | LSM BPF | Điểm móc bảo mật | Thực thi chính sách kiểm soát truy cập |
Sự đa dạng điểm móc như vậy có nghĩa là một công nghệ duy nhất có thể xử lý tích hợp mạng, khả năng quan sát và bảo mật. Cốt lõi của thiết kế là hiểu tính chất của từng điểm móc — XDP đảm nhận hiệu năng, tracepoint đảm nhận tính ổn định, LSM BPF đảm nhận thực thi chính sách bảo mật — và lựa chọn phù hợp với mục đích.
3. Các lĩnh vực ứng dụng chính
Ứng dụng của eBPF phát triển theo ba nhánh lớn, và ở mỗi nhánh đã hình thành các dự án tiêu chuẩn trên thực tế.
flowchart LR
K["Runtime kernel eBPF"] --> N["Mạng"]
K --> O["Khả năng quan sát"]
K --> S["Bảo mật"]
N --> N1["Cilium: CNI cho container"]
N --> N2["Bộ cân bằng tải XDP (Katran)"]
O --> O1["Pixie / Parca"]
O --> O2["Profiling·truy vết"]
S --> S1["Falco: phát hiện mối đe dọa runtime"]
S --> S2["Tetragon: thực thi chính sách"]
Trong mạng, dự án tiêu biểu nhất là Cilium — một CNI (Container Network Interface) cho Kubernetes.
CNI truyền thống xếp các quy tắc dịch vụ và chính sách thành danh sách tuyến tính trong iptables của Linux, nên mang giới hạn về khả năng mở rộng: số dịch vụ càng tăng thì chi phí dò quy tắc cho mỗi gói tin càng tăng tuyến tính.
Cilium thay thế việc xử lý quy tắc này bằng tra cứu băm dựa trên map eBPF để duy trì hiệu năng ổn định ngay cả trong cụm quy mô lớn, và xử lý chính sách L3~L7 cùng cân bằng tải trong kernel mà không cần sidecar proxy của service mesh.
Katran — bộ cân bằng tải dựa trên XDP của Facebook (Meta) — được trích dẫn như trường hợp xử lý hàng triệu gói tin mỗi giây trên một máy chủ.
Trong khả năng quan sát, thế mạnh là có thể tự động đo lường lời gọi giữa các dịch vụ, độ trễ và lời gọi hệ thống mà hoàn toàn không cần sửa mã ứng dụng. Thay vì cài sidecar hay SDK vào từng dịch vụ, đặt một agent eBPF trên mỗi nút để quan sát toàn bộ lưu lượng và lời gọi hàm đi qua kernel, nên trung lập với ngôn ngữ và ít bỏ sót đo lường. Continuous profiling thực hiện profiling CPU thường xuyên (ví dụ: Parca) và tự động tạo bản đồ dịch vụ (ví dụ: Pixie) thuộc nhóm này.
Trong bảo mật, eBPF giám sát thời gian thực lời gọi hệ thống và sự kiện kernel để phát hiện và chặn mối đe dọa runtime. Falco định nghĩa các mẫu lời gọi hệ thống đáng ngờ (ví dụ: chạy shell trong container, truy cập tệp nhạy cảm) thành quy tắc để phát hiện xâm nhập, còn Tetragon không dừng ở phát hiện mà chặn ngay các tiến trình vi phạm chính sách ở cấp kernel. Sử dụng điểm móc LSM (Linux Security Module) BPF còn có thể hiện thực linh hoạt các chính sách kiểm soát truy cập như SELinux, AppArmor bằng eBPF.
4. So sánh với mô-đun kernel và phương thức không gian người dùng
Để hiểu chính xác vị thế của eBPF, cần so sánh với hai phương án có sẵn: phương thức mô-đun kernel và phương thức agent không gian người dùng. Ba phương thức nằm trên thế đánh đổi giữa "chạy ở đâu" và "an toàn đến mức nào".
| Hạng mục so sánh | Mô-đun kernel | eBPF | Agent không gian người dùng |
|---|---|---|---|
| Vị trí thực thi | Kernel | Kernel (sandbox) | Không gian người dùng |
| Tính an toàn | Thấp (nguy cơ panic) | Cao (bộ kiểm chứng bảo đảm) | Cao (cô lập tiến trình) |
| Hiệu năng | Rất cao | Cao | Tương đối thấp |
| Linh hoạt triển khai | Thấp (nạp lại·khởi động lại) | Cao (gắn động) | Cao |
| Truy cập sự kiện kernel | Toàn diện | Giới hạn trong điểm móc | Hạn chế (gián tiếp) |
Mô-đun kernel mạnh nhất về hiệu năng và phạm vi truy cập, nhưng yếu về tính an toàn và khả năng bảo trì nên gánh nặng khi đưa vào production rất lớn. Agent không gian người dùng an toàn và dễ phát triển, nhưng không thể nhìn trực tiếp sự kiện kernel nên độ sâu quan sát nông và tốn chi phí chuyển ngữ cảnh. Khác biệt bản chất của eBPF là dung hòa ưu điểm của cả hai, cung cấp hiệu năng và khả năng truy cập gần với mô-đun kernel cùng với tính an toàn gần với không gian người dùng. Lý do gốc rễ của khác biệt này là eBPF đồng thời có cơ chế an toàn tĩnh là kiểm chứng trước khi thực thi và cơ chế hiệu năng là JIT. Tuy nhiên, cần thừa nhận rằng vì điểm móc và hàm trợ giúp bị giới hạn trong phạm vi kernel công khai, tính linh hoạt xử lý tự do toàn bộ kernel không bằng mô-đun kernel.
5. Chuyên sâu: Xu hướng chuẩn hóa và mở rộng
eBPF khởi đầu là công nghệ riêng của Linux, nhưng khi hệ sinh thái trưởng thành, tính di động và chuẩn hóa nổi lên như nhiệm vụ cốt lõi. Ban đầu, phải biên dịch chương trình theo header kernel của từng nút thực thi nên việc triển khai rườm rà; khi kỹ thuật CO-RE (Compile Once – Run Everywhere) và siêu dữ liệu BTF (BPF Type Format) xuất hiện, tệp nhị phân biên dịch một lần có thể tái sử dụng trên các phiên bản kernel khác nhau. Đây là bước ngoặt giúp triển khai eBPF một cách thực tế trên hạ tầng quy mô lớn.
Về quản trị, eBPF Foundation được thành lập trực thuộc Linux Foundation với sự tham gia của Google, Meta, Microsoft, Isovalent, v.v., tạo nền tảng phát triển trung lập giảm sự phụ thuộc vào một nhà cung cấp cụ thể. Về mở rộng nền tảng, dự án eBPF for Windows đang được tiến hành, cho thấy khả năng eBPF vượt ra ngoài Linux để trở thành khung đo lường và chính sách đa hệ điều hành. Trong lĩnh vực service mesh, kiến trúc không sidecar (sidecarless) — loại bỏ sidecar proxy và xử lý phần lớn trong kernel bằng eBPF — đang nổi lên, và các thảo luận tiếp tục theo hướng giảm tiêu thụ tài nguyên và độ trễ của mặt phẳng dữ liệu (data plane).
Tuy nhiên, thay vì mô tả các xu hướng này một cách khẳng định, thái độ đúng đắn trong bài thi là nêu rõ rằng công nghệ đang tiến hóa nhanh và hiệu năng, mức độ trưởng thành chi tiết có thể khác nhau tùy workload và phiên bản kernel.
6. Những điểm cần cân nhắc và hàm ý
Thứ nhất, cần kiểm soát tính hai mặt về bảo mật. eBPF là phương tiện quan sát và thực thi bảo mật mạnh mẽ, nhưng đồng thời nếu bị lạm dụng thông qua quyền cấp sai, nó có thể trở thành rootkit hoặc công cụ đánh cắp dữ liệu ở cấp kernel. Vì vậy, phải kiểm soát chặt quyền nạp chương trình eBPF (CAP_BPF, v.v.) theo nguyên tắc đặc quyền tối thiểu, và song hành với cơ chế quản trị thường xuyên kiểm toán danh sách và tính toàn vẹn của các chương trình đã gắn.
Thứ hai, cần chiến lược triển khai có tính đến ràng buộc của bộ kiểm chứng và độ phức tạp phát triển. Để bảo đảm an toàn, bộ kiểm chứng đặt ràng buộc về kích thước, độ phức tạp và vòng lặp của chương trình, nên logic phức tạp phải được chia thành nhiều chương trình hoặc phân vai với không gian người dùng. Vì phát triển cấp thấp khó, cách tiếp cận theo giai đoạn là thực tế: thay vì tự phát triển, tận dụng các khung cấp cao đã được kiểm chứng như Cilium, Falco, rồi mở rộng sang tự phát triển khi năng lực tổ chức đã trưởng thành.
Thứ ba, chiến lược quản lý phụ thuộc phiên bản kernel và tính di động là quan trọng. Điểm móc và hàm trợ giúp có mức khả dụng khác nhau tùy phiên bản kernel, nên cần lấy CO-RE/BTF làm tiền đề để định nghĩa rõ phạm vi kernel được hỗ trợ, và trong môi trường lẫn kernel cũ phải chuẩn bị sẵn đường đo lường thay thế.
Thứ tư, cần tiếp cận từ góc độ kiến trúc tích hợp khả năng quan sát, mạng và bảo mật. Tích hợp ba lĩnh vực vốn được vận hành tách biệt bằng các công cụ khác nhau lên một nền tảng kernel duy nhất là eBPF có thể giảm độ phức tạp vận hành và tiêu thụ tài nguyên. Với tư cách Kỹ sư chuyên nghiệp, cần đánh giá giá trị của eBPF không phải từ góc độ triển khai từng công cụ riêng lẻ mà từ góc độ chiến lược nền tảng, lấy eBPF làm nền tảng chung của mặt phẳng dữ liệu để thiết kế nhất quán quan sát, chính sách và bảo mật.
Tài liệu tham khảo
- Trang chính thức eBPF, https://ebpf.io/
- Tài liệu dự án Cilium, https://docs.cilium.io/
- Linux Foundation, eBPF Foundation, https://ebpf.foundation/
Tóm tắt một câu: eBPF là công nghệ nền tảng "kernel có thể lập trình", gắn động các chương trình sandbox được bộ kiểm chứng bảo đảm an toàn vào sự kiện kernel để xử lý tích hợp mạng, khả năng quan sát và bảo mật ở cấp kernel với hiệu năng cao mà không cần khởi động lại hay mô-đun kernel.