一、先总述核心定位
K8s 的自动缩扩容 是为了弹性适配业务流量 ,避免资源浪费或过载;崩溃恢复 是为了保证应用高可用 ,核心都是基于 「期望状态 vs 实际状态」的调和机制------ 控制器持续监控状态差异,自动触发调整。
二、自动缩扩容(面试重点:HPA)
K8s 自动缩扩容分 3 类,但面试只需要重点讲 水平 Pod 自动伸缩(HPA),另外两类简单带过即可。
1. 三类伸缩对比(答题时一句话概括)
| 类型 | 核心作用 | 关键依赖 |
|---|---|---|
| 水平 Pod 伸缩(HPA) | 调整 Pod 的副本数量(比如 2 个扩到 5 个),无状态应用首选 | Metrics Server(指标采集) |
| 垂直 Pod 伸缩(VPA) | 调整单个 Pod 的 CPU / 内存规格(比如 1 核扩到 2 核) | VPA 控制器 |
| 集群级伸缩(CA) | 节点资源不足时新增节点,闲置时删节点(云厂商场景) | 云厂商节点池 + CA 控制器 |
2. HPA 核心工作流程(面试必背,分 4 步讲)
HPA 是最常用的伸缩方式,分**「配置→采集→判断→执行」** 四步:
- 配置伸缩规则:通过 HPA 资源对象,绑定目标 Deployment/RS,设置「最小 / 最大副本数」「伸缩指标阈值」(比如 CPU 使用率 80%、内存使用率 70%)。
- 指标采集 :依赖
Metrics Server(必须部署,K8s 默认没有),定期采集 Pod 的 CPU、内存等核心指标。 - 阈值对比计算 :HPA 控制器默认每 15 秒 查询一次指标,对比实际指标和预设阈值,计算需要的目标副本数。
- 计算公式(可提可不提,加分项):
目标副本数 = 当前副本数 × (当前指标值 / 目标指标值)
- 计算公式(可提可不提,加分项):
- 执行伸缩 :HPA 直接修改 Deployment/RS 的
replicas字段 ------ 指标超标就扩容,指标过低就缩容,由 RS 控制器负责创建 / 删除 Pod。
3. HPA 面试高频考点(踩中得分点)
- 必问 1 :为什么 HPA 必须设置 Pod 的
resources.requests?答:因为 HPA 计算资源使用率的分母是requests(不是实际使用量),没有requests,HPA 无法计算使用率,会直接失效。 - 必问 2 :HPA 伸缩有什么限制?答:① 只支持无状态应用(有状态用 StatefulSet + 自定义伸缩);② 避免短时间内频繁伸缩(可通过
--horizontal-pod-autoscaler-stabilization-window设置稳定窗口)。
在 Pod 的 YAML 里,requests和limits写在containers的resources字段下,比如:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.24
resources:
requests: # 核心:声明最低保障
cpu: 100m # 申请0.1核CPU
memory: 128Mi # 申请128MB内存
limits: # 可选:声明最大上限
cpu: 500m # 最多用0.5核CPU
memory: 256Mi # 最多用256MB内存
用表格记最清晰:
| 特性 | resources.requests(资源请求) | resources.limits(资源限制) |
|---|---|---|
| 核心含义 | Pod 运行的「最低资源保障」 | Pod 运行的「最大资源上限」 |
| 调度依据 | 调度器必须参考,决定 Pod 放哪个节点 | 调度器不参考,只在 Pod 运行时生效 |
| 超量后果 | 不会被限制,可使用节点空闲资源 | 超 CPU:被限流(throttle);超内存:被 OOM 杀死(crash) |
| 和 HPA 的关系 | 是 HPA 计算使用率的分母(必须设) | 和 HPA 无直接关系 |
面试示例话术(HPA 部分)
我们线上主要用 HPA 做水平伸缩,首先部署 Metrics Server 采集指标,然后定义 HPA 绑定 Deployment,设置最小 2 副本、最大 10 副本,CPU 阈值 80%。HPA 控制器每 15 秒查一次指标,比如流量高峰时 Pod CPU 使用率到了 90%,就自动把副本数从 2 扩到 5;流量下降后再缩回去。这里要注意,Pod 必须配置 resources.requests,否则 HPA 无法工作。
HPA 的核心决策依据是 「计算后的目标副本数是否和当前副本数一致」,而不是 "使用率是否严格等于 80%"。公式:目标副本数=当前副本数*(实际平均使用率/目标阈值)
HPA 会对计算结果取整 ,只要取整后的值和当前副本数一致 ,就不扩也不缩!
举个例子:当前副本数 = 2,阈值 80%
| 实际使用率 | 目标副本数计算 | 实际决策 | 原因 |
|---|---|---|---|
| 84% | 2×(84%/80%)=2.1 | 不扩容 | 目标副本数 2.1 只比当前多 0.1,差值太小,属于正常波动,不操作 |
| 90% | 2×(90%/80%)=2.25 | 不扩容 | 2.25 比 2 多 0.25,依然是小幅波动,不满足 "新增 1 个 Pod" 的需求 |
| 120% | 2×(120%/80%)=3 | 扩容到 3 | 3 比 2 多 1,差值足够大,说明流量确实上涨,需要新增 Pod |
| 75% | 2×(75%/80%)=1.875 | 不缩容 | 1.875 比 2 少 0.125,波动太小;且 minReplicas=2,也不能再缩 |
| 50% | 2×(50%/80%)=1.25 | 缩容到 2 | 虽然计算值 1.25<2,但 minReplicas=2,最低保留 2 个副本 |
三、崩溃恢复(面试重点:控制器 + 重启策略)
崩溃恢复的核心是 「控制器兜底 + 容器重启优先」
核心原理前置(一句话点明)
所有恢复操作的本质:控制器持续监控实际状态,当实际状态≠期望状态时,自动触发修正。
1. Pod 级崩溃恢复(最常见,分 2 种情况)
Pod 崩溃的原因:容器进程退出、OOM 被杀、配置错误等,恢复分两步:
(1)第一步:容器级重启(优先策略)
由 Pod 的restartPolicy决定,这是恢复的第一道防线,面试必问 3 种策略的区别:
| 对比维度 | Always(默认策略) |
OnFailure |
Never |
|---|---|---|---|
| 重启触发条件 | 容器任何原因退出(正常 / 异常),立即重启 | 仅容器异常退出(非 0 退出码) 时重启;正常退出(0 退出码)不重启 | 容器任何原因退出(正常 / 异常),永不重启 |
| 退出码依赖 | 不依赖退出码,0 / 非 0 码都触发重启 | 仅非 0 退出码触发重启,0 码不触发 | 不依赖退出码,任何码都不触发重启 |
| 核心目标 | 保证容器长期持续运行,不中断服务 | 任务失败重试,成功停止,避免空跑 | 容器退出后依赖控制器重建新 Pod,不复用原容器环境 |
| 适用场景 | 无状态长期运行服务 | 批处理 / 周期性任务(失败可重试,成功即停) | 一次性初始化任务(失败后需全新环境重试) |
| 典型业务案例(Java 后端) | Nginx 网关、Spring Boot 微服务 API、Redis 代理 | MySQL 定时备份、跨库数据同步、日志批量清理 | Flyway/MyBatis 表结构初始化、Redis 集群搭建、临时诊断任务 |
| 推荐搭配 K8s 资源 | Deployment/ReplicaSet(保证副本数) | CronJob(定时任务)/Job(批处理任务) | Job(一次性任务),配合backoffLimit设置重试次数 |
| 正常退出(0 码)后 Pod 状态 | 容器立即重启,Pod 状态保持 Running |
容器不重启,Pod 状态变为 Completed |
容器不重启,Pod 状态变为 Completed |
| 异常退出(非 0 码)后 Pod 状态 | 容器立即重启,Pod 状态保持 Running;反复失败触发CrashLoopBackOff |
容器立即重启,Pod 状态保持 Running;反复失败持续重试 |
容器不重启,Pod 状态变为 Error;控制器重建新 Pod |
| 面试关键备注 | 1. 适配 K8s 核心场景(长期服务);2. 反复崩溃触发退避策略(暂停重启) | 1. 任务需满足幂等性(重试不重复造数据);2. 成功后容器自动停止,节省资源 | 1. 失败后原容器有环境残留(如临时文件),需重建 Pod;2. 完全依赖控制器兜底,无容器级重启 |
记忆口诀
Always:长期服务必选,任何退出都续命;OnFailure:批处理任务专用,失败重试成功停;Never:初始化任务专属,死活不重启,重建新 Pod。
(2)第二步:控制器重建(兜底保障)
如果容器重启后还是崩溃(比如镜像错误、代码 bug),或者 Pod 被删除,由 Deployment/RS/StatefulSet 控制器兜底:
- 无状态应用(Deployment/RS):控制器监控到「实际 Pod 数 < 期望副本数」,直接在健康节点上重建新 Pod,不保留任何状态。
- 有状态应用(StatefulSet) :针对数据库、中间件等,恢复时会保留两个核心状态:
- 网络标识:Pod 名称固定(比如 mysql-0、mysql-1),通过 Headless Service 保证 DNS 解析不变;
- 存储状态:绑定的 PVC 不会随 Pod 删除而删除,新 Pod 重建后直接挂载原有数据。
2. 节点级崩溃恢复(面试加分项)
当整个节点宕机(比如服务器断电、网络失联),由 Node Controller 负责恢复:
- Node Controller 默认每 5 秒 检查一次节点状态,节点失联超过5 分钟 (可配置),标记为
NotReady; - 控制器将该节点上的所有 Pod 标记为
Terminating; - 触发 Deployment/RS 在其他健康节点上重建这些 Pod,保证整体副本数符合期望。
崩溃恢复面试高频考点
- 必问 1:Deployment 和 StatefulSet 的崩溃恢复有什么区别?答:Deployment 是无状态的,恢复的 Pod 是全新的,没有固定名称和存储;StatefulSet 是有状态的,恢复的 Pod 名称固定,会挂载原有 PVC,保证数据不丢失。
- 必问 2 :Pod 崩溃后,重启和重建的区别是什么?答:重启 是在原 Pod 内重启容器,Pod 的 IP、名称等信息不变;重建是删除原 Pod,创建新 Pod,IP 和名称可能变化(StatefulSet 除外)。
四、面试答题总结模板(直接背)
K8s 的自动缩扩容和崩溃恢复,核心都是「期望状态 vs 实际状态」的调和机制。
- 自动缩扩容:重点是 HPA,通过 Metrics Server 采集 Pod 指标,对比阈值后自动调整 Deployment 的副本数,实现水平伸缩,关键是要配置 Pod 的 resources.requests。
- 崩溃恢复:分两层 ------ 第一层是 Pod 的 restartPolicy,优先重启容器;第二层是控制器兜底,Deployment/RS 保证无状态应用的副本数,StatefulSet 保证有状态应用的网络和存储不变;节点级故障则由 Node Controller 触发跨节点重建。
五、面试避坑提醒
- 不要只讲概念,一定要结合实际使用场景(比如无状态用 HPA+Deployment,有状态用 StatefulSet)。
- 遇到追问(比如 HPA 为什么失效?),优先答「没部署 Metrics Server」「没设置 requests」这两个最常见原因。
相关名词解释:
一、自动缩扩容相关组件
| 缩写 | 全称 | 中文翻译 | 核心作用(面试必答) | 面试关联考点 |
|---|---|---|---|---|
| HPA | Horizontal Pod Autoscaler | 水平 Pod 自动伸缩器 | 最常用的缩扩容组件:调整 Pod 的副本数量(比如 2 个扩到 5 个),适配流量变化 | 1. 依赖 Metrics Server 采集指标;2. 必须给 Pod 设置 resources.requests(否则无法计算资源使用率);3. 只适合无状态应用 |
| VPA | Vertical Pod Autoscaler | 垂直 Pod 自动伸缩器 | 调整单个 Pod 的 CPU / 内存规格(比如 1 核扩到 2 核),解决单 Pod 资源不足问题 | 1. 和 HPA 的区别:HPA 调数量 ,VPA 调单 Pod 资源;2. 生产中一般不与 HPA 同时启用(避免冲突) |
| CA | Cluster Autoscaler | 集群自动伸缩器 | 集群节点层的伸缩:节点资源不足时自动新增节点 ,资源闲置时删除节点 | 1. 依赖云厂商的节点池(如 AWS EKS、阿里云 ACK);2. 伸缩层级:HPA(Pod 层)→ VPA(Pod 资源层)→ CA(节点层) |
| Metrics Server | 无(本身是组件名) | 指标服务器 | K8s 集群的核心指标采集组件:采集 Pod / 节点的 CPU、内存使用率等基础指标 | 1. HPA 的必备依赖,K8s 默认不安装,需手动部署;2. 面试高频问:HPA 失效的常见原因?答:没装 Metrics Server 或 Pod 没设 requests |
二、崩溃恢复相关组件
| 缩写 | 全称 | 中文翻译 | 核心作用(面试必答) | 面试关联考点 |
|---|---|---|---|---|
| Deployment | 无(本身是资源对象名) | 部署控制器 | K8s 管理无状态应用 的核心控制器,底层依赖 RS | 1. 核心能力:保证 Pod 副本数(崩溃后重建)+ 滚动更新 + 版本回滚;2. 崩溃恢复逻辑:监控实际 Pod 数 → 对比期望副本数 → 不足则通过 RS 重建;3. 面试必问:和 StatefulSet 的区别? |
| RS | ReplicaSet | 副本集 | Deployment 的底层依赖组件 ,核心职责就是保证指定数量的 Pod 副本始终运行 | 1. 作用:Deployment 负责版本管理,RS 负责副本数兜底;2. 对比 Replication Controller(RC):RS 是 RC 的升级版,支持更灵活的标签选择器 |
| StatefulSet | 无(本身是资源对象名) | 有状态集控制器 | 管理有状态应用(如 MySQL、Kafka)的控制器,崩溃恢复时保证状态不丢失 | 1. 恢复核心特性: - 固定 Pod 名称(如 mysql-0、mysql-1); - 绑定固定 PVC(数据持久化); - 通过 Headless Service 提供固定 DNS 解析;2. 面试必问:和 Deployment 的区别?(看下面表格) |
| Node Controller | 无(本身是控制器名) | 节点控制器 | K8s 核心控制器之一,监控节点健康状态,处理节点级故障 | 1. 节点宕机处理流程:节点失联 5 分钟 → 标记为 NotReady → 触发 Pod 跨节点重建;2. 面试问:节点挂了,上面的 Pod 怎么办?答:Node Controller 标记节点异常,Deployment/RS 在其他节点重建 Pod |
面试高频对比:Deployment vs StatefulSet
| 特性 | Deployment(无状态) | StatefulSet(有状态) |
|---|---|---|
| Pod 名称 | 随机生成(如 nginx-7f987f67c8-2xq5z) | 固定有序(如 mysql-0、mysql-1) |
| 存储 | 所有 Pod 共享一个 PVC(可选) | 每个 Pod 绑定独立 PVC(数据隔离) |
| 网络 | 通过普通 Service 访问(IP 不固定) | 通过 Headless Service 访问(DNS 固定) |
| 适用场景 | Nginx、微服务 API、前端应用 | MySQL 集群、Kafka 集群、Redis 集群 |
三、配套核心组件
| 缩写 | 全称 | 中文翻译 | 核心作用 | 面试关联点 |
|---|---|---|---|---|
| PVC | PersistentVolumeClaim | 持久化卷声明 | 用户申请存储资源的接口,比如申请 10G 的 SSD 存储 | 1. StatefulSet 的核心依赖:每个 Pod 绑定独立 PVC,崩溃重建后数据不丢;2. 面试问:PVC 和 PV 的关系?答:PV 是集群的存储资源,PVC 是用户对 PV 的申请(类似租房:PV 是房子,PVC 是租房合同) |
| Headless Service | 无(本身是 Service 类型) | 无头服务 | 一种没有 ClusterIP 的 Service | 1. 专为 StatefulSet 设计:给每个 Pod 分配固定的 DNS 域名(如 mysql-0.mysql-service.default.svc.cluster.local);2. 区别普通 Service:普通 Service 通过 ClusterIP 转发流量,Headless Service 直接解析 Pod IP |