CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
Kubernetes 入门/课时/资源配额与 HPA
RawBlame
课时目录12 节

Kubernetes 入门

  1. 01Kubernetes 是什么
  2. 02核心概念与架构
  3. 03本地集群与 kubectl
  4. 04Pod
  5. 05Deployment 与滚动更新
  6. 06Service 与网络
  7. 07ConfigMap 与 Secret
  8. 08存储卷
  9. 09Ingress 入口
  10. 10资源配额与 HPA
  11. 11RBAC 与安全基础
  12. 12综合练习:部署 backend

资源配额与 HPA

requests/limits、Namespace 配额、自动扩缩容概念。

30 分钟

资源配额与 HPA

这一课你将能做到

  1. 在容器 spec 写出 CPU/内存的 requests 与 limits,并解释二者对「调度」与「运行」的不同影响
  2. 说出三级 QoS 的区别,了解 Namespace 级 ResourceQuota / LimitRange 的用途
  3. 读懂并创建一份 HPA(autoscaling/v2),解释它按什么指标、算什么公式扩缩副本

为什么要学

集群资源有限,不立规矩就是「丛林法则」:不写 requests,Scheduler 只能瞎猜这个 Pod 占多大,节点被塞爆后所有服务一起变慢;不写 limits,一个内存泄漏的进程能 OOM 掉整台机器上的邻居。流量高峰靠人肉改 replicas 太慢——HPA(Horizontal Pod Autoscaler) 按指标自动在 min/max 区间扩缩副本。

对本站:backend 是 JVM 应用,启动期和稳态内存差异大,requests/limits 写得太随意会频繁 OOMKilled;扩副本后每个实例都连 MySQL,HPA 的 max 要和数据库连接池一起算。这些都是面试真题(「requests 和 limits 区别」「HPA 原理」)。

先建立图像

requests:调度「预约」——节点剩余量 ≥ requests 才放得下;也是 HPA 利用率的分母
limits:  运行「天花板」——内存超限 → OOMKill;CPU 超限 → 被节流(变慢但不死)

HPA 决策循环(每 15 秒左右):
  采集指标(metrics-server) → 算期望副本 = ceil(当前副本 × 当前利用率/目标利用率)
  → 与上次决策对比(扩容防抖 0s、缩容稳定窗口默认 5 分钟)→ 调整 replicas
机制作用范围一句话
requests / limits单容器自己的份
LimitRangeNamespace给没写资源的 Pod 发默认值/卡上下限
ResourceQuotaNamespace全命名空间总量封顶
HPADeployment 等自动改副本数
Cluster Autoscaler节点池副本放不下就加机器(了解)

跟着做

步骤 1:给 backend 容器加 requests/limits

在 deploy-backend.yaml 容器段追加:

          resources:
            requests:
              cpu: "100m"        # 0.1 核:调度预约
              memory: "256Mi"
            limits:
              cpu: "500m"        # 0.5 核:运行天花板
              memory: "512Mi"
kubectl apply -f deploy-backend.yaml
kubectl describe pod -l app=backend | findstr /i "Requests Limits QoS"

(Linux/macOS 用 grep。)应看到资源字段与 QoS Class: Burstable。真 backend(JVM)的经验:启动期内存峰值明显高于稳态,limits 过紧会在启动时 OOMKilled——JVM 配 -XX:MaxRAMPercentage=75.0 让堆自适应容器限额,比手写 -Xmx 更贴合。

步骤 2:看真实用量(metrics-server)

minikube addons enable metrics-server
kubectl get pods -n kube-system -l k8s-app=metrics-server -w   # 等 Running
kubectl top nodes
kubectl top pods

kubectl top 输出的是「实际用量」,和 requests(预约)、limits(上限)三个数字放在一起看,才敢谈调优。顺序:先观测 → 再定 requests/limits → 最后谈 HPA。

步骤 3:命名空间配额(ResourceQuota / LimitRange)

quota.yaml:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: coderoadmap-quota
  namespace: default
spec:
  hard:
    requests.cpu: "2"
    requests.memory: 4Gi
    limits.cpu: "4"
    limits.memory: 8Gi
    pods: "20"
---
apiVersion: v1
kind: LimitRange
metadata:
  name: coderoadmap-limits
spec:
  limits:
    - type: Container
      default:            # 没写 limits 的容器自动获得
        cpu: "500m"
        memory: "512Mi"
      defaultRequest:     # 没写 requests 的容器自动获得
        cpu: "100m"
        memory: "128Mi"
kubectl apply -f quota.yaml
kubectl get resourcequota

效果:本命名空间总申请量被封顶(防一个团队吃光集群);漏写资源的容器自动带默认值。生产多团队集群这是标配,全靠自觉是不行的。

步骤 4:创建 HPA

hpa-backend.yaml:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: backend-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: backend
  minReplicas: 2
  maxReplicas: 6
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70    # 平均利用率(相对 requests)超 70% 就扩
  behavior:                          # 可选:扩缩行为微调
    scaleDown:
      stabilizationWindowSeconds: 300
kubectl apply -f hpa-backend.yaml
kubectl get hpa backend-hpa
kubectl describe hpa backend-hpa

TARGETS 一开始可能显示 <unknown>/70%:指标管道还没就绪,等一分钟再试;一直 unknown 见卡点急救。

步骤 5:制造负载看扩缩

kubectl run load --rm -it --image=busybox:1.36 --restart=Never -- \
  sh -c "while true; do wget -qO- http://backend >/dev/null 2>&1; done"

另开终端盯 kubectl get hpa -w 与 kubectl get pods -l app=backend。注意:nginx 占位镜像几乎不吃 CPU,扩缩可能不触发——这恰恰验证了「HPA 只看真实指标」,把 averageUtilization 临时调低或换个真吃 CPU 的负载即可看到 replicas 上升;Ctrl+C 停掉负载后,缩容要等稳定窗口(默认 5 分钟,上面已配 300s)。对本站的启示:扩副本会线性放大到 MySQL 的连接数,maxReplicas 要按「每副本连接池 × 副本数 ≤ 数据库上限」反推。

步骤 6:亲手见一次 OOMKilled

把上面临时改出一份「必死配置」:memory limit 压到 32Mi(nginx 可跑,换个想多要内存的负载即可,或直接把 busybox command 改成分配大数组)。观察:

kubectl get pods -w
kubectl describe pod <名字>

Status 显示 OOMKilled、重启次数上涨——这就是「内存 limit 是硬墙」。JVM 服务尤其要按步骤 1 的建议留足余量。

讲清楚要点

  1. requests 决定「能不能调度到节点」,limits 决定「跑起来后最多用多少」:前者影响放置与密度,后者影响运行时行为;两者语义完全不同,不可混写。
  2. 内存超 limit 必死(OOMKill),CPU 超 limit 只是被限速:所以内存要留余量、CPU 可适当紧——JVM 堆务必与内存 limit 自洽。
  3. HPA 的利用率分母是 requests:requests 虚高 → 利用率永远偏低 → 不扩;虚低 → 动不动就扩还挤兑资源。先校准 requests 再上 HPA。
  4. 扩容快、缩容慢是特性:扩容立即响应防过载,缩容有稳定窗口防抖动;behavior 段可微调,别瞎砍默认值。
  5. ResourceQuota 管总量、LimitRange 管默认:多团队/多项目共享集群时防「吵闹邻居」,也强制 Pod 都带资源声明。
  6. HPA 只会自动改 replicas:它和手改 replicas 冲突时 HPA 赢(持续调谐会把你手改的值改回去);上了 HPA 就别再手动 scale。

你可能会懵的地方

  • CPU limit 会让程序变慢吗? 会——超限时被节流(throttling),延迟抖动。经验:Web 服务常不设 CPU limit 只设 request(避免限速),内存 limit 必设(防拖垮节点);团队规范优先。

  • 只写 limits 不写 requests 行吗? 行为因配置而异(有的环境会把 request 默认等于 limit)。实践:核心服务两者都显式写清,别靠隐式规则。

  • 为什么 HPA TARGETS 显示 unknown? 指标管道不通:metrics-server 没装好、Pod 没写 requests(Utilization 算不出百分比)、或刚创建还没采到数据。describe hpa 的 Conditions 会写明原因。

  • minikube 单机学 HPA 有意义吗? 有——对象字段、指标管道、扩缩窗口的概念全都能练;只是单机指标噪声大,别拿本地表现外推生产数值。

  • 垂直扩容(加内存)怎么办? 那是 VPA(改容器规格)与 Cluster Autoscaler(加节点)的领域,与 HPA(加副本)互补。入门先精通 HPA,VPA 了解即可。

错法对照

错法问题正解
全员不写 requests调度无据可依,节点被塞爆核心服务必写 requests
limits 盲目抄「2C4G 起步」浪费资源、掩盖泄漏用 top 观测后再定
HPA 不设 maxReplicas高峰雪崩式扩容打爆下游设上限并按 DB 连接数反推
无 metrics-server 硬上 HPA永远 unknown 不工作先通指标管道
JVM 忽略容器内存感知启动期 OOMKilledMaxRAMPercentage + 留足余量

卡点急救

  1. kubectl top 报 Metrics API not available:metrics-server 未装或未就绪——minikube 用 addons enable metrics-server,等 Pod Running 再试;仍不通看其日志(常见是证书问题,按官方 FAQ 处理)。
  2. Pod 反复重启,describe 显示 OOMKilled:内存 limit 过小或 JVM 堆未适配容器;上调 limit、配置 MaxRAMPercentage、必要时加 startupProbe 给慢启动留时间。
  3. HPA 一直 <unknown>/70%:确认 metrics-server 正常、目标 Deployment 的容器写了 requests(Utilization 需要)、等 1-2 分钟采集窗口;describe hpa 看 FailedGetResourceMetric 类事件。

面试常问

  • requests 和 limits 的区别? requests 是调度依据:Scheduler 保证「节点可分配资源 ≥ 所有 Pod requests 之和」,它决定 Pod 放哪、密度多高,同时也是 HPA 利用率的分母;limits 是运行时上限:CPU 超限被 CFS 节流(变慢不死),内存超限触发 OOMKill(容器重启)。由两者组合产生三级 QoS:requests==limits 为 Guaranteed(最不容易被驱逐)、设了 request<limit 为 Burstable(大多数服务)、都没设为 BestEffort(资源紧张时最先被杀)。

  • HPA 的工作原理? HPA 控制器周期性(默认 15 秒)从 metrics-server(自定义指标则从对应 API)采集指标,按公式「期望副本 = ceil(当前副本数 × 当前指标值 / 目标指标值)」计算,对 CPU 类 Utilization 指标以 requests 为分母;扩容立即生效、缩容要过稳定窗口(默认 5 分钟)防止抖动;最终修改 scaleTargetRef 对象(如 Deployment)的 replicas,再由其下层控制器完成 Pod 增删。前提:指标管道可用、目标容器声明了 requests。

  • 线上出现频繁 OOMKill 怎么排查? 定位:describe pod 看 OOMKilled 与重启次数,top 对比实际用量与 limit。常见根因与处置:limit 明显低于应用真实峰值→上调并观察;JVM 未感知容器限额→加 MaxRAMPercentage;内存泄漏→堆 dump 定位修复;旁路问题(page cache 计入 cgroup)→留余量。原则:先观测再调参,不盲目加内存掩盖泄漏。

自测三问

  1. requests 和 limits 分别影响「调度」和「运行」的哪一步?
  2. 为什么 HPA 的 averageUtilization 必须和 requests 一起理解?
  3. backend 扩到 6 副本时,最先被压垮的通常是应用还是数据库?怎么预防?

小结一句话

先用 requests/limits 划清单容器边界、用 Quota/LimitRange 守住命名空间总量,再用 HPA 在安全区间内自动调副本——下一课补上「谁有权操作这些对象」的 RBAC 与安全基础。

延伸

  • Manage Resources for Containers
  • Horizontal Pod Autoscaling
  • 下一课预告:RBAC 与安全基础——ServiceAccount、Role/Binding、auth can-i,以及容器以非 root 运行的实战。
加载本节练习…
← 上一课Ingress 入口下一课 →RBAC 与安全基础