在 Kubernetes 集群真正投入生产之后,绝大多数运维团队最先遇到的问题并不是”功能用不起来”,而是”性能不够用”和”成本下不来”。CPU 被申请了一大堆却长期闲置、内存申请远超实际需求、节点利用率长期停留在 20% 以下——这些都是 Kubernetes 性能调优中最典型的痛点。本篇将从节点层、Pod 层、调度层和集群层四个维度,系统讲解一套可落地的 Kubernetes 性能优化方法论,帮助你把集群资源利用率提升到合理水平,同时保证业务稳定性。

一、为什么 Kubernetes 需要专项性能调优
Kubernetes 的性能瓶颈,绝大多数不是硬件本身不够强,而是资源请求(Request)与资源限制(Limit)设置不合理造成的。
在 Kubernetes 调度模型中,Pod 的调度依据是 request,而不是实际用量。如果每个 Pod 的 request 都设得很大,调度器就会认为节点资源不足,于是把 Pod 分散到很多节点上。结果就是:大量节点被”占位”,但实际 CPU 和内存使用率很低,整体利用率严重浪费。反之,如果 request 设置过小,Pod 会被过度打包到少数节点,一旦业务流量突增,就会出现节点资源争抢、OOM Kill 甚至 Pod 驱逐。
因此,Kubernetes 性能调优的核心目标只有一个:让 request 尽量贴近实际用量,让 Limit 为突发留出安全边界,再配合弹性伸缩与调度策略让资源动态流动。
二、性能调优的整体框架
一套完整的 Kubernetes 性能优化方案通常包含四个层次:
- 应用层调优:Profile 应用本身,减少不必要的 CPU、内存、IO 消耗。
- 资源声明层调优:合理设置 requests/limits,启用资源度量工具。
- 调度层调优:通过污点容忍、亲和性、拓扑分布等控制 Pod 分布。
- 集群层调优:节点池分层、HPA/Cluster Autoscaler、组件参数调优。
下面逐层展开,并给出对应的命令与配置示例。
三、第一步:测量应用的真实资源消耗
优化的前提是测量。没有真实数据就调 requests,等于凭感觉猜。推荐使用 VPA(Vertical Pod Autoscaler)在测试环境里跑一段时间,让 VPA 统计出推荐值,再把这个推荐值作为生产 requests 的参考。
3.1 查看当前资源声明
# 列出所有 Pod 的资源请求与限制
kubectl get pods -A -o custom-columns=
NAMESPACE:.metadata.namespace,
NAME:.metadata.name,
REQ_CPU:.spec.containers[*].resources.requests.cpu,
REQ_MEM:.spec.containers[*].resources.requests.memory,
LIM_CPU:.spec.containers[*].resources.limits.cpu,
LIM_MEM:.spec.containers[*].resources.limits.memory
3.2 统计集群资源水位
# 节点整体用量(含实际与请求)
kubectl top nodes
# 全集群 Pod 用量,按内存排序
kubectl top pods -A --sort-by=memory
注意:
kubectl top依赖 Metrics Server,需先确认其已部署:kubectl -n kube-system get ds metrics-server。
3.3 用 VPA 生成推荐值
# vpa-recommender.yaml:仅推荐,不自动调整(模式 Off)
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: vpa-web
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: web
updatePolicy:
updateMode: "Off" # 只推荐不动手,先观察一段时间
# 查看 VPA 给出的推荐值
kubectl get vpa vpa-web -o yaml
# 关注 status.recommendation.containers[].target 与 .lowerBound
VPA 给出的 target 是过去一段时间实际用量的统计值,是设置 requests 的最佳起点。建议将 requests 设为 target 的 1.1~1.3 倍,为偶发峰值留出余量。
四、第二步:设置合理的 Requests 与 Limits
4.1 Requests 与 Limits 的原则差异
- Requests 影响调度与配额,应贴近实际中位数用量。
- Limits 影响运行时保护,CPU limit 建议设为 requests 的 2~4 倍;内存 limit 建议略高于 requests,避免 OOM。
4.2 生产推荐配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
spec:
replicas: 6
template:
spec:
containers:
- name: app
image: api:1.8.0
resources:
requests:
cpu: "250m" # VPA 推荐值附近
memory: "512Mi"
limits:
cpu: "1" # 突发可到 1 核
memory: "768Mi" # 留 256Mi 缓冲,防 OOM
terminationGracePeriodSeconds: 30
4.3 启用 LimitRange 兜底
对没有显式声明资源的 Pod,LimitRange 会自动补默认值,避免”裸奔” Pod 拖垮节点:
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
spec:
limits:
- defaultRequest:
cpu: "100m"
memory: "128Mi"
default:
cpu: "500m"
memory: "512Mi"
type: Container
4.4 用 ResourceQuota 控制命名空间总量
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-quota
namespace: team-a
spec:
hard:
requests.cpu: "20"
requests.memory: 40Gi
limits.cpu: "50"
limits.memory: 80Gi
pods: "200"
ResourceQuota 结合 LimitRange,可以让资源在集群内有序分配,防止单一业务吃光节点。
五、第三步:调度层优化,控制 Pod 分布
资源声明合理后,还需要让调度器把 Pod 摆到合适的位置。核心手段是亲和性与拓扑分布约束。
5.1 拓扑分布约束(避免单点)
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: api-server
该配置能让 6 个副本尽量均匀分散到不同节点,单节点宕机时最多只损失 1 个副本,是高可用的关键保障。
5.2 污点与容忍度隔离特殊节点
# 给高性能节点打污点,只允许特定 Pod 调度
kubectl taint nodes high-perf-01 dedicated=true:NoSchedule
spec:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "true"
effect: "NoSchedule"
5.3 节点分层(Node Pool)
生产集群应把节点按用途分层:
| 节点池 | 用途 | 特征 |
|---|---|---|
| 通用计算池 | 普通微服务 | 标准机型,可弹性伸缩 |
| 高内存池 | 大数据、缓存 | 大内存机型,打污点隔离 |
| GPU 池 | AI 推理 | 配 NVIDIA 驱动,专用调度 |
| 系统节点池 | 有状态组件 | 静态 PV,禁止驱逐 |
通过污点与亲和性,把不同 workload 引导到对应节点池,性能与隔离性都会更好。
六、第四步:弹性伸缩与集群层调优
静态优化只能解决”平均情况”,业务波峰波谷需要弹性能力补齐。
6.1 HPA 自动伸缩副本数
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-server
minReplicas: 3
maxReplicas: 30
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 65
建议同时配置基于 QPS 或自定义指标(pod 内暴露的自定义 metric)的 HPA,CPU 利用率的响应存在 1~2 分钟的滞后。
6.2 Cluster Autoscaler 自动扩缩节点
HPA 只是增加 Pod,真正扩容节点要靠 Cluster Autoscaler。它根据 Pending Pod 自动申请新节点:
# 查看当前各节点池容量与可扩容空间
kubectl describe cluster-autoscaler --namespace kube-system
关键经验:给节点池配置合理的 min/max size,并为有状态工作负载准备独立的、不参与自动缩容的节点池,避免自动缩容误删运行数据库的节点。
6.3 关键组件参数调优
控制平面在高规模集群下也会成为瓶颈,常见调优项:
# 查看 etcd 集群健康度(性能基线)
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379
endpoint health
# 查看 etcd 的 leader 与延迟
ETCDCTL_API=3 etcdctl endpoint status -w table
etcd 的 db size、leader changes、apply latency 是判断集群是否过载的核心指标。当 etcd 压力上升时,应优先减少 Watch 数量、降低 Ingress Controller 的同步频率,而不是盲目扩容 etcd 数据节点。
七、性能调优常见问题
问题 1:Pod 频繁 OOMKilled 怎么办?
先看 kubectl describe pod 里的 Last State,确认是内存超限。若 limit 设置过低,适当上调;若是内存泄漏,需在应用层修复。生产环境建议把内存 limit 设为 requests 的 1.2~1.5 倍,并开启 PodDisruptionBudget 防止抖动。
问题 2:为什么 Pod 一直 Pending?
Pending 通常意味着请求资源找不到匹配节点。用 kubectl describe pod 查看 Events,常见原因有三:CPU/内存 request 过大导致无节点可调度、污点没有对应容忍度、PVC 未绑定。用 kubectl describe nodes 核对节点剩余可调度容量。
问题 3:requests 与 limits 应该设一样吗?
不应相等。request 决定调度,limit 决定保护。相等会导致突发流量时 Pod 立即被 CPU Throttling 限制,延迟飙升。推荐 CPU limit 显著大于 request,内存 limit 适度大于 request。
问题 4:CPU Throttling 如何检测与缓解?
通过 cAdvisor 暴露的 container_cpu_cfs_throttled_periods_total 指标判断。若长期被节流,说明 CPU limit 过低,需上调 limit 或减少单 Pod 并发。
八、总结
Kubernetes 性能调优不是单点魔法,而是一套完整的度量—声明—调度—弹性体系。核心行动顺序是:
- 用 VPA 和 metrics 度量真实用量,拒绝凭感觉设置资源;
- requests 贴近实际、limits 留出缓冲,配合 LimitRange 与 ResourceQuota 兜底;
- 用拓扑分布与污点亲和把 Pod 摆到正确的节点,做好隔离与高可用;
- 用 HPA + Cluster Autoscaler 让集群随业务自动伸缩,节点池分层管理;
- 关注 etcd 与控制平面健康,避免底层成为隐性瓶颈。
把这套方法论应用到生产后,大多数集群都能把平均资源利用率从 20% 提升到 50% 以上,同时业务稳定性不下降——这才是性能调优的真正价值。
下期预告
第 25 天,我们将进入「故障排查」专题,系统讲解常见 Kubernetes 集群故障的定位方法与处理流程,包括 Pod 无法启动、节点异常、网络不通、控制平面故障等实战场景,帮你建立一套标准化的故障定位思维。


















暂无评论内容