K8s 自动扩缩容的三种玩法:HPA、VPA 和 KEDA
#K8s 自动扩缩容的三种玩法:HPA、VPA 和 KEDA
本文由 简悦 SimpRead 转码, 原文地址 zhuanlan.zhihu.com
在今天的系统里,应用和负载几乎都是动态变化、彼此牵连的,想给每个应用都分配到「刚刚好」的资源,其实挺难的。
靠人工去调参数、扩容缩容,不仅慢、效率低,风险还大。
分配得太少,任务跑的很慢,严重的时候应用直接挂掉;可要是为了保险起见一味「多给点」,又会白白浪费钱。
自动扩缩容(Autoscaling)的目标很简单:在对的时间给到对的资源,既不让你资源不够用,也不让你花冤枉钱。
当然,跟大多数技术一样,把自动扩缩容真正用好,中间也有不少坑。
#1 为什么自动扩缩容这么重要?
所谓自动扩缩容,就是根据实时的需求,动态地把集群资源(比如 CPU、内存)分配给你的应用。这样一来,不管负载高低,应用手里都有合适的资源来应对,性能和可用性自然就上去了。它的好处如下:
省钱:能帮你把基础设施成本压下来。你只为真正用到的那部分弹性资源付费,而不是为了能跑而浪费。
省时间:本来需要人工去手动调整的资源,现在交给自动化就好。在负载变化频繁的环境里,这能帮运维和 SRE 团队省下大量精力。
#2 自动扩缩容的难点
自动扩缩容在资源优化上确实很强,但它也不是没有代价。下面这几个是大家常遇到的问题:
- 很难预测该扩多少:一个应用到底需要多少资源,其实很难说准。扩缩容的决策通常是基于过去的使用规律或者当前指标做出来的,一旦碰上意料之外的流量高峰,或者使用模式突然变了,就容易扩过头或者没扩够。
- 成本可能失控:如果放任不管,自动扩缩容反而可能推高基础设施成本。尤其是遇到那种转瞬即逝的短时峰值就猛地扩容,账单会很难看。
- 资源争抢:一个集群里如果有很多应用各自独立地扩缩容,它们就会去抢有限的资源,结果就是彼此争抢、整体性能反而下降。
- 复杂度:随着微服务和应用越来越多,管理这么多套扩缩容配置和规则会变得越来越复杂,也越来越容易出错。
想把这些问题处理好,需要:合理的策略、自动化、监控,再加上对自己应用和负载真实需求的深入理解。
#3 前置条件
如果你想在自己的集群里开始尝试这些扩缩容方案,需要先准备好这些东西:
对 Kubernetes 有基本了解,包括 Pod、Deployment、Service 以及基础网络。
一个正在运行的 Kubernetes 集群。本文我们用的是 minikube。
一个配置好、能连上集群的 kubectl。
安装好 Helm。
安装好 Metrics Server。
#4 Kubernetes Metrics Server
在 Kubernetes 里,一个「指标」就是一个量化的测量值或数据点,用来反映某个资源(比如 CPU、内存,或者你自定义的应用级指标)的使用情况和运行状态。指标可以用来评估 Pod、节点、容器这些对象的性能和健康程度。
常见的指标比如:
某个容器或 Pod 消耗的 CPU 占比(CPU 使用率)
某个容器或 Pod 占用的内存量(内存使用率)
某个 Pod 的网络数据传输速率(网络吞吐量)
有了这些指标,你才能在扩缩容和资源分配上做出靠谱的判断,保证性能,也方便排查问题。
Metrics Server(也叫 Kubernetes Metrics API)是集群里的一个组件,负责收集和存储这些指标,同时提供查询和访问的接口,让你能监控整个集群以及上面各种负载的性能和资源使用情况。
对于 HPA(水平扩缩容)、VPA(垂直扩缩容)乃至整个自动扩缩容体系来说,Metrics Server 都非常关键——因为扩缩容依赖的是 CPU、内存这些实时的资源使用数据,靠它们才能做出合理的扩缩决策。
换句话说,没有 Metrics Server,集群就拿不到高效扩缩容所需要的那些关键指标,一切都无从谈起。
#5 在集群里安装 Metrics Server
对大多数通用集群来说,直接用 Kubernetes GitHub 仓库里官方的部署清单就行:
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
稍等片刻让 Metrics Server 启动起来,然后可以这样查看它的状态:
kubectl get deployment metrics-server -n kube-system
之后你就能用 kubectl top 命令查看 Pod 的 CPU、内存使用情况,或者查看各节点的资源占用:
kubectl top pods
kubectl top nodes
#6 HPA、VPA、KEDA 三者对比
Kubernetes 里主要有三种自动扩缩容方案可以选。
其中 HPA(水平 Pod 扩缩容)和 VPA(垂直 Pod 扩缩容)是最常用的两种。
而 KEDA(Kubernetes 事件驱动扩缩容)最近热度很高。
<table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal"><tbody><tr><th></th><th>HPA(水平 Pod 扩缩容)</th><th>VPA(垂直 Pod 扩缩容)</th><th>KEDA(事件驱动扩缩容)</th></tr><tr><td>扩缩方向</td><td>水平方向(调整 Pod 副本数)</td><td>垂直方向(调整 Pod 的资源请求和上限)</td><td>水平和 / 或垂直(取决于事件源)</td></tr><tr><td>触发条件</td><td>基于资源使用指标(CPU、内存、自定义指标)</td><td>基于资源使用指标(CPU、内存)</td><td>由外部或内部事件驱动</td></tr><tr><td>适用场景</td><td>适合应对应用负载或流量模式的变化</td><td>优化 Pod 内部的资源利用,减少过度分配</td><td>适合由事件触发、负载起伏不定的应用(如消息队列、HTTP 请求)</td></tr><tr><td>复杂度</td><td>相对简单,容易上手配置</td><td>需要对资源需求有一定理解,得慢慢调</td><td>灵活性高,但配置和事件源接入会更繁琐一些</td></tr><tr><td>适用负载</td><td>更适合无状态应用和负载</td><td>各类负载都适用,重点是优化资源利用</td><td>无状态、有状态负载都能覆盖,通用性强</td></tr><tr><td>对应的 K8s 资源</td><td>支持 Deployment、ReplicaSet、StatefulSet</td><td>支持 Deployment、StatefulSet、DaemonSet、Job</td><td>支持多种负载类型,常与 HPA 或 VPA 配合使用</td></tr><tr><td>依赖的工具 / 组件</td><td>依赖 Metrics Server 和 K8s 内置的扩缩容机制</td><td>需要集成 VPA 组件</td><td>需要 KEDA 控制器和事件源</td></tr></tbody></table>#6.1 水平 Pod 扩缩容(HPA)
#HPA 是什么?
HPA(Horizontal Pod Autoscaling)会根据 CPU 使用率或自定义指标等条件,自动调整 Deployment、ReplicaSet 或 StatefulSet 里 Pod 副本的数量。水平扩缩容是 Kubernetes 里最基础的一种扩缩容模式。
HPA 会设定两个参数:目标使用率,以及允许的副本数下限和上限。当某个 Pod 的使用率超过目标值时,HPA 会自动增加副本数量来分担增长的负载;反过来,当使用率掉到目标值以下,HPA 又会减少副本数量,把资源省下来。
#什么时候用 HPA
当你主要关心的是「根据应用负载和资源使用情况来调整 Pod 副本数」时,就该用 HPA:
按负载伸缩:如果你希望根据进来的流量或负载高低,自动把副本数扩上去或缩下来,HPA 很合适。
流量驱动的伸缩:如果你的应用负载主要是被流量牵着走的,HPA 能帮你自动调整副本数量,把性能维持在理想状态。
控制资源使用率:如果你想保证 Pod 的 CPU 或内存使用率始终维持在某个阈值范围内,HPA 也很适合。
#6.2 垂直 Pod 扩缩容(VPA)
#VPA 是什么?
VPA(Vertical Pod Autoscaling)会根据历史使用规律,调整 Pod 内各个容器的资源请求(requests)和上限(limits),从而优化资源分配。这样一来,Pod 不需要人工介入也能拿到合适的资源量。
VPA 也会设定两个参数:目标使用率,以及每个 Pod 允许分配资源的下限和上限。当某个 Pod 的使用率超过目标值,VPA 会自动给它增加资源;使用率降下来了,VPA 又会把资源减回去。通过这种方式,VPA 能快速、高效地上下调整单个 Pod 用到的资源。
#什么时候用 VPA
当你关心的是「怎么把单个 Pod 内部的资源利用做得更高效、性能更好」时,就该用 VPA:
微调资源 requests 和 limits:如果你希望根据容器实际观测到的使用情况,自动调整它们的资源请求和上限,VPA 很有用。
提高资源利用效率:VPA 在防止 Pod 内部资源「分配过头」或「利用不足」这类场景下尤其有价值。
优化资源分配:如果你想把 Pod 里的 CPU 和内存用到极致,VPA 能通过动态调整资源配置帮你实现。
#6.3 Kubernetes 事件驱动扩缩容(KEDA)
KEDA 全称是「Kubernetes-based Event-Driven Autoscaling」(基于 Kubernetes 的事件驱动扩缩容),是一个开源项目,专门为 Kubernetes 上的容器负载提供事件驱动的扩缩容能力。大家对 KEDA 的热情是有道理的:它在 Kubernetes 原生水平扩缩容能力的基础上做了扩展,让应用能够根据来自各种源头的事件(比如消息队列、事件总线、自定义指标)自动伸缩。这样一来,构建和运维那些需要灵活应对负载波动的事件驱动型应用就变得容易多了。
这里说的「事件」,指的是那些标志着「需要根据负载需求来伸缩应用」的外部或内部信号。在 KEDA 里,常见的事件包括定时任务(Cron Job)、消息队列、HTTP 请求等等。
要注意,KEDA 里的「事件」不要和可观测性(observability)里的「事件」搞混。两者的关键区别在于:KEDA 事件是用来触发扩缩容动作的,而可观测性事件则是用来提供洞察和数据、帮你监控和理解应用行为的。虽然名字里都有「事件」,但侧重点和用途完全不同——KEDA 事件关注的是应用运行时的伸缩管理,可观测性事件关注的则是系统性能和可靠性的监控与改进。
#什么时候用 KEDA
当你想基于「事件」这种模式来扩缩容,而不只是依赖常规的资源指标时,就该用 KEDA:
事件驱动的伸缩:KEDA 就是为这种场景设计的——根据消息队列里的消息、HTTP 请求,或其他自定义事件源来伸缩你的应用。
超越资源指标的伸缩:如果你的扩缩容决策取决于外部系统或服务产生的事件,KEDA 能帮你把自动扩缩容和这些事件对接起来。
云原生的事件模式:对于那些采用事件驱动架构、需要根据各种来源的事件做出伸缩反应的云原生应用,KEDA 非常合适。
#7 小结
扩缩容的终极目标,说到底就是把资源用得高效、用得均衡,同时把成本管好。
HPA 让你能根据 CPU、内存等观测指标,自动伸缩 Deployment 或 ReplicaSet 里的 Pod。
VPA 则根据容器观测到的资源使用规律,去调整 Pod 内容器的资源 requests 和 limits。
KEDA 关注的是基于「事件」(也就是触发器)来伸缩应用。
想把自动扩缩容真正做好,离不开细致的监控、指标调优和反复测试,这样才能保证应用既能扛住负载变化,又能保持稳定。