Tự động mở rộng Kubernetes với KEDA
Giới thiệu
Khi triển khai các dịch vụ tiêu thụ Kafka hoặc RabbitMQ trong Kubernetes, bạn có thể gặp phải tình trạng các dịch vụ này bị dư thừa tài nguyên hoặc quá tải. Cách mở rộng dựa trên CPU thông qua HPA không phải lúc nào cũng là giải pháp tối ưu. Đó là lý do tại sao KEDA (Kubernetes-based Event-Driven Autoscaling) ra đời.
KEDA cho phép bạn tự động mở rộng ứng dụng dựa trên các sự kiện hoặc chỉ số bên ngoài như độ dài hàng đợi trong Kafka hoặc RabbitMQ, các chỉ số Prometheus, hoặc sự kiện từ các dịch vụ đám mây như Azure, AWS, GCP.
KEDA là gì?
KEDA là một trình tự động mở rộng nhẹ cho phép bạn mở rộng các khối lượng công việc Kubernetes dựa trên các sự kiện hoặc chỉ số bên ngoài.
Các đặc điểm chính của KEDA:
- Không giống HPA, KEDA cho phép các pod của bạn mở rộng một cách linh hoạt dựa trên khối lượng công việc thực tế.
- KEDA hoạt động như một Deployment trong cụm Kubernetes của bạn.
- Nó không phải là một StatefulSet hay một Deployment đặc biệt của ứng dụng của bạn.
- Nó tiêu thụ CPU/memory như bất kỳ Deployment nào khác, tùy thuộc vào số lượng ScaledObjects và các trigger bạn định nghĩa.
- Điều này có nghĩa là nếu bạn định nghĩa nhiều hàng đợi, chính Deployment của KEDA sẽ tăng cường sử dụng tài nguyên.
Cách KEDA hoạt động
KEDA giới thiệu một đối tượng mới trong Kubernetes được gọi là ScaledObject:
- Mapping ScaledObject → Deployment: cho KEDA biết khối lượng công việc nào cần mở rộng.
- Mỗi ScaledObject có thể có một hoặc nhiều trigger.
- Logic mở rộng:
- Logic OR giữa các trigger (nếu bất kỳ trigger nào vượt quá ngưỡng → mở rộng).
- Không thể mở rộng độc lập các subset pod trong cùng một Deployment.
Ví dụ: ScaledObject cho RabbitMQ
yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: orders-consumer-scaler
spec:
scaleTargetRef:
name: orders-consumer
minReplicaCount: 1
maxReplicaCount: 10
triggers:
- type: rabbitmq
metadata:
queueName: orders-queue
host: amqp://guest:guest@rabbitmq:5672/
queueLength: "100"
Giải thích:
- Deployment
orders-consumer
sẽ mở rộng từ 1 đến 10 pods tùy thuộc vào độ dài hàng đợi. - Việc mở rộng sẽ xảy ra nếu độ dài hàng đợi lớn hơn 100.
Cách KEDA xác định số lượng Pods
KEDA tính toán số lượng replicas mong muốn dựa trên chỉ số hàng đợi và ngưỡng:
- Giá trị ngưỡng (
queueLength
): chỉ số mà KEDA theo dõi (độ sâu hàng đợi). - Min và Max Replicas:
yaml
minReplicaCount: 1
maxReplicaCount: 10
Cách tính toán số lượng replicas mong muốn (đơn giản):
yaml
desiredReplicas = ceil(currentQueueLength / queueLengthThreshold)
Scaling áp dụng qua HPA
KEDA cập nhật số replicas của Deployment giữa minReplicaCount
và maxReplicaCount
.
Ví dụ hình ảnh
Giả sử hàng đợi orders-queue
có ngưỡng là 100 tin nhắn:
Queue Depth → Desired Replicas → Deployment Pods
------------------------------------------------
50 → 1 → 1 pod (minReplicaCount)
120 → 2 → 2 pods
250 → 3 → 3 pods
1050 → 11 → 10 pods (maxReplicaCount)
Sơ đồ:
[Queue Depth: 250]
│
▼
[Threshold: 100 per pod]
│
▼
[Desired Replicas: ceil(250/100) = 3]
│
▼
[orders-consumer Deployment scales to 3 pods]
Hạn chế của KEDA
Mặc dù KEDA rất mạnh mẽ, nhưng nó vẫn có một số hạn chế quan trọng:
N hàng đợi → N dịch vụ tiêu thụ không được hỗ trợ một cách tự nhiên.
Bạn không thể định nghĩa nhiều hàng đợi với các Deployment tiêu thụ khác nhau trong một ScaledObject.
Logic mở rộng là OR giữa các trigger; tất cả các pods sẽ mở rộng cùng nhau.
Điều này không lý tưởng cho các microservices với nhiều hàng đợi và luồng công việc khác nhau.
Ví dụ: nếu bạn có 10 hàng đợi với các logic/xử lý khác nhau, KEDA không thể mở rộng chúng một cách độc lập.
Bạn sẽ cần nhiều Deployments + nhiều ScaledObjects, điều này có thể trở nên phức tạp.
Tiêu thụ tài nguyên
KEDA cũng là một Deployment; mỗi ScaledObject sẽ thêm vào mức tiêu thụ CPU/memory.
Việc mở rộng nhiều hàng đợi có thể làm tăng mức tiêu thụ tài nguyên trên cụm.
Ví dụ với Kubectl
Sau khi tạo nhiều ScaledObjects:
bash
kubectl get scaledobjects
Kết quả ví dụ:
NAME SCALETARGETKIND SCALETARGETNAME MIN MAX TRIGGERS
orders-consumer-scaler apps/v1.Deployment orders-consumer 1 10 rabbitmq
payments-consumer-scaler apps/v1.Deployment payments-consumer 1 5 rabbitmq
kafka-consumer-scaler apps/v1.Deployment kafka-consumer 1 15 kafka
Mỗi ScaledObject
nhắm đến một Deployment duy nhất.
Nhiều trigger cho cùng một Deployment sẽ mở rộng tất cả các pods cùng nhau (logic OR).
Những điều cần lưu ý
- KEDA rất tuyệt vời cho việc mở rộng đơn giản dựa trên sự kiện.
- Mỗi ScaledObject chỉ định một Deployment.
- Logic OR cho nhiều trigger → không phù hợp cho microservices với nhiều hàng đợi và luồng công việc khác nhau.
- KEDA tự động tính toán số lượng replicas dựa trên chỉ số và ngưỡng, mở rộng các pods của Deployment giữa min và max.
- Mức tiêu thụ tài nguyên tăng lên với nhiều ScaledObjects và trigger.
Kết luận
Phần 2 sẽ trình bày cách xây dựng một trình tự động mở rộng tùy chỉnh có thể xử lý nhiều hàng đợi, nhiều dịch vụ tiêu thụ và logic mở rộng độc lập cho các microservices phức tạp.
Mẹo chuyên nghiệp: Bắt đầu với KEDA cho việc mở rộng hàng đợi đơn giản. Đối với các microservices phức tạp với nhiều hàng đợi, thường cần một giải pháp HPA/KEDA tùy chỉnh.