Phân Loại Severity & Incident Command System
Tại sao chủ đề này quan trọng ở production
Phần lớn kỹ sư khi mới tiếp cận incident response nghĩ rằng "severity" chỉ là một nhãn mô tả mức độ nghiêm trọng — giống như gắn sao đánh giá. Đây là hiểu lầm nền tảng đầu tiên cần sửa. Severity không mô tả — severity kích hoạt. Nó là input cho một hàm quyết định: bao nhiêu người bị đánh thức lúc 3 giờ sáng, ai có quyền override quy trình bình thường, tốc độ escalation phải nhanh đến mức nào, và (quan trọng không kém) khi nào KHÔNG cần làm những điều đó.
Nếu không có một cơ chế severity rõ ràng, hai lỗi đối lập sẽ xảy ra song song trong cùng một tổ chức: một nhóm hoảng loạn huy động toàn bộ engineering cho một lỗi hiển thị sai màu nút bấm, trong khi một nhóm khác coi nhẹ một sự cố đang âm thầm làm mất dữ liệu vì "chưa thấy ai complain". Cả hai đều là hậu quả của việc thiếu cơ chế phân loại có tiêu chí khách quan thay vì cảm tính của người phát hiện đầu tiên.
Ở tầng tổ chức, việc thiếu mô hình chỉ huy rõ ràng (incident command) còn nguy hiểm hơn. Khi một sự cố lan rộng đủ để cần ba, bốn, năm kỹ sư từ các team khác nhau cùng tham gia, hệ thống social của một nhóm không có cấu trúc chỉ huy sẽ tự sụp đổ: nhiều người cùng sửa hệ thống một lúc mà không biết người khác đang làm gì, không ai cập nhật cho stakeholder, và không ai giữ được bức tranh tổng thể vì tất cả đều đang chúi đầu vào terminal của riêng mình. Đây chính là lý do Google mượn nguyên mô hình Incident Command System (ICS) — một khung tổ chức được phát triển ban đầu cho lính cứu hỏa Mỹ để phối hợp phản ứng thảm họa — và áp dụng gần như nguyên vẹn cho incident kỹ thuật.
Internal model: Severity như cơ chế trigger
Severity phải dựa trên triệu chứng người dùng, không dựa trên nguyên nhân kỹ thuật
Nguyên tắc cốt lõi từ SRE Incident Management Guide của Google: alerting hiệu quả phải "based on symptoms, not causes" — dựa trên triệu chứng mà người dùng cảm nhận được, không dựa trên hành vi nội bộ của hệ thống. Nguyên tắc này áp dụng trực tiếp vào việc định nghĩa severity. Một CPU spike lên 95% không tự nó là SEV1 — nó chỉ là SEV1 nếu nó gây ra latency vượt SLO hoặc error rate vượt ngưỡng chấp nhận được với người dùng. Ngược lại, một lỗi rất nhỏ về mặt kỹ thuật (một field bị null trong response) có thể là SEV1 nếu nó làm sập luồng thanh toán.
Đây là lý do một severity ladder tốt luôn được viết dưới dạng impact statement, không phải technical statement:
| Mức | Định nghĩa dựa trên impact | Ví dụ điển hình | Response yêu cầu |
|---|---|---|---|
| SEV1 / P0 | Toàn bộ hoặc phần lớn người dùng không thể dùng chức năng cốt lõi; mất dữ liệu đang xảy ra | Checkout không xử lý được giao dịch nào; region toàn bộ down | Kích hoạt full ICS ngay lập tức, page toàn bộ chain |
| SEV2 / P1 | Một phần đáng kể người dùng bị ảnh hưởng, hoặc chức năng phụ nhưng quan trọng bị hỏng | Latency p99 gấp 5 lần SLO ở một region; một tính năng phụ trợ die hoàn toàn | Kích hoạt IC, có thể không cần Planning Lead |
| SEV3 / P2 | Ảnh hưởng cục bộ, có workaround, chưa vi phạm SLO nghiêm trọng | Một job batch trễ; một dependency không critical bị chậm | On-call engineer tự xử lý, không cần escalate |
| SEV4 / P3 | Không ảnh hưởng người dùng, phát hiện qua giám sát nội bộ | Log noise bất thường, cảnh báo capacity sắp đạt ngưỡng | Ticket thường, xử lý trong giờ hành chính |
Bảng trên chỉ là một khung tham khảo — điều quan trọng về mặt cơ chế là: tiêu chí phải được viết ra trước khi có incident, không phải được quyết định tại chỗ bởi người đang căng thẳng nhất trong phòng. Google Cloud Well-Architected Framework nhấn mạnh điều này khi nói về postmortem criteria nhưng nguyên lý áp dụng y hệt cho severity: "Define postmortem criteria proactively before incidents occur" — càng nhiều quyết định được đưa ra trước, càng ít quyết định phải đưa ra dưới áp lực thời gian thực.
Severity là cơ chế kỹ thuật trong Cloud Monitoring, không chỉ là quy ước xã hội
Trên GCP, severity không chỉ tồn tại trong đầu người vận hành — nó có thể được nhúng trực tiếp vào alerting policy như một trường dữ liệu định tuyến. Có hai cách triển khai:
Cách 1 — Static severity qua user labels: mỗi mức severity là một alerting policy riêng, gắn nhãn cố định. Ví dụ CPU utilization > 90% được gắn severity: critical, > 80% gắn severity: warning, > 70% gắn severity: info. Notification payload khi bắn ra sẽ mang theo policy_user_labels.severity, cho phép hệ thống định tuyến downstream (PagerDuty, Slack, webhook) tự động chọn kênh và mức độ khẩn cấp tương ứng.
Cách 2 — Dynamic severity qua MQL (Monitoring Query Language): một policy duy nhất tính severity động dựa trên giá trị metric tại thời điểm alert:
fetch gce_instance
| metric 'compute.googleapis.com/instance/cpu/utilization'
| filter (metadata.user_labels.env == 'prod') && (resource.zone =~ 'asia.*')
| group_by sliding(5m), [value_utilization_mean: mean(value.utilization)]
| map add[severity: if(val() > 90 '%', 'critical',
if(val() >= 80 '%' && val() <= 90 '%', 'warning', 'info'))]
| condition val() > 70 '%'Cách tiếp cận dynamic tránh được tình trạng nổ ba incident riêng biệt (info/warning/critical) cho cùng một sự kiện leo thang dần — một vấn đề thực tế khi dùng static labels vì mỗi ngưỡng vượt qua sẽ tạo một incident Cloud Monitoring độc lập. Đây là một chi tiết cơ chế đáng chú ý: nếu bạn dùng static severity với ba policy riêng, khi CPU tăng từ 75% lên 95%, bạn sẽ nhận ba incident khác nhau thay vì một incident nâng cấp severity — điều này gây nhiễu và làm loãng tín hiệu thật.
Việc severity được nhúng vào tầng alerting, chứ không phải được con người gán thủ công sau khi nhận thông báo, chính là điều biến severity từ "nhãn mô tả" thành "cơ chế kích hoạt": hệ thống định tuyến, thời gian SLA phản hồi, và escalation chain đều có thể được tự động hoá dựa trên trường dữ liệu này ngay từ khoảnh khắc alert đầu tiên nổ ra.
Internal model: Incident Command System — cơ chế phối hợp con người
Ba chữ C làm nền tảng
SRE Workbook của Google định nghĩa mục tiêu của incident management bằng ba động từ: Coordinate (phối hợp nỗ lực phản ứng), Communicate (giao tiếp giữa các responder, trong tổ chức, và ra bên ngoài), Control (duy trì kiểm soát toàn bộ quá trình phản ứng). Ba chữ C này không phải khẩu hiệu — chúng ánh xạ trực tiếp thành ba vai trò cụ thể trong ICS, và sự tách biệt giữa ba vai trò này chính là phần cơ chế quan trọng nhất của cả mô hình.
Bốn vai trò và lý do chúng phải tách biệt
Incident Commander (IC) giữ trạng thái tổng thể ở mức cao (high-level state) của incident và cấu trúc đội phản ứng bằng cách phân công trách nhiệm. IC không tự tay sửa hệ thống. Đây là điểm dễ bị vi phạm nhất trong thực tế và cũng là điểm quan trọng nhất cần bảo vệ: nếu IC vừa điều phối vừa gõ lệnh vào production, họ sẽ mất khả năng nhìn bức tranh tổng thể ngay khi họ chúi đầu vào chi tiết kỹ thuật của một câu lệnh. IC tồn tại để trả lời câu hỏi "chúng ta đang ở đâu, cần ai, và bước tiếp theo là gì" — một công việc đòi hỏi sự tách rời có chủ đích khỏi việc thực thi.
Operations Lead (OL) làm việc trực tiếp với IC để triển khai phản ứng vận hành, và theo mô tả của SRE Book, đây là "nhóm duy nhất được phép thay đổi hệ thống trong lúc incident". Việc giới hạn quyền thay đổi hệ thống vào một nhóm duy nhất (thay vì để bất kỳ ai cũng có thể chạy lệnh vì họ "nghĩ ra một ý tưởng") là cơ chế chống lại một failure mode rất phổ biến: nhiều kỹ sư đồng thời áp dụng các thay đổi không phối hợp lên cùng một hệ thống đang bất ổn, khiến việc xác định thay đổi nào gây ra hiệu ứng nào trở nên bất khả thi.
Communications Lead (CL) là gương mặt đại diện ra bên ngoài, chịu trách nhiệm "issuing periodic updates to the incident response team and stakeholders" — phát các bản cập nhật định kỳ cho cả đội phản ứng lẫn các bên liên quan. CL tách biệt khỏi OL vì hai công việc này cạnh tranh trực tiếp về sự chú ý: người đang cố gắng chẩn đoán một race condition phức tạp không thể đồng thời soạn một thông báo dễ hiểu cho khách hàng không có nền tảng kỹ thuật.
Planning Lead xử lý các tác vụ điều phối dài hơi — theo mô tả gốc là "filing bugs, ordering dinner, arranging handoffs" — nghe có vẻ tầm thường nhưng thực chất giải quyết một vấn đề rất thật: incident kéo dài nhiều giờ sẽ làm kiệt sức đội phản ứng nếu không ai lo hậu cần và kế hoạch đổi ca. Ở incident ngắn, vai trò này thường được gộp vào IC; ở incident kéo dài qua nhiều giờ hoặc nhiều ca, tách nó ra là bắt buộc.
Live Incident Document — bộ nhớ dùng chung thay thế cho bộ nhớ con người
SRE Book gọi đây là hạ tầng nền tảng thứ nhất của ICS: một tài liệu có thể chỉnh sửa đồng thời (Google Docs hoặc wiki tương đương) ghi lại trạng thái đang tiến triển của incident, phục vụ cả điều phối thời gian thực lẫn phân tích postmortem sau này. Cơ chế quan trọng ở đây là: tài liệu này thay thế cho bộ nhớ ngắn hạn của con người trong một tình huống áp lực cao — nơi trí nhớ con người là nguồn thông tin không đáng tin cậy nhất. Mọi giả thuyết đã thử, mọi thay đổi đã áp dụng, mọi kết luận đã loại trừ đều phải được ghi vào đây theo thời gian thực, không phải tái dựng lại từ trí nhớ sau khi incident kết thúc.
Hạ tầng thứ hai là kênh giao tiếp trung tâm (SRE Book mô tả gốc dùng IRC, thực tế hiện đại thường là Slack channel dành riêng cho incident) — đóng vai trò kênh liên lạc đáng tin cậy, có log, cho các đội phân tán về địa lý.
Ngưỡng escalate và cơ chế handoff
SRE Book đưa ra ba tiêu chí cụ thể để quyết định khi nào một vấn đề phải được nâng cấp thành incident chính thức (declare an incident): cần sự tham gia của một team thứ hai, sự cố ảnh hưởng có thể nhìn thấy được với khách hàng (customer-visible outage), hoặc vấn đề vẫn chưa được giải quyết sau một giờ phân tích tập trung. Điểm đáng chú ý về mặt cơ chế: tiêu chí thứ ba không phải là "đã cố gắng đủ lâu để bỏ cuộc", mà là một tín hiệu khách quan rằng độ phức tạp của vấn đề đã vượt quá năng lực của một cá nhân đang xử lý đơn lẻ — đây là lúc chi phí của việc không escalate (tiếp tục để một người tự mò mẫm) vượt quá chi phí của việc escalate (huy động thêm người, tạo overhead phối hợp).
Cơ chế handoff khi đổi ca cũng được định nghĩa rõ: IC đang rời đi phải xác nhận rõ ràng việc bàn giao với IC kế tiếp trước khi rời khỏi vai trò — không có bàn giao ngầm định, không có giả định rằng "chắc người kia đã đọc live doc rồi". Đây là một quy tắc chống lại failure mode "khoảng trống chỉ huy" (command gap), nơi trong vài phút chuyển giao, không ai thực sự giữ vai trò IC và các quyết định quan trọng bị trì hoãn hoặc bị đưa ra bởi người không có đủ bức tranh tổng thể.
Constraints, trade-offs và failure mode khi scale
Vấn đề role collapse ở đội nhỏ
Ở một đội nhỏ (dưới 10 kỹ sư), việc áp dụng đầy đủ bốn vai trò cho mọi incident là lãng phí — thường một người vừa là IC vừa là OL cho các SEV3/SEV4. Đây không phải là sai lệch so với mô hình, mà là một compression hợp lý miễn là ranh giới vai trò vẫn được giữ trong đầu người đó: khi đang đóng vai OL (gõ lệnh sửa), họ cần chủ động dừng lại định kỳ để "đội mũ IC" và tự hỏi "bức tranh tổng thể đang ở đâu, có cần gọi thêm người không". Failure mode xảy ra khi compression này không có giới hạn: một incident SEV1 lan rộng nhưng người phụ trách vẫn cố ôm cả bốn vai trò một mình vì "đã quen làm một mình" — đây là lúc tổ chức mất khả năng phối hợp đúng lúc cần nó nhất.
Single point of failure của chính vai trò IC
Mô hình ICS giải quyết vấn đề phối hợp con người nhưng lại tạo ra một điểm lỗi đơn (single point of failure) mới: nếu IC hiện tại bị quá tải, mất kết nối, hoặc đơn giản là đưa ra phán đoán sai vì thiếu ngủ, toàn bộ cơ chế phối hợp sụp đổ theo. Đây là lý do các tổ chức vận hành ICS nghiêm túc luôn có on-call rotation cho chính vai trò IC — tách biệt hoàn toàn với on-call rotation kỹ thuật thông thường — và có tiêu chí rõ ràng để bất kỳ ai trong đội cũng có quyền yêu cầu đổi IC nếu thấy người đang giữ vai trò có dấu hiệu quá tải.
Minh hoạ cơ chế: một SEV2 leo thang thành SEV1 vận hành ICS như thế nào
Để thấy rõ vì sao severity và ICS gắn chặt với nhau như một cơ chế duy nhất chứ không phải hai khái niệm rời rạc, hãy hình dung một chuỗi sự kiện điển hình. Một alerting policy dạng MQL (đã trình bày ở trên) bắn ra cảnh báo warning khi p99 latency của luồng checkout vượt SLO tại một region. On-call engineer nhận alert, xác nhận đây không phải false positive, và tự xử lý như một SEV2 — nghĩa là chưa cần kích hoạt đầy đủ bốn vai trò, họ vừa là IC vừa là OL cho chính mình. Mười phút sau, cùng chỉ số đó vượt ngưỡng critical vì lỗi lan sang toàn bộ luồng thanh toán, không riêng một region. Đây chính là thời điểm severity tự động nâng cấp (nhờ cơ chế MQL động ở trên, không tạo ra ba incident rời rạc) và đồng thời kích hoạt ngưỡng escalate: ảnh hưởng đã "customer-visible" trên diện rộng, vượt quá năng lực xử lý đơn lẻ của một người. Ngay tại thời điểm này, on-call engineer phải tách vai trò: gọi thêm người, chỉ định rõ ai là OL (người tiếp tục gõ lệnh sửa) và ai đứng ra làm IC (người lùi lại một bước để giữ bức tranh tổng thể) — và nếu incident kéo dài vượt quá một ca làm việc, bổ sung thêm Communications Lead trước khi áp lực giao tiếp dồn ứ. Chuỗi sự kiện này cho thấy severity không chỉ là một con số hiển thị trên dashboard — nó là tín hiệu kích hoạt trực tiếp việc mở rộng cấu trúc chỉ huy tương ứng.
Severity inflation là một failure mode xói mòn lòng tin
Khi tổ chức không có tiêu chí severity rõ ràng bằng văn bản, một hiện tượng phổ biến là severity inflation: mọi vấn đề dần dần được gắn severity cao hơn thực tế vì người báo cáo muốn đảm bảo được chú ý nhanh. Hệ quả ở scale là ngược lại với ý định ban đầu — khi phần lớn incident được gắn SEV1, đội ngũ dần "quen" với việc SEV1 không thực sự khẩn cấp, và phản ứng chậm lại kể cả khi có một SEV1 thật. Cơ chế phòng tránh duy nhất hiệu quả là ràng buộc severity vào tiêu chí đo lường được (SLO burn rate, số người dùng bị ảnh hưởng, có mất dữ liệu hay không) thay vì để nó là một phán đoán chủ quan tại thời điểm báo cáo.
GCP-native implementation guidance
Ví dụ cấu hình một notification channel với routing theo severity, tận dụng user label đã gắn ở alerting policy:
# alerting-policy-sev1.yaml — ví dụ policy CPU vượt ngưỡng nghiêm trọng
displayName: "prod-cpu-critical"
combiner: OR
conditions:
- displayName: "CPU > 90% trong 5 phút"
conditionThreshold:
filter: >
resource.type="gce_instance"
metric.type="compute.googleapis.com/instance/cpu/utilization"
comparison: COMPARISON_GT
thresholdValue: 0.9
duration: 300s
userLabels:
severity: "critical"
service: "checkout"
notificationChannels:
- projects/PROJECT_ID/notificationChannels/CHANNEL_ID_PAGERDUTYViệc gắn severity và service như user labels cho phép hệ thống downstream (webhook nhận payload từ Cloud Monitoring) tự động ánh xạ sang đúng escalation chain và đúng kênh Slack đội phụ trách — thay vì con người phải đọc nội dung alert rồi tự quyết định gửi cho ai.
References
- Google SRE Book — Managing Incidents
- Google SRE Workbook — Incident Response
- Google SRE Incident Management Guide
- Google Cloud Architecture Framework — Manage incidents and problems
- DevOps best practices: add severity levels to alerts
- Cloud Monitoring — Alerting overview
- Cloud Monitoring — Create and manage notification channels