Kubernetes cluster autoscaling là một trong những năng lực quan trọng nhất khi vận hành Kubernetes trên cloud. Nếu cấu hình quá bảo thủ, ứng dụng thiếu tài nguyên khi traffic tăng. Nếu cấu hình quá rộng, node phình ra không kiểm soát và hóa đơn cloud tăng rất nhanh. Autoscaling tốt không chỉ là bật HPA rồi quên, mà là thiết kế đồng bộ giữa pod, node pool, request/limit, metric, thời gian scale-up, thời gian scale-down và quy trình kiểm chứng.
Bài viết này là runbook thực chiến cho môi trường production/lab trên AWS EKS, Google GKE hoặc Azure AKS. Trọng tâm là hiểu đúng vai trò của HPA, VPA, Cluster Autoscaler/Karpenter, cách đặt ngưỡng an toàn, lệnh kiểm tra, lỗi thường gặp, troubleshooting, checklist nghiệm thu và bài lab cuối bài.
1. Bức tranh tổng thể: autoscaling có 3 lớp
Trong Kubernetes, autoscaling thường nằm ở ba lớp. Lớp workload quyết định cần bao nhiêu pod. Lớp resource recommendation điều chỉnh request/limit. Lớp hạ tầng quyết định cần bao nhiêu node để chứa các pod đó. Nếu chỉ cấu hình một lớp mà bỏ lớp còn lại, hệ thống dễ rơi vào trạng thái pending pod, node dư thừa hoặc workload bị throttling.
- HPA – Horizontal Pod Autoscaler: tăng/giảm số replica dựa trên CPU, memory hoặc custom metric như RPS, queue length.
- VPA – Vertical Pod Autoscaler: gợi ý hoặc tự điều chỉnh CPU/memory request cho pod; rất hữu ích để tìm request thực tế.
- Cluster Autoscaler/Karpenter: thêm hoặc bỏ node khi pod không schedule được hoặc node không còn cần thiết.
- FinOps guardrail: giới hạn node pool, instance type, budget alert và policy để autoscaling không thành “auto-spending”.
2. Kiến trúc production/lab mẫu
Giả sử một ứng dụng web chạy trong namespace prod-web. Workload có Deployment 3 replica tối thiểu, tăng lên tối đa 30 replica khi CPU trung bình vượt 65% hoặc số request tăng. Cluster có hai node pool: một node pool on-demand cho workload nền ổn định và một node pool spot/preemptible cho batch hoặc traffic đột biến có thể chịu restart.
- Node pool
system: chạy add-on, ingress controller, monitoring; không nên bị scale về 0. - Node pool
app-ondemand: workload production quan trọng, min 2 node, max 8 node. - Node pool
app-burst: workload co giãn, có thể dùng spot/preemptible, min 0, max 12 node. - Monitoring: Prometheus/Grafana hoặc managed metrics để xem pending pod, CPU throttling, node utilization, scale event.
3. Điều kiện tiên quyết trước khi bật autoscaling
Autoscaling chỉ hoạt động tốt khi request/limit và metric đáng tin. Một Deployment không khai báo request CPU/memory sẽ khiến scheduler và autoscaler thiếu dữ liệu để ra quyết định. Đây là lỗi rất phổ biến trong cluster mới.
kubectl -n prod-web get deploy web -o jsonpath="{range .spec.template.spec.containers[*]}{.name}{" cpu="}{.resources.requests.cpu}{" mem="}{.resources.requests.memory}{"\n"}{end}"
# Output mẫu
app cpu=250m mem=512Mi
Nếu output rỗng, hãy bổ sung request trước. Limit không phải lúc nào cũng bắt buộc cho CPU, nhưng request gần như bắt buộc nếu muốn schedule và autoscale ổn định. Với memory, nên có limit để tránh một process lỗi nuốt hết RAM node.
4. Cấu hình HPA autoscaling/v2
HPA phiên bản autoscaling/v2 hỗ trợ nhiều metric và behavior để kiểm soát tốc độ scale. Trong production, nên tránh scale xuống quá nhanh vì có thể gây flapping: vừa giảm pod xong traffic tăng lại, hệ thống mất thời gian warm-up.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-hpa
namespace: prod-web
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 3
maxReplicas: 30
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 65
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 100
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 25
periodSeconds: 60
Giải thích: minReplicas=3 giữ baseline để chịu lỗi một pod/node. maxReplicas=30 là guardrail chi phí và capacity. Scale-up cho phép tăng nhanh khi có tải. Scale-down chậm hơn để tránh giảm pod quá sớm khi traffic dao động.
5. Kiểm tra HPA bằng kubectl
kubectl -n prod-web apply -f web-hpa.yaml
kubectl -n prod-web get hpa web-hpa
kubectl -n prod-web describe hpa web-hpa
# Output mẫu
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web-hpa Deployment/web 58%/65% 3 30 6 12m
Nếu cột TARGETS hiển thị unknown, thường là metrics-server chưa hoạt động, pod thiếu request CPU/memory, hoặc RBAC/APIService của metrics bị lỗi.
6. Cluster Autoscaler và Karpenter: chọn công cụ nào?
Cluster Autoscaler là lựa chọn phổ biến, ổn định và có mặt trên nhiều managed Kubernetes. Nó làm việc với node group/node pool có min/max rõ ràng. Karpenter linh hoạt hơn trên AWS EKS, có thể chọn instance type động, binpack tốt hơn và scale nhanh hơn trong nhiều tình huống. GKE/AKS cũng có cơ chế autoscaling node pool riêng.
- Dùng Cluster Autoscaler nếu bạn muốn mô hình node group rõ ràng, ít thay đổi, dễ giải thích cho team vận hành.
- Dùng Karpenter trên EKS nếu workload đa dạng, cần tối ưu instance type, scale nhanh, hoặc muốn consolidation giảm node dư.
- Dù dùng công cụ nào, vẫn phải đặt max capacity, label/taint, PodDisruptionBudget và budget alert.
7. Ví dụ node pool autoscaling theo cloud
7.1. GKE
gcloud container node-pools update app-ondemand \
--cluster prod-cluster \
--region asia-southeast1 \
--enable-autoscaling \
--min-nodes 2 \
--max-nodes 8
7.2. AKS
az aks nodepool update \
--resource-group rg-prod \
--cluster-name aks-prod \
--name appondemand \
--enable-cluster-autoscaler \
--min-count 2 \
--max-count 8
7.3. EKS managed node group
aws eks update-nodegroup-config \
--cluster-name eks-prod \
--nodegroup-name app-ondemand \
--scaling-config minSize=2,maxSize=8,desiredSize=3
Các lệnh trên chỉ là baseline. Trong production, hãy kết hợp tag/label/taint, quyền IAM phù hợp cho autoscaler, và kiểm tra quota cloud trước khi tin rằng node sẽ scale được.
8. Test tải trong lab
Trong lab, bạn có thể dùng kubectl run hoặc công cụ như hey, wrk, k6 để tạo tải. Mục tiêu không phải phá hệ thống, mà là quan sát HPA tăng replica, pod pending kích hoạt node scale-up, sau đó scale-down an toàn khi tải giảm.
kubectl -n prod-web run loadgen --rm -it --image=busybox:1.36 --restart=Never -- /bin/sh
# Trong shell của pod:
while true; do wget -q -O- http://web.prod-web.svc.cluster.local/ > /dev/null; done
watch -n 5 "kubectl -n prod-web get hpa web-hpa; echo; kubectl -n prod-web get pods -o wide; echo; kubectl get nodes"
Output kỳ vọng: HPA tăng replica từ 3 lên 5, 8, 12 tùy tải. Nếu node hiện tại không đủ chỗ, một số pod sẽ Pending trong thời gian ngắn, sau đó autoscaler thêm node mới và pod được schedule.
9. Troubleshooting lỗi thường gặp
9.1. HPA hiện unknown
kubectl get apiservice | grep metrics
kubectl -n kube-system logs deploy/metrics-server --tail=100
kubectl top pod -n prod-web
Nếu kubectl top không có dữ liệu, xử lý metrics-server trước. Nếu chỉ một Deployment bị unknown, kiểm tra container có khai báo CPU request chưa.
9.2. Pod Pending nhưng node không tăng
kubectl -n prod-web describe pod <pending-pod>
kubectl -n kube-system logs deploy/cluster-autoscaler --tail=200
kubectl get events -A --sort-by=.lastTimestamp | tail -50
Nguyên nhân thường gặp: node group đã chạm max, quota cloud hết, instance type không đủ capacity, pod có nodeSelector/affinity không khớp, taint chưa có toleration, hoặc PVC chỉ gắn được trong một zone.
9.3. Scale-down không xảy ra
Autoscaler không xóa node nếu node còn pod không thể di dời, có PodDisruptionBudget quá chặt, pod dùng local storage, hoặc system pod không có nơi thay thế. Kiểm tra annotation và event của autoscaler trước khi ép xóa node.
kubectl get pdb -A
kubectl describe node <node-name>
kubectl -n kube-system logs deploy/cluster-autoscaler | grep -i "scale down" | tail -30
9.4. Hóa đơn cloud tăng bất thường
Đây không phải lỗi kỹ thuật thuần túy. Hãy kiểm tra max node, instance type được phép, workload bị loop/retry, HPA max quá cao, request quá lớn hoặc load test quên tắt. Autoscaling cần đi kèm budget alert và dashboard chi phí theo cluster/node pool/namespace.
10. Checklist nghiệm thu production
- Tất cả workload quan trọng có CPU/memory request hợp lý.
- HPA dùng autoscaling/v2, có min/max replica và behavior scale-up/scale-down rõ ràng.
- Node pool có min/max, label/taint và giới hạn instance type phù hợp.
- PodDisruptionBudget không chặn toàn bộ scale-down hoặc node drain.
- Dashboard có CPU, memory, pending pod, replica count, node count, unschedulable pod và cost.
- Đã test tải để chứng minh pod scale-up và node scale-up hoạt động.
- Đã test scale-down sau khi tải giảm, không gây gián đoạn dịch vụ.
- Có quota cloud và budget alert để tránh autoscaling vượt kiểm soát.
- Có runbook xử lý HPA unknown, pod pending, quota hết, node không scale down.
11. Bài lab cuối bài
- Tạo một cluster lab nhỏ trên GKE/AKS/EKS hoặc local cluster có metrics-server.
- Triển khai Deployment web với request CPU/memory rõ ràng.
- Áp dụng HPA autoscaling/v2 với min 2, max 10.
- Tạo tải bằng busybox, hey hoặc k6 và quan sát replica tăng.
- Giảm tải, chờ stabilization window và quan sát replica giảm.
- Nếu dùng managed cloud, bật node pool autoscaling và cố tình tạo pod cần nhiều CPU để kiểm tra node scale-up.
- Ghi lại output kubectl, event và log autoscaler thành runbook nội bộ.
Kết luận
Kubernetes cluster autoscaling hiệu quả là sự phối hợp giữa HPA, request/limit, node autoscaler, policy và quan sát chi phí. Bật autoscaling mà không có guardrail sẽ biến sự linh hoạt thành rủi ro tài chính. Ngược lại, cấu hình quá chặt sẽ khiến pod pending và trải nghiệm người dùng xấu đi. Hãy bắt đầu từ request đúng, HPA có behavior rõ ràng, node pool có giới hạn, dashboard đủ tín hiệu và một bài test tải lặp lại được. Khi đó autoscaling mới trở thành năng lực production thật sự, không chỉ là một checkbox trên cloud console.
