Debug Kubernetes như một chuyên gia: Giám sát thời gian thực với Inspektor Gadget

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

Những lỗi “vô hình” trong Kubernetes

Tất cả chúng ta đều đã từng gặp tình huống này: một microservice báo lỗi 500 Internal Server Error, nhưng application log lại trống rỗng. Bạn kiểm tra kubectl logs và không thấy gì cả. Bạn kiểm tra Prometheus, và mức sử dụng CPU vẫn ổn định. Tuy nhiên, dịch vụ rõ ràng là đang gặp sự cố. Đây là thực tế của việc debug các hệ thống phân tán—những lỗi nghiêm trọng nhất thường xảy ra ở khoảng trống giữa mã ứng dụng và nhân (kernel) hệ thống.

Các kỹ sư DevOps thường xuyên gặp phải ba kịch bản “hộp đen” sau:

  • Một container bị crash ngay lập tức với mã thoát (exit code) 137 hoặc 139, khiến việc thu thập log không kịp ghi lại stack trace.
  • Các đợt tăng độ trễ 50ms chập chờn chỉ xảy ra khi ghi cơ sở dữ liệu với số lượng kết nối đồng thời cao.
  • Các lỗi phân quyền âm thầm khi một tiến trình cố gắng ghi vào một volume chỉ đọc, nhưng ứng dụng lại bỏ qua thông báo lỗi.

Tại sao các công cụ truyền thống thất bại trên môi trường Production

Các công cụ Linux tiêu chuẩn như strace hoặc tcpdump không được xây dựng cho kỷ nguyên cloud-native. Nếu bạn thử chạy strace trên một tiến trình production có lưu lượng truy cập cao, bạn có thể thấy ứng dụng chậm đi gấp 10 hoặc thậm chí 50 lần. Tác động hiệu năng này thường làm cho lỗi biến mất ngay khi bạn đang theo dõi nó—một hiện tượng “Heisenbug” điển hình. Quan trọng hơn, các công cụ này nhìn thấy Process ID (PID), chứ không phải tên Pod hay Namespace. Việc ánh xạ một PID thô trở lại một container cụ thể trong một cụm 500 node là một “cơn ác mộng” thủ công.

Lợi thế của eBPF: Inspektor Gadget

Inspektor Gadget giải quyết vấn đề này bằng cách sử dụng eBPF (Extended Berkeley Packet Filter). Thay vì chặn mọi system call và chuyển đổi ngữ cảnh (context-switching) giữa kernel và user space, it chạy các chương trình sandboxed trực tiếp bên trong Linux kernel. Điều này giúp giảm thiểu chi phí tài nguyên xuống gần như bằng không—thường là dưới 1%—giúp việc sử dụng an toàn ngay cả dưới tải production nặng.

Tính năng Công cụ truyền thống (strace/tcpdump) Inspektor Gadget (eBPF)
Tác động hiệu năng Nghiêm trọng (có thể làm treo ứng dụng) Không đáng kể (<1% tải CPU)
Ngữ cảnh K8s Yêu cầu ánh xạ thủ công Tích hợp sẵn (lọc theo Pod, Label, Namespace)
Cài đặt Phải nằm trong container image Không cần can thiệp mã nguồn (nằm trên node)
Bảo mật Nguy cơ cao làm crash tiến trình Được xác minh an toàn bởi trình biên dịch JIT của Kernel

Những lưu ý trước khi bắt đầu

Điểm cộng: Bạn không cần phải thay đổi bất kỳ dòng mã nào hay build lại Docker image. Nó hoạt động độc lập từ bên ngoài nhìn vào.

Thực tế cần lưu ý: Bạn cần phiên bản Linux kernel từ 5.10 trở lên để truy cập đầy đủ bộ công cụ. Vì nó can thiệp vào kernel, bạn cũng cần quyền quản trị (privileged) đối với cụm cluster để triển khai agent.

Chuẩn bị môi trường

Theo kinh nghiệm của tôi, cách gọn gàng nhất để quản lý việc này là thông qua plugin của kubectl. Nó cho phép bạn thực hiện các lệnh debug giống như bất kỳ thao tác kubectl nào khác.

1. Cài đặt CLI

Nếu bạn đã cài đặt Krew, bạn có thể bắt đầu sau vài giây:

kubectl krew install gadget
kubectl gadget version

2. Triển khai DaemonSet

Inspektor Gadget cần một “manager” trên mỗi node để tải các chương trình eBPF. Chạy lệnh này để triển khai các tài nguyên cần thiết vào namespace gadget:

kubectl gadget deploy

Chờ khoảng 30 giây, sau đó xác nhận rằng các pod đang ở trạng thái Running trên các node của bạn.

Các kịch bản debug thực tế

Hãy tạm gác lý thuyết sang một bên và giải quyết một số vấn đề thực tế.

Bắt các tiến trình lạ

Bạn đã bao giờ thắc mắc liệu một container có bị xâm nhập hoặc đang chạy các script trái phép không? Gadget trace exec ghi lại mọi tiến trình mới ngay khi nó bắt đầu.

kubectl gadget trace exec --namespace production --pod-label app=payment-gw

Lệnh này sẽ truyền dữ liệu thời gian thực cho thấy chính xác những lệnh nào đang được thực thi. Nếu bạn thấy curl http://malicious-site.com hoặc /bin/sh bên trong một container vốn chỉ nên chạy file thực thi Java, bạn đã tìm thấy một lỗ hổng bảo mật lớn.

Giải mã bí ẩn lỗi “Connection Refused”

Mạng trong Kubernetes rất phức tạp. Khi một dịch vụ không thể kết nối, đó là do lỗi DNS, do NetworkPolicy chặn, hay do mất gói tin? Hãy sử dụng trace tcp để xem quá trình bắt tay (handshake) theo thời gian thực:

kubectl gadget trace tcp --namespace my-app

Bạn sẽ thấy IP nguồn, cổng đích và trạng thái TCP. Nếu bạn thấy gói SYN được gửi đi nhưng không có SYN-ACK phản hồi, các gói tin của bạn có khả năng đang bị chặn bởi tường lửa hoặc Service Mesh bị cấu hình sai.

Xác định lỗi Permission Denied

Khi một ứng dụng báo “File not found”, nhưng bạn vẫn thấy tệp đó khi thực hiện exec vào pod, đó thường là do không khớp quyền hạn. Gadget trace open hiển thị mọi nỗ lực truy cập tệp và mã trả về của nó:

kubectl gadget trace open --namespace backend --pod-label component=db

Hãy tìm các mã trả về như -13 (EACCES). Nó cho bạn biết chính xác đường dẫn tệp nào gây ra lỗi, giúp bạn tiết kiệm hàng giờ kiểm tra ls -la thủ công.

Tự động hóa bảo mật đặc quyền tối thiểu

Gadget advise network-policy là một công cụ tiết kiệm thời gian cực lớn. Thay vì phải viết YAML cho NetworkPolicies một cách thủ công, bạn có thể ghi lại lưu lượng thực tế của ứng dụng và để công cụ tự tạo chính sách cho bạn.

  1. Ghi lại: Chạy kubectl gadget advise network-policy monitor --namespace staging --output ./traffic.json trong 10 phút khi đang chạy các bài kiểm tra tích hợp (integration tests).
  2. Tạo chính sách: Chạy kubectl gadget advise network-policy report --input ./traffic.json.

Nó sẽ xuất ra một Kubernetes NetworkPolicy sẵn sàng cho production, chỉ cho phép các lưu lượng cụ thể mà ứng dụng của bạn thực sự cần.

Vận hành an toàn trên Production

Mặc dù eBPF rất hiệu quả, bạn không nên để các trình theo dõi này chạy mãi mãi. Tôi khuyên bạn nên tuân thủ các nguyên tắc sau:

  • Lọc dữ liệu chặt chẽ: Đừng bao giờ chạy trace trên toàn bộ cụm cluster mà không có bộ lọc. Luôn sử dụng --namespace hoặc --pod-label để giữ cho khối lượng dữ liệu ở mức có thể kiểm soát được.
  • Phiên làm việc có mục tiêu: Sử dụng các gadget như một con dao mổ của bác sĩ phẫu thuật. Bật chúng lên để xác định lỗi, sau đó tắt đi. Để giám sát dài hạn, hãy sử dụng các metric tiêu chuẩn.
  • Kiểm soát RBAC: Đảm bảo chỉ những kỹ sư SRE được ủy quyền mới có thể chạy kubectl gadget, vì nó cung cấp khả năng hiển thị sâu vào các dữ liệu hệ thống nhạy cảm.

Tổng kết

Inspektor Gadget biến “hộp đen” Kubernetes thành một môi trường minh bạch. Bằng cách đưa các sự kiện kernel cấp thấp lên và ánh xạ chúng với các khái niệm Kubernetes cấp cao, nó loại bỏ việc phỏng đoán khi debug. Cho dù bạn đang khắc phục sự cố bắt tay TCP thất bại hay kiểm tra quyền truy cập tệp, eBPF cung cấp cho bạn sự thật mà không làm treo môi trường production của bạn.

Share: