K8S(十四)—— K8s实战:HPA(Pod水平自动伸缩)完整部署与测试指南
文章目录
- 前言
- 一、HPA核心概念解析
- 1.1 HPA定义与核心作用
- 1.2 HPA工作原理
- 1.3 HPA依赖组件:metrics-server
- 二、部署metrics-server(HPA依赖组件)
- 2.1 准备metrics-server镜像
- 2.2 使用Helm安装metrics-server
- 2.2.1 初始化Helm仓库
- 2.2.2 配置metrics-server.yaml
- 2.2.3 执行Helm安装
- 2.3 验证metrics-server部署成功
- 三、部署HPA及测试验证
- 3.1 准备HPA测试镜像
- 3.2 创建测试用Deployment与Service
- 3.3 创建HPA控制器
- 3.4 模拟负载验证HPA伸缩效果
- 3.4.1 启动负载生成器
- 3.4.2 观察HPA伸缩过程
- 3.4.3 验证Pod数量变化
- 3.4.4 验证缩容逻辑
- 3.5 测试负载不足时的解决方案
- 四、K8s资源限制扩展配置
- 4.1 Pod级资源限制(容器维度)
- 4.2 命名空间级资源限制
- 4.2.1 资源配额(ResourceQuota):命名空间总资源限制
- 4.2.2 对象数量配额:限制命名空间内资源对象数量
- 4.2.3 默认限制(LimitRange):为未配置资源的Pod设置默认值
- 总结
- 附录:常见问题排查
前言
在Kubernetes(简称K8s)集群管理中,Pod的负载会随着业务流量波动而变化——高峰期若Pod数量不足,会导致服务响应缓慢;低谷期若Pod数量过多,又会造成资源浪费。HPA
(Horizontal Pod Autoscaling,Pod水平自动伸缩)正是解决这一问题的核心组件,它能根据CPU利用率(或其他自定义指标)自动调整Pod副本数量,实现“按需伸缩”,既保障服务稳定性,又提升资源利用率。
本文将从HPA核心概念入手,逐步讲解依赖组件metrics-server
的部署、HPA的实际部署与负载测试,并补充K8s资源限制的扩展配置,确保每个步骤可复现、每个命令有解释,帮助读者快速掌握HPA的实战应用。
一、HPA核心概念解析
在部署HPA前,需先明确其核心原理与依赖,避免后续操作中出现“知其然不知其所以然”的情况。
1.1 HPA定义与核心作用
HPA是K8s中的一种资源对象,与Deployment、ReplicaSet等类似,可通过声明式配置或命令行创建。其核心作用是:周期性检测目标Pod的负载(如CPU利用率),并根据预设阈值自动调整Pod副本数,支持对Deployment、ReplicaSet、Replication Controller管理的Pod进行伸缩。
1.2 HPA工作原理
HPA的伸缩逻辑依赖“周期性检测+阈值对比”,具体流程如下:
- 周期检测:HPA通过Master节点的
kube-controller-manager
服务实现,检测周期由启动参数horizontal-pod-autoscaler-sync-period
控制,默认每30秒检测一次Pod负载(CPU使用率)。 - 负载获取:HPA不直接采集Pod指标,需依赖
metrics-server
(资源指标聚合器),通过resource metrics API
获取Pod的CPU、内存等实时数据。 - 伸缩决策:HPA对比实际负载与预设阈值(如CPU利用率50%),若实际负载超过阈值则增加Pod副本数,若低于阈值则减少副本数(但不低于
min
值,不高于max
值)。
1.3 HPA依赖组件:metrics-server
metrics-server
是K8s集群的“资源数据管家”,主要功能包括:
- 采集所有Node和Pod的CPU、内存使用数据;
- 通过
resource metrics API
向集群内组件(如HPA、kubectl top命令、Scheduler)提供标准化的指标数据; - 自身不存储历史数据,仅提供实时指标查询。
二、部署metrics-server(HPA依赖组件)
由于HPA需通过metrics-server
获取负载数据,因此需先部署metrics-server
,步骤如下:
2.1 准备metrics-server镜像
metrics-server
运行依赖镜像,需先在所有Node节点上加载本地镜像(避免在线拉取失败):
- 将
metrics-server.tar
镜像包上传至所有Node节点的/opt
目录; - 执行以下命令加载镜像:
# 切换到镜像包所在目录
cd /opt/
# 加载本地镜像(无需联网)
docker load -i metrics-server.tar
2.2 使用Helm安装metrics-server
Helm是K8s的包管理工具,可简化metrics-server
的部署流程,具体步骤如下:
2.2.1 初始化Helm仓库
首先清理旧仓库并添加稳定版仓库(若第一个仓库访问失败,可切换第二个国内镜像仓库):
# 1. 创建metrics-server部署目录并进入
mkdir /opt/metrics && cd /opt/metrics# 2. 移除旧的stable仓库(若存在)
helm repo remove stable# 3. 添加Helm稳定版仓库(二选一,优先选国内镜像)
# 选项1:官方仓库(可能因网络问题失败)
helm repo add stable https://charts.helm.sh/stable
# 选项2:国内Azure镜像仓库(推荐,速度更快)
helm repo add stable http://mirror.azure.cn/kubernetes/charts# 4. 更新Helm仓库索引(确保获取最新版本)
helm repo update# 5. 拉取metrics-server的Helm Chart包(本地查看配置)
helm pull stable/metrics-server
2.2.2 配置metrics-server.yaml
创建metrics-server.yaml
配置文件,解决metrics-server
与Kubelet通信的常见问题(如TLS验证、地址类型):
vim metrics-server.yaml
# metrics-server.yaml 配置文件
args:- --logtostderr # 日志输出到标准错误流(便于排查问题)- --kubelet-insecure-tls # 忽略Kubelet的TLS证书验证(测试环境使用,生产环境需配置合法证书)- --kubelet-preferred-address-types=InternalIP # 优先使用Node的InternalIP与Kubelet通信(避免DNS解析问题)
image:repository: k8s.gcr.io/metrics-server-amd64 # 镜像仓库地址tag: v0.3.2 # 镜像版本(与本地加载的镜像版本一致,避免拉取新镜像)
2.2.3 执行Helm安装
通过Helm安装metrics-server
,并指定命名空间为kube-system
(系统组件推荐放置于此):
helm install metrics-server stable/metrics-server -n kube-system -f metrics-server.yaml
2.3 验证metrics-server部署成功
metrics-server
启动后需等待1-2分钟(指标采集初始化),通过以下命令验证:
# 1. 查看metrics-server Pod状态(确保STATUS为Running)
kubectl get pods -n kube-system | grep metrics-server
# 预期输出示例:
metrics-server-xxxx-xxxx 1/1 Running 0 1m# 2. 查看Node节点资源使用情况(验证指标采集功能)
kubectl top node
# 预期输出示例:显示每个Node的CPU(cores)、MEMORY(bytes)使用量
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
master01 263m 13% 1802Mi 49%
node01 81m 4% 452Mi 26%
node02 90m 4% 514Mi 29%
# 3. 查看所有命名空间Pod资源使用情况
kubectl top pods --all-namespaces
若kubectl top
命令能正常输出数据,说明metrics-server
部署成功。
三、部署HPA及测试验证
metrics-server
就绪后,即可部署HPA并通过模拟负载验证其自动伸缩功能。
3.1 准备HPA测试镜像
谷歌提供了hpa-example
镜像,内置CPU密集型代码,用于测试HPA伸缩效果,步骤如下:
- 将
hpa-example.tar
镜像包上传至所有Node节点的/opt
目录; - 执行以下命令加载镜像并验证:
# 1. 切换到镜像包目录
cd /opt# 2. 加载本地镜像
docker load -i hpa-example.tar# 3. 验证镜像是否加载成功(查看REPOSITORY和TAG)
docker images | grep hpa-example
# 预期输出:
gcr.io/google_containers/hpa-example latest 4ca4c13a6d7c 10 years ago 481MB
3.2 创建测试用Deployment与Service
创建hpa-pod.yaml
文件,定义一个Deployment(管理Pod)和Service(暴露访问入口),并设置Pod的CPU请求资源(HPA计算利用率的基准):
vim hpa-pod.yaml
# hpa-pod.yaml 配置文件
apiVersion: apps/v1
kind: Deployment
metadata:labels:run: php-apache # Deployment标签,用于关联Service和HPAname: php-apache # Deployment名称
spec:replicas: 1 # 初始Pod副本数selector:matchLabels:run: php-apache # 匹配Pod标签template:metadata:labels:run: php-apache # Pod标签spec:containers:- image: gcr.io/google_containers/hpa-example # 测试镜像name: php-apache # 容器名称imagePullPolicy: IfNotPresent # 优先使用本地镜像,不存在再拉取(避免在线拉取失败)ports:- containerPort: 80 # 容器暴露端口(与Service关联)resources:requests:cpu: 200m # Pod初始CPU请求(HPA计算CPU利用率的基准,200m=0.2核)
---
# 定义Service,暴露Deployment的Pod访问入口
apiVersion: v1
kind: Service
metadata:name: php-apache # Service名称
spec:ports:- port: 80 # Service暴露端口protocol: TCP # 协议类型targetPort: 80 # 转发到Pod的端口(与容器暴露端口一致)selector:run: php-apache # 匹配Deployment管理的Pod标签
执行以下命令创建资源:
# 应用配置文件
kubectl apply -f hpa-pod.yaml# 查看Pod状态(确保STATUS为Running)
kubectl get pods
# 预期输出示例:
NAME READY STATUS RESTARTS AGE
php-apache-6c64bcf88b-ls8g6 1/1 Running 0 10s
3.3 创建HPA控制器
使用kubectl autoscale
命令创建HPA,指定伸缩规则(CPU阈值、副本数范围):
# 创建HPA,关联php-apache Deployment
kubectl autoscale deployment php-apache \
--cpu-percent=50 \ # HPA伸缩阈值:Pod CPU利用率超过50%则扩容,低于则缩容
--min=1 \ # 最小Pod副本数(即使负载为0,也保留1个Pod)
--max=10 # 最大Pod副本数(避免过度扩容导致资源耗尽)
创建后需等待1-2分钟(HPA获取初始指标),执行以下命令查看HPA状态:
kubectl get hpa
# 预期输出示例(初始TARGETS为0%/50%,说明暂无负载):
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 0%/50% 1 10 1 16skubectl top pods
# 预期输出
NAME CPU(cores) MEMORY(bytes)
php-apache-6c64bcf88b-ls8g6 1m 6Mi
3.4 模拟负载验证HPA伸缩效果
通过创建测试客户端,循环访问php-apache
Service,模拟高负载场景,观察HPA是否自动扩容;停止负载后,观察是否自动缩容。
3.4.1 启动负载生成器
创建一个busybox
容器作为测试客户端,执行循环访问命令:
# 创建并进入busybox容器(-it表示交互式终端)
kubectl run -it load-generator --image=busybox /bin/sh# 在容器内执行循环访问命令(向php-apache Service发送请求,增加CPU负载)
while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done
注:
php-apache.default.svc.cluster.local
是Service的集群内部DNS地址,格式为“Service名称.命名空间.svc.cluster.local”,默认命名空间为default
。
3.4.2 观察HPA伸缩过程
打开新的终端窗口,执行以下命令实时监控HPA状态(-w
表示持续监听):
kubectl get hpa -w
# 预期输出示例(关键过程解析):
# 1. 初始负载较低:php-apache Deployment/php-apache 39%/50% 1 10 1 13m
# 2. 负载超过阈值:php-apache Deployment/php-apache 54%/50% 1 10 1 13m
# 3. 负载急剧升高:php-apache Deployment/php-apache 342%/50% 1 10 1 14m
# 4. HPA开始扩容:php-apache Deployment/php-apache 315%/50% 1 10 4 14m
# 5. 继续扩容至最大:php-apache Deployment/php-apache 67%/50% 1 10 10 15m
# 6. 负载下降(扩容后分摊压力):php-apache Deployment/php-apache 34%/50% 1 10 10 16m
3.4.3 验证Pod数量变化
执行以下命令查看Pod数量,确认是否扩容至10个(HPA的max
值):
kubectl get pods
# 预期输出:包含1个load-generator Pod和10个php-apache Pod(名称前缀相同,后缀不同)
3.4.4 验证缩容逻辑
停止负载生成器(在busybox
容器内按Ctrl+C
终止循环命令,然后执行exit
退出容器),等待5-10分钟(HPA缩容策略较保守),再次查看HPA和Pod状态:
# 查看HPA状态(负载低于50%,开始缩容)
kubectl get hpa# 查看Pod数量(逐渐减少至min=1个)
kubectl get pods
关键说明:HPA“扩容快、缩容慢”是故意设计的——避免业务高峰期因网络波动导致负载短暂下降时,HPA快速缩容,剩余Pod无法承受后续突增负载,从而保障服务稳定性。
3.5 测试负载不足时的解决方案
若CPU性能较好,单客户端负载无法使Pod利用率超过50%,可再创建一个测试客户端,同时发送请求:
# 创建第二个负载生成器容器
kubectl run -i --tty load-generator1 --image=busybox /bin/sh# 执行相同的循环访问命令
while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done
四、K8s资源限制扩展配置
HPA的伸缩依赖Pod的资源请求(requests
),而K8s还支持通过“Pod级限制”和“命名空间级限制”防止资源滥用,保障集群稳定性。
4.1 Pod级资源限制(容器维度)
通过resources.limits
和resources.requests
为单个Pod的容器设置资源上限和初始请求,配置示例如下:
spec:containers:- image: xxxx # 业务镜像imagePullPolicy: IfNotPresentname: auth # 容器名称ports:- containerPort: 8080protocol: TCPresources:limits: # 资源上限(超过会触发限制,如CPU节流、内存OOM)cpu: "2" # 最大CPU限制(2核)memory: 1Gi # 最大内存限制(1GB)requests: # 初始资源请求(K8s调度时分配的最小资源)cpu: 250m # 初始CPU请求(0.25核)memory: 250Mi# 初始内存请求(250MB)
- CPU单位说明:
1
=1核,100m
=0.1核(1核=1000毫核); - 内存单位说明:支持
Ki
(千字节)、Mi
(兆字节)、Gi
(吉字节),1Gi=1024Mi。
4.2 命名空间级资源限制
当多个团队共享集群时,可通过“资源配额(ResourceQuota)”和“默认限制(LimitRange)”为命名空间设置资源总上限和默认值,避免单个命名空间过度占用资源。
4.2.1 资源配额(ResourceQuota):命名空间总资源限制
创建resource-quota.yaml
,限制指定命名空间(如spark-cluster
)的总Pod数量、CPU和内存上限:
# resource-quota.yaml 配置文件
apiVersion: v1
kind: ResourceQuota # 资源类型:资源配额
metadata:name: compute-resources # 配额名称namespace: spark-cluster # 目标命名空间(需提前创建)
spec:hard: # 硬限制(无法突破)pods: "20" # 命名空间内最大Pod数量requests.cpu: "2" # 命名空间内所有Pod的CPU请求总和上限(2核)requests.memory: 1Gi # 命名空间内所有Pod的内存请求总和上限(1GB)limits.cpu: "4" # 命名空间内所有Pod的CPU限制总和上限(4核)limits.memory: 2Gi # 命名空间内所有Pod的内存限制总和上限(2GB)
执行以下命令创建资源配额:
# 1. 创建命名空间(若不存在)
kubectl create namespace spark-cluster# 2. 应用资源配额配置
kubectl apply -f resource-quota.yaml# 3. 查看命名空间的资源配额
kubectl get resourcequota -n spark-cluster
4.2.2 对象数量配额:限制命名空间内资源对象数量
除了计算资源,还可限制命名空间内ConfigMap、Secret等对象的数量,配置示例:
apiVersion: v1
kind: ResourceQuota
metadata:name: object-counts # 配额名称namespace: spark-cluster # 目标命名空间
spec:hard:configmaps: "10" # 最大ConfigMap数量persistentvolumeclaims: "4" # 最大PVC(持久化存储声明)数量replicationcontrollers: "20" # 最大ReplicationController数量secrets: "10" # 最大Secret数量services: "10" # 最大Service数量services.loadbalancers: "2" # 最大LoadBalancer类型Service数量
4.2.3 默认限制(LimitRange):为未配置资源的Pod设置默认值
若Pod未显式配置requests
和limits
,则会使用当前命名空间的最大资源;如果命名空间也没设置,则会使用集群的最大资源。
我们可以通过LimitRange
设置默认值,避免Pod无限制占用资源,配置示例:
# limit-range.yaml 配置文件
apiVersion: v1
kind: LimitRange # 资源类型:默认限制
metadata:name: mem-limit-range # 限制名称namespace: test # 目标命名空间(需提前创建)
spec:limits:- default: # 默认的limits值(对应resources.limits)memory: 512Mi # 默认内存上限(512MB)cpu: 500m # 默认CPU上限(0.5核)defaultRequest: # 默认的requests值(对应resources.requests)memory: 256Mi # 默认内存请求(256MB)cpu: 100m # 默认CPU请求(0.1核)type: Container # 限制类型:Container(支持Container、Pod、PVC)
执行以下命令创建默认限制:
# 1. 创建命名空间(若不存在)
kubectl create namespace test# 2. 应用默认限制配置
kubectl apply -f limit-range.yaml# 3. 查看命名空间的默认限制
kubectl get limitrange -n test
关键规则:
- Pod资源限制的优先级为
Pod显式配置 > LimitRange默认值 > 集群默认值
;- 当Pod内存超过
limits
时,K8s会通过cgroup触发OOM(内存溢出),终止Pod以释放资源。
总结
本文详细讲解了K8s HPA的部署与实战,从核心概念到依赖组件metrics-server
部署,再到HPA的创建、负载测试,最后补充了资源限制的扩展配置,核心要点总结如下:
- HPA依赖:必须先部署
metrics-server
,否则HPA无法获取Pod负载数据,导致伸缩功能失效; - 伸缩逻辑:HPA基于CPU利用率(默认)触发伸缩,“扩容快、缩容慢”,保障业务高峰期稳定性;
- 资源配置:Pod的
resources.requests
是HPA计算CPU利用率的基准,需合理设置;命名空间级的ResourceQuota
和LimitRange
可防止资源滥用; - 测试关键:模拟负载时需确保CPU利用率超过阈值(如50%),若负载不足可增加测试客户端。
通过HPA,可实现K8s集群的“智能化资源调度”,减少人工干预,提升服务稳定性和资源利用率。后续可进一步探索HPA的高级用法,如基于内存、自定义指标(如QPS、并发连接数)的伸缩,以及结合Prometheus+Grafana实现指标监控与可视化。
附录:常见问题排查
- kubectl top命令无输出:检查
metrics-server
Pod是否Running,查看日志(kubectl logs -n kube-system metrics-server-xxxx
),确认是否存在Kubelet通信问题(如--kubelet-insecure-tls
参数未配置); - HPA的TARGETS显示
<unknown>
:等待1-2分钟,若仍异常,检查metrics-server
是否正常提供API(kubectl api-versions | grep metrics
); - HPA不扩容:确认Pod的CPU利用率是否超过阈值,检查
requests.cpu
是否配置(HPA需基于此计算利用率),查看HPA事件(kubectl describe hpa php-apache
)。