Skip to content
nkh.do
Go back

Linh Khí Rò Rỉ Chapter 1

Pager 3 Giờ Sáng

June 20, 2026

Pager bép lúc 3:07 sáng.

Hồ Hoàng Vinh mở mắt trước khi tiếng rung của điện thoại kịp rung lần thứ hai. Đó là phản xạ đã được tôi luyện — không phải thứ gì đáng tự hào, chỉ là tổn thương nghề nghiệp. Anh với tay lấy điện thoại trên đầu giường, mắt nheo lại trước ánh sáng xanh.

[P1] PROD ALERT: Holistics Dashboard — All services unreachable.

P1. Mức nghiêm trọng cao nhất. Bốn năm on-call tại Holistics, mỗi lần pager kêu lúc giữa đêm, cơ thể vẫn phản ứng y hệt: tim đập nhanh, miệng khô, bàn chân chạm sàn trước khi não khởi động.

Vinh bật đèn bàn. Căn hộ mười tám mét vuông trên đường Nguyễn Đình Chiểu — giường đơn, bàn làm việc chiếm phân nửa diện tích, hai màn hình 27 inch đứng song song. Tủ quần áo mở hé, bên trong toàn áo thun đen và hoodie xám xếp theo màu đậm nhạt. Bếp trống — hộp cơm tối anh quên ăn vẫn nằm trên kệ. Quầng mắt sâu đến mức bạn cùng team gọi là “panda on-call,” và anh coi đó là badge of honor.

Mười bảy giây để mở laptop. Bốn giây để SSH vào jump host. Trang Grafana load lên — toàn đỏ.

Vinh ack alert trên Slack channel #incident-war-room, gõ nhanh: On it. Investigating.

Bốn mươi ba service, tất cả đỏ. Không phải kiểu đỏ dần — kiểu tắt phụt. Như ai đó rút phích cắm rồi đút lại chỉ để xem chuyện gì xảy ra.

Việc đầu tiên: check deployment log. Không có deploy nào trong sáu tiếng qua. CI/CD pipeline sạch, không có commit nào merge, không có config change. Vinh mở tab mới, check Kubernetes cluster — pods vẫn running, không có restart bất thường. Network policy không thay đổi. Load balancer health check vẫn pass.

Mọi thứ vẫn sống. Nhưng traffic không đi.

Vinh mở distributed tracing — Jaeger UI — và zoom vào khoảng thời gian 3:04 đến 3:07. Traces đứt đoạn. Không phải timeout, không phải connection refused. Requests đi vào, rồi biến mất. Như rơi vào lỗ đen ở giữa pipeline.

Anh copy timestamp, paste vào Slack.

@here Traces drop at 03:04:12. Requests enter ingress, never reach backend. No error, no timeout. Just... gone.

Minh trả lời gần như ngay lập tức. Con quỷ này cũng on-call.

Đang check frontend. Cũng vậy. Request gửi đi, response không bao giờ về. Console không log gì.

DB vẫn sống không?

Up. CPU 12%. Disk I/O bình thường. Nó đang ngồi đó, chờ, không ai gọi.

Database đang rảnh. Service đang chạy. Load balancer đang healthy. Mọi thứ trên lý thuyết đều ổn — nhưng dashboard báo toàn bộ user không truy cập được.

Vinh đào tiếp. Logs application — không có exception. Logs infrastructure — không có kernel panic, không có OOM kill. Metrics network — throughput drop về zero trong đúng khoảng 3:04, rồi nhích lên lại lúc 3:05, lại drop. Dao động. Không đều. Không có pattern nào anh nhận ra được.

Anh mở terminal thứ ba, SSH thẳng vào app server, chạy curl localhost:8080/health. Response 200 OK. Service đang trả lời. Nhưng từ bên ngoài — không.

@minh Thử curl từ máy mày vào prod endpoint xem.

Ba mươi giây sau.

Timeout. Nhưng curl localhost từ trong cluster thì được. Network giữa bên ngoài và bên trong... bị gì rồi.

Vinh kiểm tra DNS. Resolve đúng. Kiểm tra TLS handshake. Complete. Kiểm tra firewall rules. Không có rule nào block. Gói tin đi vào, TLS bắt tay thành công, rồi — im. Như thư đã bỏ vào hòm thư, hòm thư nhận, nhưng người nhận không tồn tại.

@minh T đang chạy tcpdump. Hold on.

Anh khởi chạy packet capture, đợi. Terminal bắt đầu scroll những dòng text — SYN, ACK, SYN-ACK. Bàn tay bình thường. Nhưng rồi Vinh thấy thứ lạ: gói tin đi đến một nửa thì dừng. Không có RST, không có FIN. Gói tin chỉ đơn giản biến mất khỏi capture, như bị nuốt chửng ở đâu đó giữa hai hop.

@minh Packets disappearing mid-transit. No RST, no FIN. Just gone.

Gone kiểu gì?

Kiểu tcpdump thấy nó vào, rồi không thấy nó ra. Layer 3 accepted, layer 4 swallowed.

Minh im một lúc. Ê, kiểu này tao chưa gặp bao giờ.

Tao cũng vậy.

Vinh đã xử lý hàng trăm incident trong đời. Memory leak, database deadlock, cascading failure, DNS propagation fuck-up, certificate expired đúng ngày Black Friday. Anh có playbook cho mọi thứ. Lần này playbook rỗng. Anh đứng trước một hệ thống mà mọi instrument — logs, traces, metrics, packet capture — đều nói cùng một điều: không có gì sai. Hệ thống chỉ ngừng hoạt động, rồi tiếp tục, như người ta nhắm mắt rồi mở mắt lại. Không có lý do. Không có dấu vết.

Anh đang capture thêm khi nó xảy ra.

3:15 sáng. Tất cả service báo green. Đồng loạt. Cùng một giây.

Dashboard Grafana flip từ đỏ sang xanh. Vinh ping: @minh comeback chưa?

Được rồi??? Tự nhiên được rồi???

Tcpdump của mày chạy chưa?

Đang chạy. Ping bình thường rồi. Tao gửi packet, nó trả về. Trước đó im ru.

Vinh check deployment log lần nữa. Không có thay đổi. Không ai fix gì. Không có rollback, không có restart, không có autoscale event. Hệ thống đứng dậy.

Từ 3:04:12 đến 3:15:38. Mười một phút hai mươi sáu giây downtime. Rồi tự phục hồi.


Vinh không ngủ lại được.

Anh ngồi trước màn hình, cà phê instant nguội ngắt trong tay, và làm việc mà mọi kỹ sư làm sau một incident: đọc lại mọi thứ. Từ đầu.

Bốn mươi ba service, tất cả unreachable trong mười một phút. Nguyên nhân: không xác định. Cơ chế phục hồi: không xác định. Mọi log, mọi metric, mọi trace đều clean — không có exception, không có error, không có dấu hiệu gì ngoại trừ traffic drop về zero rồi tự trở lại.

Anh chạy query trên Loki, log aggregator, kéo toàn bộ raw logs trong khoảng thời gian incident. Hàng trăm nghìn dòng. Filter theo severity: ERROR, WARN, CRITICAL.

Rỗng.

Không có một dòng error nào trong suốt mười một phút downtime. Hệ thống down mà không có lỗi. Đó không phải cách phần mềm hoạt động. Phần mềm luôn có lỗi. Phần mềm down thì luôn có lý do, dù lý do đó ngớ ngẩn đến đâu — config typo, dependency xung đột, OOM, race condition, certificate expired. Luôn có cái gì đó.

Lần này thì không.

Vinh mở rộng query — không lọc severity, lọc theo timestamp. Mọi log line từ 3:04:00 đến 3:16:00. Hàng nghìn dòng INFO, DEBUG, metric sampling bình thường.

Và lẫn trong đó, một dòng không nên ở đó.

[03:04:12.387] [unknown] [unmapped] signal: 0.0047 / 0.0031 / 0.0089

Không có service name. Không có log level. Format không match bất kỳ logging pattern nào Holistics dùng. Structured JSON với requestId, serviceId, timestamp ISO 8601 — dòng này không có thứ gì trong số đó. Chỉ timestamp, hai tag lạ (unknown, unmapped), và ba con số.

Vinh scroll. Thêm.

[03:04:14.102] [unknown] [unmapped] signal: 0.0051 / 0.0029 / 0.0092 [03:04:15.883] [unknown] [unmapped] signal: 0.0044 / 0.0034 / 0.0081 [03:04:18.001] [unknown] [unmapped] signal: 0.0062 / 0.0026 / 0.0103

Khoảng cách giữa các dòng không đều — hai giây, gần hai giây, hơn hai giây. Ba con số thay đổi nhẹ mỗi lần. Không phải zero, không phải round number, không phải hash. Chúng trông như readings. Giống output của một sensor nào đó.

Nhưng Holistics không có sensor nào ghi log như thế này.

Vinh grep unmapped trong toàn bộ Loki. Kết quả: 347 dòng, tất cả trong khoảng 3:04 đến 3:16. Không có trước, không có sau. Chúng chỉ tồn tại đúng trong lúc downtime.

Anh ngồi thẳng dậy.

Đây không phải log của Holistics. Nó không thuộc application nào anh maintain, không thuộc infrastructure component nào anh quản lý. Nó lọt vào log aggregator — nghĩa là thứ gì đó có quyền ghi vào logging pipeline đã tạo ra nó. Nhưng không ai deploy component mới, không ai thêm integration. Vinh check access control — không có credential mới, không có service account mới. Pipeline chỉ nhận input từ các service đã đăng ký.

Thế thì 347 dòng này đến từ đâu?

Vinh export ra CSV. Mở Jupyter Notebook, load vào pandas. Ba cột số, anh tạm gọi A, B, C.

Cột A dao động quanh 0.005. Cột B quanh 0.003. Cột C quanh 0.009. Xem raw numbers thì chỉ là noise.

Anh plot lên.

Chart line đầu tiên — cột A — hiện ra. Dao động nhẹ, lên xuống, lên xuống. Vinh zoom ra để xem toàn bộ 347 điểm.

Nó có nhịp.

Không phải sinusoidal, không phải periodic theo nghĩa toán học chính xác. Nhưng có dao động — tăng dần, đạt đỉnh, giảm dần, đạt đáy, lặp lại. Khoảng bốn mươi giây một chu kỳ. Cột B cũng vậy, nhưng ngược pha — khi A lên thì B xuống. Cột C dao động nhanh hơn, biên độ nhỏ hơn, như sóng gợn trên mặt nước lớn.

Vinh copy ba cột số, dán vào ba tab mới, plot riêng từng cột, rồi overlay. Đường A và B đan xen — khi một đường lên, đường kia xuống, điểm giao nhau đều đặn. Đường C chạy qua lại giữa hai đường kia, dao động theo nhịp riêng nhưng đồng pha với tổng thể.

Vinh đã nhìn hàng nghìn biểu đồ trong đời. Latency, throughput, error rate, CPU, memory, disk I/O. Anh biết đọc data như đọc chữ. Và anh biết data nhìn như thế này nghĩa là gì.

Nó có cấu trúc. Nó có nhịp. Nó lên xuống đều đặn.

Nó thở.

Anh ngồi yên. Cà phê trong tay đã nguội hẳn, nhưng anh không đặt xuống. Bên ngoài cửa sổ, Sài Gòn 4 giờ sáng đang ngủ. Tiếng xe tải xa xa trên đại lộ. Đèn đường hắt bóng lên trần.


Sáng hôm sau, standup meeting trên Google Meet. Team Holistics — sáu người — lọt vào frame, mặt ai cũng như chưa ngủ.

Minh ngồi trước, ly trà sữa size L, mắt sưng. «Tao vẫn chưa tìm được gì. Frontend không có error, không có network issue. Mày sao?»

«Tao cũng vậy,» Vinh nói. «Hệ thống down mà không có root cause. Mọi thứ clean.»

«Hay quá. Vậy mình viết RCA gì? ‘Hệ thống tự hết’ à?»

Hải xuất hiện trên Meet — CTO Holistics, bốn mươi hai tuổi, tóc cắt ngắn, mặt không có biểu cảm. Anh không chào.

«Status.»

Vinh tóm tắt: downtime mười một phút, không có error, không có deployment, tự phục hồi. Hải nghe xong, gương mặt không thay đổi. «RCA trong 48 giờ. Tôi cần biết tại sao, và tôi cần biết nó có lặp lại không. Khách hàng enterprise đang hỏi. SLA của chúng ta là 99.9%. Incident này ăn 0.008% uptime tháng. Nếu lặp thêm hai lần, chúng ta vi phạm SLA với VPBank.»

Không phải đe dọa. Chỉ là con số. Hải luôn nói bằng con số.

«Hiểu,» Vinh nói.

Hải thoát. Cả team nhìn nhau qua grid sáu ô vuông trên màn hình.

Minh nhấp trà sữa. «Mày biết không, tao mơ thấy server room tối, rồi có cái gì đó phát sáng trong rack. Tao đùa thôi, nhưng mà… mấy cái downtime kiểu này, ở công ty cũ tao có ông sysadmin kể chuyện máy tự restart vào đúng ngày rằm.»

«Mày nghi ma ám server hả?»

«Tao nghi gì cũng được, miễn tìm được nguyên nhân. Từ chối giả thuyết thì sao debug.»

Vinh bật cười. Nhưng anh không phản đối cái logic đó. Từ chối giả thuyết thì không debug được. Anh chỉ chưa thấy giả thuyết nào khả dĩ. Cái anh có là 347 dòng log không thuộc về hệ thống nào anh biết, và một biểu đồ không nên tồn tại.

«Ê,» Minh gọi. «48 giờ thôi đấy. Đừng đuổi theo mấy cái wild goose chase. Cái gì giải thích được thì viết, cái gì không thì ghi ‘unknown’, chuyển sang infra team check.»

«Ừ,» Vinh gật. «Tao biết.»

Anh biết. Nhưng “unknown” là thứ Vinh không chịu được.


Sau standup, Vinh quay lại với 347 dòng log.

Anh không nói cho ai về chúng. Không phải giấu — mà vì chưa có gì để nói. ‘Tìm thấy data lạ trong log’ nghe giống bước đầu của mọi investigation. Chưa đủ để kết luận gì.

Nhưng anh không dừng đọc.

Anh chạy correlation: timestamp của anomalous data so với timestamp của traffic drop. Anomalous data bắt đầu lúc 3:04:12.387. Traffic drop bắt đầu lúc 3:04:12.401. Chênh lệch: 14 mili-giây. Anomalous data dừng lúc 3:15:38.219. Traffic phục hồi lúc 3:15:38.442. Chênh lệch: 223 mili-giây.

Data lạ xuất hiện trước khi downtime bắt đầu, và biến mất trước khi hệ thống phục hồi. Không phải symptom. Nó là precursor.

Tay Vinh dừng trên bàn phím.

Mười bốn mili-giây. Nếu anomalous data là nguyên nhân, thì cái gì đã generate nó? Và tại sao nó ngừng đúng lúc hệ thống phục hồi? Phải chăng nguyên nhân và kết quả là cùng một thứ — thứ gì đó vừa gây downtime, vừa ghi lại chính mình trong log?

Anh mở chart lần nữa. Ba đường đan xen, nhịp nhàng. Rõ ràng hơn khi anh biết mình đang tìm — đó không phải noise. Đó là tín hiệu.

Nhưng tín hiệu của gì?

Vinh filter theo unmapped tag, lần này kéo dài hơn — 24 giờ trước và 24 giờ sau incident. Kết quả: 347 dòng, chỉ trong khoảng downtime. Không có dấu vết nào khác. Bất kể thứ gì đã generate data này, nó chỉ hoạt động đúng mười một phút hai mươi sáu giây, rồi tắt.

Hoặc nó vẫn ở đó, nhưng anh chưa biết tìm ở đâu.

Anh lưu chart vào thư mục ~/investigation/incident-0304/, đặt tên file anomaly_pattern.png. Mở note app, gõ:

- Incident: 03:04–03:15, P1, all services unreachable
- No error, no deployment, auto-recovery after 11m26s
- Anomalous data: 347 log entries, unknown source, unmapped tag
- Correlation: data appears 14ms before downtime, disappears 223ms before recovery
- Pattern: rhythmic oscillation, ~40s cycle, 3 correlated signals
- Status: UNEXPLAINED

Anh nhìn dòng cuối cùng. UNEXPLAINED. Bốn năm làm DevOps, chưa bao giờ anh viết chữ đó vào incident report. Mọi thứ đều có nguyên nhân. Đôi khi khó tìm, đôi khi ngớ ngẩn, đôi khi mất vài ngày — nhưng luôn có.

Lần này thì chưa có. Chưa.

Anh tắt note, mở chart lần cuối. Ba đường cong đan xen trên nền đen, dao động nhẹ, lên xuống, lên xuống. Đều đặn. Nhịp nhàng.

Bên ngoài cửa sổ, Sài Gòn sáng. Tiếng xe máy bắt đầu đông. Cuộc đời vẫn chạy.

Nhưng trên màn hình, cái gì đó đang thở.


Share this chapter on:

Next Chapter
Data Không Thuộc Hệ Thống Nào