Giới thiệu
Trong phần 1 của bài viết, mình đã đề cập đến những hạn chế của Kubernetes service khi thực hiện Load Balancing cho GRPC. Ở phần 2 này, chúng ta sẽ cùng khám phá các giải pháp hiệu quả giúp khắc phục tình trạng này.
Kho lưu trữ mã nguồn: https://github.com/phamsyhung2110/test-grpc-lb
Giải pháp 1: Sử dụng Client-side Load Balancing
Client-side Load Balancing là phương pháp mà client có thể tự quản lý việc phân phối các yêu cầu tới các instance backend mà không cần phải dựa vào một load balancer bên ngoài. Thay vào đó, client sẽ sử dụng danh sách các endpoint để tự quyết định nơi để gửi yêu cầu.
Cách hoạt động
- Service Discovery: Client cần phải biết danh sách các endpoint của backend. Việc này thường được thực hiện thông qua DNS hoặc API của Kubernetes.
- Chọn Endpoint: Client sẽ dùng các thuật toán như Round Robin, Least Connections, hoặc Random để chọn endpoint từ danh sách.
- Gửi Request: Client sẽ gửi yêu cầu trực tiếp tới pod backend.
Điều kiện cần thiết
- Headless Service: Cần cấu hình Kubernetes headless service để DNS trả về danh sách các IP của các pod backend thay vì chỉ trả về ClusterIP.
- Thư viện hỗ trợ: Sử dụng các thư viện hoặc framework hỗ trợ client-side Load Balancing, ví dụ như gRPC balancer trong các SDK chính thức của gRPC.
Ví dụ triển khai
1. Cập nhật mã nguồn của Service A (HTTP proxy)
Tạo file service-A-lb.js trong folder grpc-app/ với cấu hình sử dụng DNS cho Service Discovery:
javascript
const grpcServiceAddress = process.env.GRPC_SERVICE_ADDRESS || 'dns:///service-b-grpc.default.svc.cluster.local:50051';
2. Thêm logic Load Balancing
- Mục đích: Cho phép gRPC client tự động phát hiện các pod của Service B trong môi trường Kubernetes.
- Chi tiết cấu hình:
dns:///
: là prefix cần thiết khi sử dụng DNS để định tuyến trong gRPC.service-b-grpc.default.svc.cluster.local
: tên DNS đầy đủ của Service B trong Kubernetes.- Dùng cấu hình load balancing:
javascriptconst client = new echoService(grpcServiceAddress, grpc.credentials.createInsecure(), { 'grpc.service_config': JSON.stringify({ loadBalancingConfig: [{ round_robin: {} }] }) });
Như vậy, phần sửa mã nguồn đã hoàn tất. Bạn cần tự build và deploy lại Service A:
cd grpc-app/
docker build . -f dockerfile -t <repo>/testgrpc:v1
docker push <repo>/testgrpc:v1
3. Chuyển đổi Kubernetes service của Service B thành Headless service
yaml
apiVersion: v1
kind: Service
metadata:
name: service-b-grpc
spec:
clusterIP: None
selector:
app: service-b-grpc
ports:
- protocol: TCP
port: 50051
targetPort: 50051
Áp dụng manifest:
kubectl apply -f deploy/grpc-deploy.yaml -n grpc
Kiểm tra: Gửi yêu cầu tới Service A bằng K6
Trước tiên, bạn cần thực hiện port-forwarding:
kubectl port-forward svc/service-a-grpc 5000:5000 -n grpc
Chạy kiểm tra với K6:
cd k6/
k6 run grpc-loadtest.js
Kết quả: Các yêu cầu đã được phân phối qua lại đến các pod của Service B thành công.
Giải pháp 2: Sử dụng Service Mesh
Giải pháp này không yêu cầu thay đổi mã nguồn nhưng yêu cầu bạn sử dụng công cụ service mesh, ở đây mình sẽ sử dụng Istio.
Lưu ý: Hướng dẫn này không bao gồm cách cài đặt Istio, bạn cần đã có kiến thức hoặc đã cài đặt Istio trong cluster của mình.
Kích hoạt sidecar injection
kubectl label namespace dev-hung istio-injection=enabled
Khởi động lại service
kubectl delete -f deploy/grpc-deploy.yaml && kubectl apply -f deploy/grpc-deploy.yaml
Sau khi các service đã được chạy với Istio sidecar, bạn có thể thực hiện lại bài kiểm tra như đã hướng dẫn ở phần trước. Theo tài liệu của Istio, cơ chế Load Balancing mặc định của Envoy proxy là Least Connection. Bạn có thể tùy chỉnh cấu hình load balancing theo nhu cầu cụ thể của mình.
Theo mặc định, các proxy Envoy phân phối traffic giữa các service dựa trên mô hình least requests, trong đó mỗi yêu cầu được điều hướng tới host có ít yêu cầu hơn từ việc chọn ngẫu nhiên hai host từ nhóm load balancing.
Đọc thêm tại: https://istio.io/latest/docs/concepts/traffic-management/#introducing-istio-traffic-management
Kết luận
Qua bài viết này, mình đã trình bày lý thuyết cũng như thực tế triển khai các giải pháp khắc phục vấn đề Load Balancing cho gRPC trong Kubernetes. Hy vọng những thông tin này sẽ giúp bạn có thêm kiến thức về Networking và cách triển khai gRPC hiệu quả trong môi trường Kubernetes.
source: viblo