Phân tích hậu sự cố gián đoạn ngày 18 tháng 11 năm 2025 của Cloudflare
(blog.cloudflare.com)- Vào 11:20 (UTC) ngày 18 tháng 11 năm 2025, chức năng phân phối lưu lượng cốt lõi của mạng Cloudflare bị gián đoạn, khiến người dùng trên toàn cầu nhìn thấy trang lỗi
- Nguyên nhân là tệp
featurecủa hệ thống Bot Management phình to bất thường do thay đổi quyền cơ sở dữ liệu, không liên quan đến tấn công mạng - Việc kích thước tệp tăng lên khiến phần mềm định tuyến lưu lượng vượt quá ngưỡng giới hạn và thất bại, gây ra lỗi HTTP 5xx trên diện rộng
- Khoảng 14:30, Cloudflare dừng triển khai tệp có vấn đề và thay bằng phiên bản ổn định trước đó để khôi phục lưu lượng cốt lõi; đến 17:06, mọi dịch vụ đã hoạt động bình thường trở lại
- Cloudflare đánh giá đây là sự cố nghiêm trọng nhất kể từ năm 2019, và đang thúc đẩy các biện pháp ngăn tái diễn như tăng cường kiểm tra tệp cấu hình và bổ sung công tắc ngắt toàn cục
Tổng quan sự cố
- Khoảng 11:20, mạng Cloudflare gặp lỗi phân phối lưu lượng cốt lõi, người dùng thấy trang lỗi nội bộ của Cloudflare
- Không phải tấn công mạng hay hành vi ác ý, mà nguyên nhân trực tiếp là thay đổi quyền trong hệ thống cơ sở dữ liệu
- Thay đổi này khiến kích thước của tệp
featuremà hệ thống Bot Management sử dụng tăng gấp đôi, rồi được triển khai trên toàn mạng - Trong quá trình phần mềm định tuyến lưu lượng đọc tệp này, nó đã vượt quá giới hạn kích thước tệp, gây lỗi hệ thống
- Ban đầu sự cố bị nhầm là một cuộc tấn công DDoS quy mô lớn, nhưng sau khi xác định được nguyên nhân, Cloudflare đã thay bằng tệp ổn định trước đó để tiến hành khôi phục
Diễn biến và tác động của sự cố
- Trước 11:20, tỷ lệ lỗi 5xx ở mức bình thường; sau đó tăng vọt do triển khai nhầm tệp
featurelỗi - Trên một số node của cụm cơ sở dữ liệu ClickHouse, kết quả truy vấn sai được tạo ra theo chu kỳ 5 phút, khiến các tệp bình thường và bất thường luân phiên được triển khai, làm hệ thống liên tục rơi vào vòng lặp phục hồi rồi lại thất bại
- Từ 14:30, Cloudflare ngừng tạo tệp có vấn đề và chèn thủ công tệp bình thường, sau đó khôi phục bằng cách khởi động lại proxy lõi
- 17:06, toàn bộ dịch vụ trở lại bình thường
| Dịch vụ | Nội dung ảnh hưởng |
|---|---|
| Core CDN và dịch vụ bảo mật | Xuất hiện lỗi HTTP 5xx |
| Turnstile | Tải thất bại, không thể đăng nhập |
| Workers KV | Lỗi gateway khiến lỗi 5xx tăng mạnh |
| Dashboard | Không thể đăng nhập do Turnstile gặp sự cố |
| Email Security | Độ chính xác phát hiện spam tạm thời giảm, một số thao tác di chuyển tự động thất bại |
| Access | Xảy ra nhiều lỗi xác thực, nhưng phiên hiện có vẫn được duy trì |
- Trong thời gian sự cố, độ trễ phản hồi của CDN tăng lên, nguyên nhân là mức sử dụng CPU của hệ thống debug tăng đột biến
Nguyên nhân sự cố: hệ thống Bot Management
- Mô-đun Bot Management của Cloudflare dùng mô hình máy học để tạo điểm bot cho từng request
- Tệp cấu hình
featuredùng làm đầu vào cho mô hình được triển khai trên toàn mạng sau mỗi vài phút để phản ứng với các mối đe dọa mới nhất - Do thay đổi hành vi truy vấn của ClickHouse, nhiều dòng
featuretrùng lặp đã được đưa vào, làm kích thước tệp tăng lên - Vì vậy mô-đun Bot Management gặp lỗi và trả về phản hồi HTTP 5xx, đồng thời ảnh hưởng đến Workers KV và Access
- Trên engine proxy mới FL2, lỗi 5xx xảy ra; còn trên phiên bản cũ FL, điểm bot bị đặt về 0, làm tăng false positive
Thay đổi hành vi truy vấn ClickHouse
- Lúc 11:05, thay đổi quyền truy cập cơ sở dữ liệu của ClickHouse được triển khai
- Trước đó chỉ có thể truy vấn metadata của cơ sở dữ liệu
default, nhưng sau thay đổi, metadata của cơ sở dữ liệur0cũng được lộ ra - Truy vấn tạo tệp
featurecủa Bot Management được chạy mà không lọc theo tên cơ sở dữ liệu, nên cuối cùng trả về các cột trùng lặp - Điều này khiến số dòng trong tệp
featuretăng hơn gấp đôi, vượt quá giới hạn của hệ thống
Cấp phát bộ nhớ trước và panic hệ thống
- Mô-đun Bot Management giới hạn tối đa 200
featurecủa mô hình máy học và cấp phát bộ nhớ trước dựa trên giới hạn đó - Khi tệp sai chứa số
featurevượt quá 200, mã Rust phát sinh panic, với thông báo lỗi
thread fl2_worker_thread panicked: called Result::unwrap() on an Err value - Kết quả là lỗi HTTP 5xx xảy ra trên diện rộng
Các ảnh hưởng khác và quá trình khôi phục
- Workers KV và Access phụ thuộc vào proxy lõi nên mức ảnh hưởng lan rộng hơn
- Lúc 13:04, Workers KV được vá để đi vòng qua proxy, giúp tỷ lệ lỗi giảm xuống
- Dashboard phụ thuộc vào Turnstile và Workers KV nên không thể đăng nhập
- Có hai giai đoạn suy giảm khả dụng: 11:30~13:10 và 14:40~15:30
- Độ trễ tăng do backlog và các request thử lại, rồi được khôi phục vào khoảng 15:30
- Sau 14:30, phần lớn dịch vụ trở lại bình thường; 17:06 hoàn tất khôi phục hoàn toàn
Biện pháp ngăn tái diễn
- Tăng cường kiểm tra đầu vào cho các tệp cấu hình do Cloudflare tạo ra
- Mở rộng công tắc ngắt tính năng toàn cục (
kill switch) - Ngăn cạn kiệt tài nguyên hệ thống do báo lỗi
- Rà soát các điều kiện lỗi trên toàn bộ các mô-đun proxy lõi
Tóm tắt timeline (UTC)
| Thời điểm | Trạng thái | Mô tả |
|---|---|---|
| 11:05 | Bình thường | Triển khai thay đổi kiểm soát truy cập cơ sở dữ liệu |
| 11:28 | Bắt đầu ảnh hưởng | Xuất hiện lỗi đầu tiên trên lưu lượng khách hàng |
| 11:32–13:05 | Điều tra đang diễn ra | Phân tích nguyên nhân lỗi của Workers KV, thử các biện pháp giảm nhẹ |
| 13:05 | Mức ảnh hưởng giảm | Áp dụng đường vòng cho Workers KV và Access |
| 13:37 | Tập trung khôi phục | Chuẩn bị rollback tệp cấu hình của Bot Management |
| 14:24 | Dừng triển khai tệp lỗi | Hoàn tất kiểm thử tệp bình thường |
| 14:30 | Giải quyết phần lớn tác động | Triển khai toàn cục tệp bình thường, bắt đầu khôi phục dịch vụ |
| 17:06 | Khôi phục hoàn toàn | Tất cả dịch vụ hoạt động bình thường trở lại |
Kết luận
- Sự cố lần này xảy ra do tương tác giữa logic tạo tệp cấu hình của Bot Management và thay đổi quyền cơ sở dữ liệu
- Cloudflare đánh giá đây là sự cố gián đoạn mạng nghiêm trọng nhất kể từ năm 2019
- Trong thời gian tới, công ty sẽ thúc đẩy các cải tiến mang tính cấu trúc và tăng cường hệ thống phòng vệ tự động để nâng cao khả năng phục hồi của hệ thống
8 bình luận
Sự cố liên quan đến tệp cấu hình thì ở đâu cũng xảy ra nhỉ.
Cloudflare bị sự cố khiến đủ loại dịch vụ ngừng hoạt động, đúng là địa ngục..
Tài liệu phân tích nguyên nhân được công bố khá nhanh nhỉ, ghê thật
Mà tiện thể, tác giả của bài viết này lại chính là CEO.
Ý kiến trên Hacker News
Đây là một câu chuyện tai nạn
.unwrap()trị giá hàng triệu đôViệc gọi
.unwrap()trên đường đi của hạ tầng cốt lõi Internet chẳng khác nào tuyên bố rằng “việc này tuyệt đối không thể thất bại, nếu thất bại thì giết luôn thread ngay lập tức”Trình biên dịch Rust buộc phải biểu đạt rõ khả năng thất bại, nhưng ở đây họ đã chọn panic thay vì xử lý một cách mềm dẻo
Tôi nghĩ đây là một ví dụ điển hình của phản mẫu “parse, don’t validate”
.unwrap(). Có lẽ vì nó xuất hiện quá thường xuyên trong code ví dụTrong code vận hành thực tế,
.unwrap()hay.expect()nên được review như panicNếu dùng
.unwrap()trong code production thì bắt buộc phải có chú thích “INFALLIBILITY”, và có thể cưỡng chế điều này bằngclippy::unwrap_usedKhông chỉ vì
.unwrap(), mà còn vì truy vấn không phân biệt cơ sở dữ liệu nên payload phình to, và ClickHouse lại phơi bày thêm nhiều DB hơnThay vì khẳng định đơn giản là “do unwrap”, tôi nghĩ điều quan trọng hơn là cải thiện thiết kế để có global kill switch hoặc tránh làm quá tải tài nguyên hệ thống
Ở tầng FL2 cần bắt panic của từng component, nhưng fail-open không phải lúc nào cũng tốt hơn
Cần thêm logic để quyết định một cách tường minh ở cấp FL2 xem có nên bắt panic và xử lý hay không
Nếu là hệ thống sharding, tôi cũng thắc mắc tại sao lại không có rollout dần và giám sát
!và unwrap tường minh?Tôi hầu như không dùng unwrap ngầm. Kể cả với giá trị đã được đảm bảo, tôi vẫn luôn xử lý tường minh
Ví dụ tôi sẽ định nghĩa
@IBOutlet weak var someView?thay vì@IBOutlet weak var someView!Đây là kiểu tiếp cận belt & suspenders
Việc công bố post mortem chưa đầy 24 giờ sau sự cố thật sự rất ấn tượng
Với hầu hết các tập đoàn lớn, việc công bố code gần như là bất khả thi vì phải qua nhiều vòng xem xét của các stakeholder
Khi đọc phần giải thích sự cố của Cloudflare, tôi đã tự hỏi “tại sao khôi phục lại mất lâu đến vậy”
Tôi hiểu nguyên nhân gây sự cố, nhưng nếu phần lớn mạng lưới bị sập thì chẳng phải ưu tiên số một là hoàn tác thay đổi cấu hình gần nhất sao
Tất nhiên nhìn lại thì mọi thứ đều rõ ràng hơn, nhưng việc họ bắt đầu điều tra chỉ sau 7 phút vẫn rất đáng nể
Vụ việc này gợi cảm giác giống sự cố CrowdStrike
Một file cấu hình được tạo tự động đã làm phần mềm hỏng và lan ra toàn bộ mạng lưới
Tôi hiểu việc cần triển khai nhanh, nhưng lần này đã bộc lộ sự thiếu vắng của chiến lược rollout dần và rollback
Nhìn vào kế hoạch cải thiện trong tương lai mà Cloudflare công bố,
có các mục như vậy
Nhưng lại không thấy canary deployment hay triển khai cấu hình dần dần
Global switch có thể nguy hiểm, và chỉ một lỗi cũng có thể làm dừng toàn bộ hệ thống
Tôi cũng thắc mắc vì sao lại dùng ClickHouse làm kho lưu feature flag. Ngay cả tài liệu deduplication của ClickHouse cũng có nói đến các yếu tố rủi ro
Nếu có bản đồ quan hệ phụ thuộc giữa các dịch vụ thì việc lần ra nguyên nhân sẽ dễ hơn rất nhiều
Việc triển khai code thì cẩn trọng, còn triển khai cấu hình thì không. Cần nhìn nhận cấu hình cũng là code
Chi tiết trạng thái trang status cũng bị sập, dẫn tới việc ban đầu bị nhầm là bị tấn công, khá thú vị
Họ nói nó hoàn toàn tách biệt với hạ tầng Cloudflare, nhưng lại không giải thích vì sao nó cũng chết theo
Tôi đã tích hợp Turnstile theo chiến lược fail-open, và lần sự cố này nó đã phát huy tác dụng
Nếu JS không tải được thì vẫn cho phép gửi bằng token giả, còn ở backend nếu xác thực thất bại thì cũng xử lý theo fail-open
Một số người dùng vẫn bị chặn, nhưng tác động tổng thể đã giảm bớt
Đây là cách tiếp cận chỉ khả thi khi có các biện pháp giảm thiểu bot khác
Nhưng có lẽ điều này chỉ hiệu quả khi không phải tấn công có chủ đích
Tôi thắc mắc tại sao code của Cloudflare lại cho phép
.unwrap()Ít nhất họ cũng nên dùng
expect("chuyện này tuyệt đối không xảy ra")Triết lý coi lỗi là giá trị vốn là để ngăn những vấn đề kiểu này, và nó cũng sẽ giúp việc chẩn đoán dễ hơn rất nhiều
Trong code có lời gọi mạng, khả năng thất bại là quá nhiều
Lúc phát triển thì tôi có dùng
.unwrap(), nhưng trong production đôi khi vẫn để lại expect(). Vì có những lúc thực sự không còn cách nào để tiếp tụcBài học thật sự là có quá nhiều chức năng đang phụ thuộc vào một số ít người chơi
Cấu trúc người thắng ăn cả đang ngày càng trầm trọng, làm suy giảm tính đàn hồi của hệ thống
Tất nhiên vị thế đó là do họ có năng lực mà đạt được, nhưng kỳ vọng Internet lúc nào cũng sẽ “hoạt động bình thường” có lẽ là hơi quá
Câu nói “cứ là Rust thì sẽ an toàn” là phóng đại
Dù là ngôn ngữ nào thì dùng sai cũng chẳng khác gì tự chĩa súng vào chân mình
Ngay cả một công ty tầm cỡ như CF mà cũng dùng
.unwrap()nhỉ, ghê thật.Không hiểu đoạn code đó đã được đưa vào production bằng cách nào
Có vẻ không phải vấn đề của
unwrapVấn đề cốt lõi là truy vấn bị sai.
Nhưng tôi cũng nghĩ việc bỏ qua khâu kiểm chứng vấn đề bằng
unwrapcũng là một vấn đề.Dù nội bộ có phát sinh sự cố đi nữa, nếu đã xử lý lỗi thì có lẽ lưu lượng sẽ không bị sập.