Nguyen Le PhongNguyen Le Phong

Có cần service mesh không? Hãy nhìn vào lỗi trước

Service mesh chỉ đáng thêm khi lỗi giữa các dịch vụ đã lặp lại và đo được. Đây là cách đọc số liệu, nhìn trước điểm hỏng, thử trên phạm vi nhỏ và chuẩn bị đường rút.

Một buổi rà soát sự cố rất dễ bắt đầu bằng câu hỏi nghe có vẻ đơn giản: vì sao một lượt thanh toán lại mất tám giây? Nhật ký của ứng dụng không báo lỗi rõ ràng. Dịch vụ này đã thử lại hai lần, dịch vụ kia chờ lâu hơn thời hạn của bên gọi, còn dịch vụ cuối cùng trả kết quả thành công khi người dùng đã bỏ cuộc. Đến lúc đường đi của yêu cầu được vẽ kín bảng, mọi người mới thấy đây không còn là một lỗi riêng lẻ. Luật giao tiếp giữa các dịch vụ đang nằm rải rác, mỗi nơi một kiểu và chẳng ai nhìn được trọn vẹn.

Sơ đồ lần theo đường gọi giữa API, Order, Payment, Inventory và Notify, kèm các nhánh retry và timeout.
Câu hỏi có cần service mesh hay không chỉ đáng bàn sau khi đường đi và điểm hỏng đã được vẽ rõ.

Service mesh có thể giúp sắp xếp đúng nhóm vấn đề đó. Lớp data plane đứng trên đường các dịch vụ gọi nhau, thường thông qua sidecar proxy; control plane phân phối cấu hình về định danh, định tuyến và chính sách. Nhờ vậy, mTLS, timeout, retry, chia luồng truy cập, số liệu và trace có thể dùng chung một cách làm, thay vì mỗi đội tự lắp một bộ trong code của mình.

Nghe hợp lý chưa có nghĩa là nên dùng ngay. Service mesh không sửa được ranh giới dịch vụ nhập nhằng, code thiếu tin cậy, cơ sở dữ liệu dùng chung vô tội vạ hay tình trạng không ai chịu trách nhiệm đến cùng. Nó cũng không trả lời hộ câu hỏi một lượt gọi đồng bộ có nên tồn tại hay không. Service mesh có thể soi rất rõ một mớ dây đang rối, nhưng soi rõ không đồng nghĩa với gỡ được. Vì thế, đừng hỏi công cụ này mạnh đến đâu. Hãy hỏi loại sự cố đang gây tổn thất có đúng là loại mà service mesh có thể giảm hay không.

Muốn trả lời cho chắc, phải bắt đầu từ số liệu thật. Đừng chỉ nhìn độ trễ ở cổng vào; hãy xem từng chặng và tách p50, p95, p99 vì phần đuôi chậm thường kể một câu chuyện khác. Đếm tỷ lệ lỗi, kết nối bị ngắt, số lần quá hạn và số lượt gọi tới các dịch vụ phụ thuộc phát sinh từ một yêu cầu đầu vào. Kiểm tra có bao nhiêu trace đi được trọn đường. So độ phủ mTLS mong muốn với luồng gọi thật sự đã được mã hóa và xác thực. Lật lại các sự cố do chính sách lệch nhau, chứng thư xoay vòng, thư viện gọi mạng không đồng nhất hoặc mất hàng giờ chỉ để dựng lại đường phụ thuộc. Có bao nhiêu dịch vụ chưa quan trọng bằng những lỗi này lặp lại bao nhiêu lần và làm đội vận hành tốn bao nhiêu công.

Service mesh đáng cân nhắc khi nhiều dấu hiệu cùng xuất hiện. Các đội dùng nhiều ngôn ngữ và bộ khung khác nhau nên một thư viện chung không còn giữ nổi cách gọi mạng thống nhất. Retry và timeout đã lệch nhau đến mức gây sự cố. Yêu cầu an toàn cần định danh cho từng workload và mTLS trên một mạng dịch vụ thay đổi liên tục. Người trực hệ thống thường xuyên bị đứt dấu vết ngay khi yêu cầu đi qua ranh giới ứng dụng. Quan trọng hơn, đã có một đội nền tảng đủ sức chăm control plane, hỗ trợ đội làm sản phẩm và chịu trách nhiệm khi chính lớp này gặp chuyện.

Bảng tín hiệu hiển thị p95 latency, error rate, phần trace bị thiếu và độ phủ mTLS.
Các dấu hiệu vận hành lặp lại thuyết phục hơn nhiều so với việc chạy theo mốt hạ tầng.

Cũng có những lúc service mesh rõ ràng là quá tay. Vài dịch vụ cùng một ngôn ngữ thường chỉ cần một thư viện gọi mạng được chăm tử tế và chính sách chung ở gateway. Khi ranh giới nghiệp vụ còn đổi liên tục, một khối ứng dụng chia module rõ ràng có khi dễ sống hơn việc tách thêm dịch vụ. Nếu log, số đo vận hành, trace, health check và người chịu trách nhiệm còn chưa đủ, thêm mesh chỉ tạo ra nhiều tín hiệu hơn trong khi đội ngũ chưa dùng tốt tín hiệu cũ. Nếu không ai có thời gian lo nâng cấp, chứng thư, rà chính sách và trực sự cố cho lớp nền tảng này, công việc không biến mất; nó chỉ được dồn vào một chỗ có phạm vi ảnh hưởng lớn hơn.

Bản thân mesh cũng có những cách hỏng rất khó chịu. Ứng dụng thử lại một lần, proxy lại thử thêm vài lần, thế là tải bị nhân lên đúng lúc dịch vụ phía sau đang hụt hơi. Proxy cho chờ lâu cũng không cứu được bên gọi đã hết hạn trước đó. Sidecar ăn CPU và bộ nhớ; tính thiếu tài nguyên thì chính lớp hạ tầng lại làm chậm hệ thống. Một luật định tuyến sai có thể đưa hàng nghìn yêu cầu nhầm chỗ. Cấu hình truyền xuống chậm khiến mỗi workload chạy theo một luật khác nhau. Chứng thư xoay vòng lỗi có thể làm ứng dụng đang khỏe bỗng mất liên lạc dù không đổi một dòng code.

Khi control plane không hoạt động, đội vận hành phải biết data plane còn giữ được gì, cấu hình nào sẽ cũ dần và chính sách an toàn sẽ chặn hay cho qua. Cách lần lỗi cũng đổi khác: ứng dụng báo hủy yêu cầu, proxy ghi nhận kết nối tới dịch vụ phía sau bị ngắt, còn dịch vụ đích lại báo thành công. Ba mẩu chuyện đó phải có chung mã liên kết thì mới ghép lại được. Chênh phiên bản giữa proxy và control plane cũng cần quy tắc quản lý. Một service mesh chỉ có hai người hiểu vẫn là điểm yếu của tổ chức, dù phần mềm được thiết kế dự phòng tốt đến đâu.

Nếu bằng chứng đã đủ mạnh, hãy thử trên một đường gọi nhỏ và ghi lại số liệu hiện tại trước khi thay đổi. Chọn hai hoặc ba dịch vụ có vấn đề đã nhìn thấy, nhưng mức ảnh hưởng tới người dùng vẫn khoanh được. Ghi lại độ trễ phần đuôi, tỷ lệ lỗi, số lần retry bị nhân lên, độ đầy đủ của trace, thời gian người trực cần để tìm nguyên nhân, tài nguyên proxy tiêu tốn và độ phủ mTLS. Sau đó viết rõ mức cải thiện nào đáng để đổi lấy công vận hành mới. “Cài mesh thành công” không phải kết quả; giảm lỗi lặp lại hoặc tìm đúng chỗ hỏng nhanh và an toàn hơn mới là kết quả.

Trong lúc thử, đừng để retry ở ứng dụng và retry ở proxy âm thầm chồng lên nhau. Chủ động mô phỏng dịch vụ phản hồi chậm, kết nối bị rớt, chứng thư hết hạn, luật định tuyến sai và control plane tạm vắng mặt. Mỗi lần thử phải nhìn cả phía ứng dụng lẫn phía proxy. Mục tiêu không phải làm ra một bảng theo dõi đẹp mắt, mà là biết hệ thống phản ứng ra sao khi chỉ hỏng một phần và giải thích được lớp mới đã làm tình hình tốt hơn ở điểm nào.

Sơ đồ chỉ đánh dấu Order và Payment trong một pilot service mesh nhỏ, kèm đường rollback.
Pilot có phạm vi hẹp giúp kiểm chứng giá trị mà không đặt cả platform vào vùng ảnh hưởng.

Phương án rollback phải được thiết kế trước khi triển khai. Giữ lại cấu hình định tuyến và bảo mật trước đó, viết rõ cách đưa workload ra khỏi data plane, đồng thời thử luôn thao tác triển khai lại hoặc khởi động lại nếu cần. Phải biết biện pháp bảo vệ nào tạm chuyển về ứng dụng hoặc gateway. Không thể gọi là rollback an toàn nếu cùng lúc làm mất mTLS hoặc giới hạn lưu lượng mà chưa có phương án thay thế. Đợt thử cũng cần hạn chót và điều kiện dừng khi độ trễ, tỷ lệ lỗi, mức dùng tài nguyên hoặc độ rối trong vận hành vượt ngưỡng. Khả năng rút lại là một phần của kiến trúc, không phải tờ hướng dẫn viết sau khi có chuyện.

Chỉ mở rộng khi kết quả thử đủ thuyết phục. Đi rộng hơn đồng nghĩa phải có người sở hữu, lịch nâng cấp, kiểm tra tương thích, hạn mức CPU và bộ nhớ, cảnh báo cho chính mesh và ranh giới trách nhiệm rõ ràng. Mesh có thể lo định danh đường truyền và chính sách luồng gọi. Đội làm ứng dụng vẫn phải giữ hợp đồng nghiệp vụ, tính toàn vẹn dữ liệu, khả năng xử lý lặp an toàn và quyết định xem một lượt gọi có thật sự cần chạy đồng bộ hay không.

Câu trả lời cuối cùng khá mộc mạc: chỉ thêm service mesh khi lỗi giữa các dịch vụ đã lặp lại và đo được, cách làm đơn giản hơn không còn theo kịp, và có người sẵn sàng chịu trách nhiệm khi chính lớp mới này hỏng. Nếu chưa đến mức đó, hãy làm cho timeout, retry, trace, định danh và người chịu trách nhiệm của từng dịch vụ nhất quán bằng những thứ đang có. Quyết định đúng phải gắn với một loại lỗi cụ thể và một mức cải thiện đo được. Chưa có hai thứ đó, lớp mới chỉ là thêm một hệ thống phải nuôi.

Bạn thấy bài viết thế nào?