Kubernetes 成本优化完全指南

平均浪费率
40-60%
K8s 资源请求
VPA 节省
20-40%
Pod 资源
Spot 节点
60-91%
vs On-Demand
监控工具
Kubecost
免费+开源

$ kubectl top pods --sort-by=memory

Kubernetes 是当今最流行的容器编排平台,但如果你在 AWS EKS、GKE 或 Azure AKS 上运行 Kubernetes,你可能会惊讶地发现:平均有 40-60% 的计算资源被浪费了。今天我们就来聊聊如何优化 Kubernetes 的云成本。

Kubernetes 成本浪费的根源

1. Resource Request/Limit 设置不合理

开发者通常为了"保险"而请求过多资源:

resources:
  requests:
    cpu: "2"        # 实际只需要 0.2
    memory: "4Gi"   # 实际只需要 512Mi
  limits:
    cpu: "4"
    memory: "8Gi"

结果:每个 Pod 占用大量调度空间,但实际利用率极低。

2. 过度配置节点

为了应对突发流量,节点规格通常选得过大:

3. 缺乏自动伸缩

优化策略一:正确的 Resource 设置

使用 VPA(Vertical Pod Autoscaler)

VPA 可以自动分析 Pod 历史资源使用,并推荐或自动调整请求值:

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: my-app-vpa
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: my-app
  updatePolicy:
    updateMode: "Auto"
VPA 有三种模式:Off(仅推荐)、Initial(仅初始设置)、Auto(自动更新)。建议先使用 Off 模式收集数据,再切换到 Auto。

基于历史数据设置 Request

用 Prometheus + 监控工具分析真实使用量:

# Prometheus 查询 99 分位数 CPU 使用率
quantile_over_time(0.99,
  rate(container_cpu_usage_seconds_total{container!=""}[5m])[14d]
)

优化策略二:多实例类型和 Spot 节点池

EKS 节点组配置

# eksctl 创建 Spot 节点组
eksctl create nodegroup \
  --cluster=my-cluster \
  --name=spot-ng \
  --node-type=m5.large \
  --nodes=10 \
  --node-spot-enabled \
  --spot-fleet-enabled

Karpenter(动态节点管理)

Karpenter 是 AWS 原生的 K8s 节点管理工具:

apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: default
spec:
  requirements:
    - key: node.kubernetes.io/instance-type
      operator: In
      values: [m5.large, m5.xlarge, c5.large]
    - key: topology.kubernetes.io/zone
      operator: In
      values: [us-east-1a, us-east-1b]
  limits:
    resources:
      cpu: "100"
  provider:
    instanceProfile: KarpenterNodeRole
    spotPool:
      strategy: lowest-price
      poolSize: 3

优化策略三:Namespace 配额和 LimitRange

设置 ResourceQuota

apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota
spec:
  hard:
    requests.cpu: "40"
    requests.memory: 100Gi
    limits.cpu: "80"
    limits.memory: 200Gi
    pods: "50"

设置 LimitRange(默认值)

apiVersion: v1
kind: LimitRange
metadata:
  name: limits
spec:
  limits:
  - default:
      cpu: 500m
      memory: 256Mi
    defaultRequest:
      cpu: 100m
      memory: 128Mi
    type: Container

优化策略四:KEDA 实现事件驱动伸缩

KEDA(Kubernetes Event-driven Autoscaling)可以根据外部指标伸缩:

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: my-scaler
spec:
  scaleTargetRef:
    name: my-deployment
  minReplicaCount: 1
  maxReplicaCount: 10
  triggers:
  - type: prometheus
    metadata:
      serverAddress: http://prometheus:9090
      metricName: http_requests
      threshold: "100"

监控工具:Kubecost

Kubecost 是 Kubernetes 原生的成本监控工具:

# Helm 安装 Kubecost
helm install kubecost kubecost/cost-analyzer \
  --namespace kubecost \
  --set kubecostToken="xxxxx" \
  --set prometheus.enabled=true

最佳实践总结

Kubernetes 成本优化不是一次性的工作,而是需要持续监控和迭代改进的过程。

$ share --net https://981263.xyz/S-003-Kubernetes-Cost-Optimization.html

Practical review before using this page

The S 003 Kubernetes Cost Optimization resource should be read together with the rest of Cloud Cost Optimization Dashboard, not as an isolated shortcut. Before acting on the page, write down the current baseline, the assumption you are making, and the result you expect to see. This makes the page more useful for comparison and reduces the chance of changing several variables at once.

For FinOps planning, cloud cost allocation, rightsizing, tagging governance, and monthly cost review, a good review habit is to separate stable facts from estimates. Stable facts might include dates, page URLs, account names, measured values, or the exact checklist items you completed. Estimates should be labeled as estimates and revisited later. If the result affects money, health, safety, compliance, or operational risk, use the page as preparation for a more careful review rather than as the final authority.

Common mistakes to avoid

Use this page as a planning reference before changing cloud accounts. Confirm pricing, contracts, and technical limits in the relevant provider console because cloud terms can change.