Lab 4 - Autoscaling hệ thống với Horizontal Pod Autoscaler (HPA)
Series: Kubernetes từ Zero đến Production
Tình huống thực tế
Website của công ty chuẩn bị mở chương trình Flash Sale.
Ngày thường:
100 Users
Ngày diễn ra Flash Sale:
100,000 Users
Nếu hệ thống vẫn chỉ chạy với 3 Backend Pods như Lab 3, điều gì sẽ xảy ra?
- CPU tăng lên 100%
- Request xử lý chậm
- Người dùng phải chờ lâu
- Có thể xảy ra timeout hoặc lỗi 5xx
Một lựa chọn là tăng số lượng Pod lên 20.
Nhưng sau khi Flash Sale kết thúc thì sao?
20 Pod sẽ tiếp tục chạy dù chỉ còn vài chục người dùng, gây lãng phí tài nguyên.
Giải pháp tốt hơn là để Kubernetes tự động điều chỉnh số lượng Pod theo tải thực tế.
Đó chính là nhiệm vụ của Horizontal Pod Autoscaler (HPA).
Mục tiêu
Sau bài lab này, bạn sẽ:
- Hiểu Horizontal Pod Autoscaler hoạt động như thế nào
- Cài đặt Metrics Server
- Tạo HPA cho Backend
- Sinh tải bằng Apache Benchmark và k6
- Quan sát Kubernetes tự động scale Pods
- Hiểu vòng đời Scale Up và Scale Down
Kiến trúc Autoscaling
CPU Usage
│
▼
Metrics Server
│
▼
Horizontal Pod Autoscaler
│
Scale Deployment
│
Backend Pods (2~20)
│
PostgreSQL
Luồng hoạt động:
- Metrics Server thu thập CPU của Pod.
- HPA đọc các chỉ số này.
- Nếu CPU vượt ngưỡng, HPA tăng số lượng Pod.
- Khi tải giảm, HPA tự động giảm Pod.
Điều kiện tiên quyết
Tiếp tục sử dụng hệ thống Todo ở Lab 3.
Kiểm tra:
kubectl get all -n todo-app
Đảm bảo:
- Frontend Running
- Backend Running
- PostgreSQL Running
Nếu chưa chạy thì hãy thực hiện deploy kubernetes lần nữa:
- Tách namespace.yaml ra khỏi thư mục kubernetes và ưu tiên chạy trước. Để đảm bảo ko lỗi thiếu namespace khi chạy các file yaml khác trong kubernetes
- Sau đó thực thi lệnh sau để deploy lại
kubectl apply -f namespace.yaml && until kubectl get ns todo-app >/dev/null 2>&1; do sleep 1; done && kubectl apply -f kubernetes/
Kiểm tra lại:
kubectl get all -n todo-app
Ví dụ mong đợi:
NAME READY STATUS RESTARTS AGE
pod/todo-backend-5f4cb76f55-4nhxz 1/1 Running 0 32s
pod/todo-backend-5f4cb76f55-59nzd 1/1 Running 0 32s
pod/todo-backend-5f4cb76f55-k6wsd 1/1 Running 0 32s
pod/todo-frontend-6566c9b7fd-6l7jg 1/1 Running 0 32s
pod/todo-frontend-6566c9b7fd-9tssq 1/1 Running 0 32s
pod/todo-postgres-9fcc6fd7b-25bwd 1/1 Running 0 32s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/todo-backend-service ClusterIP 10.105.34.249 <none> 8080/TCP 32s
service/todo-frontend-service ClusterIP 10.109.155.152 <none> 80/TCP 32s
service/todo-postgres-service ClusterIP 10.99.208.196 <none> 5432/TCP 32s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/todo-backend 3/3 3 3 32s
deployment.apps/todo-frontend 2/2 2 2 32s
deployment.apps/todo-postgres 1/1 1 1 32s
NAME DESIRED CURRENT READY AGE
replicaset.apps/todo-backend-5f4cb76f55 3 3 3 32s
replicaset.apps/todo-frontend-6566c9b7fd 2 2 2 32s
replicaset.apps/todo-postgres-9fcc6fd7b 1 1 1 32s
Phần 1. Kiểm tra Metrics Server
HPA cần Metrics Server để lấy thông tin CPU và Memory.
Kiểm tra:
kubectl top nodes
Nếu hiển thị CPU và Memory nghĩa là Metrics Server đã hoạt động.
Ví dụ:
NAME CPU(cores) CPU(%) MEMORY(bytes) MEMORY(%)
minikube 419m 3% 1586Mi 20%
Kiểm tra Pod:
kubectl top pods -n todo-app
Ví dụ:
NAME CPU(cores) MEMORY(bytes)
todo-backend-6f4d78586b-fvzfz 13m 211Mi
todo-backend-6f4d78586b-kwbqn 10m 208Mi
todo-backend-6f4d78586b-s5xhc 10m 224Mi
todo-frontend-6566c9b7fd-6l7jg 0m 8Mi
todo-frontend-6566c9b7fd-9tssq 0m 8Mi
todo-postgres-9fcc6fd7b-25bwd 3m 69Mi
Nếu các lệnh trên báo lỗi, hãy cài hoặc bật Metrics Server trước khi tiếp tục.
minikube addons enable metrics-server
Phần 2. Tạo Horizontal Pod Autoscaler
Tạo backend-hpa.yaml:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: todo-backend-hpa
namespace: todo-app
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: todo-backend
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Ý nghĩa:
- Tối thiểu 2 Pods
- Tối đa 20 Pods
- Scale khi CPU trung bình vượt 70%
Lưu ý:
- HPA không tính toán dựa trên tổng dung lượng CPU của máy Mac/Node, mà tính phần trăm dựa trên con số requests.cpu bạn đã khai báo trong Deployment
- Vì vậy để test HPA và quan sát dễ dàng khi làm lab, hãy giảm requests.cpu xuống 200m. Và nhớ chạy apply deployment của backend.
Áp dụng HPA:
kubectl apply -f backend-hpa.yaml
Phần 3. Quan sát HPA bằng K9s
Khởi động K9s:
k9s --context minikube -n todo-app
Tại màn hình chính:
- Nhấn
:hpađể xem danh sách Horizontal Pod Autoscaler. - Chọn
todo-backend-hpa.
Bạn sẽ thấy các thông tin như:

Ý nghĩa:
- TARGETS: CPU hiện tại / CPU mục tiêu
- MINPODS: số Pod tối thiểu
- MAXPODS: số Pod tối đa
- REPLICAS: số Pod đang chạy
Trong suốt bài lab, bạn chỉ cần giữ nguyên màn hình này để quan sát HPA thay đổi theo thời gian thực.
Phần 4. Sinh tải với Apache Benchmark
Apache Benchmark (ab) là công cụ đơn giản để gửi nhiều HTTP request trong thời gian ngắn.
Ví dụ:
kubectl run ab-test --rm -it --restart=Never --image=httpd:2.4 -- \
ab -n 100000 -c 1000 http://todo-backend-service.todo-app.svc.cluster.local:8080/api/todos
Ý nghĩa:
- 100.000 request
- 1000 request đồng thời
Sau khi chạy lệnh, quay lại cửa sổ K9s.
Quan sát:
- Giá trị TARGETS tăng dần.
- Khi CPU vượt ngưỡng 70%, HPA sẽ bắt đầu tăng số lượng Replica.
Bạn không cần chạy thêm kubectl top pods, vì K9s sẽ tự động cập nhật trạng thái HPA.
Ví dụ:
- Tôi đã mở 2 terminal chạy k9s để quan sát backend hpa và backend pod khi chạy apache benchmark

- Quan sát ta thấy khi chạy 100.000 request với 1000 request đồng thời tới /api/todos
- Tuy nhiên TARGETS chỉ tới 54% nên ko có pod mới đc sinh ra.
- Hãy thử lên gấp với 1.000.000 request với 1000 request đồng thời tới /api/todos

- Quan sát ta thấy khi chạy 1.000.000 request với 500 request đồng thời tới /api/todos
- Tuy nhiên TARGETS vượt 70% nên pod mới đã đc sinh ra.
- Khi pod mới sinh ra, chia sẻ áp lực với các pod khác, TARGETS đã giảm xuống, ko khiến server bị sập
- Cho đến khi hết request, TARGETS về 0, sau 1 khoảng thời gian, những pod mới sinh ra ko cần nữa nên chúng được xoá bỏ, tiết kiệm tài nguyên hệ thống
Có lẽ bạn sẽ thắc mắc:
- Tại sao tôi ko chạy 1.000.000 request với 1000 request đồng thời tới /api/todos
- Vì tôi đã thử và đã sập server, thông số này hãy tự điều chỉnh để nhận được kết quả phù hợp nhé
- Tại sao TARGETS có thể vượt 100%
- Chỉ số này được tính dựa trên CPU thực tế / CPU request
- Ý nghĩa của nó là pod đang dùng CPU cao hơn mức request nhưng vẫn chưa chắc vượt limit
- Nó chỉ là tín hiệu để HPA xem có nên scale up hay ko
- VD: 134% tức là CPU thực tế dùng cao gấp 1,34 CPU request
- Một số chỉ số trong bảng pod của k9s:
- CPU: lượng CPU pod đang dùng thực tế, thường là m cores. Ví dụ 250m = 0.25 CPU core.
- %CPU/R: phần trăm CPU đang dùng so với requests.cpu.
- %CPU/L: phần trăm CPU đang dùng so với limits.cpu.
- MEM: lượng RAM pod đang dùng thực tế.
- %MEM/R: phần trăm RAM đang dùng so với requests.memory.
- %MEM/L: phần trăm RAM đang dùng so với limits.memory.
- Có công thức nào tính chính xác được số request và số request đồng thời mà hệ thống có thể chịu tải ko?
- Có công thức gần đúng: Concurrency = RPS × ResponseTime
- Không có công thức đóng để biết chính xác “chịu được bao nhiêu”
- Con số thật phải lấy từ benchmark theo nấc (điểm bão hòa throughput, điểm latency tăng vọt, điểm bắt đầu có lỗi, điểm HPA bắt đầu scale)
Phần 5. Sinh tải với k6
Ngoài Apache Benchmark, một công cụ rất phổ biến trong kiểm thử hiệu năng là k6.
Ví dụ script:
import http from 'k6/http';
export default function () {
http.get('http://todo.company.local/api/todos');
}
Chạy:
k6 run script.js
Trong khi k6 đang chạy, quay lại K9s.
Quan sát:
- CPU của Backend tăng.
- HPA cập nhật TARGETS.
- Deployment tăng Replica.
- Các Pod mới được tạo tự động.
So với Apache Benchmark:
| Công cụ | Phù hợp với |
|---|---|
| Apache Benchmark | Kiểm tra nhanh một endpoint |
| k6 | Mô phỏng nhiều kịch bản người dùng, dễ tích hợp vào CI/CD |
Trong các dự án thực tế, k6 thường được sử dụng nhiều hơn khi cần kiểm thử tải một cách linh hoạt.
HPA hoạt động như thế nào?
Khi CPU tăng:
CPU tăng
│
Metrics Server
│
Horizontal Pod Autoscaler
│
Deployment
│
ReplicaSet
│
Pods tăng từ 2 → 5 → 8 ...
Khi CPU giảm:
CPU giảm
│
Metrics Server
│
Horizontal Pod Autoscaler
│
Deployment
│
Pods giảm về mức tối thiểu
Điểm quan trọng là HPA không tạo Pod trực tiếp.
Nó chỉ thay đổi số lượng Replica của Deployment, còn Deployment sẽ chịu trách nhiệm tạo hoặc xóa Pod.
Thử tạo lỗi
Tình huống 1: Metrics Server không hoạt động
Kiểm tra:
kubectl top pods
Nếu xuất hiện lỗi:
Metrics API not available
HPA sẽ không thể lấy số liệu CPU và sẽ không tự động scale.
Tình huống 2: Không khai báo Resource Requests
Nếu Deployment không có:
resources:
requests:
cpu: 500m
HPA có thể không tính được tỷ lệ sử dụng CPU chính xác.
Đây là lý do Lab 3 luôn yêu cầu cấu hình Resource Requests trước khi triển khai HPA.
Dọn dẹp
Nếu không muốn giữ HPA:
kubectl delete hpa todo-backend -n todo-app
Hoặc tiếp tục sử dụng để chuẩn bị cho Lab 5.
Những gì bạn đã học
Sau bài lab này, bạn đã biết:
✅ Vai trò của Metrics Server
✅ Horizontal Pod Autoscaler (HPA)
✅ Cấu hình minReplicas và maxReplicas
✅ Scale theo CPU Usage
✅ Sinh tải bằng Apache Benchmark
✅ Sinh tải bằng k6
✅ Quan sát Scale Up
✅ Quan sát Scale Down
✅ Mối quan hệ giữa HPA và Deployment
Bài học rút ra
Một hệ thống production không nên sử dụng số lượng Pod cố định.
Khi lượng người dùng tăng, hệ thống cần mở rộng đủ nhanh để duy trì hiệu năng.
Khi lượng truy cập giảm, hệ thống cũng cần tự động thu hẹp để tiết kiệm tài nguyên.
Horizontal Pod Autoscaler giúp Kubernetes thực hiện điều đó một cách tự động dựa trên các chỉ số thực tế, thay vì phụ thuộc vào thao tác thủ công của DevOps Engineer.
Ở bài lab tiếp theo, chúng ta sẽ tiếp tục xây dựng khả năng quan sát (Observability) cho hệ thống bằng cách triển khai Prometheus và Grafana để theo dõi CPU, Memory, Request và nhiều chỉ số quan trọng khác của toàn bộ Kubernetes Cluster.
All rights reserved