Kiến trúc hoạt động của Linkerd với eBPF
Trong kiến trúc truyền thống, Linkerd sử dụng một container proxy (sidecar) chạy song song với ứng dụng, bắt buộc lưu lượng phải đi qua iptables để chuyển hướng (redirect) vào proxy. Cách này tạo ra độ trễ do phải chuyển ngữ cảnh (context switch) giữa không gian kernel và user-space.
Khi tích hợp eBPF, Linkerd thay thế cơ chế chuyển hướng của iptables bằng các hook trực tiếp trong kernel Linux. Lưu lượng mạng được xử lý ngay tại tầng Network Stack của kernel thông qua BPF Maps, loại bỏ việc copy dữ liệu ra không gian user-space cho mỗi gói tin.
Điều này giảm thiểu số lần chuyển ngữ cảnh, giảm bộ nhớ đệm (buffering) và giảm độ trễ (latency) đáng kể, đặc biệt là với các workload có lưu lượng cao (high-throughput).
Yêu cầu Kernel và Driver eBPF
Trước khi triển khai, cụm Kubernetes của bạn phải đáp ứng các yêu cầu phần cứng và hệ điều hành cụ thể để eBPF hoạt động ổn định.
Kiểm tra phiên bản Kernel
Linkerd eBPF yêu cầu phiên bản Linux Kernel tối thiểu là 4.19, nhưng khuyến nghị sử dụng 5.15 trở lên để đảm bảo tính năng đầy đủ và ổn định.
Thực hiện lệnh sau trên tất cả các node worker của cụm Kubernetes:
uname -r
Kết quả mong đợi: Phiên bản kernel hiển thị phải lớn hơn hoặc bằng 5.15 (ví dụ: 5.15.0-1040-aws hoặc 6.1.x).
Kiểm tra tính sẵn sàng của eBPF và BPF Maps
Các module eBPF cần được kích hoạt trong kernel. Bạn cần kiểm tra xem hệ thống đã hỗ trợ BPF Maps hay chưa.
cat /sys/kernel/bpf/map_type
Kết quả mong đợi: Lệnh này có thể không trả về gì nếu kernel chưa load module, nhưng quan trọng hơn là kiểm tra module bpf đã được load chưa.
lsmod | grep bpf
Kết quả mong đợi: Phải thấy dòng bpf xuất hiện trong danh sách các module đang chạy. Nếu không thấy, bạn cần cập nhật kernel hoặc load module thủ công.
Kiểm tra cấu hình Kernel (CONFIG_BPF_SYSCALL)
Để chắc chắn kernel được compile với hỗ trợ eBPF, kiểm tra file cấu hình:
grep CONFIG_BPF_SYSCALL /boot/config-$(uname -r)
Kết quả mong đợi: Trả về CONFIG_BPF_SYSCALL=y. Nếu trả về n hoặc không có, bạn không thể sử dụng eBPF.
Cài đặt Linkerd với chế độ eBPF
Linkerd đã tích hợp sẵn công cụ để kích hoạt chế độ eBPF trong bước cài đặt. Chúng ta sẽ sử dụng cờ --enable-eBPF để thay đổi cấu hình Data Plane.
Tải và cấu hình Linkerd CLI
Đảm bảo bạn đã có Linkerd CLI phiên bản mới nhất (v2.14+ hỗ trợ eBPF tốt nhất). Nếu chưa, tải về:
curl -sSfL https://run.linkerd.io/install.sh | sh -
Cập nhật linkerd vào biến môi trường (nếu chưa có):
export PATH=$HOME/.linkerd2/bin:$PATH
Tạo cấu hình cài đặt với eBPF
Thay vì chạy linkerd install thông thường, ta sẽ thêm cờ --enable-eBPF. Lệnh này sẽ tạo cấu hình YAML với các ConfigMap và DaemonSet đặc biệt để deploy eBPF agent.
linkerd install --enable-eBPF --wait | kubectl apply -f -
Lệnh này thực hiện:
- Sinh cấu hình cài đặt bao gồm
linkerd-cni (nếu dùng CNI) hoặc cấu hình eBPF native.
- Tải xuống các binary eBPF cần thiết.
- Deploy các component vào namespace
linkerd.
- Chờ (wait) cho đến khi các pod trong control plane và CNI agent chuyển sang trạng thái
Running.
Kết quả mong đợi: Terminal sẽ hiển thị quá trình apply các resource và kết thúc bằng dòng thông báo Linkerd installed successfully.
Verify trạng thái eBPF Agent
Sau khi cài đặt, hãy kiểm tra xem agent eBPF đã chạy trên các node chưa:
kubectl get pods -n linkerd -l app=linkerd-cni
Kết quả mong đợi: Bạn phải thấy ít nhất 1 pod cho mỗi node worker, với trạng thái Running và 1/1 container đã sẵn sàng. Pod này thường có tên linkerd-cni-xxxxx.
Verify khả năng của Linkerd CLI
Chạy lệnh kiểm tra tổng quát để đảm bảo Linkerd nhận diện được chế độ eBPF:
linkerd check --prefix linkerd
Kết quả mong đợi: Tất cả các kiểm tra phải trả về ok. Đặc biệt chú ý dòng using eBPF for traffic management hoặc thông báo tương tự trong phần data-plane hoặc proxy-injector.
So sánh hiệu năng và độ trễ
Để chứng minh lợi ích của eBPF, chúng ta sẽ thực hiện một bài test so sánh độ trễ (latency) giữa hai kịch bản: một pod được inject proxy truyền thống (iptables) và một pod được inject proxy eBPF.
Chuẩn bị Workload Test
Tạo một ứng dụng đơn giản (ví dụ: nginx) và một pod client để thực hiện request.
kubectl run nginx-server --image=nginx:alpine --port=80
Deploy pod client sử dụng image busybox để thực hiện lệnh wget:
kubectl run client --image=busybox --rm -it --restart=Never -- /bin/sh
Kết quả mong đợi: Terminal của bạn sẽ chuyển vào shell của pod client.
Test độ trễ với Proxy truyền thống (Iptables)
Đầu tiên, hãy thử nghiệm với một pod được inject proxy theo cách cũ (nếu bạn có một cluster cũ hoặc tạo một pod mới không dùng eBPF). Tuy nhiên, trong môi trường đã bật eBPF toàn cục, Linkerd tự động dùng eBPF. Để so sánh, ta sẽ dùng công cụ linkerd tap để đo lường và so sánh với dữ liệu lý thuyết, hoặc sử dụng curl với -w để đo thời gian.
Tuy nhiên, cách chính xác nhất là so sánh metric linkerd_proxy_request_latency_ms trong Prometheus. Nhưng để demo trực tiếp trên terminal, ta dùng wget với thời gian.
Trong pod client, thực hiện 100 request liên tục và lấy trung bình:
for i in {1..100}; do wget -q -O /dev/null http://nginx-server -T 0 -t 1 2>&1 | grep -oP 'Total time: \K[0-9.]+'; done | awk '{sum+=$1} END {print sum/NR " seconds average per request"}
Kết quả mong đợi: Bạn sẽ có một con số trung bình (ví dụ: 0.015s). Đây là baseline khi dùng eBPF (vì cluster đã bật eBPF).
Phân tích sự khác biệt (Mô phỏng so sánh)
Vì cluster hiện tại đang chạy toàn bộ eBPF, để thấy sự khác biệt, bạn cần hiểu lý thuyết số liệu:
- Iptables (Proxy truyền thống): Độ trễ tăng thêm khoảng 2-5ms cho mỗi request do phải chuyển ngữ cảnh (context switch) và copy dữ liệu qua
socket của container proxy.
- eBPF (Linkerd): Độ trễ tăng thêm chỉ khoảng 0.1-0.5ms vì xử lý trong kernel.
Để verify điều này trong thực tế, hãy sử dụng linkerd viz tap để xem chi tiết độ trễ của từng gói tin:
kubectl exec -it client -- wget -q -O /dev/null http://nginx-server && linkerd tap --from client --to nginx-server -o text
Kết quả mong đợi: Đầu ra của linkerd tap sẽ hiển thị các dòng log với trường latency. Bạn sẽ thấy giá trị latency rất thấp (thường dưới 1ms cho các request nội bộ) và phân bố đều, không có các spike độ trễ lớn như khi dùng iptables.
Verify thông qua Prometheus Metrics
Nếu bạn có Grafana hoặc truy cập Prometheus, hãy truy vấn metric độ trễ:
linkerd viz metrics --prometheus-query 'histogram_quantile(0.99, sum(rate(linkerd_proxy_request_latency_ms{dst_namespace="default"}[1m])) by (le))'
Kết quả mong đợi: Giá trị P99 (99%) của độ trễ khi dùng eBPF sẽ thấp hơn đáng kể so với con số trung bình 2-5ms của kiến trúc cũ. Nếu kết quả dưới 1ms, chứng tỏ eBPF đang hoạt động tối ưu.
Kiểm tra cuối cùng: Trạng thái eBPF trên Pod
Cuối cùng, để chắc chắn 100% rằng một pod cụ thể đang sử dụng eBPF thay vì iptables, hãy kiểm tra cấu hình của proxy trong pod đó.
Chọn một pod đã được inject Linkerd:
kubectl get pods -n default | grep linkerd
Tiếp theo, xem logs của container proxy trong pod đó để tìm dòng log khởi động:
kubectl logs -n default -c proxy
Kết quả mong đợi: Trong logs, bạn phải thấy dòng thông báo:
Using eBPF for traffic management hoặc traffic-shaping: eBPF.
Nếu thấy dòng traffic-shaping: iptables, có nghĩa eBPF chưa kích hoạt đúng cách trên pod đó (thường do pod chạy trước khi eBPF được bật, cần xóa và tạo lại pod).
Điều hướng series:
Mục lục: Series: Xây dựng nền tảng Service Mesh trên Kubernetes với Linkerd và eBPF
« Phần 3: Cấu hình bảo mật và quản lý lưu lượng với Linkerd
Phần 5: Giám sát nâng cao và phân tích lưu lượng với eBPF »