K8s HPA自动扩缩容

在安装完k8s相关的部署后,随着业务的发展,比如说电商系统遇到大促,这个时候k8s里面的pod的cpu使用率就会大幅上升,可能会导致cpu使用率达到100%,从而导致系统反应缓慢,甚至不可用,如果使用人工去观察cpu的使用情况,这个不仅费时费力,而且效果也不太好,这个时候k8s提供了一种Horizontal Pod Autoscaler(HPA)的自动扩缩容的方法,在cpu使用量达到预定的百分比时就会自动进行扩容pod,HPA 的工作流程是一个闭环的反馈系统,依赖于以下组件协同工作:

  1. 指标采集Metrics Server 从集群中每个节点的 Kubelet 采集基础的 CPU、内存资源指标。

  2. 指标查询:HPA 控制器通过 Kubernetes API 定期查询 Metrics Server,获取目标 Pod 的平均资源利用率。

  3. 计算与决策 :控制器将当前指标与你在 HPA 中设定的目标值进行比较,通过特定公式计算出所需的副本数。

  4. 执行伸缩 :控制器更新目标工作负载(如 Deployment)的 replicas 字段,从而触发 Pod 的创建或销毁。

整个链路可以概括为:Metrics Server -> Kubernetes Metrics API -> HPA Controller -> 调整 Deployment replicas。

同样的我们也是在dockers desktop上面进行HPA的扩缩容验证,

HPA 依赖 Metrics Server 获取 Pod 的 CPU/内存指标。Docker Desktop 默认不包含 Metrics Server,需要手动安装。

1. 安装 Metrics Server

XML 复制代码
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

2. 修复自签名证书问题(关键步骤)

Docker Desktop 的 Kubelet 证书是自签名的,必须让 Metrics Server 跳过 TLS 验证,否则 HPA 会一直显示 <unknown>

XML 复制代码
kubectl patch deployment metrics-server -n kube-system --type='json' -p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'

3. 验证 Metrics Server 是否正常工作

等待约 1 分钟后执行:

XML 复制代码
kubectl top nodes
kubectl top pods

如果能正常显示 CPU/内存数据,说明 Metrics Server 已就绪。如果显示 error,请检查 Metrics Server Pod 的日志:kubectl logs -n kube-system deployment/metrics-server

HPA 必须基于 Pod 的 resources.requests 来计算利用率,因此 Deployment 中必须明确设置 CPU 请求值:

1.设置backend-deployment-hpa.yaml

XML 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-service-pha          # Deployment 名称,集群内唯一
  labels:
    # 【资源标签】用于标识这个 Deployment 对象本身,方便分类、查询和运维管理。
    # 注意:这里的标签不会自动传递给 Pod,也不影响 Deployment 管理哪些 Pod。
    app: backend-service-pha          # 表示这个 Deployment 属于 backend-service-pha 应用
    version: v1                       # 表示这个 Deployment 管理的是 v1 版本
spec:
  selector:
    matchLabels:
      # 【Pod 选择器】定义该 Deployment 管理哪些 Pod。
      # 必须与下面 template.metadata.labels 中的标签完全匹配,否则 Deployment 无法管理 Pod。
      # 这里同时匹配 app 和 version,确保不同版本的 Deployment 不会互相干扰。
      app: backend-service-pha        # 匹配属于该应用的 Pod
      version: v1                     # 只匹配 v1 版本的 Pod
  replicas: 1                         # 期望的 Pod 副本数;HPA 可动态调整此值
  template:
    metadata:
      labels:
        # 【Pod 标签】Pod 的标签,必须匹配上面的 selector.matchLabels。
        # 同时,Service 也通过 app 标签来发现并转发流量。
        # version 标签用于 Istio 区分不同版本,后续灰度发布时会在 VirtualService 中引用。
        app: backend-service-pha      # 表示这个 Pod 属于 backend-service-pha 应用
        version: v1                   # 表示这个 Pod 是 v1 版本
    spec:
      containers:
        - name: backend-service-pha   # 容器名称,在 Pod 内唯一;通常与 Deployment 名称保持一致
          image: client-agent-backend:1.3.5  # 容器镜像地址和标签;建议使用明确版本号,避免使用 latest
          ports:
            - containerPort: 8090     # 容器内部监听的端口;必须与应用程序实际监听的端口一致
          resources:                  # 资源限制配置,HPA 依赖 requests 计算 CPU 利用率
            requests:                 # 最低资源保证;调度器据此选择节点
              cpu: 200m               # CPU 请求量:200 毫核(0.2 核)
              memory: 256Mi           # 内存请求量:256 MiB
            limits:                   # 最大资源上限;容器超过限制可能被限流或终止
              cpu: 500m               # CPU 上限:500 毫核(0.5 核)
              memory: 512Mi           # 内存上限:512 MiB
---
apiVersion: v1
kind: Service
metadata:
  name: backend-service-pha
spec:
  ports:
    - port: 8090                      # Service 对外暴露的端口;集群内其他服务通过该端口访问
  selector:
    # 【Service 选择器】将流量转发给带有指定标签的 Pod。
    # 这里只选择 app 标签,不包含 version,这样 Service 会将流量负载均衡到所有版本的 Pod
    # (例如 v1 和未来的 v2),配合 Istio VirtualService 即可实现权重路由。
    app: backend-service-pha          # 只匹配属于该应用的 Pod,不区分版本

2.配置HPA信息

XML 复制代码
# HPA 的 API 版本,autoscaling/v2 支持多指标和更精细的扩缩容行为配置
apiVersion: autoscaling/v2

# 资源类型:HorizontalPodAutoscaler(水平 Pod 自动扩缩容)
kind: HorizontalPodAutoscaler

metadata:
  # HPA 对象的名称,集群内唯一
  name: backend-service-pha

spec:
  # 指定要伸缩的目标资源
  scaleTargetRef:
    apiVersion: apps/v1          # 目标资源的 API 版本,Deployment 属于 apps/v1
    kind: Deployment             # 目标资源类型,这里是对 Deployment 进行伸缩
    name: backend-service-pha    # 目标 Deployment 的名称,必须与集群中实际名称一致

  # 副本数下限:即使负载很低,也至少保持 1 个 Pod 运行
  minReplicas: 1

  # 副本数上限:即使负载很高,最多也只能扩展到 5 个 Pod
  maxReplicas: 5

  # 指标列表:HPA 根据这些指标来决定是否扩容或缩容
  metrics:
    # 指标类型为 Resource,表示使用 Kubernetes 内置的资源指标(如 CPU、内存)
    - type: Resource
      resource:
        # 指标名称:cpu,表示基于 CPU 使用率进行伸缩
        name: cpu
        target:
          # 目标类型为 Utilization,表示按"利用率百分比"来计算
          # 利用率 = Pod 实际 CPU 使用量 / Pod 的 CPU requests
          type: Utilization
          # 目标平均利用率:50%
          # 当所有 Pod 的平均 CPU 利用率超过 50% 时,HPA 会尝试扩容
          # 当低于 50% 时,HPA 会尝试缩容(受缩容冷却时间影响)
          averageUtilization: 50

有了这些配置后,我们就可以启动了

XML 复制代码
kubectl apply -f .\backend-deployment-hpa.yaml 

kubectl apply -f .\backend-deployment-horizontal.yaml

启动完成后我们可以观察pod的数量,执行下面的命令,我自己的代码里提供了这个接口:

XML 复制代码
kubectl run -i --tty load-generator --rm --image=busybox:1.28 --image-pull-policy=IfNotPresent --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://backend-service-pha:8090/actuator/health; done"

通过这个查看cpu的使用情况

XML 复制代码
kubectl get hpa backend-service-pha --watch

会看到随着cpu的使用量增加,pod的数量也会跟这增加,当关闭了接口查询,cpu的使用率就会下降,pod的数量也会跟着减少。

还需要注意的是执行以下命令在spec.template.spec.containers0.args列表末尾添加一行- --kubelet-insecure-tls

XML 复制代码
kubectl edit deployment metrics-server -n kube-system 

有时候我们会拉取Metrics Server 失败, 解决方法:手动拉取镜像到本地,然后重启 Pod。

✅ 解决步骤

1. 查看 metrics-server 使用的镜像

XML 复制代码
kubectl get deployment metrics-server -n kube-system -o jsonpath="{.spec.template.spec.containers[0].image}"

输出类似:registry.k8s.io/metrics-server/metrics-server:v0.7.x

2. 手动拉取镜像到本地 Docker

XML 复制代码
docker pull registry.k8s.io/metrics-server/metrics-server:v0.7.7

请将版本号替换为上一步实际查看到的版本。

如果 registry.k8s.io 拉取慢或失败,可以改用国内镜像:

XML 复制代码
# 从国内镜像源拉取
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server:v0.7.7

# 重新打标签为原镜像名
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server:v0.7.7 registry.k8s.io/metrics-server/metrics-server:v0.7.7

3. 修改 Deployment 的镜像拉取策略为 IfNotPresent

XML 复制代码
kubectl patch deployment metrics-server -n kube-system --type='strategic' -p='{"spec":{"template":{"spec":{"containers":[{"name":"metrics-server","imagePullPolicy":"IfNotPresent"}]}}}}'

如果上面这条报错,可以直接 kubectl edit deployment metrics-server -n kube-system,找到 imagePullPolicy 改为 IfNotPresent,保存退出。

4. 重启 Pod 使用本地镜像

XML 复制代码
kubectl rollout restart deployment/metrics-server -n kube-system

5. 验证

XML 复制代码
kubectl get pods -n kube-system -l k8s-app=metrics-server
kubectl top nodes

如果 kubectl top nodes 能返回 CPU/内存数据,说明 Metrics Server 正常工作。

相关推荐
小小ken1 小时前
docker容器(数据)备份及恢复:使用docker-volume-backup项目
docker·容器
wdfk_prog2 小时前
ROS教程06:ROS1 Node 启动与停止流程
运维·缓存·docker·容器·ros
阿虎儿2 小时前
2025 年的自托管(Self-Hosting)
docker·容器
叶总没有会2 小时前
Docker 基础+实战
运维·docker·云原生·容器
j7~3 小时前
【C++微服务项目开发脚手架】(环境篇)虚拟机 + Docker + MySQL/Redis/RabbitMQ/ES/etcd/FastDFS 全套配齐
linux·c++·ubuntu·docker·vmware·项目开发·微服务脚手架
天天喝旺仔3 小时前
Go 泛型实战:从类型参数、约束到可复用泛型容器与函数
数据结构·算法·容器·go
小马同学-3 小时前
docker容器
docker·容器
DarkAthena3 小时前
拒绝Docker Desktop-在win11上运行docker容器的替代方案
docker
羑悻的小杀马特4 小时前
从写 YAML 到集群自愈:KES-Operator 把 KES 集群接进 Kubernetes 原生体系
运维·数据库·容器·kubernetes