在Kubernetes整个体系中,弹性伸缩是至关重要的功能,其分为两种:水平弹性伸缩(Horizontal Pod Autoscaling,简称HPA)和垂直弹性伸缩(Vertical Pod Autoscaler,简称VPA)。HPA可以根据观察到的资源实际使用情况(如CPU/内存)或其它自定义指标负载自动调整Pod副本数,VPA可以根据资源实际使用情况为其Pod中的容器设置最新的资源配额requests。这两者合理使用既可以满足业务对实例数的要求保证系统稳定性,同时又能充分提升集群资源的利用率。
一、HPA 原理
HPA (Horizontal Pod Autoscaler) 的核心原理可以概括为:定期查询监控指标,然后根据其目标值(Target Value) 和当前值(Current Value),通过特定的算法计算出所需的 Pod 副本数量,自动控制 Deployment、StatefulSet 等资源的副本数量,以使应用的平均资源利用率(如 CPU、内存)维持在你设定的目标值。
下面是图中涉及的核心组件及其作用的文字说明:
HPA Controller:HPA 的“决策大脑”,是
kube-controller-manager的一部分。它负责[定期循环](默认每隔 15秒)通过 API Server 查询其管理的所有 HPA 对象及其对应的监控指标,并根据指标数据计算是否需要扩缩容以及需要多少个 Pod 副本。API Server:Kubernetes 的“信息枢纽”。HPA Controller 通过它查询 HPA 配置、获取监控指标,也是通过它来更新工作负载的副本数量。
Metrics API:指标数据的标准化接口。HPA Controller 只通过统一的 Metrics API 来获取指标数据,而不关心数据的具体来源。这层抽象使得 HPA 可以灵活地使用不同种类的指标。
resource.metrics.k8s.io:提供资源指标,如 Pod 的 CPU 和内存使用率,通常由 Metrics Server 实现。custom.metrics.k8s.io:提供自定义指标,这些指标通常与特定应用或 Kubernetes 对象(如 Pod 的 QPS)相关。常用 Prometheus Adapter 来从 Prometheus 中获取并暴露这些指标。external.metrics.k8s.io:提供外部指标,这些指标完全来自于 Kubernetes 集群之外的系统,如消息队列的长度、云服务的监控指标等。Metrics Server:一个集群范围内的资源使用数据聚合器。它从每个节点上的 kubelet 收集核心资源指标(如 CPU 和内存),并通过
resource.metrics.k8s.ioAPI 暴露它们,供 HPA 等组件使用。Prometheus + Prometheus Adapter:一个常见的自定义指标方案。Prometheus 负责采集和存储丰富的监控数据。Prometheus Adapter 则作为一个桥梁,查询 Prometheus 中的数据,并将其转换为 Kubernetes 能够理解的格式,通过
custom.metrics.k8s.ioAPI 暴露给 HPA Controller。
HPA 的工作流程是一个持续的控制循环,上图的数字编号也大致对应了这些步骤:
查询 HPA 配置:HPA Controller 定期(默认 15s,可通过
--horizontal-pod-autoscaler-sync-period参数调整)通过 API Server 查询所有 HPA 对象的配置定义,包括目标工作负载、目标指标类型及其目标值、最小/最大副本数等。获取监控指标:对于每个 HPA,Controller 通过对应的 Metrics API(资源、自定义或外部)来获取当前的监控指标值。
源指标(如 CPU、内存)由 Metrics Server 提供。Metrics Server 通过 Kubelet 从每个节点的 cAdvisor 中采集所有 Pod 的资源使用数据,并聚合到集群层面。
metrics.k8s.io: 主要提供Pod和Node的CPU和Memory相关的监控指标。
custom.metrics.k8s.io: 主要提供Kubernetes Object相关的自定义监控指标。
external.metrics.k8s.io:指标来源外部,与任何的Kubernetes资源的指标无关。
自定义指标(如 QPS、应用内部指标)由 Kubernetes Custom Metrics API 提供,这通常需要安装像 Prometheus Adapter 这样的组件来将 Prometheus 等监控系统的指标转换为 Kubernetes API 可以理解的格式。
计算所需副本数:Controller 使用获取到的当前指标值和 HPA 中定义的目标指标值,通过算法计算出期望的 Pod 副本数量。
计算公式:
期望副本数 = ceil[当前副本数 * (当前指标值 / 目标指标值)]。例如,当前有 2 个 Pod,CPU 使用率为 80%,HPA 目标 CPU 使用率为 40%,则期望副本数 = ceil[2 * (80 / 40)] = ceil[4] = 4。HPA 会考虑多种指标(选择计算结果中最大的副本数)并内置了容忍度(默认 0.1,即比率变化不超过 10% 则忽略)和冷却窗口等机制来防止副本数抖动
调整副本数:如果计算出的期望副本数与当前副本数不同,HPA Controller 会通过 API Server更新目标工作负载(如 Deployment)的
replicas字段,为了避免副本数量因指标瞬时波动而剧烈变化(“抖动”),HPA 引入了冷却机制。扩容:如果计算出的
期望副本数>当前副本数,HPA 就会增加副本数。扩容冷却 (默认 3 分钟):扩容操作没有全局等待期,但快速连续扩容时,每次扩容后等待时间会逐渐增加。
缩容:如果计算出的
期望副本数<当前副本数,HPA 就会减少副本数。缩容冷却 (
--horizontal-pod-autoscaler-downscale-stabilization,默认 5 分钟):在一次缩容操作后,会等待一段时间(默认5分钟),再执行下一次缩容操作。工作负载控制器响应:相应的工作负载控制器(如 Deployment Controller)检测到
replicas字段变化,会开始创建或删除 Pod,以使实际运行的 Pod 数量等于期望值。调度新 Pod:新创建的 Pod 会被 Scheduler 调度到合适的节点上运行。如果节点资源不足,这些 Pod 会处于 Pending 状态。
节点扩缩容(可选):如果集群中使用了 Cluster Autoscaler (CA),它会检测到因资源不足而无法调度的 Pod(Pending状态),然后自动扩容集群节点来提供更多资源。Pod 被成功调度和运行后,才能开始处理业务流量,此时指标数据也会随之变化,HPA 的下一个循环周期又会开始。
在实际应用中,基于原生HPA系统架构实现适配业务自定义特性的整体设计架构如下:
二、基于 CPU 和内存的最佳实践示例
前提条件
安装 Metrics Server:
HPA 需要 Metrics Server 来获取 CPU/内存指标。
安装命令(对于大多数集群):
验证安装:
kubectl top nodes为 Pod 设置资源请求:
这是最关键的一步! HPA 计算使用率的公式是:
(Pod 当前实际使用量 / Pod 的资源请求值) * 100%。如果 Pod 没有设置
spec.containers[].resources.requests,HPA 将无法进行有意义的计算。
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
示例:为 Nginx Deployment 配置同时基于 CPU 和内存的 HPA
1. 创建 Deployment (nginx-deployment.yaml)
这个 Deployment 明确设置了 CPU 和内存的 requests。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 # 初始副本数 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.25 ports: - containerPort: 80 resources: requests: cpu: "250m" # 每个 Pod 请求 0.25 核 CPU memory: "256Mi" # 每个 Pod 请求 256MiB 内存 limits: cpu: "500m" memory: "512Mi"
应用它:kubectl apply -f nginx-deployment.yaml
2. 创建 HPA (nginx-hpa.yaml)
我们使用 autoscaling/v2 API,它支持多指标和更丰富的配置。
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: nginx-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: nginx-deployment minReplicas: 2 # 最小副本数 maxReplicas: 10 # 最大副本数 metrics: - type: Resource resource: name: cpu target: type: Utilization # 目标类型为利用率 averageUtilization: 50 # CPU 平均使用率目标为 50% - type: Resource resource: name: memory target: type: Utilization # 目标类型为利用率 averageUtilization: 70 # 内存平均使用率目标为 70% behavior: # (可选) 高级伸缩行为控制 scaleDown: stabilizationWindowSeconds: 300 # 缩容冷却期 300 秒 (5分钟) policies: - type: Pods value: 2 periodSeconds: 60 scaleUp: stabilizationWindowSeconds: 0 policies: - type: Pods value: 2 periodSeconds: 60
应用它:kubectl apply -f nginx-hpa.yaml
HPA 行为解释
CPU 规则:HPA 会努力使所有 Pod 的 CPU 平均使用率 维持在 50%。
如果平均使用率是 75%,
期望副本数 = ceil[3 * (75 / 50)] = ceil[3 * 1.5] = ceil[4.5] = 5。HPA 会将副本数扩容到 5。内存规则:HPA 会努力使所有 Pod 的 内存平均使用率 维持在 70%。
如果平均使用率是 85%,
期望副本数 = ceil[3 * (85 / 70)] = ceil[3 * 1.21] = ceil[3.63] = 4。多指标决策:当同时配置了多个指标时,HPA 会分别计算每个指标所需的副本数,然后选择其中最大的那个值。
在上面的例子中,CPU 算出来需要 5 个,内存算出来需要 4 个,那么 HPA 最终会将副本数扩容到 5。
验证与监控
1.查看 HPA 状态:
kubectl get hpa nginx-hpa -w
输出会显示当前的指标值、目标值、最小/最大副本数和当前的副本数。
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE nginx-hpa Deployment/nginx-deployment 50%/70%, 45%/65% 2 10 3 5m # TARGETS 列显示为 CPU目标%/内存目标%,当前CPU%/当前内存%
2.查看 HPA 详细信息:
kubectl describe hpa nginx-hpa
这个命令会输出非常详细的信息,包括事件日志,帮助你诊断 HPA 为什么不伸缩。
三、最佳实践总结
必须设置
resources.requests:没有它,HPA 无法工作。使用
autoscaling/v2API:v2比v2beta2更稳定,且功能强大。谨慎设置目标值:
目标值设置过高(如 CPU 90%)可能导致 Pod 在触发扩容前就已过载。
目标值设置过低(如 CPU 10%)可能导致资源浪费和过多的副本。
建议:从保守值开始(如 CPU 50-70%),根据实际生产监控数据进行调整。
合理配置
minReplicas和maxReplicas:minReplicas应保证应用的基本可用性。maxReplicas应避免因意外流量或程序 Bug 导致资源耗尽。利用
behavior字段控制伸缩速率和冷却:根据应用的启动和冷却特性,调整scaleUp和scaleDown策略,避免抖动。结合就绪探针和存活探针:确保新扩容的 Pod 真正准备好接收流量后,才被纳入服务的负载均衡。
结合日志与事件:注意容忍度、冷却窗口对扩缩容的影响,关注 ScalingActive、ScalingLimited 等状态变化。
考虑使用自定义指标:对于 Web 服务,基于 HTTP QPS(每秒请求数)进行扩缩容通常比基于 CPU 更直接、更灵敏。这需要安装 Prometheus 和 Prometheus Adapter。
让应用支持平滑启动和终止:确保新 Pod 启动后能快速就绪(利用就绪探针),并在终止时能优雅处理完已有请求(处理 SIGTERM 信号),避免服务中断。
四、关于 HPA 的进阶思考
1. HPA 的局限性及与其他自动伸缩方案的搭配
HPA 主要负责 Pod 水平扩缩容,但它依赖于集群有足够的资源来调度新创建的 Pod。如果集群资源不足,即使 HPA 创建了新的 Pod,这些 Pod 也会因无法调度而处于 Pending 状态,无法提供服务。
因此,在生产环境中,HPA 通常需要与 Cluster Autoscaler (CA) 或 Karpenter 搭配使用:
2. 克服“弹性滞后”:AHPA 与预测性伸缩
传统 HPA 基于当前的监控指标进行反应式扩缩容,这存在一定的“弹性滞后”(Reactive Scaling)。即从流量增加到 HPA 完成扩容需要一定时间(指标采集、计算、Pod 启动、应用预热等),可能导致流量高峰时应用响应变慢。
为解决这个问题,出现了预测性弹性伸缩(Predictive Scaling)方案,如 Advanced Horizontal Pod Autoscaler (AHPA)。AHPA 能够分析历史指标数据(如过去几天的 CPU 负载、QPS 变化规律),预测未来的负载波动,并提前进行扩容。例如,对于每天早高峰流量明显增大的应用,AHPA 可以在高峰来临前就提前扩容,避免流量激增时的响应延迟。在业务低谷时,它也会定时回收资源,节约成本。
参考:


