Vào lúc 2:14 sáng, điện thoại của tôi rung lên dồn dập với cảnh báo PagerDuty khẩn cấp: NodeMemoryPressure, kéo theo sau là hàng loạt lỗi OOMKilled dây chuyền trên hai worker node. Chỉ trong vài phút, sáu pod trong namespace xử lý thanh toán của chúng tôi rơi vào trạng thái CrashLoopBackOff. Nguyên nhân thì quen thuộc đến đau lòng.
Một microservice mới triển khai chỉ yêu cầu (request) 100Mi memory nhưng lại không hề cấu hình giới hạn (limit), khiến nó phình to tới hơn 9.2Gi trong quá trình đối soát theo lô (batch reconciliation). Ngay cạnh đó, một service webhook nội bộ lại giữ chỗ trước tới 4 CPU core trong khi chỉ tiêu thụ vỏn vẹn 15 millicore suốt cả ngày. Về mặt lý thuyết trên giấy tờ, cluster đang cạn kiệt tài nguyên; nhưng trên thực tế, hệ thống gần như chạy không tải.
Thiết lập requests và limits trong Kubernetes dựa trên phỏng đoán phải trả một cái giá rất đắt. Hoặc là bạn đốt hàng ngàn đô la cho phần tài nguyên dư thừa không dùng đến, hoặc bạn phải cuống cuồng thức trắng lúc 2 giờ sáng khi Linux kernel buộc phải dừng các workload quan trọng. Kết hợp Fairwinds Goldilocks với Kubernetes Vertical Pod Autoscaler (VPA) sẽ giúp bạn chấm dứt thói quen đoán mò này. Bộ đôi này sẽ chuyển đổi các chỉ số tiêu thụ tài nguyên thực tế thành các đề xuất cấu hình pod chuẩn xác và có thể áp dụng được ngay.
Bắt đầu nhanh (5 phút)
Khi sự cố đang diễn ra, bạn không cần những bài tiểu luận dài dòng về mặt kiến trúc. Điều bạn cần là cái nhìn trực quan tức thì về lượng tài nguyên container đang thực sự tiêu thụ so với mức tài nguyên bạn đã cấp phát cho chúng.
Bước 1: Kiểm tra Metrics Server
VPA phụ thuộc vào các chỉ số metrics thực tế của node và pod. Trước tiên, hãy xác minh pipeline thu thập metrics trong cluster của bạn đang hoạt động bình thường:
kubectl top nodes
kubectl top pods -A
Nếu cả hai lệnh đều trả về bảng thống kê tài nguyên, bạn đã sẵn sàng. Nếu bạn nhận được thông báo error: Metrics API not available, hãy deploy manifest metrics-server chính thức trước khi tiếp tục.
Bước 2: Cài đặt Vertical Pod Autoscaler
Goldilocks dựa vào engine VPA Recommender để tính toán mức tài nguyên tham chiếu. Hãy clone repository của autoscaler và cài đặt các CRD cùng controller tiêu chuẩn:
git clone https://github.com/kubernetes/autoscaler.git
cd autoscaler/vertical-pod-autoscaler
./hack/vpa-up.sh
Xác nhận cả ba core controller của VPA đều đang hoạt động:
kubectl get pods -n kube-system | grep vpa
Đảm bảo các pod vpa-recommender, vpa-updater và vpa-admission-controller đều ở trạng thái Running.
Bước 3: Deploy Goldilocks qua Helm
Goldilocks sẽ kiểm tra các deployment của bạn, tự động tạo các đối tượng VPA tương ứng và hiển thị các đề xuất thông qua một dashboard trực quan, gọn nhẹ. Thêm repository và cài đặt Helm chart:
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm repo update
helm install goldilocks fairwinds-stable/goldilocks \
--namespace goldilocks \
--create-namespace \
--set dashboard.enabled=true
Bước 4: Bật Goldilocks trên namespace mục tiêu
Goldilocks chỉ giám sát các namespace được bật tính năng này một cách rõ ràng. Hãy gắn label kiểm tra cho namespace mục tiêu của bạn:
kubectl label namespace production goldilocks.fairwinds.com/enabled=true
Forward port của dashboard service về máy làm việc của bạn:
kubectl -n goldilocks port-forward svc/goldilocks-dashboard 8080:80
Truy cập vào http://localhost:8080. Goldilocks sẽ hiển thị từng deployment trong namespace kèm theo các đề xuất cụ thể cho cả hai cấp Quality of Service (QoS): Guaranteed và Burstable.
Đi sâu vào chi tiết
Để ngăn chặn các sự cố tái diễn, các đội ngũ kỹ thuật cần hiểu rõ cách engine VPA tính toán các giá trị này cũng như cách Kubernetes diễn giải chúng.
Cách VPA tính toán tài nguyên mục tiêu
Ngay sau khi bạn gắn label cho một namespace, controller của Goldilocks sẽ tạo một custom resource VerticalPodAutoscaler tương ứng cho mỗi deployment. Mặc định, nó thiết lập updateMode: "Off". Thiết kế này giúp việc đánh giá diễn ra an toàn: recommender sẽ theo dõi lưu lượng traffic trên production mà không khởi động lại pod hay làm thay đổi manifest đang chạy.
Bạn có thể kiểm tra trực tiếp bất kỳ đối tượng VPA tự động nào:
kubectl get vpa -n production
kubectl get vpa payment-service -n production -o yaml
Hãy xem phần status.recommendation.containerRecommendations. Bạn sẽ thấy bốn giá trị tính toán riêng biệt được đánh giá dựa trên khung thời gian trượt (sliding window) 8 ngày:
- LowerBound: Ngưỡng tối thiểu. Nếu hạ requests xuống dưới mức này, nguy cơ bị CPU throttling hoặc thiếu hụt memory là rất cao.
- Target: Điểm tối ưu đã được tính toán. Hãy sử dụng chính xác giá trị này cho trường
requestscủa container. - UpperBound: Mức trần ghi nhận được trong các đợt tăng đột biến lưu lượng (peak usage spike). Giá trị này dùng để tham khảo khi cấu hình memory limit cho container.
- UncappedTarget: Giá trị target thô được tính toán trước khi áp dụng bất kỳ ràng buộc min/max nào do người dùng định nghĩa trong policy của VPA.
So sánh QoS Guaranteed và Burstable trong Goldilocks
Mỗi pod được gán một phân tầng Quality of Service dựa trên cách bạn khai báo CPU và memory:
- Guaranteed:
requestsbằng vớilimitscho mọi container. Kubernetes scheduler sẽ dành riêng toàn bộ khối tài nguyên này trên node. Goldilocks đặt cả hai trường này bằng giá trị Target của VPA. Hãy áp dụng tầng này cho các database quan trọng và các consumer xử lý hàng đợi (queue consumer). - Burstable:
requestskhớp với Target của VPA, nhưnglimitsđược đặt cao hơn hoặc để trống đối với CPU. Cấu hình này cho phép các microservice hấp thụ các đợt tăng đột biến traffic tạm thời mà không lãng phí phần tài nguyên đặt trước trên node vào những khung giờ thấp điểm.
Trong sự cố lúc 2 giờ sáng của chúng tôi, payment proxy chính chạy dưới phân lớp BestEffort vì hoàn toàn không khai báo tài nguyên. Khi node cạn kiệt memory, Linux kernel đã nhắm vào proxy đó đầu tiên. Các pod thuộc lớp BestEffort có giá trị oom_score_adj là 1000, biến chúng thành nạn nhân đầu tiên bị tiêu diệt khi node gặp áp lực tài nguyên.
Sử dụng nâng cao
Các thiết lập tiêu chuẩn thường phù hợp với các ứng dụng stateless cơ bản. Tuy nhiên, các workload stateful, telemetry sidecar và các background worker có tải biến động mạnh đòi hỏi cấu hình cẩn trọng hơn.
Định nghĩa ràng buộc VPA tùy chỉnh
Đôi khi bạn cần thiết lập các ranh giới cứng. Ví dụ: một lỗi rò rỉ bộ nhớ (memory leak) chưa được vá không nên khiến VPA đề xuất mức cấp phát tới 32Gi trên một node pool chỉ dùng các instance 16Gi. Bạn có thể định nghĩa một manifest VPA tùy chỉnh với các ngưỡng bảo vệ rõ ràng:
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: checkout-worker-vpa
namespace: production
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: checkout-worker
updatePolicy:
updateMode: "Off"
resourcePolicy:
containerPolicies:
- containerName: checkout-worker
minAllowed:
cpu: 100m
memory: 256Mi
maxAllowed:
cpu: 2000m
memory: 4Gi
controlledResources: ["cpu", "memory"]
Áp dụng manifest này để ghi đè các giá trị mặc định tự động. VPA recommender sẽ luôn giữ các mục tiêu đề xuất nằm trong ngưỡng an toàn mà bạn chỉ định.
Loại trừ Sidecar của Service Mesh
Các telemetry sidecar như Envoy, Linkerd hoặc Datadog agent thường làm sai lệch việc định cỡ tài nguyên ứng dụng. Goldilocks cho phép bạn lọc bỏ chúng để các đề xuất chỉ tập trung hoàn toàn vào các container ứng dụng chính.
Cập nhật bản phát hành Helm của Goldilocks với danh sách loại trừ:
helm upgrade goldilocks fairwinds-stable/goldilocks \
--namespace goldilocks \
--set "controller.flags.exclude-containers=istio-proxy\,datadog-agent"
Thao tác này giúp các chỉ số của bạn bám sát thực tế bằng cách tách biệt hiệu năng của ứng dụng cốt lõi khỏi chi phí phụ trội của proxy.
Export Metrics của Goldilocks cho CI/CD Automation
Việc kiểm tra thủ công qua dashboard sẽ không thể mở rộng khi quản lý hàng chục cluster. Thay vào đó, hãy export dữ liệu của Goldilocks trực tiếp sang Prometheus:
helm upgrade goldilocks fairwinds-stable/goldilocks \
--namespace goldilocks \
--reuse-values \
--set controller.metrics.enabled=true
Sau khi được export, bạn có thể gắn cờ các workload cấu hình sai trên Grafana hoặc trong các bước linting của CI. Chẳng hạn, gửi cảnh báo cho đội ngũ kỹ thuật bất cứ khi nào request được cấu hình vượt quá 2 lần mục tiêu khuyến nghị, hoặc khi request nằm dưới 50% ngưỡng target.
Lời khuyên thực tế
Tinh chỉnh các workload trên production là một quá trình lặp đi lặp lại. Hãy ghi nhớ bốn nguyên tắc sau trước khi áp dụng thay đổi trên toàn bộ cluster của bạn:
1. Cẩn trọng với cái bẫy CPU Limit Throttling
Memory là tài nguyên không thể nén (incompressible resource). Nếu vượt quá limit, kernel sẽ lập tức tắt container. Ngược lại, CPU là tài nguyên có thể nén (compressible). Nếu vượt quá CPU limit, Completely Fair Scheduler (CFS) sẽ điều tiết (throttle) thời gian chạy của container theo các chu kỳ hạn mức (quota period).
Cấu hình CPU limit quá chặt chẽ thường dẫn đến hiện tượng độ trễ tăng đột biến một cách giả tạo. Ở một service API xử lý 1.200 req/giây, việc gỡ bỏ mức CPU limit 500m đã giúp giảm thời gian phản hồi p99 từ 840ms xuống chỉ còn 38ms. Hãy thiết lập CPU request dựa theo Target của Goldilocks, nhưng cân nhắc để trống hoặc nới rộng CPU limit để tránh hiện tượng throttling không mong muốn.
2. Tính toán đến chi phí bộ nhớ phụ trội của JVM và Runtime
Các môi trường runtime như Java, Node.js và Python tiêu thụ bộ nhớ vượt xa mức heap của ứng dụng. Một JVM chạy với -Xmx2g vẫn cấp phát thêm bộ nhớ ngoài heap (off-heap memory) cho thread stack, Metaspace và metadata của GC. Nếu đặt container limit đúng mức 2Gi, ứng dụng gần như chắc chắn sẽ bị OOMKill. Goldilocks ghi nhận giá trị Resident Set Size (RSS) thực tế. Với một heap 2Gi, bạn nên cấp phát tối thiểu 2.8Gi đến 3.0Gi cho container limit để bù đắp phần phụ trội của runtime một cách an toàn.
3. Tuyệt đối không kết hợp VPA Auto-Mode với HPA dựa trên CPU hoặc Memory
Tránh chạy VPA ở chế độ updateMode: "Auto" cùng lúc với Horizontal Pod Autoscaler hoạt động dựa trên metrics CPU hoặc memory. Hai controller này sẽ xung đột lẫn nhau. HPA sẽ scale tăng thêm replica trong khi VPA lại tăng kích thước pod, tạo ra một vòng lặp phản hồi tiêu cực đẩy dung lượng của node đến mức cạn kiệt. Nếu muốn auto-scaling theo chiều ngang, hãy cấu hình HPA dựa trên các custom business metric như độ sâu hàng đợi SQS hoặc tỷ lệ HTTP request.
4. Thiết lập quy trình rà soát kích thước tài nguyên hàng tuần
Hãy dành ra 20 phút vào mỗi sáng thứ Hai để rà soát tình trạng tài nguyên. Kiểm tra các workload được cảnh báo trong Goldilocks, sau đó cập nhật manifest GitOps trên ArgoCD hoặc Flux. Tối ưu kích cỡ (right-sizing) cho khoảng hai mươi microservice với chỉ 500m CPU và 1Gi memory cho mỗi service cũng có thể dễ dàng giúp bạn tiết kiệm 1.200 USD mỗi tháng trên hóa đơn hạ tầng đám mây.

