Lối Nhỏ
← Chủ đề

Service Mesh là gì, và vì sao mình bắt đầu quan tâm

15 tháng 8, 20262 phút đọc
hệ thốngkubernetes
Dây cáp mạng đan xen nhau trong một trung tâm dữ liệu

Cụm Kubernetes ở chỗ mình làm bắt đầu với vài service. Rồi vài chục. Đến lúc nào đó, phần lớn thời gian debug không còn nằm ở logic nghiệp vụ nữa, mà nằm ở câu hỏi: request này đi từ đâu đến đâu, tại sao nó chậm, và tại sao đôi khi nó thất bại mà không ai biết vì sao.

Vấn đề không nằm ở code

Mỗi service khi gọi sang service khác đều cần lo vài việc giống nhau: retry khi thất bại, timeout khi chờ quá lâu, mã hoá kết nối, và ghi lại việc request đó đã đi qua đâu. Cách thông thường là nhét những thứ này vào một thư viện dùng chung, rồi import vào từng service.

Cách đó có hai vấn đề. Thứ nhất, mỗi ngôn ngữ lập trình cần một bản thư viện riêng, và chúng không bao giờ đồng bộ hành vi hoàn toàn với nhau. Thứ hai, khi cần đổi chính sách retry cho toàn hệ thống, mình phải đi sửa và deploy lại từng service một.

Service mesh chuyển việc đó ra khỏi code

Ý tưởng của service mesh đơn giản đến bất ngờ: thay vì để mỗi service tự lo phần mạng, đặt một proxy nhỏ (thường gọi là sidecar) cạnh mỗi service, và để proxy đó lo toàn bộ việc giao tiếp thay cho service. Service chỉ cần gọi localhost, proxy sẽ lo phần còn lại: retry, timeout, mã hoá, và báo cáo số liệu.

Tập hợp các proxy này gọi là data plane. Còn thứ điều khiển và cấu hình cho toàn bộ proxy gọi là control plane. Khi muốn đổi chính sách retry, mình chỉ cần sửa cấu hình ở control plane, nó tự đẩy xuống mọi proxy, không cần đụng vào code hay deploy lại service nào.

apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: payment-service
spec:
  host: payment-service
  trafficPolicy:
    connectionPool:
      http:
        maxRetries: 3
    outlierDetection:
      consecutive5xxErrors: 5
      interval: 30s
      baseEjectionTime: 30s

Đoạn cấu hình trên không nằm trong code của payment-service. Nó áp dụng cho mọi request đi đến service đó, bất kể request được viết bằng Go, Node hay Python.

Cái giá phải trả

Mỗi pod giờ có thêm một container proxy chạy cùng, tốn thêm CPU và RAM, và thêm một chặng mạng cho mỗi request (qua proxy). Control plane cũng là một thành phần mới cần vận hành, và khi nó gặp sự cố, ảnh hưởng lan ra toàn cụm chứ không riêng một service.

Đây là lý do mình không đề xuất dùng service mesh cho một cụm chỉ có dăm service. Cái giá về độ phức tạp chỉ đáng trả khi số lượng service đủ lớn để vấn đề giao tiếp giữa chúng trở thành nỗi đau thật sự.

Ở phần sau, mình sẽ so sánh vài lựa chọn service mesh phổ biến cho Kubernetes, và vì sao mình cuối cùng chọn một trong số đó cho cụm của mình.