eBPF: Cách mở rộng kernel Linux mà không cần viết driver

Bảng điều khiển monitoring và observability thời gian thực

eBPF: Cách mở rộng kernel Linux mà không cần viết driver – Công nghệ thay đổi game cho observability và security

H kernel Linux là trái tim của hệ điều hành, chịu trách nhiệm quản lý tài nguyên phần cứng, cung cấp dịch vụ cho các ứng dụng, và đảm bảo sự ổn định và bảo mật của toàn bộ hệ thống. Tuy nhiên, kernel cũng nổi tiếng với việc khó evolución: bất kỳ thay đổi nào cũng cần phải trải qua quy trình kiểm tra chặt chẽ, và một lỗi nhỏ có thể dẫn tới hiện tượng kernel panic khiến toàn bộ hệ thống ngừng hoạt động.

Đó là lý do vì sao từ lâu, việc thêm chức năng mới vào kernel thường được thực hiện qua kernel modules hoặc việc viết device drivers – nhưng cả hai cách này đều có những hạn chế lớn: modules vẫn chạy trong kernel space và có thể gây không ổn định; việc viết driver đòi hỏi kiến thức sâu về phần cứng và API kernel phức tạp.

Ra đời từ nhu cầu này, eBPF (extended Berkeley Packet Filter) đã xuất hiện như một cáchปฏิวัติ để mở rộng chức năng của Linux kernel an toàn, hiệu quả, và không cần thay đổi mã nguồn kernel. Công nghệ này đang thay đổi cách chúng ta nhìn về mạng lưới, monitoring, và segurança trong thời đại cloud native.

eBPF là gì? Định dạng và lịch sử ngắn gọn

BPF ban đầu viết tắt của Berkeley Packet Filter – một công nghệ được phát triển vào đầu những năm 1990 để lọc và bắt gói tin tại mức kernel mà không cần sao chép tất cả gói tin lên user space. BPF cho phép các quy định произвольных được đưa vào kernel để quyết định xem gói tin nào sẽ được giữ lại, bỏ qua, hoặc chuyển hướng.

Sequal thời gian, các nhà phát triển Linux nhận ra rằng mô hình BPF (một máquina virtual đơn giản với một tập hợp hạn chế các hướng dẫn) có thể được ứng dụng cho nhiều mục đích hơn chỉ là lọc gói tin. Ra đời eBPF (extended BPF) với những cải tiến quan trọng:

  • Tăng số lượng thanh ghi và kích thước instruction set
  • Thêm khả năng gọi các hàm phụ trợ (helper calls) từ kernel
  • Thêm maps – cấu trúc dữ liệu để chia sẻ dữ liệu giữa eBPF program và user space
  • Đầu ra: không chỉ dùng để lọc gói tin nữa mà có thể thực hiện các tác vụ phức tạp

Hôm nay, khi mọi người nói về eBPF, họ thực sự chỉ cần nói về eBPF, vì khả năng của nó đã vươn ra khỏi chỉ việc lọc gói tin rất nhiều.

Kiến trúc eBPF: Từ source code tới kernel

Một eBPF programtypical đi qua các bước sau:

  1. Viết mã: Người lập trình viết mã bằng một thể con của C (thường được gọi là “C [giới hạn]” hoặc “BPF C”)
  2. Biên dịch: Mã C được biên dịch bằng LLVM/clang thành eBPF bytecode (nhất định là định dạng ELF)
  3. Load vào kernel: Một ứng dụng user space (thường dùng libbpf) sử dụng hệ thống gọi bpf() để tải eBPF bytecode vào kernel
  4. Verification: Trước khi cho phép chạy, kernel chạy một trình xác thực mạnh mẽ để kiểm tra xem chương trình có:
    • Luôn kết thúc (không có vòng lặp vô hạn)
    • Truy cập bộ nhớ an toàn (không truy cập ngoài bounds)
    • Không gây nguy hiểm để kernel (ví dụ: không gây ra exception)

    Nếu chương trình không qua verification, nó sẽ bị từ chối tải.

  5. JIT Compilation: Sau khi qua verification, eBPF bytecode thường được biên dịch Just-In-Time thành mã máy native của CPU để đạt hiệu suất tối đa
  6. Attach tới hook point: eBPF program được gắn vào một địa chỉ cụ thể trong kernel (hook point) và sẽ tự động chạy mỗi khi sự kiện đó xảy ra
  7. Chạy và tương tác: Khi sự kiện hook xảy ra, eBPF program chạy, có thể đọc/ghi dữ liệu qua maps, gọi helper functions, và cuối cùng trả về một giá trị quyết định hành động tiếp theo (ví dụ: cho gói tin qua, vứt gói tin, hoặc thay đổi một số trường)

Hook points: Đâu là nơi eBPF program có thể chạy?

eBPF program là event-driven - chúng chạy khi một sự kiện cụ thể xảy ra trong kernel hoặc user space. Các hook point phổ biến bao gồm:

Trong kernel space

  • Socket filters: Xét gói tin khi vào/ra khỏi stack mạng (đây là form ban đầu của BPF)
  • Tracepoints: Các điểm có sẵn trong kernel mà nhà phát triển đã đặt để cho phép tracing (ví dụ: sys_enter, sys_exit, block_rq_insert)
  • Kprobes và Uprobes: Cho phép gắn eBPF function tới hầu như bất kỳ function nào trong kernel (kprobe) hoặc trong ứng dụng user space (uprobe)
  • Perf events: Tích hợp với subsystem perf của kernel để đo lường hiệu suất
  • Network device queues (XDP - eXpress Data Path): Chạy cực sớm trong quá trình xử lý gói tin mạng, ngay khi gói tin vừa vào NIC
  • cgroup: Áp dụng chính sách dựa trên Linux control groups

Trong user space

  • USDТ probes (User Statically Defined Tracing): Các điểm probe đã được tích hợp sẵn vào ứng dụng
  • USDТ probes (User Statically Defined Tracing): Tương tự như trên nhưng cho user space

Các thành phần chính của eBPF program

Maps: Chia sẻ dữ liệu giữa kernel và user space

Maps là cách chính để eBPF program trao đổi dữ liệu với ứng dụng user space. Một số loại maps phổ biến:

  • Hash map: Lưu trữ key-value pairs, tra cứu O(1)
  • Array map: Lưu trữ các giá trị trong một mảng, truy cập bằng index
  • Per-CPU array: Mảng riêng cho mỗi CPU, giảm nhu cầu đồng bộ hóa
  • LRU hash: Hash map tự động xoá các mục ít được sử dụng nhất
  • Stack trace: Lưu trữ stack traces để debugging
  • Event ring buffer: Buffer cho việc stream sự kiện từ kernel tới user space

Helper functions: Giao diện với kernel

eBPF program không thể gọi trực tiếp các hàm kernel tùy ý vì lí do bảo mật. Thay vào đó, chúng có thể gọi một số helper functions được kernel cho phép xác định trước. Một số helper quan trọng:

  • bpf_map_lookup_elem, bpf_map_update_elem: Thao tác với maps
  • bpf_trace_printk: Gửi thông báo debug tới trace pipe (tương tự như printf)
  • bpf_get_current_pid_tgid: Lấy PID và TGID của task hiện tại
  • bpf_get_current_comm: Lấy tên tiến trình hiện tại
  • bpf_probe_read_user/kernel: Đọc an toàn từ user hoặc kernel space
  • bpf_ktime_get_ns: Lấy thời gian hiện tại ở độ phân giải nanosecond
  • bpf_tcp_sendmsg, bpf_tcp_recvmsg: Thao tác với TCP sockets (phức tạp hơn)

Use cases thực tế: eBPF trong sản xuất

eBPF đã được triển khai rộng rãi trong các môi trường sản xuất hiện đại, đặc biệt là trong các hệ thống đòi hỏi yüksek độ tin cậy và hiệu suất. Dưới đây là một số ứng dụng tiêu biểu:

1. Mạng lưới và Cloud Native

  • Cilium: Một dự án mã nguồn mở cung cấp kết nối, bảo mật, và monitoring cho containers sử dụng eBPF và XDP. Thay thế cho iptables-based network policies trong Kubernetes.
  • Load balancing và DDoS protection: eBPF chương trình có thể hoạt động ở lớp card mạng để vứt bỏ lưu lượng độc hại hoặc áp dụng mức độ giới hạn tốc độ。
  • Service mesh: Một số triển khai service mesh lightweight sử dụng eBPF để tái định hướng luồng và thực hiện giám sát.

2. Observability và Monitoring

  • Ứng dụng tracing: Công cụ như bpftrace và Bolt cho phép bạn viết các kịch bản một dòng để trace hệ thống, tương tự như strace nhưng mạnh mẽ hơn và có hiệu suất tốt hơn.
  • Performance profiling: Thu thập dữ liệu về cách CPU thời gian được sử dụng, riêng biệt theo hàm, tiến trình, hoặc thread.
  • Monitoring tài nguyên: Theo dõi sử dụng bộ nhớ, I/O đĩa, và mạng lưới trong thời gian thực.

3. Security và Runtime Protection

  • Container security: Công cụ như Falco (sử dụng eBPF) có thểตรวจจับ hành vi bất thường bên trong containers, như попытка đọc các tệp nhạy cảm, tạo ra các kết nối mạng lạ, hoặc thực thi các tệp nhị phân không được phép.
  • Malware detection: Phát hiện hành vi caractéristique của malware như попытка thay đổi các tệp hệ thống, tạo ra các kết nối outbound đến địa chỉ IP đáng doute.
  • Enforcing security policies: Áp dụng các quy tắc như "không cho phép các tiến trình không đặc quyền mounts hệ thống tệp" hoặc "giới hệ thống một ứng dụng chỉ có thể mở ra một số lượng hạn chế các kết nối mạng".

4. Tối ưu hóa hiệu suất

  • Network stack optimization: Bỏ qua các lớp không cần thiết trong stack mạng khi xử lýCertain types of traffic.
  • File system caching: Tối ưu cách kernel đọc/ghi tệp dựa trên mẫu sử dụng thực tế.
  • Scheduler improvements: Thông tin từ eBPF có thể được sử dụng để tinh chỉnh hành trình của kernel scheduler.

Công cụ phổ biến để làm việc với eBPF

May mắn thay, bạn không nhất thiết phải viết eBPF bytecode bằng tay. Hệ sinh thái eBPF hiện nay rất giàu có với nhiều công cụ giúp dễ dàng hơn:

Các framework và thư viện

  • libbpf: Thư viện C offiziell cho việc tải và tương tác với eBPF objects
  • BPF Compiler Collection (BCC): Một bộ công cụ từ iovisor cung cấp các công cụ thực dụng trongPython và C++ để xây dựng eBPF programs. Ví dụ: opensnoop, bashreadline, tcplife.
  • bpftrace: Công cụ tracing cao cấp dựa trên Lua, cho phép viết các scripts một dòng để trace hệ thống (tương tự như DTrace trên Solaris/macOS).
  • eunomia-bpf: Framework để xây dựng eBPF applications với mô hình "write once, deploy everywhere".

Các công cụ monitoring và security

  • Cilium: Như đã nói ở trên, cung cấp kết nối và segurança cho Kubernetes dựa trên eBPF/XDP.
  • Falco: Công cụ bảo mật runtime cho containers và Kubernetes, sử dụng eBPF để thu thập sự kiện hệ thống.
  • Pixie: Công cụ monitoring tự động cho ứng dụng dựa trên eBPF (được công khai bởi New Relic).

So sánh eBPF với các giải pháp truyền thống

Yếu tố eBPF Kernel modules Kprobes/Ftrace User space agents (strace, perf)
An toàn Cao (verifier ngăn chặn các hoạt động nguy hiểm) Thấp (có thể gây kernel panic) Trung bình (có thể ảnh hưởng hiệu suất) Cao (chạy hoàn toàn trong user space)
Hiệu suất Rất cao (có JIT, chạy trong kernel context) Cao Trung bình đến cao (tùy vào loại probe) Thấp (overhead từ context switching và ptrace)
Khả năng lập trình Trung bình (giới hạn bởi instruction set và verifier) Cao (full C và truy cập kernel toàn bộ) Thấp (chỉ có thể quan sát, không thể thay đổi hành vi kernel) Cao (full quyền trong user process)
Triển khai Đơn giản (tải bytecode qua hệ thống gọi) Phức tạp (cần biên dịch module, đồng bộ với kernel version) Đơn giản (nhưng cần quyền) Đơn giản (chạy như một ứng dụng thường)
Use cases tốt nhất Networking, observability, security, performance tuning Device drivers, filesystems Ad-hoc debugging, kernel tracing Ứng dụng-level debugging, performance measurement

Bắt đầu với eBPF

Nếu bạn muốn bắt đầu khám phá eBPF, dưới đây là một số bước đầu tiên:

  1. Hiểu bản chất: Đọc qua tài liệu концептуальный như eBPF.io hoặc sách "Linux Observability with BPF"
  2. Thử công cụ sẵn có:
    • Chạy opensnoop từ BCC để xem các tiến trình nào đang mở các file nào
    • Dùng bpftrace để viết một script đơn giản: bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %sn", comm, filename); }'
    • Thử tcplife để xem tuổi thọ của các kết nối TCP
  3. Viết chương trình đầu tiên: Bắt đầu với một chương trình đơn giản như "hello world" که فقط یک پیام را از طریق bpf_trace_printk выводит.
  4. Khám phá maps: Thử tạo một hash map để đếm số lượng sự kiện xảy ra.
  5. Xây dựng use case thực tế: Ví dụ: tạo một công cụ để monitor số lượng kết nối mới đến một cổng cụ thể.

Tương lai của eBPF

eBPF vẫn đang trong fase phát triển mạnh mẽ. Một số xu hướng và hướng phát triển đáng chú ý bao gồm:

  • eBPF for Windows: Những nỗ lực mang eBPF tới hệ điều hành Windows
  • Windows Subsystem for Linux (WSL) enhancements: Tích hợp eBPF tốt hơn vào WSL
  • eBPF trong các thiết bị eingebetted: Ứng dụng trong IoT và các hệ thống thời gian thực
  • Mở rộng hook points: Thêm nhiều hơn nhiều điểm móc để eBPF có thể can thiệp vào nhiều khu vực_kernel hơn
  • Better tooling và developer experience: Các IDE plugin, debugging tools mạnh mẽ hơn
  • Formal verification: Sử dụng các phương pháp xác thực định lý để chứng minh sự an toàn của eBPF programs

Kết luận

eBPF biểu diễn một bước tiến đột phá trong cách chúng ta mở rộng và tương tác với hệ điều hành Linux. Thay vì phải cân đối giữa an toàn và linh hoạt như trong quá khứ, eBPF cung cấp cả hai:

  • An toàn: Nhờ vào hệ thống verification nghiêm ngặt, eBPF programs không thể gây nguy hiểm cho kernel ổn định của hệ thống.
  • Linh hoạt: Với khả năng gắn vào praticamente mọi hook point trong kernel và user space, cùng với truy cập tới maps và helper functions, eBPF có thể được dùng để giải quyết một incredibly wide range of problems.
  • Hiệu quả: Nhờ JIT compilation và việc chạy trong kernel context, eBPF đạt hiệu suất gần như với mã nguyên bản, vượt trội so với các giải pháp user space truyền thống.
  • Động lực: Vì eBPF programs có thể được tải, cập nhật, và loại bỏ mà không cần khởi động lại kernel, chúng rất thích hợp cho các môi trường đòi hỏi sự thay đổi nhanh chóng như cloud và DevOps.

Từ việc cung cấp khả năng có thể nhìn thấy mạng cho các nhà điều hành đám mây, tới việc cho phép nhà phát triển tự động đo lường và tối ưu hóa ứng dụng của mình, eBPF đang nhanh chóng trở thành một công cụ không thể thiếu trong bộ công cụ của các kỹ sư hệ thống, nhà phát triển phần mềm, và chuyên gia bảo mật trong thời đại nguyênChild của phần mềm.

Nếu bạn đang làm việc với Linux - bất kể là là quản trị viên hệ thống, nhà phát triển backing, nhà nghiên cứu bảo mật, hoặc đơn giản là là một người đam mê công nghệ - hiểu và biết cách sử dụng eBPF sẽ mở ra cánh cửa để bạn giải quyết các vấn đề mà trước đây chỉ có thể được giải quyết bằng cách viết kernel modules phức tạp và rủi ro.

Sơ đồ kiến trúc eBPF: từ mã nguồn C đến bytecode, verifier, JIT và kernel hook
Hệ thống mạng hiện đại với khả năng theo dõi và bảo mật cấp kernel
Bảng điều khiển monitoring và observability thời gian thực

Tôi là một lập trình viên IOS. Code chính là IOS nhưng thỉnnh thoảng vẫn đá sang Android hoặc web. Mặc dù không quá thông thạo nhưng tôi sẽ chia sẻ những kiến thức mà mình đã tìm hiểu, áp dụng qua.

Bài viết liên quan

Li-Fi: Truyền dữ liệu qua ánh sáng thay thế WiFi

Li-Fi: Truyền dữ liệu qua ánh sáng thay thế WiFi Li-Fi (Light Fidelity) là công nghệ truyền thông không dây sử dụng ánh sáng thay vì sóng radio như Wi-Fi….

Xem thêm

WebAssembly: Chạy Python, C/C++ trên web với tốc độ gần native

WebAssembly: Chạy Python, C/C++ trên web với tốc độ gần native JavaScript longtemps đã là ngôn ngữ độc quyền chạy trong trình duyệt web, nhưng có thể bạn từng tự…

Xem thêm

Matter & OpenThread: Giao thức nhà thông minh thế hệ mới

Matter & OpenThread: Giao thức nhà thông minh thế hệ mới Sau nhiều năm mảnh dỡ do vô số giao thức riêng tư như Zigbee, Z-Wave, Bluetooth Mesh hay Weave,…

Xem thêm
0 0 đánh giá
Article Rating
Theo dõi
Thông báo của
guest
0 Comments
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất