7 điểm bởi dongho42 2 giờ trước | Chưa có bình luận nào. | Chia sẻ qua WhatsApp

Mở đầu

Khi dịch vụ phát triển, các tín hiệu cần theo dõi trong quá trình vận hành cũng tăng lên. Trong bài viết này, chúng tôi giới thiệu quá trình quản lý Alert bằng codechuẩn hóa luồng ứng phó nối tiếp qua Slack và PagerDuty.

Mục tiêu ban đầu rất đơn giản: tạo Alert dễ hơn, gửi đi dễ nhìn hơn, và làm rõ ai là người cần xem. Sau đó, trong quá trình vận hành, chúng tôi tiếp tục cải thiện cả grouped Alert, định nghĩa lặp lại, tự động hóa ứng phó và độ ổn định của hệ thống giám sát.


Động lực

Có nhiều cách để nâng cao tính sẵn sàng của dịch vụ và giảm tác động đến người dùng

Trong số đó, công việc lần này tập trung vào cải thiện hệ thống Alert

Alert gần giống một giao diện vận hành kết nối giữa phòng ngừa sự cố và ứng phó sự cố. Nếu phát hiện tín hiệu rủi ro sớm hơn, ta có thể xử lý trước khi nó dẫn đến sự cố thực tế; và ngay cả sau khi sự cố xảy ra, người phụ trách cũng có thể nhận biết nhanh hơn và bắt đầu ứng phó

Hướng cải thiện khi đó cũng rất rõ ràng: nắm bắt tín hiệu rủi ro tốt hơn, giúp người phụ trách nhận ra nhanh hơn, dẫn ngay đến việc điều tra và ứng phó, và giảm bớt các luồng ứng phó lặp lại

Dù không bắt đầu bằng việc đo lường định lượng mọi thứ ngay từ đầu, chúng tôi có nhận thức rõ ràng rằng Alert không chỉ là thông báo đơn thuần, mà phải trở thành một hệ thống vận hành giúp phòng ngừa sự cố và kết nối tới ứng phó


Vai trò của Alert

Để có một dịch vụ ổn định, việc phòng ngừa sự cố là quan trọng, nhưng phát hiện nhanh các dấu hiệu bất thường của dịch vụ đang vận hành cũng quan trọng không kém

Ở điểm này, Alert đảm nhận hai vai trò. Trước khi sự cố xảy ra, nó giúp nhận biết nhanh tín hiệu rủi ro và chủ động xử lý trước khi dẫn đến sự cố thực tế; sau khi sự cố xảy ra, nó thông báo vấn đề cho người phụ trách và kết nối tới các hành động tiếp theo như context, Runbook, Dashboard, Log, Silence cần thiết để nắm bắt tình hình

Nói cách khác, Alert không chỉ là thông báo cho biết "đã xảy ra vấn đề", mà gần giống một giao diện vận hành kết nối phòng ngừa và ứng phó sự cố


Những điểm chưa hài lòng ở các Alert hiện có

Có ba điểm lớn chưa hài lòng ở các Alert hiện có: khó tạo, nhận được cũng khó hiểu ngay, và không rõ ai phải ứng phó và quản lý

Khó tạo Alert

Khi đó, việc tạo và chuyển tiếp Alert liên quan đến nhiều hệ thống như Grafana, Slack, PagerDuty, CloudWatch, EventBridge, Lambda, và nguồn dữ liệu cũng rất đa dạng như NewRelic, VictoriaMetrics, Steampipe, OpenSearch, Druid, MySQL

Cách làm cũng khác nhau theo từng Alert. Có Alert được gửi thẳng từ Grafana đến Slack, có Alert gắn Lambda sau CloudWatch Alarm, có Alert dùng Steampipe để truy vấn trạng thái tài nguyên AWS rồi phán đoán, và với trường hợp cần tích hợp PagerDuty thì còn phải cân nhắc cấu hình riêng

Vấn đề là thiếu convention ở cấp tổ chức. Việc quản lý Alert nào ở đâu, chỉ gửi Slack hay nối đến cả PagerDuty, đưa mô tả và link nào vào message, quản lý team phụ trách và tuyến chuyển tiếp ở đâu... đều chưa được sắp xếp đầy đủ

Kết quả là Alert vẫn được tạo mỗi khi cần, nhưng theo thời gian, cách tạo và cách quản lý ngày càng phân mảnh

Khó xem Alert

Việc tạo Alert không có nghĩa là message Slack thực tế luôn ở dạng dễ nhìn. Tùy theo người tạo và hệ thống, format và chất lượng thông tin khác nhau; có Alert có tiêu đề dài và phức tạp, có Alert để lộ nguyên các giá trị nội bộ như Value hay Labels

Ngay cả khi có link, cũng có trường hợp không rõ phải xem gì trước; dù có nút Dashboard hay Log nhưng thực tế lại không được tích hợp. Ngoài ra, do thiếu context của Alert, nhiều trường hợp người phụ trách phải tự tìm lại service, cluster, resource và khoảng thời gian

Trong tình huống sự cố, chênh lệch vài phút cũng được cảm nhận rất lớn. Vì vậy, ngay khi nhận Alert, cần có thể nắm bắt ngay đây là vấn đề gì, quan trọng đến mức nào, là vấn đề của service và resource nào, cần kiểm tra đâu trước, và hành động tiếp theo là gì

Khó quản lý trách nhiệm ứng phó với Alert

Khi Alert kêu, cũng có những trường hợp không rõ ai phải kiểm tra và ứng phó. Nếu team hoặc người phụ trách không được thể hiện rõ, người thấy Alert trước tiên phải tự phán đoán "cái này mình có phải xem không?", "nên hỏi ai đây?"; trong tình huống sự cố, cả phán đoán ngắn ngủi này cũng có thể dẫn đến chậm trễ ứng phó

Không chỉ trách nhiệm ứng phó sau khi Alert kêu, việc ai sở hữu và quản lý chính Alert đó cũng quan trọng. Cần thể hiện rõ Alert liên quan đến service của team nào, ai có thể thay đổi điều kiện, sẽ review message hoặc threshold như thế nào, và ai sẽ dọn dẹp các Alert cũ

Tóm lại, các tình huống muốn cải thiện là như sau

  • Cách tạo và quản lý Alert bị phân mảnh
  • Ngay cả khi nhận Alert cũng khó nắm bắt ý nghĩa trong nháy mắt
  • Khi Alert kêu, không rõ ai phải kiểm tra và ứng phó
  • Không rõ team nào phải sở hữu và quản lý chính Alert đó

Đã cải thiện những gì và như thế nào

Hướng cải thiện gồm ba điểm: chuẩn hóa cách tạo Alert, cung cấp nhất quán thông tin cần thiết trong message Slack theo một cấu trúc thống nhất, và sắp xếp cấu trúc để mỗi Alert đều thể hiện người phụ trách và tuyến chuyển tiếp

Chuẩn hóa cách tạo và quản lý Alert

Trước hết, chúng tôi gom cách tạo và quản lý Alert về một mối. Việc đánh giá và thực thi Alert rule được thống nhất trên Grafana, phần tích hợp giữa Grafana·Slack·PagerDuty được trừu tượng hóa bằng Terraform Module, và mọi định nghĩa Alert được quản lý bằng IaC dưới thư mục alerts/ trong repo alerts nội bộ. Việc kết nối kênh Slack, tích hợp PagerDuty, format message và tạo các nút chung cũng được sắp xếp để module chung xử lý

Giờ đây, thay vì phải hiểu toàn bộ pipeline Alert, người viết Alert có thể tập trung hơn vào cần phát hiện điều kiện nào, Alert quan trọng đến mức nào, ai cần kiểm tra, và cần thông tin gì để ứng phó

Trong repo, chúng tôi quản lý cùng lúc cách viết, cấu trúc thư mục, các field cần thiết và convention khuyến nghị; nhờ quản lý Alert bằng code, review và lịch sử thay đổi cũng được lưu lại theo từng PR và commit

Cấu trúc thư mục Alert

Tất cả Alert được sắp xếp để tuân theo cấu trúc {main-category}/{sub-category}/{severity}/{alert-name}.yml

Ví dụ như sau

  • infra/kubernetes/critical/pod-unhealthy.yml
  • data/airflow/warning/task-failed.yml
  • finops/aws/warning/cost-increase.yml

Thông qua cấu trúc này, chỉ cần nhìn vị trí file cũng có thể nắm được đây là Alert thuộc lĩnh vực nào, được xử lý với mức độ nghiêm trọng nào; đồng thời có thể dùng làm tiêu chuẩn để gom xem các Alert của một lĩnh vực cụ thể, kiểm tra Alert trùng lặp và Alert cũ, hoặc liên kết kênh Slack, PagerDuty Service, CODEOWNERS

Cách định nghĩa Alert

Trong mỗi file Alert có chứa các thông tin như datasource, query, threshold, condition, message

Chúng tôi không tạo mới một DSL riêng. Cách này gần với việc biểu diễn bằng YAML nội dung Grafana Alert được serialize thành JSON; nhờ đó, hầu hết các Alert có thể định nghĩa trong Grafana đều có thể được đưa vào IaC với cùng cấu trúc

Gần đây chúng tôi cũng đang tận dụng LLM. Khi con người mô tả bằng ngôn ngữ tự nhiên rằng "muốn nhận Alert với message nào trong điều kiện nào", LLM sẽ tham khảo các ví dụ và convention hiện có để tạo bản nháp định nghĩa Alert ở dạng YAML. Nhờ vậy, người viết Alert có thể tập trung hơn vào cần phát hiện điều gì và vì sao cần thiết, thay vì format serialize phức tạp

Làm cho message Alert có thể hiểu và ứng phó ngay

Chúng tôi cũng xem message Alert như một interface. Trong tình huống sự cố, thường không có nhiều thời gian để diễn giải message một cách chậm rãi, nên dù Alert nào đến, người nhận cũng cần có thể kiểm tra cùng loại thông tin ở cùng một vị trí

Vì vậy, chúng tôi đã sắp xếp cấu trúc tin nhắn Slack một cách nhất quán. Tiêu đề chứa tên Alert, trạng thái và mức độ nghiêm trọng; phần nội dung chứa mô tả mà con người có thể hiểu ngay, cùng người phụ trách, đội, dịch vụ, region, tên tài nguyên và các label chính. Các nút cũng được chia thành nút chung và nút tùy chọn: mặc định cung cấp IaC, PagerDuty, Silence, và chỉ khi cần mới hiển thị Runbook, Dashboard, Log

Các nút chung được hệ thống tự động tạo và liên kết, đồng thời mọi thay đổi trạng thái của Alert cũng được để lại trong Slack thread. Nhờ đó có thể xem toàn bộ diễn tiến trong một luồng: ai đã Acknowledge, xử lý từ Slack hay từ PagerDuty, Resolve vào lúc nào, và trong quá trình ứng phó đã để lại những ghi chú nào

Kết quả là dù ai tạo Alert nào, hình thức hiển thị trên Slack cũng trở nên tương tự nhau, và các thành viên có thể phán đoán nhanh hơn nên nhìn vào đâu

Làm rõ cấu trúc trách nhiệm của Alert

Điều quan trọng không kém việc nhìn Alert là hiểu ngay, là làm nổi bật ai chịu trách nhiệm kiểm tra Alert đó

Vì vậy, chúng tôi tận dụng thông tin tag và label của tài nguyên trong luồng ứng phó. Thay vì chỉ định trực tiếp đội hoặc người phụ trách cho từng Alert, chúng tôi dùng metadata như dịch vụ, đội, tài nguyên, môi trường để Slack message tự động mention đúng đội và người phụ trách phù hợp

Đường đi khi gửi cũng được sắp xếp theo cùng một bộ quy tắc. Dựa trên phân loại và severity của Alert, Slack channel, PagerDuty Service và Escalation Policy được tự động liên kết; Alert mức Warning chỉ được gửi tới Slack channel, còn Critical Alert có tác động tới người dùng hoặc khả năng gây sự cố lớn thì tạo cả PagerDuty Incident

Chúng tôi cũng sử dụng CODEOWNERS. Các file Alert được chia thành thư mục theo category và phạm vi dịch vụ, đội phụ trách từng đường dẫn được chỉ định trong CODEOWNERS, để ngay trong repo có thể thấy đội nào sở hữu khu vực Alert nào

Kết quả là trách nhiệm của Alert được quản lý ở hai điểm. Khi Alert thực sự phát ra, đội và người phụ trách được mention dựa trên tag và label, còn khi thay đổi định nghĩa Alert, có thể kiểm tra đó là phạm vi của đội nào dựa trên cấu trúc thư mục và CODEOWNERS

Vai trò của Alert proxy

Để cấu trúc này thực sự hoạt động, cần có một lớp trung gian diễn giải và chuyển tiếp Alert. Vì vậy, chúng tôi đặt một proxy dựa trên AWS Lambda giữa Grafana, Slack và PagerDuty

Grafana đánh giá Alert rule và gửi webhook. Proxy nhận webhook này, diễn giải Alert context như category, severity, label, annotation, fingerprint, rồi quyết định sẽ gửi tới Slack channel nào, tạo PagerDuty Incident nào, mention ai, gắn nút nào, cập nhật Slack thread hiện có ra sao, và quản lý lifecycle Ack/Resolve thế nào

Nói cách khác, nếu Terraform module và cấu trúc thư mục đã chuẩn hóa "định nghĩa Alert như thế nào", thì proxy đảm nhận vai trò kết nối để định nghĩa đó được hiển thị và vận hành theo cùng một cách trong luồng vận hành thực tế

Nhờ proxy, chúng tôi có thể quản lý nhất quán tại một nơi các phần như format tin nhắn Slack, mention người phụ trách, tích hợp PagerDuty, cập nhật Slack thread, tương tác Ack/Resolve; về sau cũng có thể dễ dàng mở rộng các cải tiến như grouped Alert, custom action button, tích hợp AI agent, mô hình Alert chung


Còn điều gì chưa hài lòng

Sau cải tiến đầu tiên, định nghĩa Alert được quản lý bằng IaC, còn Slack message và đường đi khi gửi cũng vận hành theo các quy tắc nhất quán. Nhưng hệ thống Alert không phải là công cụ chỉ tạo một lần rồi xong. Sau gần một năm vận hành, khi số lượng Alert tăng lên, những vấn đề mới bắt đầu lộ ra: làm sao hiển thị nhiều instance phát sinh trong cùng một Alert, quản lý các định nghĩa Alert lặp lại thế nào, sau khi con người nhìn thấy Alert thì có thể thực sự làm gì, và làm sao đảm bảo cũng như kiểm chứng độ ổn định của chính hệ thống Alert

Khó quan sát khi cùng một Alert đồng thời phát ra cho nhiều đối tượng

Khi việc tạo Alert trở nên dễ hơn, số lượng Alert cũng tự nhiên tăng lên. Khi đó, điều đặc biệt bất tiện là trường hợp một Alert rule đồng thời phát ra cho nhiều đối tượng

Trong Grafana, dù cùng một rule, nếu giá trị label như region, name, node, pod, app khác nhau thì mỗi giá trị được xem là một Alert instance riêng. Ví dụ, khi có Pod unhealthy Alert, nếu nhiều pod đồng thời rơi vào trạng thái unhealthy thì mỗi pod sẽ sinh ra một Alert instance

Grafana vốn đã có tính năng Alert Grouping, nhưng chỉ gom lại thành group là chưa đủ. Điều quan trọng là phải hiển thị trạng thái của các Alert được gom nhóm sao cho người vận hành dễ hiểu: trong group có những đối tượng nào, đối tượng nào vẫn đang firing, đối tượng nào vừa resolve, có đối tượng mới được thêm vào hay không, và các thay đổi trạng thái trong cùng một group có được nối thành một luồng hay không

Định nghĩa Alert lặp lại ngày càng nhiều

Khi số lượng định nghĩa Alert tăng lên, cách sao chép YAML rồi chỉnh sửa từng chút cũng bắt đầu lộ giới hạn. Những Alert như SQS lag, CloudWatch error log, Pod OOM, ALB 5xx, Lambda error/throttle được tạo lặp đi lặp lại; ban đầu chỉ cần sao chép file cũ rồi đổi name, query, threshold, label là được

Nhưng khi số lượng file nhiều lên, việc sửa hành vi chung trở nên khó khăn, và dù là Alert cùng mục đích, dashboard link, cấu hình labels, cách biểu diễn threshold lại dần khác nhau. Vì vậy, cần có một cấu trúc có thể tái sử dụng các pattern lặp lại

Sau khi xem Alert, vẫn còn khoảng cách đến hành động tiếp theo

Việc gắn các nút Runbook, Dashboard, IaC, PagerDuty vào Slack message có ích, nhưng trong ứng phó sự cố thực tế, chỉ có link thôi thường là chưa đủ. Đặc biệt Runbook rõ ràng có hiệu quả, nhưng không dễ để gắn một Runbook tốt cho mọi Alert và liên tục duy trì chúng ở trạng thái mới nhất

Ngoài ra, trong ứng phó thực tế, các tác vụ điều tra tương tự nhau lặp đi lặp lại, như kiểm tra log Kubernetes, kiểm tra trạng thái pod, kiểm tra rollout history, kiểm tra chỉ số SQS·Lambda, kiểm tra error log. Phần lớn các tác vụ này diễn ra bên ngoài Slack message; người phụ trách phải đọc label và value từ Alert, chuyển sang công cụ khác, nhập lại giá trị rồi chia sẻ kết quả trở lại Slack thread

Cuối cùng, cải tiến đầu tiên đã giúp đọc Alert tốt hơn, nhưng việc điều tra và ứng phó vẫn còn nằm khá nhiều bên ngoài Alert message

SPOF trong hệ thống monitoring tăng lên

Khi sắp xếp lại hệ thống Alert, các điểm có thể trở thành SPOF cũng tăng lên. Việc định nghĩa và triển khai Alert rule được gom về alerts repo và Terraform; Grafana đảm nhận đánh giá Alert rule; còn Slack message, PagerDuty Incident và lifecycle Ack/Resolve do proxy quản lý

Việc vai trò trở nên rõ ràng là một thay đổi tốt, nhưng khả năng toàn bộ luồng Alert bị ảnh hưởng khi các điểm đó thất bại cũng tăng lên. Điều khó hơn là những thất bại như vậy có thể không dễ lộ ra bên ngoài. Nếu đường dẫn dùng để thông báo bất thường của các hệ thống khác âm thầm dừng lại, ngay cả khi sự cố thực sự xảy ra cũng có thể không ai biết

Cuối cùng, điều này dẫn tới câu hỏi "ai sẽ monitoring hệ thống monitoring"


Cải tiến thứ hai

Cải tiến đầu tiên đã định hình khung cơ bản của hệ thống Alert, nhưng khi việc tạo và gửi Alert trở nên dễ hơn, các vấn đề cần xem xét trong quá trình vận hành cũng thay đổi

Ở cải tiến thứ hai, chúng tôi tập trung vào bốn điểm. Khi nhiều đối tượng đồng thời phát ra từ cùng một Alert rule, gom các thay đổi trạng thái thành một luồng để có thể nhìn tổng quan, cho phép tái sử dụng các định nghĩa Alert lặp lại dưới dạng pattern chung, bổ sung Runbook đồng thời kết nối các tác vụ điều tra lặp lại và một số tác vụ giảm thiểu có giới hạn vào nút Slack, và đo lường, kiểm chứng độ ổn định của các đường dẫn định nghĩa, đánh giá và chuyển tiếp Alert có thể trở thành SPOF

Xử lý Grouped Alert đúng cách

Trước tiên, chúng tôi đã cải thiện cách biểu diễn grouped Alert. Khi nhiều instance trong cùng một Alert rule cùng phát cảnh báo, nếu gửi từng cái như một tin nhắn độc lập thì kênh Slack sẽ trở nên rối; ngược lại, nếu chỉ gom tất cả vào một group thì lại dễ bỏ sót tài nguyên nào thực sự đang gặp vấn đề.

Điểm cốt lõi là gom nhóm, nhưng không làm mất trạng thái bên trong nhóm đó. Trên Slack, grouped Alert được hiển thị bằng một tin nhắn đại diện, đồng thời hiển thị các đối tượng hiện đang bị ảnh hưởng; khi có đối tượng mới được thêm vào hoặc đối tượng cũ được xử lý xong, thay đổi đó sẽ được ghi lại trong cùng một thread. Khi có nhiều thay đổi trạng thái xảy ra cùng lúc, các thay đổi sẽ được gom thành batch để hiển thị, và phía PagerDuty cũng được điều chỉnh để trỏ tới cùng một vấn đề như grouped Alert đang thấy trên Slack.

Kết quả là có thể xem nhiều Alert phát sinh từ cùng một nguyên nhân trên Slack như một luồng duy nhất.

Giảm các định nghĩa Alert lặp lại

Cách sao chép rồi chỉnh sửa từng chút một sẽ làm tăng chi phí bảo trì và khả năng mắc lỗi khi số lượng Alert tăng lên. Để giảm điều này, chúng tôi đã thêm global/templatesmatrix.

global/templates là chức năng định nghĩa cấu trúc Alert lặp lại dưới dạng template chung, còn matrix là chức năng mở rộng cùng một Alert thành nhiều Alert theo các tổ hợp region, queue, datasource, service khác nhau.

Chúng tôi tạo template cho các mẫu lặp lại như SQS queue lag, CloudWatch error log, Pod OOM trên nhiều cluster, ALB 5xx, Lambda error/throttle, ECS memory/CPU/max-capacity, và chỉ đưa các giá trị thay đổi như tên queue, region, cluster, threshold, biến dashboard vào matrix.

Nhờ vậy, có thể sửa cấu trúc tin nhắn chung, nút bấm, cách xử lý liên kết Runbook/dashboard và cách xử lý datasource ở một nơi, đồng thời giảm các sai lệch và chi phí bảo trì phát sinh khi số lượng Alert tăng lên.

Bắt đầu ứng phó ngay từ tin nhắn Slack

Tiếp theo, chúng tôi tăng những việc có thể làm ngay trong tin nhắn Slack. Liên kết Runbook và dashboard vẫn quan trọng, nhưng chúng tôi muốn giảm bớt trong tin nhắn Slack các thao tác tra cứu lặp đi lặp lại hoặc các thao tác giảm nhẹ có phạm vi hạn chế.

Vì vậy, ngoài các nút hiện có, chúng tôi đã thêm custom action button. Khi định nghĩa lệnh trong message.actions của Alert YAML, lệnh sẽ được hiển thị thành nút trong tin nhắn Slack; khi nhấn nút, proxy sẽ thực thi lệnh bằng một Lambda invocation riêng, rồi để lại bình luận trong cùng thread Slack về việc ai đã nhấn nút nào và kết quả thực thi ra sao.

Các nút này cho phép cung cấp các tác vụ như tra cứu log, kiểm tra trạng thái Kubernetes rollout, rollout restart trong các tình huống hạn chế, thực thi một lệnh đơn lẻ, hoặc thực thi tuần tự nhiều lệnh.

Phần được chú trọng nhất là an toàn. Nếu tên nút kết thúc bằng !, Slack confirm dialog sẽ được hiển thị; các giá trị label như ${labels.namespace}, ${labels.pod} được thay thế vào lệnh nhưng có áp dụng shell quoting để ngăn command injection; những tác vụ cần quyền bổ sung sẽ assume IAM role thông qua actionRole. Việc sử dụng role không được phép được xử lý theo cơ chế fail-closed, còn webhook và tương tác Slack được xác minh lần lượt bằng Bearer token, chữ ký HMAC-SHA256 và replay protection.

Tích hợp với AI agent

Chúng tôi cũng muốn giảm quá trình thu thập thông tin cần thiết sau khi nhận Alert. Vì vậy, chúng tôi đã kết nối AI agent nội bộ abot vào luồng Alert.

Khi nhấn nút abot trong tin nhắn Slack, proxy sẽ gom tên Alert, mô tả, labels, values, liên kết IaC và context người dùng nhập thêm trong modal rồi gửi yêu cầu phân tích. abot hoạt động bằng identity dựa trên OAuth của người đã nhấn nút, để ngay cả khi truy vấn các thông tin cần thiết từ Grafana, AWS, Kubernetes, v.v., nó cũng chỉ lấy trong phạm vi người dùng đó thực sự có quyền xem.

Kết quả phân tích được để lại dưới dạng bình luận trong cùng thread Slack. Kết quả này cũng ghi lại những metric và log đã kiểm tra, những khả năng nào nên được ưu tiên nghi ngờ, và các manh mối có thể tổng hợp vào RCA; nhờ đó có thể giảm thời gian mở nhiều hệ thống để thu thập lại thông tin.

Giám sát hệ thống monitoring

Ở lần cải tiến thứ hai, chính quá trình định nghĩa, đánh giá và chuyển tiếp Alert cũng được đưa vào đối tượng quan sát.

Trước tiên, chúng tôi thu thập các chỉ số vận hành của proxy. Các chỉ số như thời gian đến khi Ack, thời gian đến khi Resolve, số Alert hiện đang mở, Alert đã mở trong bao lâu, số lần cùng một Alert phát lại được thu thập; chúng tôi cũng thêm watchdog để phát hiện khi Lambda tiến gần đến timeout. Nếu proxy thất bại trong quá trình xử lý, nó sẽ lưu lại full stack trace cùng với event payload gốc.

Tuy nhiên, cách để proxy tự gửi thông báo có giới hạn. Vì nếu proxy chết trước cả khi gửi thông báo đó, Alert lẽ ra phải được gửi có thể bị bỏ sót hoàn toàn.

Vì vậy, chúng tôi đặt các cơ chế phát hiện bên ngoài proxy, dựa vào những hệ thống khác nhau. Một cơ chế là Grafana: metric do proxy gửi được đánh giá thành Alert trong monitoring domain để bộc lộ bất thường. Tuy nhiên, vì Grafana và VictoriaMetrics cùng nằm trên cùng EKS, nếu EKS hoặc Grafana chết toàn bộ thì sẽ không thể phát hiện.

Cơ chế còn lại là deadman switch. Khi Grafana bình thường, nó gửi /api/health dưới dạng heartbeat, và heartbeat này được CloudWatch nhận, độc lập với EKS. CloudWatch alarm sẽ coi là sự cố nếu heartbeat giảm hoặc bị missing; trong trường hợp này, nó sẽ thông báo trực tiếp tới PagerDuty và Slack mà không đi qua Grafana hay proxy.

Nói cách khác, phía phát hiện và phía bị phát hiện được đặt trên các hạ tầng khác nhau; nhờ đó, miễn là EKS và CloudWatch không chết cùng lúc, có thể biết được khi hệ thống monitoring bị down.


Các hạng mục cải tiến tiếp theo

Lần cải tiến thứ hai đã hoàn tất, nhưng vẫn còn những phần cần tiếp tục cải thiện.

Tận dụng đúng cách các chỉ số vận hành đã thu thập

Khi proxy thu thập các chỉ số vận hành Alert, chúng tôi có thể trả lời bằng dữ liệu cho các câu hỏi như Alert nào reo ở kênh nào với tần suất bao nhiêu, có Alert nào bị dồn quá nhiều vào một người phụ trách hoặc một team cụ thể không, hay có Alert nào chỉ lặp lại firing và auto resolve mà không có bất kỳ tương tác nào không.

Nhưng việc có thể xem dữ liệu và việc thực sự tinh chỉnh Alert dựa trên dữ liệu đó là hai chuyện khác nhau. Hiện vẫn chưa thực sự bắt tay vào các cải tiến theo hướng điều chỉnh threshold, gom các Alert tương tự, loại bỏ Alert không cần thiết, giảm noisy alert, và thực sự rút ngắn thời gian nhận biết cũng như thời gian xử lý.

Cải thiện Alert IaC

Hiện tại, định nghĩa Alert được triển khai bằng CI/CD từ repo alerts, nhưng vẫn đang phụ thuộc vào resource grafana_rule_group của Grafana Terraform provider. Vấn đề là chỉ cần sửa một rule, trong PR vẫn trông như toàn bộ rule group đã thay đổi nên diff khó đọc; đồng thời interval_seconds nằm ở cấp rule group, nên để đặt chu kỳ đánh giá khác nhau cho từng Alert thì phải chia nhỏ group.

Gần đây Grafana đã có alerting API mới để xử lý Alert rule giống như Kubernetes resource, và Terraform provider cũng đã thêm resource grafana_apps_rules_alertrule_v0alpha1. Vì vẫn còn ở alpha nên hiện chưa áp dụng ngay, nhưng khi stable, chúng tôi dự định xem xét chuyển từ grafana_rule_group hiện tại sang resource này.

Kỳ vọng rất rõ ràng: định nghĩa tách biệt rule group và rule, có được diff hiển thị gọn gàng chỉ phần thay đổi ngay cả khi chỉ sửa một rule, điều chỉnh chi tiết chu kỳ đánh giá theo từng rule, và sử dụng tài nguyên monitoring hiệu quả hơn.


Kết luận

Mục tiêu ban đầu rất đơn giản: làm cho Alert dễ tạo hơn, dễ hiểu ngay khi nhận được, và làm rõ ai là người chịu trách nhiệm.

Ở lần cải tiến đầu tiên, chúng tôi đã gom định nghĩa Alert bằng IaC, chuẩn hóa tin nhắn Slack và đường dẫn chuyển tiếp, kết nối mention người phụ trách với CODEOWNERS, và sắp xếp lại việc quản lý lifecycle Slack/PagerDuty thông qua proxy.

Những vấn đề lộ ra trong quá trình vận hành được xử lý ở vòng cải tiến thứ hai. Các Alert đổ về từ cùng một rule được gom lại để hiển thị thành một nhóm, các định nghĩa lặp lại được rút gọn bằng template và matrix, có thể bắt đầu điều tra và giảm thiểu ngay trong thông báo Slack, đồng thời cũng chuẩn bị cơ chế để nhận biết khi chính hệ thống monitoring dừng hoạt động.

Nhờ vậy, việc tạo, gửi và xử lý Alert trở nên dễ dàng hơn trước.

Tuy nhiên, việc có thể xem dữ liệu và việc thực sự cải thiện vận hành dựa trên dữ liệu đó là hai chuyện khác nhau. Nếu đến nay là giai đoạn chuẩn hóa hệ thống Alert và biến nó thành thứ có thể đo lường, thì từ giờ trở đi vẫn còn việc nhìn vào các chỉ số đó để thực sự cắt giảm và tinh chỉnh.


Có những nội dung không thể đưa vào bài viết này vì giới hạn dung lượng. Nếu muốn tìm hiểu chi tiết hơn, bạn nên đọc cả bài gốc.

Chưa có bình luận nào.

Chưa có bình luận nào.