HPA thêm bản. VPA sửa requests của từng bản. Bài này đo VPA trên cụm thật và tìm ra nó làm hai việc khác nhau mà nhiều người tưởng là một.
Khuyến nghị đầu tiên sau khoảng một phút
Ứng dụng khai requests: cpu=500m, memory=512Mi. Dùng thật: 338m CPU, 83Mi bộ nhớ — khai thừa rõ ràng.
VPA sau ~60 giây:
lowerBound: cpu=25m mem=262144k
target: cpu=410m mem=262144k
upperBound: cpu=8856410m mem=2372108436351
target là con số dùng được: 410m — cao hơn mức dùng thật 338m một chút, đúng như mong đợi vì VPA cộng biên an toàn.
upperBound thì 8.856 nhân và 2,2 terabyte. Vô nghĩa.
Đó không phải lỗi: VPA chưa đủ dữ liệu lịch sử nên khoảng tin cậy rộng gần như vô hạn. Phải để nó chạy vài ngày trước khi con số có ý nghĩa — và phần dưới sẽ cho thấy vì sao điều đó ảnh hưởng tới hành vi chứ không chỉ tới độ chính xác.
Bộ nhớ khuyến nghị là 262144k = 250Mi, đúng bằng mức sàn mặc định của VPA, dù ứng dụng chỉ dùng 83Mi. VPA không khuyến nghị thấp hơn 250Mi trừ khi bạn khai minAllowed.
Auto mode: hai cơ chế khác nhau
Đây là phần bất ngờ nhất.
1) Bộ admission ghi đè requests lúc tạo pod
Deployment khai: {"cpu":"50m","memory":"64Mi"}
Pod thực tế có: {"cpu":"410m","memory":"262144k"}
VPA khuyến nghị: {"cpu":"410m","memory":"262144k"}
Tôi đặt requests: cpu=50m trong Deployment. Pod chạy ra với 410m.
Bộ admission của VPA chặn ở giữa (phần 46 — admission nằm ngay trên đường ghi) và thay giá trị. Manifest nói một đằng, pod chạy một nẻo — và kubectl get deployment vẫn hiện con số cũ.
Với GitOps, điều này gây bối rối thật: kho Git là nguồn sự thật cho Deployment, nhưng không phải cho requests mà pod thực sự nhận.
2) Bộ updater giết pod cũ — nhưng chỉ khi cần
Pod cũ có requests: cpu=500m, khoảng tin cậy [187m .. 196122m].
500m nằm TRONG khoảng -> KHÔNG bị giết
sau 110 giây vẫn nguyên, RESTARTS=0
VPA không giết pod chỉ vì target khác requests hiện tại. Nó chỉ giết khi requests nằm ngoài khoảng tin cậy.
Vì sao VPA trông như "không làm gì"
Ghép hai điều trên lại:
- Khoảng tin cậy ban đầu rất rộng (
upperBound8.856 nhân), nên gần như mọirequestsđều nằm trong. - Chỉ pod mới nhận giá trị khuyến nghị, qua bộ admission.
Nên bật VPA Auto rồi ngồi chờ nó sửa pod đang chạy là chờ vô ích. Muốn thấy hiệu quả ngay thì phải:
kubectl rollout restart deployment/<ten>
Hoặc chờ tới khi VPA thu thập đủ dữ liệu và khoảng tin cậy hẹp lại — thường là vài ngày.
Đây là lý do khuyến nghị phổ biến là bắt đầu với updateMode: "Off": để VPA quan sát và đưa khuyến nghị, con người đọc rồi tự sửa manifest. Bạn được giá trị chính của VPA (biết nên khai bao nhiêu) mà không có phần khó đoán.
Bốn chế độ
Off chỉ khuyến nghị, không đụng gì <- nên bắt đầu ở đây
Initial chỉ đặt requests lúc pod được TẠO
Recreate giết pod để áp giá trị mới
Auto hiện tại giống Recreate
Auto được thiết kế để một ngày nào đó dùng cơ chế sửa tại chỗ, nhưng hiện tại nó vẫn giết pod.
Và đó là điểm yếu lớn nhất của VPA: nó phải giết pod để đổi requests. Với ứng dụng khởi động chậm hoặc có trạng thái, việc bị giết định kỳ là cái giá thật.
Kubernetes 1.27 có tính năng thử nghiệm InPlacePodVerticalScaling cho phép đổi requests mà không khởi động lại. Khi nó ổn định, VPA sẽ hữu dụng hơn nhiều.
VPA và HPA không dùng chung được
VPA và HPA theo CPU cùng lúc trên một Deployment sẽ đá nhau:
- Tải tăng → HPA thêm bản → CPU mỗi bản giảm → VPA hạ
requests→ tỉ lệ CPU/requests tăng → HPA thêm bản nữa.
Kết hợp được khi HPA dùng chỉ số khác: số yêu cầu mỗi giây, độ dài hàng đợi (phần 66). Khi ấy hai bộ điều khiển nhìn hai thứ khác nhau và không xung đột.
Quy tắc thực dụng:
- Tải thay đổi theo thời gian → HPA. Thêm bản là cách đúng.
- Không biết nên khai bao nhiêu → VPA ở chế độ
Off, đọc khuyến nghị, sửa tay. - Cả hai → HPA theo chỉ số ứng dụng, VPA
Offđể hiệu chỉnhrequests.
Ba tham số nên khai
spec:
resourcePolicy:
containerPolicies:
- containerName: "*"
minAllowed: {cpu: 50m, memory: 64Mi}
maxAllowed: {cpu: 2, memory: 2Gi}
controlledResources: [cpu, memory]
maxAllowed là quan trọng nhất: không có nó, một đỉnh tải bất thường có thể khiến VPA khuyến nghị con số lớn tới mức không node nào xếp nổi pod — và pod nằm Pending mãi (phần 47).
minAllowed chặn chiều ngược lại: VPA hạ requests quá thấp khiến pod thành gần BestEffort và bị đuổi trước (phần 55).
Thử ba mươi giây
Xem VPA khuyến nghị gì so với những gì bạn đang khai:
kubectl get vpa -A -o custom-columns=\
NS:.metadata.namespace,TEN:.metadata.name,\
CHE_DO:.spec.updatePolicy.updateMode,\
CPU:.status.recommendation.containerRecommendations[0].target.cpu,\
RAM:.status.recommendation.containerRecommendations[0].target.memory
So với requests trong manifest. Chênh lệch lớn theo chiều khai thừa là tiền đang lãng phí; chênh lệch theo chiều khai thiếu là pod sắp bị đuổi khi node cạn.
Phần sau đo Cluster Autoscaler — và nói rõ phần nào tôi không dựng được để đo.