Làm chủ bpftrace: Giải mã các bí ẩn hiệu năng Linux bằng câu lệnh one-liner

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

Vượt xa bảng điều khiển: Tại sao các công cụ truyền thống thất bại

Tôi đã dành một thập kỷ trực tiếp quản lý máy chủ Linux, và những lỗi khó nhằn nhất luôn là những lỗi “ẩn thân”. Bạn có thể thấy CPU tăng vọt trong top hoặc độ trễ đĩa tăng qua iostat, nhưng những công cụ đó chỉ hiển thị triệu chứng chứ không phải nguyên nhân. Trong nhiều năm, strace là lựa chọn hàng đầu để đi sâu vào vấn đề. Tuy nhiên, sử dụng strace trên một cơ sở dữ liệu đang chạy thực tế (production) là rất rủi ro; tôi đã thấy nó làm tăng 50-100% chi phí tài nguyên cho các syscall tần suất cao, làm nghẹt chính dịch vụ mà bạn đang cố gắng cứu vãn.

Hãy làm quen với bpftrace. Nó sử dụng eBPF (Extended Berkeley Packet Filter) để chạy các chương trình trong môi trường sandbox bên trong nhân (kernel). Đây không chỉ là một cải tiến nhỏ—đó là một sự thay đổi tư duy. Trên một máy chủ web Ubuntu 22.04 bận rộn xử lý 10.000 yêu cầu mỗi giây, tôi đã sử dụng bpftrace để xác định chính xác các vấn đề về độ trễ mà ứng dụng thậm chí không nhận thấy trình theo dõi đang chạy. Nó móc nối vào các sự kiện với tác động gần như bằng không đối với thông lượng.

Bắt đầu nhanh: Từ con số không đến Tracing trong 5 phút

Thiết lập bpftrace cực kỳ đơn giản trên các bản phân phối hiện đại. Nó đóng vai trò như một lớp bao bọc cấp cao, biên dịch một ngôn ngữ chuyên biệt, gọn gàng thành mã bytecode BPF hiệu quả ngay tức thì.

Cài đặt

Trên Ubuntu/Debian:

sudo apt update
sudo apt install bpftrace

Trên Fedora/RHEL:

sudo dnf install bpftrace

Lệnh One-Liner thực tế đầu tiên của bạn

Bạn cần biết những tệp nào đang được truy cập trên toàn bộ hệ thống ngay bây giờ? Hãy chạy lệnh này:

sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s (%d) đã mở %s\n", comm, pid, str(args->filename)); }'

Hãy cùng phân tích. tracepoint là điểm móc của chúng ta. Biến comm cho chúng ta tên tiến trình, trong khi args->filename trích xuất đường dẫn tệp. Gần đây tôi đã sử dụng lệnh này để bắt một script xoay vòng nhật ký (log-rotation) bị lỗi, nó vô tình cố gắng mở 500.000 tệp không tồn tại mỗi giờ.

Cơ chế hoạt động: Các Probe thực sự hoạt động như thế nào

Tracing hiệu quả đòi hỏi sự hiểu biết về các cảm biến của bạn. Hãy coi các probe như các công cụ phẫu thuật mà bạn có thể đặt ở bất kỳ đâu trong kernel hoặc không gian người dùng (user-space).

Hệ thống phân cấp Probe

  1. Tracepoints: Đây là các điểm đánh dấu ổn định, được xác định trước trong kernel. Luôn ưu tiên sử dụng những điểm này; chúng hiếm khi bị thay đổi khi nâng cấp kernel.
  2. Kprobes (Kernel Probes): Sử dụng chúng để móc vào hầu như bất kỳ hàm nội bộ nào của kernel. Thực tế chúng rất mạnh mẽ nhưng dễ bị lỗi vì tên hàm có thể thay đổi giữa các phiên bản kernel.
  3. Uprobes (User Probes): Những probe này nhắm vào các hàm bên trong các tệp thực thi của riêng bạn, chẳng hạn như một phương thức cụ thể trong tiến trình MySQL hoặc Node.js.
  4. Sự kiện Phần mềm/Phần cứng: Theo dõi các chỉ số cấp thấp như chu kỳ CPU, tập lệnh hoặc lỗi trang (page faults).

Tổng hợp dữ liệu với Maps

Việc in mọi sự kiện ra màn hình sẽ làm giảm hiệu suất của bạn. Thay vào đó, hãy sử dụng ‘maps’ để tóm tắt dữ liệu ngay trong kernel. Lệnh one-liner này đếm các syscall theo tên tiến trình:

sudo bpftrace -e 'tracepoint:syscalls:sys_enter_read { @[comm] = count(); }'

Nhấn Ctrl+C sau vài giây. Bạn sẽ nhận được một bảng thống kê gọn gàng về các tiến trình hoạt động mạnh nhất. Đây là cách nhanh nhất để tìm ra các “hàng xóm ồn ào” trong môi trường container đông đúc.

Các tình huống thực chiến

Dưới đây là ba lệnh one-liner mà tôi tin dùng khi một hệ thống production bắt đầu có dấu hiệu bất ổn.

1. Trực quan hóa độ trễ Block I/O

Trễ đĩa thường là thủ phạm ẩn giấu sau các truy vấn cơ sở dữ liệu chậm. Thay vì một con số trung bình duy nhất, lệnh này tạo ra một biểu đồ phân phối (histogram):

sudo bpftrace -e 'kprobe:vfs_read { @start[tid] = nsecs; } kretprobe:vfs_read /@start[tid]/ { @latency = hist(nsecs - @start[tid]); delete(@start[tid]); }'

Nếu bạn thấy một cụm các sự kiện trên 10.000.000 nan giây (10ms), có khả năng ổ SSD hoặc SAN của bạn đang bị quá tải.

2. Bắt các tiến trình tồn tại ngắn

Các tiến trình zombie hoặc việc thực thi shell thường xuyên có thể làm giảm hiệu năng. Lệnh này ghi lại mọi lượt thực thi mới với đầy đủ các đối số:

sudo bpftrace -e 'tracepoint:syscalls:sys_enter_execve { printf("%-10u %-15s", pid, comm); join(args->argv); }'

Hàm join() thực sự là phép màu ở đây. Nó tái cấu trúc chuỗi dòng lệnh để bạn có thể thấy chính xác công việc cron mơ hồ đó đang thực hiện những gì.

3. Gỡ lỗi truyền lại TCP (TCP Retransmissions)

Độ trễ mạng nổi tiếng là khó cô lập. Điểm móc này sẽ kích hoạt mỗi khi kernel phải gửi lại một gói tin:

sudo bpftrace -e 'kprobe:tcp_retransmit_skb { printf("Truyền lại: %s (PID %d)\n", comm, pid); }'

Nếu lệnh này bắt đầu cuộn nhanh liên tục, hãy ngừng xem xét mã nguồn của bạn và bắt đầu kiểm tra cáp, switch hoặc trang trạng thái của nhà cung cấp dịch vụ đám mây.

Các biện pháp an toàn khi chạy Production

Bpftrace hiệu quả, nhưng không phải là không có rủi ro. Một vài quy tắc đơn giản sẽ giúp bạn tránh khỏi rắc rối.

Giới hạn đầu ra của bạn

Đừng bao giờ sử dụng printf cho các sự kiện xảy ra hàng triệu lần mỗi giây, chẳng hạn như xử lý gói tin trên đường truyền 10Gbps. Bạn sẽ làm nghẽn terminal và lãng phí chu kỳ CPU để định dạng văn bản. Thay vào đó, hãy sử dụng biểu đồ (histograms) hoặc bộ đếm; hãy để kernel thực hiện tính toán và chỉ báo cáo lại kết quả tóm tắt.

Xác minh trước khi Hook

Trước khi giả định một probe tồn tại, hãy xác minh nó cho phiên bản kernel cụ thể của bạn:

sudo bpftrace -l '*openat*'

Điều này giúp tiết kiệm thời gian và ngăn lỗi ‘không tìm thấy lệnh’ khi chuyển đổi giữa các bản phân phối Linux khác nhau.

Thoát một cách sạch sẽ

Luôn đảm bảo tiến trình bpftrace của bạn kết thúc đúng cách. Mặc dù các chương trình BPF được thiết kế để an toàn và tự dọn dẹp, nhưng việc chạy hàng chục trình theo dõi bị lãng quên trên một cụm máy chủ có thể dẫn đến chi phí tài nguyên tích tụ đáng kể. Hãy bắt đầu đơn giản, sử dụng maps cho các tác vụ nặng, và bạn sẽ sớm thấy bpftrace là công cụ không thể thiếu trong bộ kỹ năng của mình.

Share: