K8s 弹性伸缩:Metrics-Server、HPA 与 VPA 全面解析
- [Kubernetes Metric Server](#Kubernetes Metric Server)
-
- 环境准备
- [Metrics-Server 概述](#Metrics-Server 概述)
- [Metrics-Server 部署](#Metrics-Server 部署)
- [Metrics-Server 使用](#Metrics-Server 使用)
- [Horizontal Pod Autoscaler](#Horizontal Pod Autoscaler)
-
- 环境准备
- [Horizontal Pod Autoscaler](#Horizontal Pod Autoscaler)
-
- [HPA 介绍](#HPA 介绍)
- [HPA 配置](#HPA 配置)
- [基于 CPU 使用率伸缩](#基于 CPU 使用率伸缩)
- [基于 Mem 使用率伸缩](#基于 Mem 使用率伸缩)
- [HPA 精细管控](#HPA 精细管控)
-
- [持续高负载 → 扩容](#持续高负载 → 扩容)
- [持续低负载 →缩容](#持续低负载 →缩容)
- 扩容、缩容对比
- [Vertical Pod Autoscaler](#Vertical Pod Autoscaler)
-
- [VPA 作用](#VPA 作用)
- [VPA 适用场景](#VPA 适用场景)
- [VPA 核心特点](#VPA 核心特点)
- [HPA 与 VPA 对比](#HPA 与 VPA 对比)
- 环境清理
Kubernetes Metric Server
摘要:本文全面介绍了 Kubernetes 中的资源监控与自动扩缩容机制。首先详细讲解了 Metrics-Server 的部署与使用,它是 Kubernetes 内置的容器资源指标来源,为 HPA 和 VPA 提供数据支持。接着深入探讨了 HPA(Horizontal Pod Autoscaler)的扩容与缩容控制机制,包括时间参数配置、稳定窗口期、限速策略等核心概念,并通过实际案例展示了基于 CPU 和内存使用率的自动扩缩容实践。最后对比了 HPA 横向扩缩容与 VPA(Vertical Pod Autoscaler)纵向扩缩容的差异、适用场景及核心特点,为生产环境中的自动扩缩容配置提供了完整参考。
学习参考:Metric Server
环境准备
bash
#创建名为 metric 的命名空间
root@master30:~# kubectl create ns metric
#后续执行所有 kubectl 命令,不再需要手动加 -n metric,默认操作 metric 命名空间资源。
root@master30:~# kubectl config set-context --current --namespace metric
bash
# 查看当前默认命名空间
kubectl config view --minify | grep namespace
#或者
kubectl config get-contexts
# 查看所有命名空间
kubectl get ns
Metrics-Server 概述
我们在使用 Kubernetes 中过程中面临的问题:
-
如何监控 node 计算资源使用情况?
-
如何监控 pod 计算资源使用情况?
-
如何根据 pod 计算资源使用情况,自动扩展?
我们可以使用 Metrics-Server监控:
- node 和 pod 计算资源使用情况。
- Metrics Server 是 Kubernetes 内置自动缩放管道的可扩展、高效的容器资源指标来源。
- Metrics Server 通过 Kubelet 收集资源指标,并通过 Metrics API 将它们公开在 Kubernetes apiserver 中,供 Horizontal Pod Autoscaler 和 Vertical Pod Autoscaler 使用。
- Metrics API 还可以通过 kubectl top 访问,从而更轻松地调试自动缩放管道。
Metrics Server 不适用于非自动缩放目的。 请勿将其用于将指标转发到监控解决方案,或作为监控解决方案指标的来源。 在这种情况下,请直接从 Kubelet /metrics/resource 端点收集指标。
指标服务器提供:
- 适用于大多数集群的单一部署(请参阅要求)。
- 快速自动缩放,每 15 秒收集一次指标。
- 资源效率,集群中每个节点使用 1 mili 核心 CPU 和 2 MB 内存。
- 可扩展支持多达 5,000 个节点集群。
Metrics-Server 部署
bash
# 下载 Metrics-Server
root@master30:~# wget -O components.yaml http://192.168.46.200/class/course-materials/softwares/stage03/metrics-server-components-v0.7.1.yaml
# 修改 Metrics-Server,不校验tls
# 上面的yaml文件已经修改完成了
# root@master30:~# sed -i '/metric-resolution/a\ - --kubelet-insecure-tls' components.yaml
# 修改镜像
root@master30:~# grep image: components.yaml
image: registry.k8s.io/metrics-server/metrics-server:v0.7.1
root@master30:~# sed -i 's/registry.k8s.io/hub.laoma.cloud/g' components.yaml
# 部署 Metrics-Server
root@master30:~# kubectl apply -f components.yaml
bash
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
bash
# 查看 Metrics-Server 状态
root@master30:~# kubectl get pods -n kube-system |grep metrics
metrics-server-6556f8cb6c-78mhq 1/1 Running 0 45s
Metrics-Server 使用
查看node状态
bash
root@master30:~# kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
master30.laoma.cloud 97m 4% 1328Mi 35%
worker31.laoma.cloud 49m 2% 912Mi 24%
worker32.laoma.cloud 45m 2% 926Mi 24%
查看 pod 状态
bash
root@master30:~# kubectl top pods -n kube-system
NAME CPU(cores) MEMORY(bytes)
calico-kube-controllers-6dfcd885bf-8rhg2 2m 11Mi
calico-node-crfr7 27m 57Mi
calico-node-sbmjt 22m 57Mi
calico-node-z9dvd 24m 56Mi
coredns-6d56c8448f-nhjpg 3m 12Mi
coredns-6d56c8448f-w2f48 2m 10Mi
etcd-master.laoma.cloud 16m 54Mi
kube-apiserver-master.laoma.cloud 46m 355Mi
kube-controller-manager-master.laoma.cloud 11m 50Mi
kube-proxy-hx566 1m 18Mi
kube-proxy-t2r4x 1m 18Mi
kube-proxy-x6k8h 1m 18Mi
kube-scheduler-master.laoma.cloud 4m 22Mi
metrics-server-6556f8cb6c-78mhq 1m 11Mi
单位:1cpu=1000m
Horizontal Pod Autoscaler
环境准备
bash
root@master30:~# kubectl create ns hpa
root@master30:~# kubectl config set-context --current --namespace hpa
Horizontal Pod Autoscaler
学习参考:hpa
HPA 介绍
控制器将从Metrics Server中获取度量值。根据 HPA 中定义的指标动态实现控制器中pod伸缩,支持deployment、replication controller和replicaset。
适用场景:
- 流量波动大的无状态服务(nginx、api、网关、微服务)
- 需要提高并发 、削峰填谷
核心特点:
- 不修改 Pod 配置,只改副本数
- 实时、秒级扩缩
- 最常用、最稳定
支持指标:
- CPU 使用率
- 内存使用率
- 自定义指标(Prometheus 对接)
- QPS、延迟等
HPA 配置
pod 数量扩容和缩容由kube-controller-manager管理,核心参数包括:
-
HPA 指标采样周期:
--horizontal-pod-autoscaler-sync-period duration,默认15s,kube-controller-manager 控制器每 15s 执行一轮循环:拉取指标 → 计算期望副本 → 判断是否扩容。 -
启动就绪窗口期:
--horizontal-pod-autoscaler-initial-readiness-delay duration,默认:30s,Pod 刚启动前 30 秒,视为 "启动中",不参与 HPA 计算。 -
缩容稳定窗口期:
--horizontal-pod-autoscaler-downscale-stabilization duration,默认:300s(5 分钟),缩容冷却时间。
实验环境为了演示快速扩容和缩容,设置参数如下:
bash
root@master30:~# vim /etc/kubernetes/manifests/kube-controller-manager.yaml
yaml
spec:
containers:
- command:
- kube-controller-manager
- --allocate-node-cidrs=true
......
# 增加下面三行参数
- --horizontal-pod-autoscaler-sync-period=10s
- --horizontal-pod-autoscaler-initial-readiness-delay=20s
- --horizontal-pod-autoscaler-downscale-stabilization=30s
保存退出,静态 Pod 会自动重启生效。
实际扩容冷却时间范围:20s-30s。
- 最短时间20s:如果pod启动20秒后,此时正好拉取到 Metric 指标,判断需要扩容,则立刻进行扩容。
- 最长时间30s:如果pod启动20秒后,10秒后拉取到 Metric 指标,判断需要扩容,再进行扩容。
基于 CPU 使用率伸缩
准备资源
bash
root@master30:~# kubectl create deployment web --image=docker.io/library/nginx
root@master30:~# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-68b95c775c-xksf4 1/1 Running 0 4s
创建 hpa
bash
Usage: kubectl autoscale (-f FILENAME | TYPE NAME | TYPE/NAME) [--min=MINPODS]--max=MAXPODS [--cpu-percent=CPU] [options]
# 示例
root@master30:~# kubectl autoscale deployment web --max=5 --min=2 --cpu-percent=80 -o yaml
yaml
# 省略部分不重要配置
# 注意这里版本是v1
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: web
namespace: metric
spec:
maxReplicas: 5
minReplicas: 2
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
targetCPUUtilizationPercentage: 80
bash
# 稍等片刻,hpa会自动创建一个新的pod
root@master30:~# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-68b95c775c-48ngs 1/1 Running 0 13s
web-68b95c775c-xksf4 1/1 Running 0 41s
root@master30:~# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web cpu: <unknown>/80% 2 5 2 34s
# CPU 目标为unknown
要想看到 HPA 的 TARGETS 值必须满足2个条件:
- 安装 metric server。
- 为 pod 设定资源限制。
bash
root@master30:~# kubectl edit deployments.apps web
# 修改spec.template.spec.containers.[N].resources属性,添加limit属性,如下:
resources:
limits:
cpu: 100m
memory: 200Mi
# 再次查看hpa
root@master30:~# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web cpu: 0%/80% 2 5 2 83s
root@master30:~# kubectl expose deployment web --port=80 --target-port=80
root@master30:~# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web ClusterIP 10.100.255.92 <none> 80/TCP 6s
压力测试
bash
# 打开一个监控窗口
root@master30:~# \
while true
do
clear;
date;echo
kubectl get hpa;echo
kubectl get pod;echo
kubectl top pods
sleep 1
done | tee hpa.log
# 上 CPU 压力
root@master30:~# apt install -y apache2-utils
root@master30:~# while true ;do ab -n 300000 -c 100 http://10.100.255.92/;sleep 1;done
# -n 300000,总请求数
# -c 100,每次并发数
CPU负载 cpu: 98%
bash
Every 2.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 09:57:22 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web cpu: 100%/80% 2 5 2 8m32s
NAME CPU(cores) MEMORY(bytes)
web-6dcdc45c94-6gwd2 101m 3Mi
web-6dcdc45c94-dvd2m 100m 3Mi
超过目标值后,稍等片刻(20s左右),HPA 新建了一个pod
bash
Every 2.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 09:58:04 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web cpu: 95%/80% 2 5 3 9m14s
NAME CPU(cores) MEMORY(bytes)
web-6dcdc45c94-2zbmb 93m 3Mi
web-6dcdc45c94-6gwd2 100m 3Mi
web-6dcdc45c94-dvd2m 90m 3Mi
稍等片刻(20s左右),HPA又新建了一个pod
bash
Every 2.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 09:58:59 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web cpu: 99%/80% 2 5 4 11m
NAME CPU(cores) MEMORY(bytes)
web-6dcdc45c94-2zbmb 100m 3Mi
web-6dcdc45c94-6gwd2 100m 3Mi
web-6dcdc45c94-dvd2m 97m 3Mi
web-6dcdc45c94-tsjkr 99m 3Mi
稍等片刻(20s左右),HPA又新建了一个pod
bash
Every 2.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 09:59:59 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web cpu: 100%/80% 2 5 5 11m
NAME CPU(cores) MEMORY(bytes)
web-6dcdc45c94-2zbmb 101m 3Mi
web-6dcdc45c94-6gwd2 100m 3Mi
web-6dcdc45c94-dvd2m 100m 3Mi
web-6dcdc45c94-hpg45 98m 3Mi
web-6dcdc45c94-tsjkr 101m 3Mi
观察过程:
-
随着pod CPU使用率上升,自动扩展pod数量。
-
正常情况,20秒左右创建一个新pod,
-
即使pod CPU使用率超过阈值,但pod数量不会超过5。
-
停止压力测试,负载降低后,pod数量会立刻减少为2。
清理资源
bash
# 删除 hpa
root@master30:~# kubectl delete hpa web
# 删除 deployment
root@master30:~# kubectl delete deployment web
# 保留 svc,后续使用
基于 Mem 使用率伸缩
我们仍然以nginx应用实践。想要Nginx 内存涨,要访问会占用内存的页面 。最简单方法:让 Nginx 返回一个超大响应体。
准备资源
bash
# worker节点创建big.img
[root@worker31 ~]# mkdir /www
[root@worker31 ~]# dd if=/dev/zero of=/www/big.img bs=1M count=200
[root@worker32 ~]# mkdir /www
[root@worker32 ~]# dd if=/dev/zero of=/www/big.img bs=1M count=200
root@master30:~# vim deployment.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: big-file
mountPath: /usr/share/nginx/html
resources:
limits:
cpu: 100m
memory: 200Mi
volumes:
- name: big-file
hostPath:
path: /www
bash
root@master30:~# kubectl apply -f deployment.yaml
创建 hpa
bash
root@master30:~# vim hpa-mem.yaml
yaml
# 注意这里版本为v2
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
minReplicas: 2
maxReplicas: 5
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
metrics:
- resource:
name: memory
target:
type: Utilization
# 使用20% 效果比较明显,这里实用60%
averageUtilization: 60
type: Resource
bash
root@master30:~# kubectl apply -f hpa-mem.yaml
# 稍等片刻:目标值中内存才会正常显示
root@master30:~# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web memory: 2%/60% 2 5 1 13m
# 稍等片刻,创建一个新的pod
root@master30:~# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-6dcdc45c94-2zj8s 1/1 Running 0 13m
web-6dcdc45c94-w62pr 1/1 Running 0 13s
压力测试
bash
# 打开一个监控窗口
root@master30:~# \
while true
do
clear;
date;echo
kubectl get hpa;echo
kubectl get pod;echo
kubectl top pods
sleep 1
done | tee hpa.log
# 上 MEM 压力
root@master30:~# while true ;do ab -n 300000 -c 100 http://10.99.129.137/big.img;sleep 1;done
本机作为压测客户端,向外大量发起 HTTP 请求,产生海量 TCP 收发数据包。
如果master30节点硬件配置低,则导致master30节点自身CPU性能出现瓶颈。
通过top命令可以看到 si 指标偏高,特定cpu的si指标接近100%:压测产生巨量网络数据包,软中断全部堆积在 CPU1 核心处理。
负载上来了
bash
Every 4.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 11:13:29 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web memory: 86%/60% 2 5 2 16m
NAME CPU(cores) MEMORY(bytes)
web-88cff78bb-2b7vh 15m 174Mi
web-88cff78bb-76pg2 15m 171Mi
新建了一个pods
bash
Every 4.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 11:13:46 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web memory: 58%/60% 2 5 3 16m
NAME CPU(cores) MEMORY(bytes)
web-88cff78bb-2b7vh 15m 174Mi
web-88cff78bb-4hcm5 5m 3Mi
web-88cff78bb-76pg2 15m 171Mi
又新建了一个pods
bash
Every 4.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 11:15:46 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web memory: 58%/60% 2 5 4 16m
NAME CPU(cores) MEMORY(bytes)
web-88cff78bb-2b7vh 15m 174Mi
web-88cff78bb-4hcm5 5m 3Mi
web-88cff78bb-76pg2 15m 171Mi
web-88cff78bb-ws6t4 1m 3Mi
又新建了一个pods
bash
Every 4.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 11:17:46 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web memory: 58%/60% 2 5 5 16m
NAME CPU(cores) MEMORY(bytes)
web-88cff78bb-2b7vh 15m 174Mi
web-88cff78bb-4hcm5 5m 3Mi
web-88cff78bb-76pg2 15m 171Mi
web-88cff78bb-ws6t4 1m 3Mi
web-88cff78bb-t4q2p 100m 3Mi
观察过程:
- 随着pod MEM使用率上升,自动扩展pod数量。
- 正常情况,20秒左右创建一个新pod,
- 即使pod MEM使用率超过阈值,但pod数量不会超过5。
- 停止压力测试,负载降低后,pod数量会立刻减少为2。
- 太高的负载可能会导致pod出现OOMKilled.
清理资源
bash
# 删除 hpa
root@master30:~# kubectl delete hpa web
# 删除 deployment
root@master30:~# kubectl delete deployment web
# 删除 svc
root@master30:~# kubectl delete svc web
HPA 精细管控
持续高负载 → 扩容
从 K8s 1.18 起,HPA 通过 spec.behavior.scaleUp 精细管控缩容速度、冷却、单次扩容幅度。
核心参数
yaml
scaleUp:
# 扩容稳定窗口:负载突增后等待多久再扩容
stabilizationWindowSeconds: 0
# 扩容限速策略:控制每个周期最多新增多少Pod
policies:
- type: Percent
value: 数值
periodSeconds: 周期时长
- type: Pods
value: 数值
periodSeconds: 周期时长
# 多策略选择逻辑
selectPolicy: Max / Min / Disabled
1. stabilizationWindowSeconds
扩容稳定窗口时间用来过滤瞬时突刺流量,避免瞬间飙升立刻扩容。
- 扩容逻辑:窗口内取指标计算的最小副本数作为目标,只有持续高负载才会扩容;
- 扩容默认值:0(无等待,负载一超标立刻扩容);
2. policies
策略用于控制单次扩容幅度。每条策略包含三要素:
type:两种模式Percent:周期内最多新增当前副本百分比Pods:周期内最多新增固定数量Pod
value:阈值(百分比/固定Pod数)periodSeconds:策略生效周期(单位秒,最大1800)
3. selectPolicy
Max:取新增Pod更多的策略(激进缩容,默认)Min:取新增Pod更少的策略(保守缩容,生产推荐)Disabled:完全禁止缩容
默认扩容策略
yaml
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 15
- type: Pods
value: 4
periodSeconds: 15
selectPolicy: Max
策略解读:
-
stabilizationWindowSeconds:0:无扩容稳定窗口,指标达标立刻尝试扩容。窗口取值规则:取窗口内最小期望副本。
-
两条限速策略(15s 滑动窗口):
- Percent:每 15s 最多新增当前副本 100%(翻倍)
- Pods:每 15s 最多新增 4 个 Pod
-
selectPolicy:Max:两条策略取允许扩容更多的值作为本轮扩容上限;
⚠️ policy 是上限,最终扩容数量由指标计算公式决定,不是强制每次扩多少。
扩容执行流程
- Metrics Server 15s 采集一次指标;
- HPA计算目标副本数;
- 读取稳定窗口内历史推荐值,取最小值作为候选副本;
- 判断需要扩容,进入限速策略计算本周期允许新增Pod上限;
- 按限速分步扩容,不会一次性拉满maxReplicas;
- 下个周期重新采集指标,逐步扩容。
典型场景配置案例
案例1:禁止扩容
yaml
scaleUp:
policies:
- type: Percent
value: 0
periodSeconds: 3600
selectPolicy: Max
案例2:激进扩容(无等待)
yaml
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 50
periodSeconds: 15
selectPolicy: Max
案例3:平缓扩容(等待长)
- 扩容稳定窗口60秒,过滤瞬时流量毛刺;
- 每30秒最多扩容当前副本20%,或单次最多新增4个Pod;
- 保守模式,两种策略取扩容更少的值,放缓扩容节奏。
yaml
scaleUp:
# 扩容稳定窗口,等待60秒确认持续高负载
stabilizationWindowSeconds: 60
policies:
# 策略1:每30s最多扩容20%
- type: Percent
value: 20
periodSeconds: 30
# 策略2:每30s最多新增4个Pod
- type: Pods
value: 4
periodSeconds: 30
# 保守扩容,取新增Pod更少的方案
selectPolicy: Min
持续低负载 →缩容
从 K8s 1.18 起,HPA 通过 spec.behavior.scaleDown 精细管控缩容速度、冷却、单次缩容幅度。
核心参数
yaml
scaleDown:
# 缩容稳定窗口:负载突降后等待多久再缩容
stabilizationWindowSeconds: 0
# 缩容限速策略:控制每个周期最多减少多少Pod
policies:
- type: Percent
value: 数值
periodSeconds: 周期时长
- type: Pods
value: 数值
periodSeconds: 周期时长
# 多策略选择逻辑
selectPolicy: Max / Min / Disabled
1. stabilizationWindowSeconds
HPA 稳定窗口周期内计算出的期望副本,缩容时取窗口内最大值作为目标副本;只有持续低负载超过窗口时长,才会真正缩容,避免瞬时流量下跌立刻删Pod导致反弹。
- 默认值:
300(5分钟) - 取值范围:0~3600(1小时)
- 逻辑举例:当前副本10,指标瞬时建议缩到6,窗口5分钟内历史最大值仍为10 → 不缩容;5分钟后高值过期,才按更低副本缩容。
2. policies
缩容限速规则用于控制单次缩容幅度。每条策略包含三要素:
type:两种模式Percent:周期内最多删除当前副本百分比Pods:周期内最多删除固定数量Pod
value:阈值(百分比/固定Pod数)periodSeconds:策略生效周期(单位秒,最大1800)
3. selectPolicy
Max:取删Pod更多的策略(激进缩容,默认)Min:取删Pod更少的策略(保守缩容,生产推荐)Disabled:完全禁止缩容
默认缩容策略
yaml
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 100
periodSeconds: 15
selectPolicy: Max
# 只有单条策略,selectPolicy字段存在但不产生取舍效果
策略解读:
-
stabilizationWindowSeconds:300:5 分钟稳定窗口。窗口取值规则:取窗口内最大期望副本,防止流量抖动反复扩缩。
-
一条策略:每 15s 滑动窗口内最多删除当前副本 100%,理论上可以一次性缩到最小副本数。
-
缩容只有一条 policy ,不存在多条策略对比,所以
selectPolicy默认值 Max 在此场景没有实际作用;
缩容执行流程
- Metrics Server每15s采集CPU/指标;
- HPA计算理论期望副本;
- 查询稳定窗口历史推荐值,取最大值作为候选目标;
- 对比当前副本,判断需要缩容;
- 执行policies限速规则,计算本周期允许删除的最大Pod数;
- 按限速值缩减副本,不会一次性缩到最低;
- 下一个周期重复计算,分步缓慢下降。
典型场景配置案例
案例1:禁止缩容(活动高峰)
yaml
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 0
periodSeconds: 3600
selectPolicy: Max
案例2:激进缩容(无等待、快速缩容)
yaml
scaleDown:
stabilizationWindowSeconds: 30
policies:
- type: Percent
value: 100
periodSeconds: 15
selectPolicy: Max
案例3:平缓缩容(等待长,慢速缩容)
-
稳定窗口10分钟,避免毛刺缩容;
-
每60秒最多缩容当前副本10% 或 最多删2个Pod;
-
保守模式,两种策略取删得更少的方案。
yaml
scaleDown:
# 稳定窗口:等待10分钟确认低负载再缩容
stabilizationWindowSeconds: 600
policies:
# 策略1:每分钟最多缩容10%
- type: Percent
value: 10
periodSeconds: 60
# 策略2:每分钟最多删除2个Pod
- type: Pods
value: 2
periodSeconds: 60
# 缩容保守:两种策略选删除Pod更少的
selectPolicy: Min
扩容、缩容对比
| 配置项 | scaleUp(扩容) | scaleDown(缩容) |
|---|---|---|
| stabilizationWindowSeconds 默认值 | 0 | 300(5 分钟) |
| 稳定窗口取值逻辑 | 窗口内取最小期望副本 | 窗口内取最大期望副本 |
| 默认 policies 条数 | 2 条(Percent+Pods) | 1 条(仅 Percent) |
| 默认策略内容 | 15s 最多扩容 100% / 最多新增 4Pod | 15s 最多删除 100% 副本 |
| 默认 selectPolicy | Max | Max(单策略无实际效果) |
| selectPolicy 支持选项 | Max / Min / Disabled | Max / Min / Disabled |
| 触发阈值 | 利用率 > target × 1.1 | 利用率 < target × 0.9 |
| 设计思想 | 优先快速扩容保障业务 | 谨慎缩容,避免流量反弹 |
Vertical Pod Autoscaler
VPA 使用场景不多,这里不做实践演示。
VPA 作用
控制器将从一系列API(metrics.k8s.io、custom.metrics.k8s.io 和 external.metrics.k8s.io)中获取度量值,metrics.k8s.io API 通常由Metrics Server提供。根据 VPA 中定义的指标动态调整 Pod 的 requests 和 limits。
VPA 适用场景
- 资源配置不合理的服务
- 长期运行、流量稳定的服务
- Java、Go 等内存占用固定的应用
- 不适合频繁扩缩的服务。
VPA 核心特点
- 不改变 Pod 数量
- 自动给 Pod 推荐 / 设置 CPU / 内存
- 生效需要重启 Pod(默认)
- 比 HPA 少用,因为有侵入性
HPA 与 VPA 对比
| 项目 | HPA 横向扩缩容 | VPA 纵向扩缩容 |
|---|---|---|
| 全称 | Horizontal | Vertical |
| 扩缩方式 | 增加 / 减少 Pod 数量 | 调整 CPU / 内存 request/limit |
| 是否重启 Pod | ❌ 不重启 | ✅ 一般需要重启 |
| 适合负载 | 流量波动大 | 资源配置不合理 |
| 生效速度 | 快 | 慢 |
| 稳定性 | 高 | 中 |
| 生产使用 | 非常普遍 | 较少 |
| 能否一起开 | 不能同时开(会冲突) | - |
| 支持资源 | CPU、内存、自定义 | CPU、内存 |
环境清理
bash
root@master30:~# kubectl delete ns hpa