优化Kubernetes集群性能的最佳实践
通过合理资源分配、自动扩缩容、高效网络、存储选择和持续可观测性来优化Kubernetes性能。
优化Kubernetes集群性能的最佳实践
Kubernetes集群性能问题通常表现为滚动更新缓慢、Pod挂起、资源争抢或意外的云账单。修复方案很少是单一的魔法设置;你需要准确的资源规格、匹配需求的扩缩容规则,以及足够的可观测性来发现压力源头。
使用这份清单来调整集群,无需猜测。
从请求和限制开始
调度器使用CPU和内存的requests来决定Pod的放置位置。如果请求值过低,节点看起来比实际更空闲,工作负载会争夺资源。如果请求值过高,调度器会浪费容量,Pod可能保持挂起状态。
根据实际使用数据设置请求值。例如,如果一个API容器在正常流量下使用约300毫核,在部署预热期间峰值接近700毫核,你可以从以下配置开始:
resources:
requests:
cpu: "300m"
memory: "512Mi"
limits:
memory: "1Gi"
注意CPU限制。严格的CPU限制可能会限制延迟敏感的服务,即使节点有空闲CPU。内存限制仍然有用,因为超过内存限制的容器可能会被杀死,避免整个节点进入内存压力状态。
使用清晰的信号进行自动扩缩容
当你的指标跟踪用户需求时,水平Pod自动扩缩容效果良好。对于简单的无状态服务,CPU可能足够,但队列深度、请求速率或自定义应用指标通常是更好的扩缩容信号。
kubectl autoscale deployment api \
--cpu-percent=70 \
--min=3 \
--max=20
集群自动扩缩容、Karpenter或云提供商的节点自动扩缩容层应有足够的空间在Pod长时间挂起前添加节点。检查节点组是否覆盖了工作负载所需的实例大小、区域、GPU要求或污点。
保持调度可预测
当关键Pod落在过载或不合适的节点上时,性能会下降。对高流量服务使用拓扑分布约束,对硬件特定工作负载使用节点亲和性,对只应运行特定类型Pod的节点使用污点。
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: api
这可以防止副本在集群有更好放置选项时堆积到一个节点上。
在真正有问题的环节调整网络
大多数集群不需要奇特的网络调整。从找到慢路径开始:DNS查找时间、服务网格开销、跨区域流量、过载的入口或Pod到数据库的延迟。
有用的检查包括:
kubectl top pods -A
kubectl get endpointslices -A
kubectl describe ingress <name>
kubectl logs -n kube-system -l k8s-app=kube-dns
对于通信频繁的服务,将Pod及其主要依赖项保持在同一个区域,如果可能的话,同一个可用区。如果你使用服务网格,在广泛部署网格更改之前,先测量一个工作负载在有无sidecar注入时的p95和p99延迟。
根据工作负载匹配存储
存储选择可能对数据库、队列和CI工作负载的性能起主导作用。根据延迟、IOPS、吞吐量和故障行为选择卷,而不仅仅是容量。
例如,PostgreSQL Pod需要具有可预测延迟和清晰备份行为的持久卷类。构建缓存可能更关心吞吐量,并且可以容忍重建。无状态Web服务应完全避免持久卷,除非有真正的原因。
注意这些症状:
- Pod因卷挂载缓慢而卡在
ContainerCreating状态。 - 应用延迟上升而CPU保持正常。
- 节点磁盘压力导致Pod被驱逐。
- StatefulSet因卷绑定到单个区域而阻塞。
在更改前观察集群
没有基线指标的优化只是无意义的变动。至少跟踪CPU、内存、重启次数、挂起Pod、节点压力条件、API服务器延迟和工作负载p95延迟。
kubectl get nodes
kubectl describe node <node-name>
kubectl get pods -A --field-selector=status.phase=Pending
kubectl top nodes
如果你运行Prometheus,添加对持续节点压力、高重启率、HPA达到最大副本数以及关键Deployment上不可用副本的警报。
要点
从工作负载出发优化Kubernetes。合理设置请求值,避免不必要的CPU限制,根据需求信号进行扩缩容,保持副本分散,选择适合工作负载的存储。然后在每次更改后进行测量,以便知道集群是变得更快、更便宜,还是仅仅不同。