Incident response và blameless postmortem

4 câu hỏi phỏng vấn~25 phútTừ khóa: incident, severity, incident commander, ops lead, comms lead, scribe, triage, mitigate, resolve, rollback, feature flag, status page, MTTD, MTTR, blameless postmortem, timeline, contributing factors, 5 whys, action items

Bài cuối Observability: xử lý sự cố. Lần trước payment lỗi, 6 người cùng nhảy vào một kênh Slack, ai cũng restart Pod, không ai báo khách hàng. Nên tổ chức lại thế nào?

Đó là cảnh "ai cũng là anh hùng" rất hay gặp. Công cụ thì bạn đã đủ từ 19.1 tới 19.5; cái thiếu là quy trình và vai trò. Bài này đi từ lúc alert kêu tới lúc postmortem xong.

1. Bài toán

Thứ Sáu 20:05, alert CheckoutErrorBudgetFastBurn kêu (bài 19.2). 25% POST /orders trả 502. 20:07 có 6 người trong kênh #shop-alerts:

An:    restart payment-service nhé?
Bình:  mình đang scale postgres lên
Chi:   ai deploy gì không?
Dũng:  mình vừa restart rồi đó
CS:    khách hỏi sao không thanh toán được, trả lời sao ạ?
(không ai trả lời CS; 40 phút sau mới có người thấy bản deploy 19:50)

2. Vấn đề

3. Giải pháp: vai trò, giai đoạn, postmortem

Vai tròLàm gìKhông làm gì
Incident Commander (IC)Điều phối, quyết định, giao việc, đặt nhịp cập nhậtKhông tự gõ lệnh sửa
Ops / Tech leadĐiều tra, thực hiện thay đổi (sau khi IC đồng ý)Không tự ý thay đổi ngoài kế hoạch
Comms leadCập nhật status page, CS, quản lý theo nhịp 15–30 phútKhông hứa thời gian khắc phục khi chưa chắc
ScribeGhi timeline: giờ, ai làm gì, quan sát gì

Sự cố nhỏ: một người kiêm IC và ops. Sự cố SEV1: tách vai.

SeverityVí dụ shop-appPhản ứng
SEV1Không ai checkout được, mất dữ liệu, lộ dữ liệuPage ngay, đủ vai, status page, báo lãnh đạo
SEV2Một phần user lỗi (một cổng thanh toán), chậm rõ rệtPage on-call, IC, status page nếu khách thấy
SEV3Tính năng phụ lỗi, có cách vòng (email xác nhận chậm)Giờ hành chính, ticket

Ba giai đoạn, theo đúng thứ tự: Triage (nặng cỡ nào, ảnh hưởng ai) → Mitigate (cầm máu: rollback, tắt flag, chuyển traffic) → Resolve (sửa gốc, có thể ngày hôm sau). Sau đó là postmortem.

4. Code từng bước

Bước 1: Tuyên bố sự cố (một người, trong 5 phút)

/incident declare sev2 "Checkout 25% 502"     # bot tạo kênh #inc-2026-10-09-checkout
IC: Dũng.  Ops: An.  Comms: Chi.  Scribe: Bình.
Mọi thay đổi lên prod phải nói trong kênh trước khi làm.
Cập nhật tiếp theo: 20:25.

Bước 2: Triage bằng tín hiệu đã có

# Có gì thay đổi gần đây? (nghi phạm số 1)
kubectl rollout history deploy/payment-service -n shop
helm history shop -n shop
# Grafana: dashboard checkout có annotation deploy lúc 19:50

# Lỗi ở đâu? (RED theo service)
sum by (app) (rate(http_server_requests_seconds_count{namespace="shop",outcome="SERVER_ERROR"}[5m]))

# Trace lỗi: TraceQL
{ status = error && resource.service.name = "payment-service" }

# Log của một trace lỗi (Loki)
{namespace="shop", app="payment-service"} | json | level="ERROR"

Bước 3: Mitigate trước, điều tra sau

# Có deploy gần đây → rollback ngay, không cần chắc chắn 100%
kubectl rollout undo deploy/payment-service -n shop
kubectl rollout status deploy/payment-service -n shop

# Hoặc tắt tính năng mới bằng feature flag (nhanh hơn rollback)
curl -X PATCH "$FLAGS_API/flags/new-fee-engine" \
     -H "Authorization: Bearer ${FLAGS_TOKEN}" -d '{"enabled":false}'

# Các lựa chọn khác: scale out, chuyển cổng thanh toán dự phòng, bật degraded mode
// Degraded mode: không cho inventory chậm kéo checkout chết theo
@CircuitBreaker(name = "inventory", fallbackMethod = "reserveLater")
public Reservation reserve(String orderId, List<Item> items) { ... }

private Reservation reserveLater(String orderId, List<Item> items, Throwable t) {
    outbox.save(new ReserveCommand(orderId, items));   // xử lý sau qua Kafka
    return Reservation.pending(orderId);
}

Bước 4: Xác nhận và đóng

# Error ratio về dưới SLO và burn rate alert tự tắt
curl -s 'localhost:9090/api/v1/query?query=sli:checkout_error_ratio:rate5m'
# Comms: status page → "Monitoring" → 30 phút ổn → "Resolved"
# IC: hạ sự cố, hẹn postmortem trong 2–5 ngày làm việc

5. Cách hoạt động: dòng thời gian và postmortem

19:50 deploy payment 3.2
20:03 lỗi bắt đầu ─┐
20:05 alert kêu    ┘ MTTD (time to detect) = 2'
20:08 tuyên bố SEV2, IC nhận
20:12 thấy annotation deploy 19:50
20:14 rollback ─┐
20:19 hết lỗi   ┘ MTTM (time to mitigate) = 16'
20:50 resolved, theo dõi
Ngày hôm sau: sửa gốc, thêm test   → MTTR tính tới lúc đóng

Template postmortem (1–3 trang, viết trong vài ngày, mọi người đọc được):

# Postmortem: Checkout 502, 2026-10-09 (SEV2)
## Tóm tắt         2–3 câu: chuyện gì, ảnh hưởng, đã khắc phục thế nào
## Ảnh hưởng       25% checkout lỗi 16 phút, ~1 900 đơn, 31% error budget tháng
## Timeline        từ scribe, theo giờ (như trên)
## Nguyên nhân & yếu tố góp phần
   - Bản 3.2 đổi timeout gọi bank-gateway từ 5s xuống 500ms (config sai đơn vị)
   - Test tích hợp dùng mock bank trả lời 20ms nên không bắt được
   - Canary chỉ kiểm tra health, không kiểm tra error rate
## Điều gì tốt     alert burn-rate kêu sau 2'; rollback 1 lệnh
## Điều gì chưa tốt mất 4' để tìm ra deploy gần đây; CS không được báo 25'
## Action items    (có owner, có hạn, có ticket)
   | Việc                                         | Loại     | Owner | Hạn   |
   | Kiểu Duration cho timeout trong config       | Phòng    | An    | 16/10 |
   | Canary tự rollback khi error rate > 1%       | Phát hiện| Bình  | 30/10 |
   | Bot tự gắn "deploy gần đây" vào kênh incident| Giảm thời gian | Chi | 23/10 |
   | Thêm CS vào danh sách thông báo SEV2         | Quy trình| Dũng  | 12/10 |

6. So sánh: blameless vs tìm người có lỗi

BlameBlameless
Câu hỏi"Ai làm hỏng?""Vì sao hệ thống cho phép điều này xảy ra?"
Kết luận điển hình"An cẩn thận hơn""Config timeout cần kiểu Duration và có validate"
Hành vi lần sauGiấu lỗi, báo muộnBáo sớm, kể đủ chi tiết
Hiệu quảLỗi lặp lại với người khácSửa hệ thống, ai cũng được bảo vệ

Blameless không có nghĩa là không ai chịu trách nhiệm: chịu trách nhiệm là làm action item, không phải bị phạt.

7. Khi nào nên dùng / không nên dùng

Lúc sự cố mình muốn tìm cho ra nguyên nhân trước rồi mới sửa, chứ rollback mù quáng nhỡ không phải do deploy thì sao?

Bạn hiểu gần đúng, chỉ cần chỉnh một điểm: mục tiêu đầu tiên là ngưng tác động lên người dùng, không phải hiểu. Rollback không mù quáng nếu bạn coi nó là một thí nghiệm rẻ và đảo ngược được:

Cẩn thận ở hai chỗ:

Viết postmortem mà phải ghi "An config sai timeout" thì có phải là đổ lỗi cho An không nhỉ? Mình không biết viết thế nào cho khéo.

Câu hỏi hay. Blameless không phải là giấu sự thật, mà là mô tả hành động trong bối cảnh và hỏi vì sao hệ thống để hành động đó gây hại:

TránhNên viết
"An config sai timeout""Bản 3.2 đặt bank.timeout=500, hiểu là ms, trong khi code cũ hiểu là giây × 0.01"
"Reviewer không để ý""Diff config không hiển thị đơn vị; review không có checklist cho timeout"
"Lẽ ra phải test kỹ hơn""Test tích hợp dùng mock trả lời 20ms nên không mô phỏng được bank chậm"

Một mẹo: thay tên người bằng vai trò ("engineer deploy", "on-call") và hỏi "một người giỏi khác ở cùng vị trí, cùng thông tin, có làm khác không?" Nếu không, lỗi nằm ở hệ thống. Kỹ thuật "5 whys" giúp đi từ hành động tới guardrail còn thiếu, nhưng nhớ là sự cố thường có nhiều yếu tố góp phần, không phải một root cause duy nhất.

Phỏng vấn hỏi về xử lý sự cố và postmortem thì trả lời sao?

Q1. Kể cách bạn xử lý một sự cố production.

🇻🇳 Tiếng Việt:

Em tuyên bố sự cố và gán vai: incident commander điều phối, một người điều tra, một người lo giao tiếp, một người ghi timeline. Sau đó triage bằng dashboard SLO và RED để biết ảnh hưởng ai và nặng cỡ nào, rồi hỏi ngay có gì thay đổi gần đây. Em ưu tiên mitigate: rollback, tắt feature flag, chuyển traffic, trước khi tìm root cause, nhưng chụp lại thread dump, log và trace trước khi restart. Khi ổn định thì theo dõi rồi đóng, và hẹn postmortem.

🇬🇧 English:

I declare an incident and assign roles: an incident commander to coordinate, someone to investigate, someone on communications, and a scribe for the timeline. Then I triage with the SLO and RED dashboards to see who's affected and how badly, and immediately ask what changed recently. I prioritize mitigation such as a rollback, disabling a feature flag, or shifting traffic before hunting for the root cause, but I capture thread dumps, logs and traces before restarting anything. Once stable we monitor, close, and schedule a postmortem.

Q2. Blameless postmortem là gì, gồm những phần nào?

🇻🇳 Tiếng Việt:

Là tài liệu phân tích sự cố tập trung vào hệ thống và quy trình thay vì cá nhân, để mọi người dám kể đầy đủ. Gồm tóm tắt, ảnh hưởng có số liệu, timeline, nguyên nhân và các yếu tố góp phần, điều gì làm tốt và chưa tốt, và action item có owner, có hạn, được theo dõi. Giá trị nằm ở action item được hoàn thành, không ở bản tài liệu.

🇬🇧 English:

It's an incident analysis that focuses on systems and processes rather than individuals, so people feel safe sharing the full story. It covers a summary, quantified impact, a timeline, the cause and contributing factors, what went well and what didn't, and action items with owners and due dates that are actually tracked. The value is in completed action items, not in the document itself.

Q3. Vì sao mitigate trước, root cause sau?

🇻🇳 Tiếng Việt:

Vì mỗi phút điều tra là thêm một phút người dùng bị ảnh hưởng và tiêu error budget. Phần lớn sự cố do thay đổi gần đây, nên rollback hay tắt flag là thí nghiệm rẻ, đảo ngược được, và thường kết thúc tác động trong vài phút. Root cause có thể tìm sau với dữ liệu đã thu thập. Ngoại lệ là khi rollback không an toàn, ví dụ migration phá ngược, thì em dùng feature flag hoặc roll forward.

🇬🇧 English:

Because every minute spent investigating is another minute of user impact and error budget burn. Most incidents come from recent changes, so a rollback or flag toggle is a cheap, reversible experiment that often ends the impact within minutes. The root cause can be found later from the data you captured. The exception is when rollback is unsafe, such as after a backward-incompatible migration, in which case I use a feature flag or roll forward.

Q4. MTTD và MTTR là gì, giảm thế nào?

🇻🇳 Tiếng Việt:

MTTD là thời gian trung bình để phát hiện sự cố, MTTR là thời gian để khôi phục. Giảm MTTD bằng alert theo SLO burn rate và synthetic check, không đợi khách báo. Giảm MTTR bằng runbook, dashboard có annotation deploy, trace và log nối nhau qua traceId, rollback một lệnh, feature flag, canary tự rollback, và diễn tập định kỳ.

🇬🇧 English:

MTTD is mean time to detect an incident and MTTR is mean time to restore service. I reduce MTTD with SLO burn-rate alerts and synthetic checks rather than waiting for customers to report. I reduce MTTR with runbooks, dashboards annotated with deploys, traces and logs linked by trace ID, one-command rollback, feature flags, canaries that roll back automatically, and regular game days.

Cách nhớ ngắn gọn

Tổng kết chương 19: Observability

BàiÝ chínhTình huống trên shop-appCông cụ
19.1 Log, metric, trace4 tín hiệu trả lời 4 câu hỏi; JSON log; traceId nối; cardinality và chi phíCheckout chậm, log 12 Pod trộn lẫnStructured logging, MDC, Loki
19.2 SLI, SLO, alertĐo trải nghiệm user, error budget, page theo triệu chứng, burn rate40 alert CPU/tuần, bỏ sót lỗi payment thậtRecording rule, Alertmanager, RED/USE
19.3 Prometheus & GrafanaPull model, 4 loại metric, PromQL, histogram_quantilePrometheus OOM vì label ID; p99 tính saiServiceMonitor, PromQL, Grafana
19.4 OpenTelemetrySDK/agent, Collector, head vs tail sampling, W3C traceparentChuyển Zipkin → Tempo, service cũ không sửa codeOTel agent, Collector, Tempo
19.5 Profiling JVMContinuous profiling, CPU/wall/alloc/lock, flame graph, span profilesBản 3.2 tốn CPU do Pattern.compilePyroscope, JFR, async-profiler
19.6 Incident & postmortemVai trò, triage → mitigate → resolve, blameless, action itemsPayment 502 sau deploy, 6 người cùng restartRunbook, rollback, feature flag, template

Tự kiểm tra

Incident commander có nên tự gõ lệnh sửa không?

Không (với sự cố lớn): IC điều phối và quyết định, để người khác thực hiện.

Trước khi restart Pod lỗi nên làm gì?

Thu bằng chứng: thread dump, JFR dump, log, link trace lỗi.

Khi nào rollback không an toàn?

Khi bản mới đã chạy migration phá ngược hoặc ghi dữ liệu mà bản cũ không đọc được.

"Engineer cẩn thận hơn" có phải action item tốt?

Không. Cần thay đổi hệ thống cụ thể, có owner và hạn.

Giảm MTTD bằng gì?

Alert theo SLO burn rate, synthetic check; không đợi khách báo.