Kiểm thử độ tin cậy (chaos, fault injection, mô phỏng tất định)

Chủ đề Dành cho thành viên
Bài đọc thử: 2/3 · còn 1 bài miễn phí · Xem gói thành viên

Bài toán

Lỗi trong hệ phân tán là chắc chắn (máy chết, zone mất, dependency chậm, cấu hình sai), nhưng phần lớn lỗi nằm ở những tổ hợp hiếm mà test chức năng không chạm tới. Bài toán là chủ động gây lỗi để biết hệ thống phản ứng thế nào trước khi lỗi thật xảy ra: ở production (chaos), ở môi trường dev/CI (fault injection có hệ thống), hay trong một simulator chạy code thật (mô phỏng tất định), và kiểm cả bất biến nhìn từ client lẫn bên trong từng node.

Trang này nói về cách kiểm chứng độ bền, gồm cả nơi chạy kiểm chứng tích hợp (staging, test trong production bằng tenant riêng, môi trường hạ tầng dựng rồi phá cho mỗi commit). Kiến trúc nhiều vùng ở Độ tin cậy và multi-region; cơ chế failover trong một cụm ở Failover, replica và dự phòng dữ liệu; kiểm chứng capacity bằng tải (không gây lỗi) ở Load test và kiểm chứng capacity.

Diễn tiến theo thời gian

  • 2011 · Netflix: sự cố AWS US-East là bài kiểm tra lớn đầu tiên; Chaos Monkey (giết instance ngẫu nhiên) đã có nhưng không mô phỏng mất cả một AZ, nên Chaos Gorilla ra đời. Diễn tập chỉ chứng minh được thứ nó mô phỏng. Netflix 2011
  • 2011→2014 · WhatsApp (qua HighScalability): tải tổng hợp không mô phỏng được thế giới thật ở quy mô hàng triệu kết nối mỗi máy, nên kiểm bằng traffic production: rẽ nhánh traffic sang hệ riêng, đưa một máy vào DNS vài lần để nhận gấp đôi, gấp ba tải. WhatsApp 2014
  • 2013 · Netflix: diễn tập Split-brain (cắt mạng giữa region) và Chaos Kong (dồn phần lớn traffic sang một region hơn 24 giờ) trước khi tin active-active; Latency Monkey tiêm latency và lỗi theo phân phối cho trường hợp dependency hỏng một phần thời gian. Netflix 2013
  • 2013→2020 · LinkedIn (dark canary): từ mapping host-host trong ZooKeeper (2013, vỡ mỗi khi host bị thay) sang dark canary cluster trong D2: cụm thật fork bản sao request đọc tới cụm dark, bỏ response; tỉ lệ fork tính theo số instance hai bên để QPS mỗi instance tương đương. LinkedIn 2020
  • 2013 · Jepsen: Kafka 0.8 (bản thiết kế): cô lập leader bằng iptables, 520/987 ghi đã ack bị mất khi ISR co về một node rồi bầu leader mới. Jepsen 2013
  • 2013 · Jepsen: Cassandra 2.0.0: sửa cell mất 28% ghi dù QUORUM + khoá; lightweight transaction (Paxos) deadlock rồi mất 1–5% ghi không cần partition; DataStax đưa test vào quy trình. Jepsen 2013
  • 2017 · LinkedIn (Waterbear): chaos ở hai tầng: LinkedOut inject lỗi trong client Rest.li, chọn đối tượng bằng hệ A/B LiX nên chạy trên production; FireDrill giả lập lỗi host (mạng, đĩa, CPU) bằng SaltStack, sau đó tới rack và nguồn. LinkedIn 2017
  • 2018→2019 · Riot Games: chuyển Redis của rate limiter vào cloud container nội bộ bằng sidecar; test tay ổn nhưng bật thật thì mọi cụm sập. Fault injection tự động (Mundo Make Fail) tìm ra: container mới nhận lại IP cũ với UUID mới làm driver ghi node :0, một secondary hỏng nằm im tới khi được promote; bầu leader trên service discovery nhất quán cuối cùng nên treo. Tiêu chí: xoá và dựng lại cụm qua 100 lần liên tiếp, rồi chạy ở production (khoảng 100 test/ngày); test không tự phán kết quả mà để monitoring phán, và nhờ vậy lộ ra không thấy được cụm suy giảm. Riot Games 2019
  • 2018 · Dropbox: harness kiểm transaction chéo shard chạy liên tục trong môi trường build với fault injection: chu trình trong đồ thị thứ tự là vi phạm serializability, đồ thị participant thiếu cạnh là vi phạm atomicity; bắt được bug từ lỗi bị nuốt tới lỗ hổng giao thức đọc. Dropbox 2018
  • 2018 · LinkedIn (LinkedOut): disruptor filter (error/delay/timeout) bật qua LiX hoặc invocation context; kiểm thử tự động bằng service account + Selenium cho mọi service phía dưới (lấy từ Call Tree), coi trang "oops"/trắng là không xuống cấp mềm; ramp chỉ trên nhân viên đã opt-in, có nút terminate. Bẫy: tài khoản test không có dữ liệu làm trang lỗi sẵn. LinkedIn 2018
  • 2019 · Appian: data store cam kết linearizability; HA (leader ghi, replica đọc và tự đuổi theo) cần kiểm failover và read-your-own-writes dưới lỗi. Jepsen chạy trong Docker (5 node, Kafka/Zookeeper đứng ngoài tầm nemesis), Knossos kiểm lịch sử thao tác; đưa vào Jenkins trên mỗi thay đổi vào master. Kết quả chia ba: vi phạm (UNSTABLE), đúng, và test hỏng (FAILURE, ví dụ nemesis crash, vì khi đó "xanh" chỉ do hệ không bị gây lỗi). Appian 2019 Appian 2019
  • 2019 · Bumble (Badoo): monolith PHP ra backend trước client hàng tháng: SoftMocks cho code cũ (kèm quy tắc code mới phải test được bằng mock chuẩn), mutation testing tự viết, DBMocks chuyển truy vấn sang bảng tạm trên tmpfs để test song song; API test chạy cả trên pre-production với cờ is_test_user cố định từ lúc đăng ký, loại khỏi analytics và A/B; QA API là backdoor có ba lớp chặn (mạng, khoá, chỉ test user). Bumble 2019
  • 2019 · Slalom Build (bài quan điểm, bốn ca khách hàng): test API/UI/tích hợp vẫn chạy tay trên laptop vì ba lý do: giá trị, kiến trúc (không có module), khả thi (không chạy được service trong test runner, không giả được dependency). Phân tầng: module test với dependency giả chặn merge, site integration test chạy sau deploy. Gỡ khả thi bằng runner gộp @SpringBootTest, Jenkins trên VM có Chrome, DB in-memory (mỗi ca khoảng một ngày công, chi phí chạy thêm 0 USD vì runner dư capacity); desktop app nguyên khối thì refactor thành module (khoảng hai tháng) với UI test làm lưới Slalom Build 2019
  • 2020 · CapitalOne (bài quan điểm): theo một enterprise architect, chaos phải dựa trên failure mode analysis và phủ cả môi trường (cạn IP, automation tự chữa), bảo mật (đổi chuỗi chứng chỉ), con người (kiến thức trong đầu), quy trình (thủ tục khôi phục ít dùng); kiểm nhiều lỗi cùng lúc; cần baseline observability theo từng phiên bản trước khi đọc kết quả; đầu tư cân với SLO, không nhắm 100%. CapitalOne 2020
  • 2020 · Atlassian: test hạ tầng Kubernetes (hơn 22 cụm tự cấu hình) trên mỗi commit: dựng cụm thật, test theo lời hứa với người dùng (DNS, ingress, IAM role, log, chặn mạng), phá bỏ bằng aws-nuke trong một tài khoản riêng (hơn 300 build không lần nào phá bỏ hỏng), giữ lại thứ chậm mà ít giá trị (gateway, chứng chỉ), nhiều môi trường song song; bắt hơn 7 lỗi đã lọt review. Atlassian 2020
  • 2020 · Trendyol: lỗi do môi trường test dùng chung kéo dài Lead Time; thêm component test chạy trong pipeline GitLab: Docker Compose dựng service + Couchbase tự tạo bucket/index + WireMock giả hai API ngoài, test hỏng thì dừng pipeline. Không nêu số Lead Time trước/sau Trendyol 2020
  • 2020 · Jepsen: sinh transaction ngẫu nhiên rồi suy tính chất từ lịch sử (Elle) tìm được bug serializability trong PostgreSQL mà test bằng ví dụ khéo dựng bỏ sót; Jepsen tự nói chỉ chứng minh được có bug, không chứng minh được không có. Jepsen 2020
  • 2021 · Dream11: game day hiệu năng (Torque) theo mức dự báo trước sự kiện lớn: tìm năng lực từng service, điểm bão hoà, hiệu ứng dây chuyền, kể cả giới hạn của cloud provider. Dream11 2021
  • 2021→2022 · DoorDash: chaos ở production không hợp (khách mất đơn đồ ăn); thử Filibuster: phân tích tĩnh tìm lỗi có thể ở từng chỗ gọi RPC, tiêm có hệ thống (đơn lẻ rồi tổ hợp) khi chạy test chức năng, buộc developer viết assertion cho hành vi khi dependency lỗi; prototype trên hai service. DoorDash 2022
  • 2021 · Swiggy: hơn 400 microservice, unit test không bắt lỗi mạng, I/O, hợp đồng API; chuyển trọng tâm sang service level test (test hộp đen qua API, dependency thật dựng cục bộ, mock gRPC/HTTP) với thư viện Oh-My-Test-Helper; gần trăm service dùng trong 6 tháng, viết SLT từ vài ngày xuống vài giờ. Swiggy 2021
  • 2021 · Trendyol: coverage 100% vẫn có thể là test không assert gì; PIT đột biến bytecode (đổi toán tử, đảo điều kiện, trả null) và đo tỉ lệ mutant bị test giết; chạy trên phần code đổi của mỗi nhánh để vừa vòng CI. Trendyol 2021
  • 2021 · HRT: test FPGA viết một lần, chạy được cả trên mô phỏng (Verilator) lẫn phần cứng thật trong lab, làm lưới an toàn cho chính sai lệch của công cụ mô phỏng. Hudson River Trading 2021
  • 2022 · Goldman Sachs: chaos trong pipeline GitLab (ChaosToolkit) cho 7 microservice trên 5 tài khoản AWS (SLO 99,99%, p95 50 ms): sandbox dựng bằng IaC, token gây lỗi ngắn hạn, test fail thì pipeline fail, kết quả lưu làm audit trail; ba nhóm lỗi (hạ tầng, mạng, hình dạng traffic bằng k6) và game day không báo trước. Tìm ra health check 30 giây làm lỗi 0,14% (rút ngắn còn 0,07%), đường cho traffic độc hại lọt vào khi dependency ngoài hỏng, runbook thiếu đường leo thang. Goldman Sachs 2022
  • 2022 · DoorDash: bỏ staging (không có observability e2e, không mô phỏng được dữ liệu vì PII, bị deploy bản chưa ổn định) để test e2e trong production bằng tenant DoorTest: tenant truyền qua mọi service bằng OpenTelemetry baggage, database riêng + cột tenant-id, CDN xoá header ngoài VPN, guardrail chặn đơn giữa thế giới test và thật, công cụ tạo user/đơn test. DoorDash 2022
  • 2022 · Jepsen: Redpanda 21.10.1: 10 vấn đề gồm ghi trùng với cấu hình mặc định, aborted read, mất ghi transaction; nhiều lỗi trên cụm khoẻ; đội Redpanda đã có fault injection riêng và tự tìm vài bug trước. Jepsen 2022
  • 2023 · Miro: API công khai chuyển nguồn sự thật từ OpenAPI sinh từ code sang file OpenAPI viết tay (design-first), mất bảo đảm "endpoint được mô tả là có thật"; dựng lại bằng test sinh từ chính đặc tả: đồ thị phụ thuộc giữa endpoint (tạo trước, xoá vào cleanup queue), BFS, plugin cho phần phải map tay; chạy theo lịch và gắn với xuất bản tài liệu. Miro 2023
  • 2023 · Jepsen (MySQL): Elle được mở rộng để bắt lost update không nằm trong chu trình nào (198 trường hợp, chỉ 47 nằm trong chu trình mà checker cũ thấy); LazyFS giả lập mất dữ liệu chưa fsync: mặc định innodb_flush_log_at_trx_commit=1 an toàn, đặt 0 thì mất giao dịch. Jepsen 2023
  • 2024 · OpenAI: sau sự cố control plane Kubernetes, cam kết test data plane sống không có control plane lâu hơn, và cố ý rollout thay đổi xấu để kiểm việc phát hiện và rollback; diễn tập thay nguyên một cụm. OpenAI 2024
  • 2025→2026 · TigerBeetle: qua Jepsen (kiểm từ ngoài vào), rồi kiểm từ trong ra bằng mô phỏng tất định có hiểu giao thức: chạy code đồng thuận và storage thật trong simulator, kiểm checksum từng request đã commit, cấu trúc LSM và dữ liệu giống nhau từng byte giữa replica, liveness theo từng replica (tự khôi phục mà không cần cụm, chỉ lấy block thiếu). Assertion bật ở production hạ vi phạm an toàn thành mất khả dụng. TigerBeetle 2026
  • 2025 · Cockroach Labs (nhà cung cấp): benchmark "Performance under Adversity": một test liên tục lồng bảy giai đoạn lỗi (bảo trì nội bộ như backup, CDC, đổi schema, rolling upgrade; disk stall; phân vùng mạng; restart node; mất zone; mất region) vào tải TPC-C, đo throughput và latency qua từng giai đoạn. Theo họ, chính việc khôi phục (snapshot, rebalance, kết nối lại dồn dập) là tải lớn, được giữ bằng admission control ưu tiên traffic client. Cockroach Labs 2025
  • 2025 · Go: testing/synctest (thử nghiệm trong Go 1.24): goroutine trong một bubble dùng đồng hồ giả, thời gian chỉ tiến khi mọi goroutine đều bị chặn bền; Wait thay cho ngủ-rồi-kiểm, vốn chỉ chọn được nhanh hoặc tin cậy; mutex và I/O mạng thật nằm ngoài mô phỏng, test mạng dùng net.Pipe. Go 2025
  • 2025 · Mercari: E2E test của API Global App chuyển từ Jest do QA giữ sang go test thường mà mọi developer viết được: server dựng theo test từ một pool, một container AlloyDB Omni với mỗi test một logical database (dọn bằng TRUNCATE), coverage của server bằng go build -cover; không chạy trên môi trường dev chung vì không kiểm được thay đổi đang sửa. Mercari 2025
  • 2025 · Jane Street: message bus Aria đã có mạng mô phỏng tất định, quickcheck, version skew test, fuzz AFL, lab test, chaos ở staging; thêm Antithesis (cả hệ trong VM dưới hypervisor tất định, tua lại được). Lần chạy đầu tìm 2 bug chưa biết; chạy hằng đêm bắt một bug trả dữ liệu hỏng khi tip-retransmitter phục vụ client vùng khác sau restart từ snapshot, bug cũ vốn bị service discovery của client cùng vùng che. (Jane Street dẫn vòng gọi vốn của Antithesis.) Jane Street 2025
  • 2025 · Jepsen: RDS for PostgreSQL Multi-AZ cluster: Long Fork trên cụm khoẻ vài phút một lần, ở mọi bản 13.15–17.4; nguyên nhân (đã biết từ 2013) do kỹ sư AWS và cộng đồng chỉ ra sau khi báo cáo công bố. Jepsen 2025
  • 2025 · Jepsen: NATS 2.12.1: không mất dữ liệu với partition/crash process, nhưng LazyFS giả lập crash OS và hỏng file .blk/snapshot gây mất message và split-brain kéo dài. Jepsen 2025
  • 2026 · Stripe: kiểm hồi quy bằng replay traffic lịch sử: tách lõi quyết định (ước tính phí mạng thẻ) thành thư viện thuần, Spark dựng lại đầu vào và trạng thái phụ thuộc từ snapshot (luật theo phiên bản, cấu hình theo ngày hiệu lực, response đã log), chạy bản cũ và bản ứng viên, ra bảng diff giải thích được. Dùng cho refactor, migration, code do AI hỗ trợ, và what-if cho luật sắp có hiệu lực; bản nhỏ là golden dataset chạy trên mỗi PR. Stripe 2026 Stripe 2026
  • 2026 · Anthropic (nhà cung cấp): nơi chạy kiểm chứng tự nó là biến: cùng model, cùng task, điểm benchmark agent lệch 6 điểm chỉ vì cách ép tài nguyên container; khuyến nghị ghi riêng mức bảo đảm và ngưỡng kill, hiệu chỉnh sao cho sàn và trần cho điểm trong nhiễu. Anthropic 2026
  • 2026 · Pulumi (blog nhà cung cấp, 10/2026): môi trường preview cho hàng trăm PR mỗi ngày: mỗi PR một stack Pulumi và namespace, sinh từ cùng component với Dev/Stage/Prod; tuần tự hoá cập nhật theo stack, job đối chiếu định kỳ dọn môi trường mồ côi và drift; khoảng 4 phút tới khi dùng được. Pulumi 2026
  • 2026 · WhatsApp: viết lại wamedia bằng Rust song song với bản C++, dùng differential fuzzing cùng unit/integration test để chứng minh hai bản cư xử như nhau trước khi chuyển. WhatsApp 2026

Các lựa chọn và đánh đổi

Lựa chọn Được Mất Nguồn
Chaos ở production Kiểm đúng môi trường thật, cả phản ứng của tổ chức Khách có thể chịu lỗi; không hợp mọi sản phẩm Netflix 2013, DoorDash 2022
Fault injection có hệ thống lúc dev/CI Phủ mọi lỗi ở từng chỗ gọi; rẻ, sớm Cần instrumentation; chỉ kiểm được thứ test chức năng chạm tới DoorDash 2022
Traffic production rẽ nhánh / dồn tải Tải thật, hành vi thật Phải chặn tác dụng phụ; khó kiểm soát WhatsApp 2014
Jepsen (từ ngoài vào) Kiểm bất biến client thấy Không thấy bất biến bên trong TigerBeetle 2026
Mô phỏng tất định chạy code thật Thời gian tăng tốc, tái hiện y hệt, kiểm bất biến nội bộ Phải thiết kế tất định từ đầu TigerBeetle 2026
Jepsen trong CI trên mỗi thay đổi Bắt hồi quy nhất quán sớm, chạy giống nhau ở local và CI Cụm container nhỏ; phải tự kiểm rằng nemesis thật sự chạy Appian 2019
Replay traffic lịch sử (bản cũ vs bản mới) Phủ phân phối đầu vào thật, diff định lượng Phải dựng lại trạng thái phụ thuộc; không mô phỏng được tác dụng phụ và hành vi bên ngoài Stripe 2026

Quy tắc rút ra

  1. Diễn tập chỉ chứng minh được thứ nó mô phỏng: mất máy, mất zone, mất region, cắt mạng, dependency chậm một phần là các bài kiểm tra khác nhau. Netflix 2011 Netflix 2013
  2. Staging nhỏ không bắt được lỗi tỉ lệ theo quy mô; cần rollout theo pha có theo dõi cả hạ tầng nền, hoặc tải thật. OpenAI 2024 WhatsApp 2014
  3. Kiểm cả đường phát hiện và rollback, không chỉ đường chạy đúng: cố ý đẩy thay đổi xấu. OpenAI 2024
  4. Tiêm lỗi có hệ thống thay vì ngẫu nhiên để không bỏ sót đúng tổ hợp gây sự cố. DoorDash 2022
  5. Tính tất định là điều kiện thiết kế, không thêm được sau, nếu muốn mô phỏng chạy code thật. TigerBeetle 2026 Replay của Stripe cần điều kiện tương tự ở mức service: lõi quyết định thuần, nhận đầu vào đầy đủ. Stripe 2026
  6. Test gây lỗi phải tự chứng minh lỗi đã xảy ra: nemesis chết giữa chừng thì "xanh" là dương tính giả; tách kết quả thành vi phạm / đúng / test hỏng. Appian 2019
  7. Với hệ đã chạy lâu, đầu vào lịch sử là bộ test tốt hơn ca viết tay; review bằng diff "đổi ở đâu, bao nhiêu" thay vì "test có qua không". Stripe 2026
  8. Tự động hoá việc gây lỗi và lặp lại đủ nhiều lần: lỗi ở secondary chỉ lộ khi đi qua đường promote; người làm tay thì "lỗi biến mất khi thêm log". Ngưỡng của Riot: qua 100 lần liên tiếp rồi mới lên production. Riot Games 2019
  9. Để monitoring sẵn có phán kết quả, không để test tự kiểm: tiêm lỗi mà không có alert nghĩa là hệ rất tốt hoặc monitoring có lỗ. Riot Games 2019 CapitalOne 2020
  10. Chaos trong pipeline cần quyền gây lỗi ngắn hạn và audit trail; game day không báo trước kiểm thêm con người và runbook. Goldman Sachs 2022
  11. Thao tác bảo trì thường ngày (backup, đổi schema, nâng cấp) và chính việc khôi phục là tải phải đưa vào kịch bản. Cockroach Labs 2025
  12. Đổi nguồn sự thật (code → đặc tả) thì phải dựng lại cơ chế kiểm mà nguồn cũ cho miễn phí; test sinh từ đặc tả phủ mọi endpoint theo định nghĩa, phần khó là thứ tự và dữ liệu (đồ thị phụ thuộc). Miro 2023
  13. Test chạy trên dữ liệu và hạ tầng thật cần danh tính test cố định từ lúc tạo, được mọi service và cả analytics, A/B tôn trọng; backdoor cho test cần chặn ở mạng, ở khoá và ở đối tượng. Bumble 2019 Cùng hướng với tenant test của DoorDash 2022.
  14. Flaky vì thời gian là việc của môi trường chạy: runtime điều khiển đồng hồ và biết khi nào mọi thứ đã đứng yên thì thay được kiểu ngủ-rồi-kiểm; ranh giới của mô phỏng (mutex dùng chung, I/O thật) phải nói rõ. Go 2025 Cùng ý với mô phỏng tất định của TigerBeetle 2026.

Câu hỏi mở

  • Mức đầu tư hợp lý cho diễn tập theo quy mô công ty: chưa có nguồn nêu ngưỡng (xem câu hỏi tương tự ở Sự cố và postmortem).
  • Chưa có nguồn đo số lỗi tìm được bởi chaos so với fault injection hay mô phỏng trên cùng hệ. Jane Street 2025 là nguồn gần nhất: cùng hệ Aria có cả mạng mô phỏng, fuzz, chaos ở staging và Antithesis, và Antithesis tìm 2 bug ngay lần đầu mà các cách kia bỏ sót; nhưng không có số đếm, và Jane Street là nhà đầu tư của Antithesis (Jane Street 2025).
  • Appian hẹn phần 3 (lỗi Jepsen tìm được và cách sửa) nhưng không tìm thấy; chưa có nguồn kể Jepsen tìm ra lỗi gì ở một hệ nội bộ.
  • Stripe không nêu số hồi quy replay bắt được hay chi phí chạy Spark; Swiggy 2021 (Swiggy 2021) chỉ nêu coverage và thời gian viết test, không nêu lỗi production giảm.
  • Nhiễu do chính môi trường kiểm chứng (tài nguyên, giờ chạy): Anthropic 2026 (Anthropic 2026) đo cho benchmark agent; chưa có nguồn đo tương tự cho test tích hợp hay e2e thông thường.
  • Benchmark "dưới nghịch cảnh" của Cockroach Labs (2025) chỉ có kết quả do nhà cung cấp tự công bố; chưa có nguồn độc lập chạy cùng kịch bản.
  • Goldman Sachs 2022 và Riot 2019 đều đưa chaos vào lịch tự động nhưng không nêu MTTD/MTTR trước-sau ở production.
  • Liên hệ: Load test và kiểm chứng capacity, Độ tin cậy và multi-region, Failover, replica và dự phòng dữ liệu, Deploy và release an toàn, Sự cố và postmortem, CI và build ở quy mô lớn (chạy test trước merge), Migration không downtime (so bản cũ và mới).