Cơn ác mộng lúc 3 giờ sáng: Tại sao cảnh báo Kubernetes tiêu chuẩn là chưa đủ
Đó là 3 giờ sáng ngày thứ Ba. Điện thoại của bạn rung lên trên tủ đầu giường với cảnh báo PagerDuty: CrashLoopBackOff trên một microservice quan trọng. Bạn loạng choạng đi đến bàn làm việc và bắt đầu quy trình thủ công quen thuộc. Bạn chạy kubectl get pods để tìm tên, sau đó là kubectl logs --previous để xem lý do tại sao nó bị sập, và cuối cùng là kubectl describe pod để kiểm tra lỗi OOMKills.
Vào lúc bạn thu thập đủ thông tin ngữ cảnh để bắt đầu sửa lỗi, 20 phút đã trôi qua. Trong khi đó, người dùng của bạn đang phải đối mặt với lỗi 500. Khoảng cách này—thời gian dành cho việc săn lùng thông tin cơ bản—là lý do khiến nhiều đội ngũ gặp khó khăn với chỉ số Thời gian trung bình để phục hồi (MTTR) cao. Việc chuyển đổi từ một người “chữa cháy” thụ động sang một kỹ sư DevOps chủ động phụ thuộc vào việc bạn có thể thu hẹp khoảng cách thông tin này nhanh đến mức nào.
Vấn đề không phải là do Prometheus hay Alertmanager bị lỗi. Chúng đã làm tốt nhiệm vụ của mình khi nhận thấy một chỉ số vượt quá giới hạn. Vấn đề là các cảnh báo tiêu chuẩn thường bị “mù”. Chúng cho bạn biết ngôi nhà đang cháy, nhưng không hề đề cập đến việc đám cháy bắt đầu từ phòng nào hay bình chữa cháy nằm ở đâu.
Nguyên nhân gốc rễ: Khoảng cách thông tin trong giám sát truyền thống
Các hệ thống giám sát truyền thống như Prometheus và Grafana được xây dựng cho các chỉ số (metrics), không phải để khắc phục sự cố ngay lập tức. Khi một cảnh báo gửi đến Slack, nó thường là một bức tường văn bản khô khan. Bạn thấy các nhãn như severity="critical" và instance="10.0.x.x", nhưng không có gì thực sự giải thích về nguyên nhân thất bại.
Việc ứng phó sự cố chậm chạp thường xuất phát từ ba điểm gây cản trở cụ thể:
- Chuyển đổi ngữ cảnh (Context Switching): Bạn lãng phí thời gian khi nhảy qua lại giữa Slack, cửa sổ terminal và các dashboard Grafana khác nhau.
- Dữ liệu tạm thời (Ephemeral Data): Kubernetes mang tính động. Khi bạn đăng nhập vào, một pod có thể đã khởi động lại, xóa sạch các log hoặc sự kiện giải thích nguyên nhân gây sập.
- Lặp lại thủ công: Nhiều lỗi có thể dự đoán được cách xử lý. Nếu đĩa cứng đầy 90%, bạn sẽ xóa cache. Việc thực hiện các bước này một cách thủ công mỗi lần sẽ làm tiêu tốn nguồn lực kỹ thuật.
So sánh các phương pháp ứng phó sự cố
Hầu hết các đội ngũ cố gắng giải quyết vấn đề “mệt mỏi vì cảnh báo” (alert fatigue) theo một trong ba cách. Hiểu rõ các cách này sẽ giúp bạn tránh được những sai lầm phổ biến.
1. Runbook thủ công
Đội ngũ làm theo một tệp PDF hoặc trang Wiki. Cách này chậm và dễ xảy ra sai sót do con người. Nó cũng khiến ca trực (on-call) trở thành nỗi ám ảnh đối với các kỹ sư mới, những người chưa có kiến thức sâu về cluster.
2. Mã tùy chỉnh (Glue Code)
Một số đội ngũ xây dựng các hàm Lambda hoặc webhook tùy chỉnh để lấy log khi có cảnh báo. Cách này hiệu quả trong một hoặc hai tháng đầu. Cuối cùng, nó trở thành một cơn ác mộng về bảo trì khi bạn phải quản lý một codebase phức tạp chỉ để quản lý các cảnh báo của mình.
3. Công cụ tự động hóa (Robusta)
Robusta là một framework mã nguồn mở được xây dựng dành riêng cho Kubernetes. Nó hoạt động dựa trên hệ thống Prometheus hiện có của bạn. Thay vì chỉ chuyển tiếp thông báo, nó thực hiện các “Playbook”. Đây là các quy trình làm việc tự động giúp lấy log, chạy chẩn đoán và thậm chí có thể thực hiện các hành động tự phục hồi ngay khi sự cố xảy ra.
Triển khai Robusta để tự động hóa thông minh
Robusta thu hẹp khoảng cách giữa các chỉ số thô và dữ liệu có thể hành động. Nó diễn giải các cảnh báo và bổ sung chính xác thông tin bạn cần. Hãy làm theo các bước sau để thay đổi trải nghiệm trực chiến của bạn.
Bước 1: Cài đặt Robusta CLI và Helm Chart
Bắt đầu bằng cách sử dụng Robusta CLI để tạo cấu hình. Tôi khuyên bạn nên sử dụng môi trường ảo Python để giữ cho thiết lập cục bộ được gọn gàng.
pip install robusta-cli --upgrade
robusta gen-config
Lệnh gen-config sẽ yêu cầu bạn cung cấp đích đến cho cảnh báo, chẳng hạn như Slack hoặc MS Teams. Nó tạo ra tệp generated_values.yaml chứa các khóa tích hợp của bạn. Bây giờ, hãy triển khai Robusta vào cluster của bạn:
helm repo add robusta https://robusta-charts.storage.googleapis.com
helm repo update
helm install robusta robusta/robusta -f generated_values.yaml
Bước 2: Trải nghiệm bổ sung thông tin trên Slack
Khi Robusta đã hoạt động, nó sẽ tự động kết nối với Alertmanager của bạn. Hãy xem xét một cảnh báo KubePodCrashLooping. Nếu không có Robusta, bạn chỉ nhận được một dòng văn bản. Với Robusta, tin nhắn Slack sẽ đi kèm với 20 dòng log cuối cùng của pod và danh sách các sự kiện Kubernetes gần đây đã được đính kèm sẵn.
Đây là một bước ngoặt lớn. Bạn có thể phát hiện lỗi java.lang.OutOfMemoryError hoặc lỗi hết thời gian kết nối cơ sở dữ liệu ngay trên điện thoại của mình. Bạn thậm chí không cần mở laptop mà vẫn biết chính xác điều gì đã xảy ra.
Bước 3: Tự động xử lý lỗi OOMKills
Thông tin ngữ cảnh rất tuyệt vời, nhưng tự động hóa còn tốt hơn. Hãy cùng cấu hình một playbook cho các pod bị sập do cạn kiệt bộ nhớ (OOMKilled). Chúng ta muốn Robusta hiển thị biểu đồ sử dụng bộ nhớ dẫn đến thời điểm sập để có thể thấy được sự đột biến.
Thêm đoạn mã sau vào tệp generated_values.yaml của bạn:
customPlaybooks:
- triggers:
- on_pod_oom_killed:
rate_limit: 3600
actions:
- pod_oom_killer_analysis:
- prometheus_graph:
graph_title: "Sử dụng bộ nhớ trước khi OOMKill"
promql_query: 'node_memory_MemFree_bytes{node="$node_name"}'
- slack_enrichment: {}
Sau khi thực hiện helm upgrade nhanh chóng, Robusta sẽ thực hiện phân tích sâu mỗi khi một pod chạm ngưỡng giới hạn. Bạn sẽ nhận được một biểu đồ hiển thị xu hướng bộ nhớ, cho phép bạn quyết định ngay lập tức xem có cần điều chỉnh resource requests trong manifest deployment hay không.
Bước 4: Sử dụng Trigger thủ công để tự phục hồi
Bạn có thể không muốn hệ thống tự động xóa pod, nhưng bạn có thể tạo cho mình tùy chọn để thực hiện việc đó chỉ với một cú nhấp chuột. Robusta hỗ trợ các nút Slack tương tác. Bạn có thể thêm nút “Restart Deployment” trực tiếp vào cảnh báo của mình.
- triggers:
- on_prometheus_alert:
alert_name: KubePodNotReady
actions:
- pod_details_enricher: {}
- add_silence_button: {}
- restart_deployment_button: {}
Nếu một pod bị treo, bạn chỉ cần nhấn vào “Restart Deployment” trên Slack. Điều này cắt giảm MTTR từ vài phút thao tác trên terminal xuống còn khoảng năm giây.
Tổng kết: Thay đổi trọng tâm
Từ bỏ các “cảnh báo vô tri” là một bước tiến lớn hướng tới một văn hóa DevOps trưởng thành. Bằng cách sử dụng một công cụ tự động hóa như Robusta, bạn ngừng đóng vai trò là người thu thập dữ liệu và bắt đầu đóng vai trò là người ra quyết định. Bạn không chỉ sửa lỗi nhanh hơn; bạn đang xây dựng một hệ thống kiên cố hơn.
Hãy bắt đầu từ những bước nhỏ bằng cách cài đặt Robusta với các thiết lập mặc định. Khi bạn thấy được giá trị của việc đính kèm log vào cảnh báo, hãy bắt đầu thêm các playbook cho những vấn đề thường gặp nhất, chẳng hạn như áp lực đĩa cứng (disk pressure) hoặc hết hạn chứng chỉ. Đội ngũ của bạn sẽ làm việc hiệu quả hơn, và bạn thực sự có thể có được những giấc ngủ ngon.

