Chương 9: GKE Autoscaling — HPA, VPA, Cluster Autoscaler & KEDA
Vì sao chương này quyết định cả chi phí lẫn độ tin cậy
Autoscaling là nơi ba mục tiêu mâu thuẫn nhau gặp nhau trên cùng một control loop: chi phí (đừng chạy nhiều hơn mức cần), độ tin cậy (đừng thiếu công suất khi traffic tới), và độ ổn định (đừng dao động lên xuống làm rung cả cluster). Bất kỳ ai từng vận hành một cluster GKE ở quy mô thật đều đã gặp ít nhất một trong ba kiểu thất bại sau:
- Scale-up quá chậm — HPA tính ra cần thêm Pod, nhưng Cluster Autoscaler mất nhiều phút để tạo node, image pull chậm, và đến lúc Pod sẵn sàng thì spike đã thành outage. Đây là failure mode tốn kém nhất vì nó biểu hiện thành lỗi 5xx cho người dùng cuối.
- Over-provisioning âm thầm —
requestsđặt quá tay, HPA không bao giờ scale xuống vì stabilization window hoặc vì metric chọn sai, node pool giữ nguyên kích thước, và hóa đơn cuối tháng gấp đôi mức cần thiết mà không ai nhận ra vì "hệ thống vẫn chạy ổn". - Flapping — HPA scale lên, Cluster Autoscaler thêm node, traffic giảm nhẹ, HPA scale xuống, node bị xóa, traffic lại tăng, lặp lại. Mỗi vòng lặp tạo ra churn: Pod bị giết và tạo lại, connection bị reset, cache nguội, và scheduler phải làm lại từ đầu.
Điểm mấu chốt mà chương này nhấn mạnh xuyên suốt: autoscaling trên GKE không phải một cơ chế mà là một chuỗi các control loop độc lập, chạy ở các tần số khác nhau, nhìn các tín hiệu khác nhau, và không hề biết về sự tồn tại của nhau. HorizontalPodAutoscaler quyết định số lượng Pod dựa trên metric. VerticalPodAutoscaler quyết định kích thước Pod dựa trên lịch sử sử dụng. Cluster Autoscaler quyết định số lượng node dựa trên Pod đang Pending. KEDA quyết định scale-to-zero dựa trên sự kiện bên ngoài. Mỗi loop đúng một cách độc lập, nhưng sự cố production gần như luôn nằm ở chỗ các loop tương tác với nhau — HPA và VPA tranh nhau cùng một metric, HPA scale lên nhưng Cluster Autoscaler không kịp cấp node, hoặc VPA bump request làm Pod không còn vừa node nào.
Theo tài liệu Google Cloud, GKE cung cấp autoscaling ở hai chiều: chiều Pod (HPA, VPA, multidimensional) thay đổi số lượng và kích thước Pod, và chiều node/infrastructure (Cluster Autoscaler, Node Auto-Provisioning) thay đổi công suất bên dưới (About GKE scalability). Hiểu đúng nghĩa là biết loop nào chịu trách nhiệm cho quyết định nào, loop nào chạy ở đâu (control plane do Google quản lý hay component bạn tự cài), và quan trọng nhất là độ trễ end-to-end từ lúc một tín hiệu xuất hiện đến lúc công suất thật sự sẵn sàng phục vụ.
Điều kiện tiên quyết
- Chương 8 (GKE Scheduler): autoscaling và scheduling là hai mặt của một đồng xu. Cluster Autoscaler scale-up vì Pod Pending (một trạng thái do scheduler quyết định), và nó dùng chính logic của scheduler để mô phỏng xem node mới có giải quyết được Pending không. Phải hiểu Filter/Score,
requests, taints, affinity, PDB trước khi hiểu autoscaling. - Chương 6 (Node Lifecycle & Pool Management): scale-up tạo node, scale-down drain và xóa node — toàn bộ vòng đời node, surge, taint mặc định,
max-pods-per-node. - Cloud Monitoring metrics: HPA và KEDA đều là cơ chế đóng-kín dựa trên metric. Phải nắm Resource metrics, Custom Metrics, External Metrics, và Google Cloud Managed Service for Prometheus.
- Kubernetes resource model:
requestsvslimits, QoS class — vì mọi autoscaler đều ra quyết định dựa trênrequests, không phải usage thật của container.
Mức độ sâu
5/5 — Chương đi tới mức công thức desiredReplicas và cơ chế tolerance/stabilization của HPA, histogram phân rã theo nửa-chu-kỳ 24 giờ của VPA recommender, thuật toán expander và các điều kiện chính xác chặn scale-down của Cluster Autoscaler, các chuỗi reason string trong log visibility (no.scale.down.node.pod.kube.system.unmovable...), cơ chế atomic vs final recommendation trong log hpa-controller, và mô hình activation/scaling của KEDA. Mọi tuyên bố kỹ thuật đối chiếu trực tiếp tài liệu Kubernetes và Google Cloud.
Cấu trúc chapter
1. HorizontalPodAutoscaler — Control Loop & Thuật Toán
Trái tim của HPA: vòng lặp và phép tính.
- Control loop chu kỳ 15 giây, vì sao HPA là loop "rời rạc" chứ không liên tục
- Công thức
desiredReplicas = ceil[currentReplicas × (currentMetricValue / desiredMetricValue)] - Tolerance 0.1 (10%): vùng chết để tránh dao động vi mô
- Xử lý Pod chưa Ready, Pod thiếu metric, Pod đang terminating — cơ chế dampening bảo thủ
initial-readiness-delay(30s) vàcpu-initialization-period(5 phút)- Nhiều metric: chọn recommendation lớn nhất
- Stabilization window scale-down mặc định 300 giây
- Log
hpa-controllertrên GKE: atomic recommendation vs final recommendation, cách đọc để debug từng quyết định
2. HPA — Behavior Policies, Metrics Sources & Debugging
Điều khiển tinh và vận hành HPA ở production.
behavior(autoscaling/v2):scaleUp/scaleDown, policyPods/Percent,periodSeconds,selectPolicy(Max/Min/Disabled),stabilizationWindowSeconds- Ba nguồn metric: Resource (CPU/Memory), Custom Metrics, External Metrics — pipeline metrics-server và Custom Metrics Adapter / Managed Prometheus
- Performance HPA Profile: GKE 1.31+ tới 1000 đối tượng, GKE 1.33+ tới 5000 đối tượng,
--hpa-profile=performance - Xung đột HPA + VPA trên cùng CPU/Memory — vì sao và cách tránh
- Tương tác HPA với rolling update của Deployment
- Debug qua conditions:
AbleToScale,ScalingActive,ScalingLimited
3. VerticalPodAutoscaler — Kiến Trúc, Recommender & Update Modes
Right-sizing tự động và những cái bẫy của nó.
- Ba thành phần: Recommender, Updater, Admission Controller — trên GKE chạy như control plane process
- Recommender: histogram phân rã (decay half-life 24h), cửa sổ lịch sử 8 ngày, CPU percentile, OOM signal bump (~20% hoặc 100Mi)
- Update modes:
Off,Initial,Recreate,Auto,InPlaceOrRecreate(preview) - In-Place Pod Resize (IPPR): đổi resource không giết Pod,
resizePolicy, điều kiện fallback về Recreate - Giới hạn VPA: scale-down chậm khi traffic giảm, không dùng cho standalone Pod, vấn đề JVM
4. Multidimensional Pod Autoscaling — HPA và VPA Cùng Lúc
Khi cần cả hai chiều mà không được xung đột.
- Vì sao HPA và VPA không được cùng chạy trên một metric
MultidimPodAutoscaler(autoscaling.gke.io/v1beta1): HPA theo CPU + VPA theo memory- Spec:
scaleTargetRef,goals.metrics,constraints,policy - Trade-offs: khi nào MPA hợp lý, khi nào tách riêng tốt hơn
5. Cluster Autoscaler — Cơ Chế Scale-Up & Scale-Down
Loop điều khiển công suất node.
- Scale-up trigger: Pod Pending, mô phỏng "fake scheduling" trên template node
- Expander:
random,most-pods,least-waste(mặc định),least-nodes,price,priority location_policy:BALANCEDvsANY- Scale-down: ngưỡng utilization 0.5,
scale-down-unneeded-time10 phút,scale-down-delay-after-add10 phút - Điều gì chặn scale-down: kube-system không PDB, local storage, PDB hạn chế, annotation
safe-to-evict - Drain sequence,
max-graceful-termination-sec, multiple node pools, autoscaling profile
6. Node Auto-Provisioning — Tự Động Tạo Node Pool
Khi Cluster Autoscaler không chỉ resize mà còn tạo pool mới.
- NAP tự tạo và xóa node pool theo nhu cầu Pod đang Pending
resourceLimits: giới hạn CPU/memory/accelerator toàn cluster- Chọn machine type theo Pod spec và ComputeClass
- Mặc định pool tự tạo: auto-repair, auto-upgrade, shielded, service account/scopes
- Tích hợp custom ComputeClass,
nodePoolAutoCreation - Giới hạn: ngưỡng 200 node pool, các hạn chế upgrade
7. CA Troubleshooting, Capacity Buffers & Provisioning Requests
Quan sát, gỡ lỗi và đặt trước công suất.
- Visibility events: status vs decision,
scaleUp/scaleDown/eventResult/nodePoolCreated/nodePoolDeleted noScaleUpreasons vànoScaleDownreasons — đọc đúng chuỗi lý do- Cloud Logging queries cho sự kiện autoscaler (
container.googleapis.com/cluster-autoscaler-visibility) - Capacity buffer / overprovisioning bằng pause Pod priority thấp
- Provisioning Requests & Dynamic Workload Scheduler: cấp công suất atomic cho batch/AI,
queued-provisioning.gke.iovscheck-capacity.gke.io
8. KEDA — Kubernetes Event-Driven Autoscaling
Scale theo sự kiện và scale-to-zero.
- Kiến trúc KEDA: operator, metrics-apiserver, admission webhooks — KEDA tạo HPA bên dưới
ScaledObjectvsScaledJob- Scale-to-zero: pha activation (deactivation/activation) vs pha scaling,
activationThreshold - Defaults:
pollingInterval30s,cooldownPeriod300s,minReplicaCount0,maxReplicaCount100 - Pub/Sub scaler: scale theo backlog (
num_undelivered_messages,oldest_unacked_message_age) - Prometheus scaler, external scalers (Cloud Tasks, BigQuery)
Bản đồ tinh thần: ai quyết định gì, ở tần số nào, chạy ở đâu
Trước khi đi vào từng file, hãy ghim bảng tổng quan này. Nó là khung tham chiếu cho mọi quyết định debug và thiết kế trong chương.
| Autoscaler | Quyết định | Tín hiệu đầu vào | Tần số loop | Chạy ở đâu trên GKE |
|---|---|---|---|---|
| HPA | Số lượng replica | Metric (CPU/mem/custom/external) | ~15 giây | Control plane (Google quản lý) |
| VPA | Kích thước Pod (requests) | Lịch sử usage + OOM | Vài phút | Control plane process trên GKE |
| Multidim (MPA) | Replica (CPU) + memory (requests) | CPU metric + lịch sử mem | ~15s + vài phút | Control plane |
| Cluster Autoscaler | Số lượng node | Pod Pending + utilization node | ~10 giây scan | Control plane (Google quản lý) |
| Node Auto-Provisioning | Tạo/xóa cả node pool | Pod Pending không pool nào nhận | Theo CA | Control plane |
| KEDA | Replica (kể cả về 0) | Sự kiện ngoài (queue, Pub/Sub...) | pollingInterval 30s | Component bạn tự cài (add-on) |
Hai quan sát quan trọng từ bảng này:
HPA, VPA, Cluster Autoscaler, NAP đều do Google quản lý trên control plane — bạn không SSH vào chúng, không sửa flag trực tiếp như cluster tự dựng. Đòn bẩy duy nhất là spec đối tượng (HPA/VPA YAML), cấu hình cluster (
gcloud container clusters update), và autoscaling profile. KEDA là ngoại lệ: nó là add-on bạn tự cài và tự nâng cấp.Độ trễ end-to-end là tổng của nhiều loop nối tiếp. Khi traffic tăng: HPA mất tới ~15s để nhận ra và tăng replica → Pod mới Pending → Cluster Autoscaler mất ~10s để phát hiện → gọi API tạo node (phút) → node join, kéo image (phút) → Pod chạy → readiness probe pass → bắt đầu nhận traffic. Tổng có thể là vài phút, và đây là lý do gốc của hầu hết sự cố scale-up chậm. Mọi chiến lược production (capacity buffer, overprovisioning, Provisioning Requests) đều nhằm cắt ngắn chuỗi này.
Cách đọc chapter theo mục tiêu công việc
Nếu bạn đang debug "scale-up quá chậm / outage khi spike"
- File 1 + 2: HPA có nhận ra cần scale không, có bị stabilization/behavior chặn không (
ScalingLimited). - File 5 + 7: Cluster Autoscaler có scale-up không, hay bị
noScaleUp(hết quota, predicate fail, GPU không có limit). - File 7: cân nhắc capacity buffer (pause Pod) hoặc Provisioning Requests để loại bỏ độ trễ tạo node.
Nếu bạn đang debug "hóa đơn quá cao / không scale xuống"
- File 3: VPA có đang giữ
requestscao do nhớ peak lịch sử không. - File 5: scale-down có bị chặn không (
noScaleDownreasons — kube-system, PDB, local storage). - File 2: HPA stabilization window scale-down có quá dài không.
Nếu bạn đang thiết kế autoscaling cho workload mới
- File 1–2 (stateless web/API): chọn metric, behavior, target utilization.
- File 3–4 (workload khó đoán resource): VPA
Offđể lấy recommendation, hoặc MPA nếu cần cả hai chiều. - File 8 (event-driven/queue worker): KEDA scale-to-zero.
- File 7 (batch/AI training): Provisioning Requests cho cấp phát atomic.
Khung quyết định production (tóm tắt)
| Quyết định | Tác động chính | Rủi ro nếu làm sai | File nên đọc |
|---|---|---|---|
| Chọn metric cho HPA | Đúng tín hiệu phản ánh tải | Scale theo CPU khi nghẽn ở I/O → không bao giờ scale đúng | 1, 2 |
behavior scale-up/down | Tốc độ phản ứng vs ổn định | Scale-down quá nhanh gây flapping; quá chậm tốn tiền | 2 |
| HPA hay VPA hay MPA | Chiều scale phù hợp workload | Dùng cả hai trên cùng metric → đánh nhau, dao động | 2, 3, 4 |
| Autoscaling profile | Đệm công suất vs đóng gói chặt | optimize-utilization scale-down quá tay → Pending khi spike | 5 |
| Capacity buffer | Bù độ trễ tạo node | Không buffer → outage; buffer quá lớn → tốn tiền | 7 |
| NAP bật/tắt | Linh hoạt machine type | NAP không giới hạn → tạo node đắt ngoài ý muốn | 6 |
| KEDA scale-to-zero | Tiết kiệm khi idle | Cold start ảnh hưởng latency request đầu tiên | 8 |
Năm sai lầm xuyên suốt thường gặp ở cấp chương
- Chọn sai metric cho HPA. Scale theo CPU trong khi bottleneck thật là độ sâu hàng đợi hoặc số connection đồng thời. CPU có thể thấp trong khi service đã quá tải về I/O — HPA không bao giờ scale, hoặc scale sai thời điểm. Luôn chọn metric phản ánh đúng đơn vị công việc (file 1, 2).
- Dùng HPA và VPA cùng lúc trên CPU/Memory. Hai loop ra quyết định ngược nhau trên cùng tín hiệu: VPA tăng request → CPU% giảm → HPA scale xuống → tải dồn → VPA lại tăng. Kết quả là dao động không hội tụ. Dùng MPA nếu cần cả hai chiều (file 2, 3, 4).
- Quên rằng scale-up Pod ≠ scale-up công suất. HPA tăng replica trong vài giây, nhưng nếu cluster hết chỗ thì Pod chỉ Pending — và Cluster Autoscaler mất vài phút để cấp node. Không có capacity buffer thì spike = outage (file 5, 7).
- Đặt
requestssai làm hỏng mọi autoscaler bên dưới. Mọi autoscaler ra quyết định dựa trênrequests, không phải usage. Request quá cao: bin-packing kém, scale-down không bao giờ đạt ngưỡng utilization. Request quá thấp: Pod bị throttle/OOM trước khi HPA kịp phản ứng (file 1, 3). - Không quan sát được quyết định của autoscaler. Khi không đọc log
hpa-controllervàcluster-autoscaler-visibility, mọi sự cố scale trở thành phỏng đoán. Các log này cho biết chính xác vì sao một quyết định được/không được thực hiện (file 1, 7).
Cross-reference với Google Cloud Architecture Framework
- Cost optimization: autoscaling là đòn bẩy chi phí lớn nhất trên GKE — scale-down đúng, bin-packing qua Cluster Autoscaler, scale-to-zero qua KEDA (Cost optimization pillar).
- Reliability: scale-up đủ nhanh để chịu spike, capacity buffer, và phân bố qua failure domain khi scale (Reliability pillar).
- Performance optimization: right-sizing qua VPA và chọn metric đúng cho HPA để giữ SLO latency (Performance pillar).
References chung của chapter
- GKE Cluster autoscaler
- GKE HorizontalPodAutoscaler
- GKE VerticalPodAutoscaler
- Kubernetes Horizontal Pod Autoscaling
- Kubernetes In-place resize of Pod resources
- Cluster Autoscaler FAQ
- GKE Node auto-provisioning
- GKE Provisioning Requests
- KEDA documentation
Bảng thuật ngữ then chốt của chương
| Thuật ngữ | Ý nghĩa ngắn gọn |
|---|---|
| desiredReplicas | Số replica mục tiêu HPA tính ra mỗi chu kỳ (file 1) |
| tolerance | Vùng chết 10% quanh tỷ lệ 1.0, dưới ngưỡng này HPA không hành động (file 1) |
| stabilization window | Khoảng giữ recommendation để chống flapping (file 1, 2) |
| behavior policy | Chính sách giới hạn tốc độ scale up/down trong autoscaling/v2 (file 2) |
| atomic / final recommendation | Hai loại log quyết định của HPA trên GKE (file 1) |
| Recommender / Updater / Admission Controller | Ba thành phần của VPA (file 3) |
| InPlaceOrRecreate / IPPR | Đổi resource Pod không cần giết Pod (file 3) |
| MultidimPodAutoscaler | Đối tượng kết hợp HPA (CPU) + VPA (memory) (file 4) |
| expander | Thuật toán chọn node pool khi scale-up (file 5) |
| Node Auto-Provisioning (NAP) | Tự tạo/xóa node pool theo nhu cầu (file 6) |
| Provisioning Request | Cấp phát công suất atomic cho batch/AI (file 7) |
| ScaledObject / ScaledJob | Đối tượng cấu hình scaling của KEDA (file 8) |
Kết luận của chapter
Autoscaling là một bài toán control theory được ngụy trang thành cấu hình YAML. Mỗi autoscaler là một bộ điều khiển vòng kín với tín hiệu đầu vào, độ trễ, và độ lợi (gain) riêng — và như mọi hệ điều khiển, ghép nhiều bộ điều khiển lên cùng một hệ vật lý mà không hiểu chúng tương tác thế nào thì kết quả là dao động chứ không phải ổn định. Mục tiêu của chương này là cho bạn mô hình tinh thần chính xác về từng loop một, rồi về cách chúng nối tiếp và xung đột với nhau, để khi nhìn một biểu đồ replica dao động hay một hóa đơn tăng bất thường, bạn truy được ngay loop nào đang ra quyết định gì và vì sao.
Cách dùng chương hiệu quả nhất là biến mỗi file thành một chuẩn vận hành: chuẩn chọn metric và behavior cho HPA, chuẩn dùng VPA Off để right-size trước khi enforce, chuẩn capacity buffer để chịu spike, và chuẩn quan sát qua log visibility. Khi đó autoscaling chuyển từ "thứ tự cấu hình rồi cầu nguyện" thành một hệ thống có thể suy luận, đo đạc, và điều chỉnh một cách kỷ luật.