Kubernetes 水平 Pod 自动伸缩器 (HPA) 调整的实用指南
Kubernetes 彻底改变了应用程序的部署、管理和扩展方式。其扩展功能的核心是水平 Pod 自动伸缩器 (HPA),这是一个强大的机制,它根据观察到的 CPU 利用率或其他选定的指标自动调整部署、复制控制器、副本集或有状态集中 Pod 副本的数量。虽然 HPA 在处理波动负载方面提供了巨大的好处,但只有通过仔细的配置和调整才能充分释放其潜力。
本指南深入探讨了配置和优化 Kubernetes 水平 Pod 自动伸缩器的实际方面。我们将介绍基本概念、核心参数、高级调整策略和最佳实践,以确保您的应用程序能够有效适应需求,在不同负载下保持性能,并优化基础设施成本。阅读完本文后,您将对如何充分利用 HPA 有扎实的理解。
理解水平 Pod 自动伸缩器 (HPA)
HPA 会自动增加或减少应用程序中的 Pod 数量,以匹配当前需求。它持续监控指定的指标并将其与目标值进行比较。如果观察到的指标超过目标值,HPA 会启动扩容事件;如果低于目标值,它会触发缩容。这种动态调整确保您的应用程序有足够的资源以最佳性能运行,而不会过度配置。
HPA 可以基于以下指标进行扩展:
- 资源指标 (Resource Metrics):主要是 CPU 利用率和内存利用率(可通过
metrics.k8s.ioAPI 获得,通常由 Kubernetes Metrics Server 提供)。 - 自定义指标 (Custom Metrics):通过
custom.metrics.k8s.ioAPI 暴露的特定于应用程序的指标(例如,每秒请求数、队列深度、活动连接数)。这通常需要一个适配器,如prometheus-adapter。 - 外部指标 (External Metrics):来自集群外部源的指标,通过
external.metrics.k8s.ioAPI 暴露(例如,Google Cloud Pub/Sub 队列大小、AWS SQS 队列长度)。这也需要一个能够获取外部指标的自定义指标 API 服务器。
有效 HPA 调整的先决条件
在深入研究 HPA 配置之前,请确保已具备以下基本要素:
1. 定义准确的资源请求和限制
这可能是最关键的先决条件。 HPA 严重依赖于正确定义的 CPU 和内存 请求 来计算利用率百分比。如果 Pod 没有定义 CPU 请求,HPA 将无法计算其 CPU 利用率,从而使基于 CPU 的扩展变得不可能。
- 请求 (Requests):定义容器的最低保证资源。HPA 使用这些值来确定 每个 Pod 的目标利用率。
- 限制 (Limits):定义容器可以消耗的最大资源。限制可防止单个 Pod 消耗过多资源并影响同一节点上的其他 Pod。
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-image:latest
resources:
requests:
cpu: "200m" # 1 个 CPU 核心的 20%
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
2. 安装 Kubernetes Metrics Server
要使 HPA 使用 CPU 和内存利用率指标,必须在集群中安装 Kubernetes Metrics Server。它从 Kubelet 收集资源指标,并通过 metrics.k8s.io API 暴露这些指标。
3. 应用程序可观测性
对于自定义或外部指标,您的应用程序必须暴露相关的指标(例如,通过 Prometheus 端点),并且您需要一种方法来收集这些指标并通过 Kubernetes API 暴露它们,通常是使用 Prometheus 适配器或自定义指标 API 服务器。
配置 HPA:核心参数
我们来看一下 HPA 清单的基本结构:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
关键参数:
scaleTargetRef:定义 HPA 将要扩展的目标资源(例如,Deployment)。指定其apiVersion、kind和name。minReplicas:HPA 缩容到的最小 Pod 数量。在零负载下,出于高可用性考虑,最好将其设置为至少 1 或 2。maxReplicas:HPA 扩展到的最大 Pod 数量。这可以作为防止失控扩展和限制成本的安全网。metrics:一个数组,定义 HPA 应监控的指标。type:可以是Resource、Pods、Object或External。resource.name:对于Resource类型,指定cpu或memory。target.type:对于Resource类型,可以是Utilization(请求资源的百分比)或AverageValue(绝对值)。averageUtilization:对于Utilization类型,是目标百分比。HPA 根据current_utilization / target_utilization * current_pods_count计算所需的 Pod 数量。
调整 HPA 以实现响应速度和稳定性
除了基本配置之外,HPA 还提供了高级调整选项,尤其是在 autoscaling/v2(或旧版本中的 v2beta2)中,可以更精细地管理扩展行为。
1. CPU 和内存目标 (averageUtilization / averageValue)
设置正确的利用率目标至关重要。较低的目标意味着更早扩展(响应更快,成本可能更高),而较高的目标意味着更晚扩展(响应较慢,成本可能更低,但有性能下降的风险)。
- 如何确定最佳目标:负载测试和性能分析是您最好的朋友。逐渐增加应用程序的负载,同时监控资源使用情况和性能指标(延迟、错误率)。确定应用程序开始性能下降时的 CPU/内存利用率。将 HPA 目标设置在此阈值以下,CPU 通常在 60-80% 范围内。
- 平衡行为:目标应留出足够的余量以应对意外的峰值,但又不能低到导致持续过度配置。
2. 扩展行为 (behavior 字段)
behavior 字段在 HPA autoscaling/v2 中引入,提供了对扩容和缩容事件的细粒度控制,防止“抖动”(快速的扩容和缩容循环)。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleUp:
stabilizationWindowSeconds: 60 # 再次扩展前等待 60 秒
policies:
- type: Pods
value: 4
periodSeconds: 15 # 每 15 秒最多添加 4 个 Pod
- type: Percent
value: 100
periodSeconds: 15 # 或者每 15 秒使当前 Pod 数量翻倍(以限制较宽松者为准)
scaleDown:
stabilizationWindowSeconds: 300 # 缩容前等待 5 分钟
policies:
- type: Percent
value: 50
periodSeconds: 60 # 每 60 秒最多移除 50% 的 Pod
selectPolicy: Max # 选择允许“最激进”(最少数量)Pod 的策略
scaleUp 配置:
stabilizationWindowSeconds:这可以防止快速的扩容和缩容循环(抖动)。HPA 在考虑扩容时会考虑此窗口中的指标,确保只有在高指标持续存在时才进行扩展。典型值是 30-60 秒。policies:定义在扩容事件中如何添加 Pod。您可以定义多个策略,HPA 将使用允许最多 Pod 数量的策略(最激进的扩容)。type: Pods:按固定数量的 Pod 进行扩展。value指定要添加的 Pod 数量。periodSeconds定义此策略适用的时间窗口。type: Percent:按当前 Pod 数量的百分比进行扩展。value是百分比。
scaleDown 配置:
stabilizationWindowSeconds:对scaleDown更关键,它指定 HPA 在考虑缩容之前必须观察指标低于目标值多长时间。较长的窗口(例如 300-600 秒)可防止在暂时低迷时过早缩容,从而避免“冷启动”和性能下降。这是稳定环境中的一个关键设置。policies:与scaleUp类似,定义如何移除 Pod。如果selectPolicy是Min,HPA 使用导致 最少 Pod 数量的策略(最保守的缩容);如果selectPolicy是Max,则使用导致 最多 Pod 数量的策略。type: Pods:移除固定数量的 Pod。type: Percent:移除当前 Pod 的百分比。
-
selectPolicy:当定义多个scaleDown策略时,确定应用哪个策略。Min是默认设置,通常推荐用于更保守的缩容;Max将选择导致最多 Pod 数量的策略(最不激进的缩容)。 -
警告:要谨慎使用激进的
scaleDown策略或较短的scaleDownstabilizationWindowSeconds。如果您的应用程序初始化时间较长或处理有状态连接,快速缩容可能会导致服务中断或用户延迟增加。
高级 HPA 指标和策略
虽然 CPU 和内存很常见,但许多应用程序在基于反映其实际工作负载的自定义或外部指标上扩展效果更好。
1. 自定义指标
当 CPU/内存不能直接指示应用程序负载或性能瓶颈时,请使用自定义指标。示例:每秒 HTTP 请求数 (QPS)、活动连接数、消息队列长度、批处理作业积压。
使用自定义指标的方法:
1. 您的应用程序必须暴露这些指标(例如,通过 Prometheus 导出器)。
2. 部署一个自定义指标适配器(例如 prometheus-adapter),它可以抓取这些指标并通过 custom.metrics.k8s.io API 暴露它们。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa-qps
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 15
metrics:
- type: Pods # 如果指标是针对整个部署,则使用 Object
pods:
metric:
name: http_requests_per_second # 应用程序/适配器暴露的指标名称
target:
type: AverageValue
averageValue: "10k" # 目标是每个 Pod 每秒 10,000 个请求
2. 外部指标
当应用程序的工作负载由不在 Kubernetes 上直接运行的外部系统驱动时,外部指标非常有用。示例:AWS SQS 队列深度、Kafka 主题延迟、Pub/Sub 订阅积压。
使用外部指标的方法:
1. 您需要一个自定义指标 API 服务器,该服务器可以从您的外部系统(例如,AWS CloudWatch 或 GCP Monitoring 的特定适配器)获取指标。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-worker-hpa-sqs
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-worker
minReplicas: 1
maxReplicas: 20
metrics:
- type: External
external:
metric:
name: aws_sqs_queue_messages_visible # 来自外部源的指标名称
selector:
matchLabels:
queue: my-queue-name
target:
type: AverageValue
averageValue: "100" # 目标是每个 Pod 对应队列中可见 100 条消息
3. 多个指标
HPA 可以配置为同时监控多个指标。指定多个指标时,HPA 会分别为每个指标计算所需的副本数,然后选择这些所需副本数中的最大值。这确保了应用程序能够充分扩展以应对所有观察到的负载维度。
# ... (HPA 样板代码)
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "10k"
监控和验证
有效的 HPA 调整是一个迭代过程,需要持续的监控和验证:
- 观察 HPA 事件:使用
kubectl describe hpa <hpa-name>查看 HPA 的状态、事件和扩展决策。这提供了关于 HPA 何时扩展或缩容的有价值的见解。 - 监控指标和副本数:使用您的可观测性堆栈(例如,Prometheus、Grafana)可视化应用程序的资源使用情况(CPU、内存)、自定义/外部指标以及随时间变化的实际 Pod 副本数量。将这些与传入负载的变化相关联。
- 负载测试:模拟预期负载和峰值负载,以验证 HPA 的响应速度,并确保您的应用程序在压力下表现符合预期。根据这些测试调整 HPA 参数。
HPA 调整的最佳实践
- 从定义明确的资源请求/限制开始:它们是准确的基于资源的 HPA 的基础。没有它们,HPA 在 CPU/内存方面无法有效运行。
- 设置合理的
minReplicas和maxReplicas:minReplicas提供可用性的基线,而maxReplicas可作为防止失控成本和资源耗尽的安全网。 - 逐步调整目标利用率:从稍微保守的 CPU 目标(例如 60-70%)开始并迭代。不要以 100% 利用率为目标,因为它没有为延迟或处理尖峰留出缓冲空间。
- 利用
stabilizationWindowSeconds:这对于防止快速的扩展振荡至关重要。为scaleDown使用较长的窗口(例如 5-10 分钟),为scaleUp使用较短的窗口(例如 1-2 分钟),以确保稳定性。 - 优先考虑特定于应用程序的指标:如果 CPU 或内存不能直接与应用程序的性能瓶颈相关,请使用自定义或外部指标来实现更准确、更高效的扩展。
- 监控、测试、迭代:HPA 调整不是一次性设置。应用程序行为、流量模式和底层基础架构都会发生变化。定期审查 HPA 性能并根据需要调整设置。
- 了解应用程序的扩展特性:它是线性扩展还是请求相关?它是否有较长的启动时间?它是无状态的吗?这些特性会影响您的 HPA 策略。
结论
Kubernetes 水平 Pod 自动伸缩器是构建在 Kubernetes 环境中具有弹性、成本效益和高性能应用程序的关键组件。通过了解其核心机制、定义准确的资源请求以及仔细调整其扩展行为参数,您可以确保应用程序能够精确地自动适应不断变化的负载。
有效的 HPA 调整是一个持续的测量、观察和调整的过程。拥抱迭代过程,在适当的情况下利用高级指标,并持续监控应用程序的性能,以充分释放 Kubernetes 动态扩展的全部潜力。