Tối ưu chi phí Kubernetes 2026: Karpenter, Spot Instances và Right-Sizing giảm 55% bill cloud
Posted on: 4/21/2026 10:12:34 AM
Table of contents
- 1. Tại sao Kubernetes lại đắt đến vậy?
- 2. Karpenter — Node Provisioning thế hệ mới
- 3. Spot Instances — Giảm 70-90% chi phí compute
- 4. VPA & Right-Sizing — Từ 12% lên 50%+ Utilization
- 5. Consolidation — Nghệ thuật bin-packing
- 6. Case Study: Từ $48K xuống $21.5K/tháng
- 7. Azure AKS: Node Auto-Provisioning (NAP)
- 8. FinOps & Governance — Duy trì kết quả lâu dài
- 9. Lộ trình triển khai 4 tuần
- 10. Kết luận
Hơn 68% tổ chức đang trả quá nhiều cho Kubernetes — từ 20% đến 40% ngân sách cloud bị lãng phí do pod request thổi phồng, node chạy không tải, và thiếu chiến lược autoscaling thông minh. Bài viết này đi sâu vào bộ công cụ tối ưu chi phí Kubernetes mạnh nhất năm 2026: Karpenter cho node provisioning thông minh, Spot Instances giảm 70-90% compute, VPA cho right-sizing chính xác, và mô hình FinOps để duy trì kết quả lâu dài. Với case study thực tế giảm từ $48K xuống $21.5K/tháng.
1. Tại sao Kubernetes lại đắt đến vậy?
Kubernetes không đắt — cách chúng ta cấu hình mới đắt. Phần lớn cluster production rơi vào pattern "set-and-forget": developer request 500m CPU và 1Gi memory cho mỗi pod "cho an toàn", nhưng thực tế pod chỉ dùng 25m CPU và 262Mi memory. Kết quả: cluster chạy ở mức 10-15% utilization nhưng trả tiền cho 100% capacity.
Ba nguồn lãng phí chính:
| Nguồn lãng phí | Nguyên nhân | % chi phí dư thừa |
|---|---|---|
| Over-provisioned pods | Request CPU/memory cao hơn thực tế sử dụng 5-20 lần | 30-60% |
| Idle nodes | Cluster Autoscaler phản ứng chậm, không consolidate | 15-25% |
| On-Demand mặc định | Không tận dụng Spot/Preemptible cho stateless workloads | 20-40% |
2. Karpenter — Node Provisioning thế hệ mới
Karpenter (nay thuộc Kubernetes SIGs, hỗ trợ cả AWS và Azure) là node autoscaler thay thế hoàn toàn Cluster Autoscaler truyền thống. Thay vì mở rộng node group cố định, Karpenter nhìn vào pending pods và hỏi trực tiếp Cloud Provider API để chọn instance type tối ưu nhất — đúng size, đúng giá, trong vài giây.
graph TB
PENDING["Pending Pods
(unschedulable)"] --> KARPENTER["Karpenter Controller"]
KARPENTER --> EVAL["Evaluate Pod
Requirements"]
EVAL --> SELECT["Select Optimal
Instance Type"]
SELECT --> SPOT{"Spot
available?"}
SPOT -->|"Yes"| LAUNCH_SPOT["Launch Spot
Instance"]
SPOT -->|"No"| LAUNCH_OD["Launch On-Demand
Instance"]
LAUNCH_SPOT --> SCHEDULE["Schedule Pods"]
LAUNCH_OD --> SCHEDULE
SCHEDULE --> MONITOR["Monitor
Utilization"]
MONITOR -->|"Underutilized"| CONSOLIDATE["Consolidate:
Bin-pack & Terminate"]
MONITOR -->|"Healthy"| MONITOR
CONSOLIDATE --> KARPENTER
style KARPENTER fill:#e94560,stroke:#fff,color:#fff
style CONSOLIDATE fill:#e94560,stroke:#fff,color:#fff
style LAUNCH_SPOT fill:#4CAF50,stroke:#fff,color:#fff
style LAUNCH_OD fill:#2c3e50,stroke:#fff,color:#fff
style PENDING fill:#f8f9fa,stroke:#e94560,color:#333
style EVAL fill:#f8f9fa,stroke:#e94560,color:#333
style SELECT fill:#f8f9fa,stroke:#e94560,color:#333
style MONITOR fill:#f8f9fa,stroke:#e94560,color:#333
style SCHEDULE fill:#f8f9fa,stroke:#e94560,color:#333
Hình 1: Vòng đời Karpenter — từ pending pod đến consolidation tự động
2.1. Karpenter vs Cluster Autoscaler
| Tiêu chí | Cluster Autoscaler | Karpenter |
|---|---|---|
| Thời gian scale-up | 2-5 phút | ~30-60 giây |
| Instance selection | Cố định theo Node Group | Dynamic — chọn từ toàn bộ instance catalog |
| Consolidation | Scale-down sau 10 phút idle | Bin-pack liên tục, terminate node thừa |
| Spot handling | Cần cấu hình Mixed Instance Policy | Native Spot + On-Demand fallback |
| Multi-arch | Cần node group riêng cho ARM64 | Tự chọn ARM64/AMD64 theo requirements |
| Pod awareness | Chỉ đếm pending pods | Phân tích topology, affinity, taints |
2.2. Cấu hình NodePool tối ưu chi phí
NodePool là đơn vị cấu hình chính của Karpenter, định nghĩa "loại node nào được phép tạo" và "khi nào nên consolidate":
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: cost-optimized
spec:
template:
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
# Chỉ dùng instance thế hệ 6+ (giá/hiệu năng tốt hơn)
- key: "karpenter.k8s.aws/instance-generation"
operator: Gt
values: ["5"]
# Ưu tiên ARM64 (Graviton) — rẻ hơn ~20%
- key: "kubernetes.io/arch"
operator: In
values: ["arm64", "amd64"]
# Spot trước, On-Demand fallback
- key: "karpenter.sh/capacity-type"
operator: In
values: ["spot", "on-demand"]
# Instance families phù hợp
- key: "karpenter.k8s.aws/instance-category"
operator: In
values: ["c", "m", "r"]
# Tránh instance quá nhỏ (overhead cao)
- key: "karpenter.k8s.aws/instance-size"
operator: NotIn
values: ["nano", "micro", "small"]
# Consolidation: gộp pods và terminate node thừa
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m
budgets:
- nodes: "20%"
- nodes: "0"
schedule: "0 9 * * 1-5"
duration: 1h
expireAfter: 168h # Recycle node mỗi 7 ngày
limits:
cpu: "1000"
memory: "4000Gi"
Disruption Budgets là gì?
Disruption Budget kiểm soát tốc độ Karpenter terminate nodes. Ví dụ nodes: "20%" nghĩa là tại bất kỳ thời điểm nào, Karpenter chỉ được disrupting tối đa 20% tổng số node. Bạn cũng có thể tạo "maintenance window" — ví dụ chặn mọi disruption vào 9h sáng thứ 2-6 (giờ peak traffic) bằng nodes: "0" với schedule cron.
2.3. EC2NodeClass — Cấu hình AMI và storage
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default
spec:
amiFamily: AL2023
role: eks-karpenter-node
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: 50Gi
volumeType: gp3
iops: 3000
encrypted: true
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: my-cluster
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: my-cluster
3. Spot Instances — Giảm 70-90% chi phí compute
Spot Instances là capacity dư thừa của cloud provider, bán với giá giảm 70-90% so với On-Demand. Đổi lại, provider có thể thu hồi instance bất kỳ lúc nào với 2 phút cảnh báo trước. Đây là công cụ tiết kiệm mạnh nhất nếu biết cách sử dụng đúng.
graph LR
subgraph SPOT["Spot Instances — Stateless Workloads"]
API["API Servers"]
WORKER["Workers"]
BATCH["Batch Jobs"]
CI["CI/CD Runners"]
end
subgraph OD["On-Demand — Stateful / Critical"]
DB["Databases"]
KAFKA["Message Brokers"]
CTRL["Control Plane"]
MONITOR["Monitoring"]
end
style SPOT fill:#4CAF50,stroke:#fff,color:#fff
style OD fill:#2c3e50,stroke:#fff,color:#fff
style API fill:#f8f9fa,stroke:#4CAF50,color:#333
style WORKER fill:#f8f9fa,stroke:#4CAF50,color:#333
style BATCH fill:#f8f9fa,stroke:#4CAF50,color:#333
style CI fill:#f8f9fa,stroke:#4CAF50,color:#333
style DB fill:#f8f9fa,stroke:#e94560,color:#333
style KAFKA fill:#f8f9fa,stroke:#e94560,color:#333
style CTRL fill:#f8f9fa,stroke:#e94560,color:#333
style MONITOR fill:#f8f9fa,stroke:#e94560,color:#333
Hình 2: Phân loại workload — Spot cho stateless, On-Demand cho stateful/critical
3.1. Chiến lược đa dạng hoá Instance Family
Quy tắc vàng khi dùng Spot: không bỏ hết trứng vào một giỏ. Khi chỉ chọn một instance type (ví dụ m5.xlarge), xác suất bị interruption cao hơn nhiều. Cần diversify qua nhiều instance families và Availability Zones:
# Karpenter NodePool cho Spot workloads
spec:
template:
spec:
requirements:
- key: "karpenter.sh/capacity-type"
operator: In
values: ["spot"]
# Diversify: nhiều family = ít interruption hơn
- key: "karpenter.k8s.aws/instance-category"
operator: In
values: ["c", "m", "r"]
- key: "karpenter.k8s.aws/instance-generation"
operator: Gt
values: ["5"]
# Cho phép cả ARM64 và AMD64
- key: "kubernetes.io/arch"
operator: In
values: ["arm64", "amd64"]
# Topology spread qua nhiều AZ
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
3.2. PriorityClass — Bảo vệ workload quan trọng
Dùng PriorityClass để đảm bảo workload critical luôn chạy trên On-Demand, trong khi batch/CI chấp nhận Spot interruption:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: critical-production
value: 1000000
globalDefault: false
description: "Workloads không thể bị interrupt"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: batch-workload
value: 100
preemptionPolicy: Never
description: "Batch jobs chấp nhận chạy Spot"
---
# Deployment critical → On-Demand
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-service
spec:
template:
spec:
priorityClassName: critical-production
nodeSelector:
karpenter.sh/capacity-type: on-demand
---
# Batch job → Spot
apiVersion: batch/v1
kind: Job
metadata:
name: data-pipeline
spec:
template:
spec:
priorityClassName: batch-workload
tolerations:
- key: "karpenter.sh/capacity-type"
operator: "Equal"
value: "spot"
4. VPA & Right-Sizing — Từ 12% lên 50%+ Utilization
Vertical Pod Autoscaler (VPA) phân tích lịch sử sử dụng CPU/memory của pods và đề xuất hoặc tự động điều chỉnh resource requests. Đây thường là bước mang lại ROI cao nhất — giảm request từ 500m xuống 25m CPU cho một pod đơn lẻ có thể free up hàng chục node.
4.1. Triển khai VPA hai giai đoạn
Giai đoạn 1 — Chỉ quan sát (7+ ngày):
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: api-service-vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: api-service
updatePolicy:
updateMode: "Off" # Chỉ recommend, không tự động thay đổi
Kiểm tra recommendation sau 7 ngày:
kubectl describe vpa api-service-vpa
# Output:
# Recommendation:
# Container Recommendations:
# Container Name: api-service
# Lower Bound: Cpu: 15m, Memory: 128Mi
# Target: Cpu: 25m, Memory: 262Mi ← Đề xuất
# Upper Bound: Cpu: 100m, Memory: 512Mi
# Uncapped Target: Cpu: 25m, Memory: 262Mi
#
# So sánh với request hiện tại: 500m CPU, 1Gi memory
# → Giảm 20x CPU, 4x memory!
Giai đoạn 2 — Tự động điều chỉnh (sau khi validate):
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: api-service-vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: api-service
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: api-service
minAllowed:
cpu: "50m"
memory: "64Mi"
maxAllowed:
cpu: "2"
memory: "2Gi"
Cẩn thận: VPA + HPA conflict
Không nên dùng VPA Auto mode cho cùng metric với HPA. Ví dụ nếu HPA scale theo CPU, thì VPA cũng điều chỉnh CPU requests → xung đột. Giải pháp: dùng VPA cho memory (thường ổn định), HPA cho CPU (thường biến động theo traffic). Hoặc chuyển sang KEDA với event-driven scaling để tránh conflict hoàn toàn.
5. Consolidation — Nghệ thuật bin-packing
Consolidation là quá trình Karpenter gộp pods từ nhiều node vào ít node hơn, sau đó terminate các node trống hoặc kém hiệu quả. Đây là tính năng giúp cluster duy trì utilization cao liên tục, không chỉ khi scale-down.
graph LR
subgraph BEFORE["Trước Consolidation"]
N1["Node 1
20% used"]
N2["Node 2
15% used"]
N3["Node 3
25% used"]
end
subgraph AFTER["Sau Consolidation"]
N4["Node 1
60% used"]
N5["Node 2 — Terminated ✓"]
end
BEFORE -->|"Karpenter
bin-pack"| AFTER
style BEFORE fill:#fff,stroke:#e0e0e0,color:#333
style AFTER fill:#fff,stroke:#e0e0e0,color:#333
style N1 fill:#f8f9fa,stroke:#ff9800,color:#333
style N2 fill:#f8f9fa,stroke:#ff9800,color:#333
style N3 fill:#f8f9fa,stroke:#ff9800,color:#333
style N4 fill:#f8f9fa,stroke:#4CAF50,color:#333
style N5 fill:#f8f9fa,stroke:#e94560,color:#333
Hình 3: Consolidation gộp pods từ 3 node kém hiệu quả thành 1 node tối ưu
5.1. Hai chính sách Consolidation
| Policy | Hành vi | Phù hợp khi |
|---|---|---|
| WhenEmpty | Chỉ terminate node khi không còn pod nào | Workload nhạy cảm với rescheduling |
| WhenEmptyOrUnderutilized | Terminate node trống HOẶC gộp pods khi node kém hiệu quả | Hầu hết production clusters |
# Cấu hình consolidation với protection windows
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 2m # Chờ 2 phút trước khi consolidate
budgets:
# Bình thường: tối đa 20% nodes bị disrupt
- nodes: "20%"
# Peak hours: chặn mọi disruption
- nodes: "0"
schedule: "0 8 * * 1-5" # 8h-9h thứ 2-6
duration: 1h
# Drifted nodes: cho phép nhanh hơn (50%)
- nodes: "50%"
reasons:
- Drifted
6. Case Study: Từ $48K xuống $21.5K/tháng
Một hệ thống e-commerce production với ~200 microservices đã áp dụng toàn bộ chiến lược trên và đạt kết quả:
Trước tối ưu
| Metric | Giá trị |
|---|---|
| Node fleet | 45× m5.2xlarge (8 vCPU, 32GB mỗi node) |
| CPU utilization | 12% |
| Memory utilization | 22% |
| Chi phí/tháng | $48,000 |
Sau tối ưu
| Metric | Giá trị |
|---|---|
| Critical nodes (On-Demand) | 8× r7g.xlarge (Graviton, 4 vCPU, 32GB) |
| Variable nodes (Spot) | 12-35× mixed instances |
| CPU utilization | 48% |
| Memory utilization | 61% |
| Chi phí/tháng | $21,500 |
Chi tiết tiết kiệm
7. Azure AKS: Node Auto-Provisioning (NAP)
Không chỉ AWS, Azure AKS cũng đã tích hợp Karpenter dưới tên Node Auto-Provisioning (NAP) từ cuối 2025. NAP mang đến cùng khả năng intelligent provisioning nhưng tối ưu cho hệ sinh thái Azure:
| Tính năng | AWS EKS + Karpenter | Azure AKS + NAP |
|---|---|---|
| Config format | NodePool + EC2NodeClass | NodePool + AKSNodeClass |
| Spot equivalent | EC2 Spot Instances | Azure Spot VMs |
| ARM equivalent | Graviton (arm64) | Ampere Altra (arm64) |
| Consolidation | WhenEmptyOrUnderutilized | Tương tự (Karpenter core) |
| Savings Plans | AWS Savings Plans / RIs | Azure Reservations |
GKE cũng có tương đương
Google GKE sử dụng GKE Autopilot — một bước xa hơn nữa, nơi Google quản lý toàn bộ node layer. Bạn chỉ cần deploy pods, GKE tự chọn instance type, scale, và consolidate. Tuy nhiên Autopilot ít flexible hơn Karpenter khi cần fine-tuning instance selection hoặc Spot strategies.
8. FinOps & Governance — Duy trì kết quả lâu dài
Tối ưu chi phí không phải việc làm một lần. Nếu không có quy trình FinOps, cluster sẽ "drift" trở lại trạng thái lãng phí trong vài tháng. Một số công cụ governance cần thiết:
8.1. ResourceQuota & LimitRange
# Giới hạn resource cho mỗi team/namespace
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-backend-quota
namespace: team-backend
spec:
hard:
requests.cpu: "20"
requests.memory: "40Gi"
limits.cpu: "40"
limits.memory: "80Gi"
pods: "100"
---
# Default requests cho pods không khai báo
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: team-backend
spec:
limits:
- type: Container
defaultRequest:
cpu: "100m"
memory: "128Mi"
default:
cpu: "500m"
memory: "512Mi"
max:
cpu: "4"
memory: "8Gi"
8.2. Cost Labeling — Visibility theo team
Enforce labeling chuẩn cho mọi resource để phân bổ chi phí chính xác:
# OPA/Gatekeeper ConstraintTemplate bắt buộc labels
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: require-cost-labels
spec:
match:
kinds:
- apiGroups: ["apps"]
kinds: ["Deployment", "StatefulSet"]
parameters:
labels:
- key: "app.kubernetes.io/team"
- key: "app.kubernetes.io/cost-center"
- key: "app.kubernetes.io/environment"
8.3. Orphaned Resources — Dọn dẹp định kỳ
Một CronJob đơn giản scan và alert orphaned resources hàng tuần:
# Tìm PVC không được mount bởi pod nào
kubectl get pvc --all-namespaces -o json | jq -r '
.items[] |
select(.status.phase == "Bound") |
select(.metadata.name as $pvc |
[env.pods[] | select(.spec.volumes[]?.persistentVolumeClaim?.claimName == $pvc)] | length == 0
) |
"\(.metadata.namespace)/\(.metadata.name) - \(.spec.resources.requests.storage)"
'
# Tìm Services type LoadBalancer không có endpoints
kubectl get svc --all-namespaces -o json | jq -r '
.items[] |
select(.spec.type == "LoadBalancer") |
select((.spec.selector | length) == 0 or
(.metadata.annotations["service.beta.kubernetes.io/aws-load-balancer-internal"] == null)) |
"\(.metadata.namespace)/\(.metadata.name)"
'
9. Lộ trình triển khai 4 tuần
10. Kết luận
Tối ưu chi phí Kubernetes không phải "bấm nút giảm giá" — đó là một quy trình kỹ thuật cần đo lường, right-sizing, autoscaling thông minh, và governance liên tục. Ba trụ cột chính:
- Karpenter thay thế Cluster Autoscaler — provisioning nhanh hơn 5x, consolidation tự động, instance selection thông minh.
- Spot Instances + Diversification — giảm 70-90% compute cho stateless workloads với PriorityClass protection.
- VPA Right-Sizing — phát hiện và loại bỏ 80-90% resource requests bị thổi phồng.
Kết quả thực tế cho thấy mức giảm 40-70% chi phí là hoàn toàn khả thi khi áp dụng đúng. Điểm mấu chốt: bắt đầu bằng việc đo lường (metrics-server + VPA Off mode), không phải bằng việc cắt giảm. Bạn không thể tối ưu thứ mình chưa đo được.
Nguồn tham khảo
- Karpenter Documentation — NodePools
- Karpenter Disruption & Consolidation
- Kubernetes Cost Optimization: From $50K to $22K/Month — ZeonEdge
- Kubernetes Cost Optimization 2026: The Complete Guide — CloudMonitor
- Configure Node Auto-Provisioning for AKS — Microsoft Learn
- Cut AWS Costs by 20% with EKS, Karpenter, and Spot — Tinybird
- Kubernetes Autoscaling Explained: HPA, VPA & Best Practices 2026 — Sedai
Pulumi — Infrastructure as Code bằng C# trên .NET 10: Quản lý Cloud như viết phần mềm
DuckDB 2026: Embedded OLAP Database — Khi phân tích dữ liệu không cần server
Disclaimer: The opinions expressed in this blog are solely my own and do not reflect the views or opinions of my employer or any affiliated organizations. The content provided is for informational and educational purposes only and should not be taken as professional advice. While I strive to provide accurate and up-to-date information, I make no warranties or guarantees about the completeness, reliability, or accuracy of the content. Readers are encouraged to verify the information and seek independent advice as needed. I disclaim any liability for decisions or actions taken based on the content of this blog.